diff --git a/.bzrignore b/.bzrignore deleted file mode 100644 index 64aa4c93e..000000000 --- a/.bzrignore +++ /dev/null @@ -1,171 +0,0 @@ -00_header -10_* -20_linux_xen -30_os-prober -40_custom -41_custom -*.1 -*.8 -aclocal.m4 -ascii.bitmaps -ascii.h -autom4te.cache -build_env.mk -.bzrignore -config.cache -config.guess -config.h -config-util.h -config-util.h.in -config.log -config.status -config.sub -configure -DISTLIST -docs/*.info -docs/stamp-vti -docs/version.texi -*.elf -example_grub_script_test -example_scripted_test -example_unit_test -*.exec -genkernsyms.sh -gensymlist.sh -gentrigtables -grub-bin2h -grub_cmd_echo -grub_cmd_regexp -grub-editenv -grub-emu -grub_emu_init.c -grub_emu_init.h -grub-fstest -grub_fstest_init.c -grub_fstest_init.h -grub-install -grub-kbdcomp -grub-macho2img -grub-menulst2cfg -grub-mk* -grub-mount -grub-pe2elf -grub-probe -grub_probe_init.c -grub_probe_init.h -grub-reboot -grub_script_blanklines -grub_script_blockarg -grub_script_break -grub-script-check -grub_script_check_init.c -grub_script_check_init.h -grub_script_comments -grub_script_continue -grub_script_dollar -grub_script_echo1 -grub_script_echo_keywords -grub_script_expansion -grub_script_final_semicolon -grub_script_for1 -grub_script_functions -grub_script_if -grub_script_not -grub_script_return -grub_script_setparams -grub_script_shift -grub_script_vars1 -grub_script_while1 -grub_script.tab.c -grub_script.tab.h -grub_script.yy.c -grub_script.yy.h -grub-set-default -grub-setup -grub_setup_init.c -grub_setup_init.h -grub-shell -grub-shell-tester -*.img -*.image -include/grub/cpu -include/grub/machine -install-sh -lib/libgcrypt-grub -libgrub_a_init.c -*.lst -*.marker -Makefile -*.mod -mod-*.c -missing -partmap_test -*.pf2 -*.pp -po/*.mo -po/grub.pot -po/POTFILES -po/stamp-po -stamp-h -stamp-h1 -stamp-h.in -symlist.c -symlist.h -trigtables.c -update-grub_lib -unidata.c -Makefile.in -GPATH -GRTAGS -GSYMS -GTAGS -Makefile.tpl -compile -depcomp -mdate-sh -texinfo.tex -grub-core/lib/libgcrypt-grub -**/.deps -**/.deps-util -**/.deps-core -**/.dirstamp -Makefile.util.am -contrib -grub-core/Makefile.core.am -grub-core/Makefile.gcry.def -grub-core/contrib -grub-core/gdb_grub -grub-core/genmod.sh -grub-core/gensyminfo.sh -grub-core/gmodule.pl -grub-core/modinfo.sh -grub-core/*.module -grub-core/*.pp -util/bash-completion.d/grub -grub-core/gnulib/alloca.h -grub-core/gnulib/arg-nonnull.h -grub-core/gnulib/c++defs.h -grub-core/gnulib/charset.alias -grub-core/gnulib/configmake.h -grub-core/gnulib/getopt.h -grub-core/gnulib/langinfo.h -grub-core/gnulib/ref-add.sed -grub-core/gnulib/ref-del.sed -grub-core/gnulib/stdio.h -grub-core/gnulib/stdlib.h -grub-core/gnulib/string.h -grub-core/gnulib/strings.h -grub-core/gnulib/sys -grub-core/gnulib/unistd.h -grub-core/gnulib/warn-on-use.h -grub-core/gnulib/wchar.h -grub-core/gnulib/wctype.h -grub-core/rs_decoder.S -widthspec.bin -widthspec.h -docs/stamp-1 -docs/version-dev.texi -Makefile.utilgcry.def -po/*.po -po/*.gmo -po/LINGUAS diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..33ffaa404 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +po/exclude.pot binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..524f2e6d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,285 @@ +# +# Ignore patterns in this directory and all subdirectories. +# +*.1 +*.8 +*.a +*.exec +*.exec.exe +*.image +*.image.exe +*.img +*.log +*.lst +*.marker +*.mod +*.o +*.pf2 +*.pp +*.pyc +*.trs +*~ +.deps-core/ +.deps-util/ +.deps/ +.dirstamp +DISTLIST +GPATH +GRTAGS +GSYMS +GTAGS +Makefile +Makefile.in +ascii.bitmaps +genkernsyms.sh +gensymlist.sh +grub-bin2h +grub-emu +grub-emu-lite +grub-emu-lite.exe +grub-emu.exe +grub-macho2img +grub_emu_init.c +grub_emu_init.h +grub_probe_init.c +grub_probe_init.h +grub_script.tab.c +grub_script.tab.h +grub_script.yy.c +grub_script.yy.h +grub_script_check_init.c +grub_script_check_init.h +grub_setup_init.c +grub_setup_init.h +mdate-sh +mod-*.c +update-grub_lib +widthspec.bin + +# +# Ignore patterns relative to this .gitignore file's directory. +# +/00_header +/10_* +/20_linux_xen +/30_os-prober +/30_uefi-firmware +/40_custom +/41_custom +/ABOUT-NLS +/ChangeLog +/INSTALL.grub +/Makefile.util.am +/Makefile.utilgcry.def +/aclocal.m4 +/ahci_test +/ascii.h +/autom4te.cache/ +/btrfs_test +/build-aux/ +/build-grub-gen-asciih +/build-grub-gen-widthspec +/build-grub-mkfont +/cdboot_test +/cmp_test +/compile +/config-util.h +/config-util.h.in +/config.cache +/config.guess +/config.h +/config.log +/config.status +/config.sub +/configure +/contrib +/core_compress_test +/cpio_test +/date_test +/depcomp +/docs/*.info +/docs/*.info-[0-9]* +/docs/stamp-1 +/docs/stamp-vti +/docs/version-dev.texi +/docs/version.texi +/ehci_test +/erofs_test +/example_grub_script_test +/example_scripted_test +/example_unit_test +/exfat_test +/ext234_test +/f2fs_test +/fat_test +/fddboot_test +/file_filter_test +/garbage-gen +/garbage-gen.exe +/gettext_strings_test +/gnulib/ +/grub-2.[0-9]*/ +/grub-2.[0-9]*.tar.gz +/grub-bios-setup +/grub-bios-setup.exe +/grub-core/*.module +/grub-core/*.module.exe +/grub-core/*.pp +/grub-core/Makefile.core.am +/grub-core/Makefile.gcry.def +/grub-core/bootinfo.txt +/grub-core/build-grub-module-verifier +/grub-core/build-grub-pe2elf.exe +/grub-core/contrib +/grub-core/gdb_grub +/grub-core/genmod.sh +/grub-core/gensyminfo.sh +/grub-core/gentrigtables +/grub-core/gentrigtables.exe +/grub-core/gmodule.pl +/grub-core/grub.chrp +/grub-core/kernel.img.bin +/grub-core/lib/gnulib +/grub-core/lib/libgcrypt-grub +/grub-core/lib/libtasn1-grub +/grub-core/modinfo.sh +/grub-core/rs_decoder.h +/grub-core/symlist.c +/grub-core/symlist.h +/grub-core/tests/asn1/tests +/grub-core/trigtables.c +/grub-core/unidata.c +/grub-editenv +/grub-editenv.exe +/grub-file +/grub-file.exe +/grub-fs-tester +/grub-fstest +/grub-fstest.exe +/grub-glue-efi +/grub-glue-efi.exe +/grub-install +/grub-install.exe +/grub-kbdcomp +/grub-macbless +/grub-macbless.exe +/grub-menulst2cfg +/grub-menulst2cfg.exe +/grub-mk* +/grub-mount +/grub-ofpathname +/grub-ofpathname.exe +/grub-probe +/grub-probe.exe +/grub-protect +/grub-protect.exe +/grub-reboot +/grub-render-label +/grub-render-label.exe +/grub-script-check +/grub-script-check.exe +/grub-set-default +/grub-shell +/grub-shell-tester +/grub-sparc64-setup +/grub-sparc64-setup.exe +/grub-syslinux2cfg +/grub-syslinux2cfg.exe +/grub_cmd_date +/grub_cmd_echo +/grub_cmd_regexp +/grub_cmd_set_date +/grub_cmd_sleep +/grub_cmd_test +/grub_cmd_tr +/grub_fstest_init.c +/grub_fstest_init.h +/grub_func_test +/grub_script_blanklines +/grub_script_blockarg +/grub_script_break +/grub_script_comments +/grub_script_continue +/grub_script_dollar +/grub_script_echo1 +/grub_script_echo_keywords +/grub_script_escape_comma +/grub_script_eval +/grub_script_expansion +/grub_script_final_semicolon +/grub_script_for1 +/grub_script_functions +/grub_script_gettext +/grub_script_if +/grub_script_leading_whitespace +/grub_script_no_commands +/grub_script_not +/grub_script_return +/grub_script_setparams +/grub_script_shift +/grub_script_strcmp +/grub_script_test +/grub_script_vars1 +/grub_script_while1 +/gzcompress_test +/hddboot_test +/help_test +/hfs_test +/hfsplus_test +/include/grub/cpu +/include/grub/gcrypt/g10lib.h +/include/grub/gcrypt/gcrypt.h +/include/grub/machine +/install-sh +/iso9660_test +/jfs_test +/lib/libgcrypt-grub +/libgrub_a_init.c +/lzocompress_test +/luks1_test +/luks2_test +/m4/ +/minixfs_test +/missing +/netboot_test +/nilfs2_test +/ntfs_test +/ohci_test +/partmap_test +/pata_test +/po/*.gmo +/po/*.mo +/po/*.po +/po/LINGUAS +/po/Makefile.in.in +/po/Makevars +/po/Makevars.template +/po/POTFILES +/po/POTFILES-shell.in +/po/POTFILES.in +/po/Rules-quot +/po/grub.pot +/po/remove-potcdate.sed +/po/stamp-po +/printf_test +/priority_queue_unit_test +/pseries_test +/reiserfs_test +/romfs_test +/squashfs_test +/stamp-h +/stamp-h.in +/stamp-h1 +/syslinux_test +/tar_test +/test_sha512sum +/test_unset +/tests/syslinux/ubuntu10.04_grub.cfg +/texinfo.tex +/udf_test +/uhci_test +/util/bash-completion.d/grub +/widthspec.h +/xfs_test +/xzcompress_test +/zfs_test diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..4bd05a30a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,109 @@ +# SPDX-License-Identifier: GPL-3.0+ +# Originally Copyright Roger Meier +# Adapted for GRUB by Alexander Graf +# +# Build GRUB on Travis CI - https://www.travis-ci.org/ +# + +dist: xenial + +language: c + +addons: + apt: + packages: + - autopoint + - libsdl1.2-dev + - lzop + - ovmf + - python + - qemu-system + - unifont + +env: + global: + # Include all cross toolchain paths, so we can just call them later down. + - PATH=/tmp/qemu-install/bin:/tmp/grub/bin:/usr/bin:/bin:/tmp/cross/gcc-8.1.0-nolibc/aarch64-linux/bin:/tmp/cross/gcc-8.1.0-nolibc/arm-linux-gnueabi/bin:/tmp/cross/gcc-8.1.0-nolibc/ia64-linux/bin:/tmp/cross/gcc-8.1.0-nolibc/mips64-linux/bin:/tmp/cross/gcc-8.1.0-nolibc/powerpc64-linux/bin:/tmp/cross/gcc-8.1.0-nolibc/riscv32-linux/bin:/tmp/cross/gcc-8.1.0-nolibc/riscv64-linux/bin:/tmp/cross/gcc-8.1.0-nolibc/sparc64-linux/bin + +before_script: + # Install necessary toolchains based on $CROSS_TARGETS variable. + - mkdir /tmp/cross + # These give us binaries like /tmp/cross/gcc-8.1.0-nolibc/ia64-linux/bin/ia64-linux-gcc + - for i in $CROSS_TARGETS; do + ( cd /tmp/cross; wget -t 3 -O - https://mirrors.kernel.org/pub/tools/crosstool/files/bin/x86_64/8.1.0/x86_64-gcc-8.1.0-nolibc-$i.tar.xz | tar xJ ); + done + +script: + # Comments must be outside the command strings below, or the Travis parser + # will get confused. + - ./bootstrap + + # Build all selected GRUB targets. + - for target in $GRUB_TARGETS; do + plat=${target#*-}; + arch=${target%-*}; + [ "$arch" = "arm64" ] && arch=aarch64-linux; + [ "$arch" = "arm" ] && arch=arm-linux-gnueabi; + [ "$arch" = "ia64" ] && arch=ia64-linux; + [ "$arch" = "mipsel" ] && arch=mips64-linux; + [ "$arch" = "powerpc" ] && arch=powerpc64-linux; + [ "$arch" = "riscv32" ] && arch=riscv32-linux; + [ "$arch" = "riscv64" ] && arch=riscv64-linux; + [ "$arch" = "sparc64" ] && arch=sparc64-linux; + echo "Building $target"; + mkdir obj-$target; + JOBS=`getconf _NPROCESSORS_ONLN 2> /dev/null || echo 1`; + [ "$JOBS" == 1 ] || JOBS=$(($JOBS + 1)); + ( cd obj-$target && ../configure --target=$arch --with-platform=$plat --prefix=/tmp/grub && make -j$JOBS && make -j$JOBS install ) &> log || ( cat log; false ); + done + + # Our test canary. + - echo -e "insmod echo\\ninsmod reboot\\necho hello world\\nreboot" > grub.cfg + + # Assemble images and possibly run them. + - for target in $GRUB_TARGETS; do grub-mkimage -c grub.cfg -p / -O $target -o grub-$target echo reboot normal; done + + # Run images we know how to run. + - if [[ "$GRUB_TARGETS" == *"x86_64-efi"* ]]; then qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -m 512 -no-reboot -nographic -net nic -net user,tftp=.,bootfile=grub-x86_64-efi | tee grub.log && grep "hello world" grub.log; fi + +matrix: + include: + # Each env setting here is a dedicated build. + - name: "x86_64" + env: + - GRUB_TARGETS="x86_64-efi x86_64-xen" + - name: "i386" + env: + - GRUB_TARGETS="i386-coreboot i386-efi i386-ieee1275 i386-multiboot i386-pc i386-qemu i386-xen i386-xen_pvh" + - name: "powerpc" + env: + - GRUB_TARGETS="powerpc-ieee1275" + - CROSS_TARGETS="powerpc64-linux" + - name: "sparc64" + env: + - GRUB_TARGETS="sparc64-ieee1275" + - CROSS_TARGETS="sparc64-linux" + - name: "ia64" + env: + - GRUB_TARGETS="ia64-efi" + - CROSS_TARGETS="ia64-linux" + - name: "mips" + env: + - GRUB_TARGETS="mips-arc mipsel-arc mipsel-qemu_mips mips-qemu_mips" + - CROSS_TARGETS="mips64-linux" + - name: "arm" + env: + - GRUB_TARGETS="arm-coreboot arm-efi arm-uboot" + - CROSS_TARGETS="arm-linux-gnueabi" + - name: "arm64" + env: + - GRUB_TARGETS="arm64-efi" + - CROSS_TARGETS="aarch64-linux" + - name: "riscv32" + env: + - GRUB_TARGETS="riscv32-efi" + - CROSS_TARGETS="riscv32-linux" + - name: "riscv64" + env: + - GRUB_TARGETS="riscv64-efi" + - CROSS_TARGETS="riscv64-linux" diff --git a/ABOUT-NLS b/ABOUT-NLS deleted file mode 100644 index 866b904ec..000000000 --- a/ABOUT-NLS +++ /dev/null @@ -1,223 +0,0 @@ -1 Notes on the Free Translation Project -*************************************** - -Free software is going international! The Free Translation Project is -a way to get maintainers of free software, translators, and users all -together, so that free software will gradually become able to speak many -languages. A few packages already provide translations for their -messages. - - If you found this `ABOUT-NLS' file inside a distribution, you may -assume that the distributed package does use GNU `gettext' internally, -itself available at your nearest GNU archive site. But you do _not_ -need to install GNU `gettext' prior to configuring, installing or using -this package with messages translated. - - Installers will find here some useful hints. These notes also -explain how users should proceed for getting the programs to use the -available translations. They tell how people wanting to contribute and -work on translations can contact the appropriate team. - - When reporting bugs in the `intl/' directory or bugs which may be -related to internationalization, you should tell about the version of -`gettext' which is used. The information can be found in the -`intl/VERSION' file, in internationalized packages. - -1.1 Quick configuration advice -============================== - -If you want to exploit the full power of internationalization, you -should configure it using - - ./configure --with-included-gettext - -to force usage of internationalizing routines provided within this -package, despite the existence of internationalizing capabilities in the -operating system where this package is being installed. So far, only -the `gettext' implementation in the GNU C library version 2 provides as -many features (such as locale alias, message inheritance, automatic -charset conversion or plural form handling) as the implementation here. -It is also not possible to offer this additional functionality on top -of a `catgets' implementation. Future versions of GNU `gettext' will -very likely convey even more functionality. So it might be a good idea -to change to GNU `gettext' as soon as possible. - - So you need _not_ provide this option if you are using GNU libc 2 or -you have installed a recent copy of the GNU gettext package with the -included `libintl'. - -1.2 INSTALL Matters -=================== - -Some packages are "localizable" when properly installed; the programs -they contain can be made to speak your own native language. Most such -packages use GNU `gettext'. Other packages have their own ways to -internationalization, predating GNU `gettext'. - - By default, this package will be installed to allow translation of -messages. It will automatically detect whether the system already -provides the GNU `gettext' functions. If not, the included GNU -`gettext' library will be used. This library is wholly contained -within this package, usually in the `intl/' subdirectory, so prior -installation of the GNU `gettext' package is _not_ required. -Installers may use special options at configuration time for changing -the default behaviour. The commands: - - ./configure --with-included-gettext - ./configure --disable-nls - -will, respectively, bypass any pre-existing `gettext' to use the -internationalizing routines provided within this package, or else, -_totally_ disable translation of messages. - - When you already have GNU `gettext' installed on your system and run -configure without an option for your new package, `configure' will -probably detect the previously built and installed `libintl.a' file and -will decide to use this. This might not be desirable. You should use -the more recent version of the GNU `gettext' library. I.e. if the file -`intl/VERSION' shows that the library which comes with this package is -more recent, you should use - - ./configure --with-included-gettext - -to prevent auto-detection. - - The configuration process will not test for the `catgets' function -and therefore it will not be used. The reason is that even an -emulation of `gettext' on top of `catgets' could not provide all the -extensions of the GNU `gettext' library. - - Internationalized packages usually have many `po/LL.po' files, where -LL gives an ISO 639 two-letter code identifying the language. Unless -translations have been forbidden at `configure' time by using the -`--disable-nls' switch, all available translations are installed -together with the package. However, the environment variable `LINGUAS' -may be set, prior to configuration, to limit the installed set. -`LINGUAS' should then contain a space separated list of two-letter -codes, stating which languages are allowed. - -1.3 Using This Package -====================== - -As a user, if your language has been installed for this package, you -only have to set the `LANG' environment variable to the appropriate -`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code, -and `CC' is an ISO 3166 two-letter country code. For example, let's -suppose that you speak German and live in Germany. At the shell -prompt, merely execute `setenv LANG de_DE' (in `csh'), -`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). -This can be done from your `.login' or `.profile' file, once and for -all. - - You might think that the country code specification is redundant. -But in fact, some languages have dialects in different countries. For -example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The -country code serves to distinguish the dialects. - - The locale naming convention of `LL_CC', with `LL' denoting the -language and `CC' denoting the country, is the one use on systems based -on GNU libc. On other systems, some variations of this scheme are -used, such as `LL' or `LL_CC.ENCODING'. You can get the list of -locales supported by your system for your language by running the -command `locale -a | grep '^LL''. - - Not all programs have translations for all languages. By default, an -English message is shown in place of a nonexistent translation. If you -understand other languages, you can set up a priority list of languages. -This is done through a different environment variable, called -`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' -for the purpose of message handling, but you still need to have `LANG' -set to the primary language; this is required by other parts of the -system libraries. For example, some Swedish users who would rather -read translations in German than English for when Swedish is not -available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. - - Special advice for Norwegian users: The language code for Norwegian -bokma*l changed from `no' to `nb' recently (in 2003). During the -transition period, while some message catalogs for this language are -installed under `nb' and some older ones under `no', it's recommended -for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and -older translations are used. - - In the `LANGUAGE' environment variable, but not in the `LANG' -environment variable, `LL_CC' combinations can be abbreviated as `LL' -to denote the language's main dialect. For example, `de' is equivalent -to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' -(Portuguese as spoken in Portugal) in this context. - -1.4 Translating Teams -===================== - -For the Free Translation Project to be a success, we need interested -people who like their own language and write it well, and who are also -able to synergize with other translators speaking the same language. -Each translation team has its own mailing list. The up-to-date list of -teams can be found at the Free Translation Project's homepage, -`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams" -area. - - If you'd like to volunteer to _work_ at translating messages, you -should become a member of the translating team for your own language. -The subscribing address is _not_ the same as the list itself, it has -`-request' appended. For example, speakers of Swedish can send a -message to `sv-request@li.org', having this message body: - - subscribe - - Keep in mind that team members are expected to participate -_actively_ in translations, or at solving translational difficulties, -rather than merely lurking around. If your team does not exist yet and -you want to start one, or if you are unsure about what to do or how to -get started, please write to `translation@iro.umontreal.ca' to reach the -coordinator for all translator teams. - - The English team is special. It works at improving and uniformizing -the terminology in use. Proven linguistic skills are praised more than -programming skills, here. - -1.5 Available Packages -====================== - -Languages are not equally supported in all packages. The following -matrix shows the current state of internationalization, as of October -2006. The matrix shows, in regard of each package, for which languages -PO files have been submitted to translation coordination, with a -translation percentage of at least 50%. - -# Matrix here is removed! - - Some counters in the preceding matrix are higher than the number of -visible blocks let us expect. This is because a few extra PO files are -used for implementing regional variants of languages, or language -dialects. - - For a PO file in the matrix above to be effective, the package to -which it applies should also have been internationalized and -distributed as such by its maintainer. There might be an observable -lag between the mere existence a PO file and its wide availability in a -distribution. - - If October 2006 seems to be old, you may fetch a more recent copy of -this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date -matrix with full percentage details can be found at -`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. - -1.6 Using `gettext' in new packages -=================================== - -If you are writing a freely available program and want to -internationalize it you are welcome to use GNU `gettext' in your -package. Of course you have to respect the GNU Library General Public -License which covers the use of the GNU `gettext' library. This means -in particular that even non-free programs can use `libintl' as a shared -library, whereas only free software can use `libintl' as a static -library or use modified versions of `libintl'. - - Once the sources are changed appropriately and the setup can handle -the use of `gettext' the only thing missing are the translations. The -Free Translation Project is also available for packages which are not -developed inside the GNU project. Therefore the information given above -applies also for every other Free Software Project. Contact -`translation@iro.umontreal.ca' to make the `.pot' files available to -the translation teams. - diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index 81bdae957..000000000 --- a/ChangeLog +++ /dev/null @@ -1,46494 +0,0 @@ -2012-06-27 Vladimir Serbinenko - - * configure.ac: Bump version to 2.00. - * grub-core/normal/main.c (features): Add feature_200_final. - -2012-06-27 Vladimir Serbinenko -2012-06-27 Jordan Uggla - - * NEWS: Fix unclarity and language mistakes. - -2012-06-27 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (find_efi_mmap_size): Increase - additional size to 3 pages. - Reported by: Stuart Hayes. - -2012-06-27 Vladimir Serbinenko - - * NEWS: Add 2.00 entry. - -2012-06-27 Vladimir Serbinenko - - * grub-core/commands/wildcard.c (check_file): Fix bad logic. - put explicit "/" for empty path. - (wildcard_expand): Improve dprintf. - -2012-06-27 Vladimir Serbinenko - - * grub-core/fs/fshelp.c (grub_fshelp_find_file): Don't free oldnode if - it's equal to currnode. This can happen with "" symlink. - -2012-06-27 Yves Blusseau - - * util/grub-mkconfig_lib.in: Fix print messages replacing builtin - echo shell command by printf command. - -2012-06-26 Vladimir Serbinenko - - * grub-core/term/arc/console.c (grub_console_init_output): Add one since - the value returned by firmware is the maximal position, not diumension. - (grub_terminfo_output_state): Use a more sane fallback. - -2012-06-26 Vladimir Serbinenko - - * grub-core/term/terminfo.c (print_terminfo): Print terminal dimensions. - -2012-06-26 Vladimir Serbinenko - - * grub-core/kern/mips/arc/init.c (grub_machine_init): Set clock - frequency to 150 MHz. - -2012-06-26 Vladimir Serbinenko - - Apple fixes. - - * grub-core/lib/i386/relocator16.S: Use correct __APPLE__ and not - __APPLE_ - * grub-core/lib/i386/relocator_common.S [__APPLE__]: Fix gdtdesc - definition. - * grub-core/lib/i386/relocator64.S [__APPLE__]: Assemble jmp manually. - -2012-06-26 Vladimir Serbinenko - - Handle slash in HFS label. - - * grub-core/fs/hfs.c (macroman_to_utf8): New argument slash_translate. - (grub_hfs_dir): Tanslate slash. - (grub_hfs_label): Don't translate slash. - -2012-06-26 Vladimir Serbinenko - - * grub-core/commands/ls.c (grub_ls_list_devices): Disable - network protocol listing since it introduces problematic dependency on - net module. - -2012-06-26 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Add Yeeloong verified hash. - -2012-06-26 Vladimir Serbinenko - - Init video early on yeeloong to avoid being rebooted by watchdog. - - * grub-core/Makefile.am (gensm712): New target. - (sm712_start.S): Likewise. - (boot/mips/loongson/fwstart.S): Depend on sm712_start.S - * grub-core/boot/mips/loongson/fwstart.S [!FULOONG2F]: Init SM712. - * grub-core/video/sm712.c [GENINIT]: Generate compact init procedure - description. - * include/grub/vga.h: Move registry definitions to... - * include/grub/vgaregs.h: ... here. - -2012-06-26 Vladimir Serbinenko - - * grub-core/boot/decompressor/minilib.c (grub_memcmp): Fix the compare - signedness. - -2012-06-25 Vladimir Serbinenko - - * util/grub-install.in: Fix dvhtool invocation. Add arc to the list of - platforms with firmware disk drivers in the core. - -2012-06-25 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (scan_disk) [GRUB_UTIL]: Put more - informative verbose message. - (read_lv): Handle 64-bit segment size. - -2012-06-25 Vladimir Serbinenko - - * grub-core/disk/lvm.c (grub_lvm_getvalue): Handle 64-bit values. - -2012-06-25 Vladimir Serbinenko - - * grub-core/fs/fat.c (grub_fat_iterate_dir_next): Don't stop on a space - character but still remove trainling spaces. - (grub_fat_label): Ignore archive flag. - -2012-06-25 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (grub_cmd_initrd): Avoid unnecessarry - cast between linux_kernel_header and linux_kernel_params. - -2012-06-25 Vladimir Serbinenko - - * include/grub/diskfilter.h (grub_raid5_recover_func_t): Use proper - type for size. - (grub_raid6_recover_func_t): Likewise. - * grub-core/disk/raid5_recover.c (grub_raid5_recover): Likewise. - * grub-core/disk/raid6_recover.c (grub_raid6_recover): Likewise. - -2012-06-25 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Add Fuloong2F verified hash. - -2012-06-25 GrĂ©goire Sutre - - Fix overflow. - - * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_size) - [__NetBSD__]: Add explicit cast before bitshift. - -2012-06-23 Vladimir Serbinenko - - * configure.ac: Bump to 2.00~rc1. - -2012-06-23 Vladimir Serbinenko - - * grub-core/boot/mips/loongson/fwstart.S: Add missing setting of high - half of $a0. - -2012-06-23 Vladimir Serbinenko -2012-06-23 Jordan Uggla - - * docs/grub.texi: Fix search syntax. - (Multi-boot manual config): Put msdos rather than GPT example. - Grammar corrections. - -2012-06-23 Vladimir Serbinenko - - * docs/grub.texi (Multi-boot manual config): Use --set. Improve remark. - -2012-06-22 Vladimir Serbinenko - - * grub-core/kern/mm.c (grub_free): Fix agglomerating of free regions. - -2012-06-22 Vladimir Serbinenko - - * grub-core/kern/mm.c (get_header_from_pointer): Put a more informative - message on double free. Put the value of magic in case of mismatch. - -2012-06-22 Vladimir Serbinenko - - Speed-up video on yeeloong. - - * grub-core/video/sm712.c (framebuffer): Remove render_target and - add cached_ptr. - (grub_video_sm712_video_fini): Unmap cached_ptr. - (grub_video_sm712_setup): Use cache address and grub_video_fb_setup. - (grub_video_sm712_set_active_render_target): Removed. - (grub_video_adapter): Use grub_video_fb_set_active_render_target. - (grub_video_sm712_swap_buffers): Call grub_video_fb_swap_buffers and - sync caches. - -2012-06-22 Vladimir Serbinenko - - Avoid flushing the same line multiple times on loongson. - - * grub-core/kern/mips/cache.S [GRUB_MACHINE_MIPS_LOONGSON]: - Step in 32 bytes and not 1 byte. - * grub-core/kern/mips/cache_flush.S [GRUB_MACHINE_MIPS_LOONGSON]: - Likewise. - -2012-06-22 Vladimir Serbinenko - - * util/getroot.c (grub_find_root_devices_from_mountinfo): Handle btrfs - subvolumes. - -2012-06-22 Vladimir Serbinenko - - Implement flow control for http. - - * grub-core/net/http.c (parse_line): Handle response 206. - (http_receive): Stall if too many packets are in the queue. - (http_establish): Fix range header. - (http_seek): Fix double free. - (http_close): Likewise. - (http_packets_pulled): New function. - (grub_http_protocol): Set http_seek - * grub-core/net/tcp.c (grub_net_tcp_socket): New field `i_stall'. - (ack_real): Set window depending on i_stall. - (grub_net_send_tcp_packet): Likewise. - (grub_net_tcp_stall): New function. - (grub_net_tcp_unstall): Likewise. - * include/grub/net/tcp.h (grub_net_tcp_stall): New proto. - (grub_net_tcp_unstall): Likewise. - -2012-06-22 Vladimir Serbinenko - - * grub-core/net/tftp.c: Decrease stall to 50 packets. - -2012-06-22 Vladimir Serbinenko - - * grub-core/net/net.c (grub_net_fs_open): Free resources on failed open. - -2012-06-22 Vladimir Serbinenko - - * tests/util/grub-shell.in: Fix a typo. - -2012-06-22 Vladimir Serbinenko - - Implement flow control for tftp. - - * grub-core/net/net.c (receive_packets): Decrease the stop to 10 - packets but stop only if stop condition is satisfied. - (grub_net_fs_read_real): Call packets_pulled after real read. Use - `stall' instead of `eof' as stop condition. - * grub-core/net/http.c (parse_line): Set `stall' on EOF. - (http_err): Likewise. - * grub-core/net/tftp.c (ack): Replace the first argument with data - instead of socket. - (tftp_receive): Stall if too many packets are in wait queue. - (tftp_packets_pulled): New function. - (grub_tftp_protocol): Set packets_pulled. - * include/grub/net.h (grub_net_packets): New field count. - (grub_net_put_packet): Increment count. - (grub_net_remove_packet): Likewise. - (grub_net_app_protocol): New field `packets_pulled'. - (grub_net): New field `stall'. - -2012-06-22 Vladimir Serbinenko - - * grub-core/net/net.c (receive_packets): Stop after 100 packets to let - sync part to handle them. - -2012-06-21 Vladimir Serbinenko - - * grub-core/kern/main.c (grub_set_prefix_and_root): Fix memory leak. - * grub-core/net/drivers/ieee1275/ofnet.c - (grub_ieee1275_net_config_real): Likewise. - -2012-06-21 Vladimir Serbinenko - - * grub-core/net/bootp.c (grub_net_configure_by_dhcp_ack): Don't create - the direct route for server/gateway. - -2012-06-21 Vladimir Serbinenko - - * grub-core/net/bootp.c (grub_net_configure_by_dhcp_ack): Prefer - IP address to server name since we may not hame the DNS. - -2012-06-21 Vladimir Serbinenko - - * grub-core/net/dns.c (grub_cmd_nslookup): Init addresses to 0 to avoid - freeing random buffer on failure. - * grub-core/net/net.c (grub_net_resolve_address): Likewise. - -2012-06-21 Vladimir Serbinenko - - * grub-core/net/bootp.c (grub_cmd_bootp): Fix packet allocation size. - -2012-06-21 Vladimir Serbinenko - - * grub-core/net/drivers/emu/emunet.c (get_card_packet): Allocate the - reserved bytes. - * grub-core/net/drivers/i386/pc/pxe.c (grub_pxe_recv): Likewise. - * grub-core/net/drivers/ieee1275/ofnet.c (get_card_packet): Likewise. - Handle malloc error correctly. - -2012-06-21 Vladimir Serbinenko - - * grub-core/script/execute.c (grub_script_arglist_to_argv): Escape - blocks. - -2012-06-21 Vladimir Serbinenko - - * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): Fix double - increment. - -2012-06-20 Vladimir Serbinenko - - * grub-core/net/dns.c (grub_cmd_nslookup): Use configured DNS servers if - none is explicitly specified. - -2012-06-20 Vladimir Serbinenko - - * grub-core/net/dns.c (grub_net_add_dns_server): Don't erase old servers - while reallocating. - -2012-06-20 Vladimir Serbinenko - - Respect netmask from bootp/dhcp. - - * grub-core/net/bootp.c (parse_dhcp_vendor): Parse mask. - (grub_net_configure_by_dhcp_ack): Use mask and grub_net_add_ipv4_local. - * grub-core/net/net.c (grub_net_add_addr): Split creating local route - into ... - (grub_net_add_ipv4_local): ... this. - (grub_cmd_addaddr): Use grub_net_add_ipv4_local. - * include/grub/net.h (GRUB_NET_BOOTP_NETMASK): New enum value. - (grub_net_add_ipv4_local): New proto. - -2012-06-20 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (grub_linux_boot): Setup video before - determining EFI memory map size. - -2012-06-20 Vladimir Serbinenko - - * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): Escape commas. - -2012-06-20 Vladimir Serbinenko - - * grub-core/kern/main.c (grub_set_prefix_and_root): Skip escaped commas - when looking for partition separator. - -2012-06-20 Vladimir Serbinenko - - * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_encode_devname): - Escape commas. - -2012-06-20 Vladimir Serbinenko - - Restructure FAT driver to avoid hook in label reading as it hits a - GCC bug. - - * include/grub/err.h (grub_err_t): New enum value GRUB_ERR_EOF. - * grub-core/fs/fat.c (grub_fat_iterate_context): New struct. - (grub_fat_iterate_dir): Split into ... - (grub_fat_iterate_init): ... this, ... - (grub_fat_iterate_fini): ... this, ... - (grub_fat_iterate_dir_next): ... and this. All users updated. - -2012-06-20 Vladimir Serbinenko - - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New enum value - GRUB_IEEE1275_FLAG_BROKEN_REPEAT. - * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set - GRUB_IEEE1275_FLAG_BROKEN_REPEAT on PowerBook3,3. - * include/grub/terminfo.h (grub_terminfo_input_state) [__powerpc__]: - New fields last_key and last_key_time. - * grub-core/term/terminfo.c (grub_terminfo_getkey): Transform - extended key-esc into extended key-extended key. - -2012-06-19 Vladimir Serbinenko - - Avoid unnecessary memcpy of whole video buffer. - - * grub-core/video/fb/video_fb.c (dirty): New struct. - (framebuffer): Add members current_dirty and previous_dirty. - (dirty): New function. - (grub_video_fb_fill_rect): Update dirty. - (common_blitter): Likewise. - (grub_video_fb_scroll): Likewise. - (doublebuf_blit_update_screen): Copy only dirty part. - (doublebuf_pageflipping_update_screen): Likewise. - (grub_video_fb_doublebuf_blit_init): Init dirty. - (doublebuf_pageflipping_init): Likewise. - (grub_video_fb_setup): Likewise. - -2012-06-19 Vladimir Serbinenko - - * grub-core/net/drivers/ieee1275/ofnet.c (search_net_devices): Decrease - poll rate. - -2012-06-19 Vladimir Serbinenko - - Fix wildcard regexp dot and other special characters handling. - Reported by: Robert Mabee. - - * grub-core/commands/wildcard.c (isregexop): Add "|+{}[]?". - (make_regex): Escape "|+{}[]". Transform '?' to '.?'. - (split_path): Trigger expansion on '?'. - (unescape): New function. - (wildcard_expand): Unescape parts copied without globbing. - * grub-core/script/execute.c (wildcard_escape): Escape '?'. - (grub_script_arglist_to_argv): Don't unescape expansions. - -2012-06-19 Vladimir Serbinenko - - * include/grub/net.h (grub_net_card): New member txbufsize. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New enum values - GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX and - GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN. - * grub-core/net/drivers/efi/efinet.c (grub_efinet_findcards): Use - txbufsize. - * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Use - compatible property to check for macs. Set - GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX and - GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN on macs. - * grub-core/net/drivers/ieee1275/ofnet.c (card_open): Don't add suffix - if GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX is set. - (send_card_buffer): Use txbuf. - (grub_ofnet_findcards): Allocate txbuf. Simplify code flow and move - nested function out of the parent while on it. - -2012-06-19 Vladimir Serbinenko - - * grub-core/net/drivers/ieee1275/ofnet.c (get_card_packet): Fix packet - presence check. - (grub_ieee1275_net_config_real): Fix config pointer. - -2012-06-19 Vladimir Serbinenko - - * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): Extend - filename parsing to non-block devices. - -2012-06-19 Vladimir Serbinenko - - * grub-core/kern/device.c (grub_device_open): Remove dead code. - -2012-06-18 Vladimir Serbinenko - - * include/grub/elf.h: Rename R_PPC to GRUB_R_PPC to avoid collisions. - All users updated. - -2012-06-18 Vladimir Serbinenko - - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Generate - UUID search command even if hints probing failed. - -2012-06-18 Vladimir Serbinenko - - * po/POTFILES.in: Regenerated. - -2012-06-17 Vladimir Serbinenko - - Speed-up video on fuloong. - - * grub-core/bus/bonito.c (grub_pci_device_map_range_cached): - New function. - (grub_pci_device_unmap_range): Handle non-cached address. - * grub-core/video/sis315pro.c (framebuffer): Remove render_target and - add direct_ptr. - (grub_video_sis315pro_video_fini): Unmap direct_ptr. - (grub_video_sis315pro_setup): Use cache address and grub_video_fb_setup. - (grub_video_sis315pro_set_active_render_target): Removed. - (grub_video_sis315pro_get_info_and_fini): Use uncached address. - (grub_video_adapter): Use grub_video_fb_set_active_render_target. - (grub_video_sis315pro_swap_buffers): Call grub_video_fb_swap_buffers and - sync caches. - * include/grub/mips/loongson/pci.h (grub_pci_device_map_range_cached): - New proto. - -2012-06-16 Vladimir Serbinenko - - * docs/grub.texi (Multi-boot manual config): New section. - -2012-06-15 Vladimir Serbinenko - - Avoid slow read-back from VRAM. - - * include/grub/video_fb.h (grub_video_fb_doublebuf_update_screen_t): - Move from here ... - * grub-core/video/fb/video_fb.c - (grub_video_fb_doublebuf_update_screen_t): ... here. Remove arguments. - * grub-core/video/fb/video_fb.c (framebuf_t): New type. - (front_target): Remove front_target. Add pages. - (grub_video_fb_init): Skip setting front_pages. - (grub_video_fb_fini): Likewise. - (doublebuf_blit_update_screen): Use pages. - (grub_video_fb_doublebuf_blit_init): Likewise. - (doublebuf_pageflipping_init): Allocate offscreen buffer. - (doublebuf_pageflipping_update_screen): Use offscreen buffer. - (grub_video_fb_setup): Prefer doublebuffing. - -2012-06-15 Vladimir Serbinenko - - * grub-core/normal/main.c (GRUB_MOD_INIT): Ignore errors when loading - gzio. - -2012-06-15 Vladimir Serbinenko - - Add loongson tests. - - * tests/util/grub-shell.in: Handle loongson. - * tests/partmap_test.in: Add loongson to the list of platform using ATA - drivers. - * grub-core/tests/boot/linux.init-mips.S (SHUTDOWN_MAGIC3) [REBOOT]: - Reboot instead of shutdown if REBOOT is defined. - -2012-06-15 Vladimir Serbinenko - - * grub-core/lib/mips/loongson/reboot.c (grub_reboot): Use 32-bit - sized ports since unlike on real hardware qemu supports only 32-bit - regs. - -2012-06-15 Vladimir Serbinenko - - * Makefile.util.def (grub-mkrescue): Enable on loongson. - * util/grub-mkrescue.in: Handle loongson. - -2012-06-14 Vladimir Serbinenko - - * util/getroot.c (convert_system_partition_to_system_disk) [__APPLE__]: - Set is_part appropriately. - (grub_util_biosdisk_get_grub_dev): Use is_part rather than comparing - names. Canonicalize partition without full disk. - -2012-06-13 Vladimir Serbinenko - - Revert usb-quiesce since it's wrong. - - * grub-core/disk/ieee1275/ofdisk.c (quiesce): Removed. - (grub_ofdisk_init): Don't do quiesce. - -2012-06-13 Vladimir Serbinenko - - * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Apply - PowerMac workaround to Xserves as well. - Information supplied by: Benjamin Herrenschmidt. - -2012-06-13 Vladimir Serbinenko - - Don't assume that beginning address is also the entry point on ppc. - - * grub-core/loader/powerpc/ieee1275/linux.c (linux_entry): New variable. - (grub_linux_boot): Use linux_entry. - (grub_linux_load32): Fill linux_entry. Fix setting linux_addr. - (grub_linux_load64): Likewise. - -2012-06-13 Vladimir Serbinenko - - * util/grub-install.in: Fix cross-disk check on non-PreP machines. - -2012-06-13 Vladimir Serbinenko - - * grub-core/term/ieee1275/console.c (grub_console_fini): Don't - needlessly lose the console. - -2012-06-13 Vladimir Serbinenko - - * grub-core/normal/dyncmd.c (read_command_list): Don't access freed - space. - -2012-06-11 Vladimir Serbinenko - - Remove non-functional EFI grub_get_rtc. Put a better fatal message - than current grub_get_rtc() not implemented when booted with - coreboot without TSC. - - * grub-core/Makefile.am: Exclude efi/time.h from kernel headers. - Add machine/time.h to kernel headers on loongson. - * grub-core/Makefile.core.def (kernel): Remove - kern/generic/rtc_get_time_ms.c on qemu-multiboot-coreboot. - * grub-core/kern/efi/efi.c (grub_rtc_get_time_ms): Removed. - (grub_get_rtc): Likewise. - * grub-core/kern/generic/rtc_get_time_ms.c: Include grub/machine/time.h. - * grub-core/kern/i386/coreboot/init.c (grub_get_rtc): Removed. - * grub-core/kern/i386/pc/init.c: Include grub/machine/init.h. - * grub-core/kern/i386/tsc.c (grub_tsc_init) - [!GRUB_MACHINE_PCBIOS && !GRUB_MACHINE_IEEE1275]: Call grub_fatal - rather than installing known non-working time source. - * grub-core/kern/ieee1275/init.c (grub_get_rtc): Removed. - * grub-core/kern/mips/loongson/init.c: Include grub/machine/time.h. - * include/grub/time.h: Don't include machine/time.h. - * include/grub/efi/time.h: Removed. - * include/grub/i386/efi/time.h: Likewise. - * include/grub/i386/ieee1275/time.h: Likewise. - * include/grub/powerpc/ieee1275/time.h: Likewise. - * include/grub/sparc64/ieee1275/time.h: Likewise. - * include/grub/x86_64/efi/time.h: Likewise. - -2012-06-11 Vladimir Serbinenko - - Remove dot on i and j when combining with above diacritics. - - * include/grub/unicode.h (GRUB_UNICODE_DOTLESS_LOWERCASE_I): New enum - value. - (GRUB_UNICODE_DOTLESS_LOWERCASE_J): Likewise. - * grub-core/font/font.c (grub_font_construct_dry_run): Replace i and j - with dotless variants when any combining above is present. - -2012-06-09 Vladimir Serbinenko - - * tests/grub_script_expansion.in: Explicitly tell grep that we handle - text and not binary. - -2012-06-09 Vladimir Serbinenko - - Stop polling as soon as we have the packet we were waiting for. - - * include/grub/net.h (grub_net_poll_cards): New argument stop_condition. - All users updated. - * grub-core/net/arp.c (have_pending): New var. - (pending_req): Likewise. - (grub_net_arp_send_request): Fill pending_req and use have_pending as - stop indicator. - (grub_net_arp_receive): Set have_pending. - * grub-core/net/dns.c (recv_data): New field stop. - (recv_hook): Set stop. - (grub_net_dns_lookup): Init stop and use as stop condition. - * grub-core/net/http.c (http_establish): Use headers_recv as stop - condition. - * grub-core/net/net.c (grub_net_poll_cards): New argument - stop_condition. Stop when it goes true. - * grub-core/net/tcp.c (grub_net_tcp_open): Use `established' as stop - indicator. - * grub-core/net/tftp.c (tftp_open): Use `have_oack' as stop indicator. - -2012-06-09 Vladimir Serbinenko - - Keep TX and RX buffers on EFI rather than always allocate new ones. - - * include/grub/net.h (grub_net_card_driver): Allow driver to modify - card. All users updated. - (grub_net_card): New members txbuf, rcvbuf, rcvbufsize and txbusy. - * grub-core/net/drivers/efi/efinet.c (send_card_buffer): Reuse buffer. - (get_card_packet): Likewise. - (grub_efinet_findcards): Init new fields. - -2012-06-09 Vladimir Serbinenko - - * grub-core/term/ieee1275/serial.c (do_real_config): Fix cast to fix - compilation error on sparc64. - -2012-06-09 Vladimir Serbinenko - - Use ITC on IA64 rather than broken routine based on daytime. - - * grub-core/kern/efi/efi.c (grub_rtc_get_time_ms) [__ia64__]: Remove on - ia64. - (grub_get_rtc) [__ia64__]: Likewise. - * grub-core/kern/ia64/efi/init.c (divisor): New variable. - (get_itc): New function. - (grub_rtc_get_time_ms): Likewise. - (grub_machine_init): Calibrate ITC. - * include/grub/efi/time.h (grub_get_rtc), (GRUB_TICKS_PER_SECOND): - Keep only on non-ia64. Don't export since it's broken and used only - if TSC is unavailable. - -2012-06-09 Vladimir Serbinenko - - * grub-core/disk/efi/efidisk.c (find_parent_device): Return the parent - even if it's used. - (name_devices): Replace #if 0 with #ifdef DEBUG_NAMES. - Skip if parent is unused. - -2012-06-08 Vladimir Serbinenko - - * tests/partmap_test.in: Skip on ppc due to serious firmware bug. - -2012-06-08 Vladimir Serbinenko - - Fix wildcard escaping. - - * grub-core/commands/wildcard.c (wildcard_escape): Moved from here ... - * grub-core/script/execute.c (wildcard_escape): .. to here. - Don't escape dot. - * grub-core/commands/wildcard.c (wildcard_unescape): Moved from here ... - * grub-core/script/execute.c (wildcard_unescape): .. to here. - Don't escape dot. - * grub-core/script/execute.c (gettext_append): Always escape. - (grub_script_arglist_to_argv): Always handle escaping/unescaping. - * grub-core/script/yylex.l: Don't cut away the escaping. - * tests/grub_script_echo1.in: Add tests with wildcard. - -2012-06-08 Vladimir Serbinenko - - * grub-core/bus/usb/serial/ftdi.c (real_config): Handle 1.5 stop bits. - (ftdi_hw_configure): Likewise. - * grub-core/bus/usb/serial/pl2303.c (GRUB_PL2303_STOP_BITS_1_5): New - define. - (real_config): Handle 1.5 stop bits. - (pl2303_hw_configure): Likewise. - -2012-06-08 Vladimir Serbinenko - - * Makefile.am: Add ppc linux bootcheck. - * grub-core/tests/boot/linux-ppc.cfg: New file. - * grub-core/tests/boot/linux.init-ppc.S: Likewise. - -2012-06-08 Vladimir Serbinenko - - * tests/grub_script_expansion.in: Skip network protocols. - -2012-06-08 Vladimir Serbinenko - - * tests/util/grub-shell.in: Use escc-ch-a port on ppc. - -2012-06-08 Vladimir Serbinenko - - * util/powerpc/ieee1275/grub-mkrescue.in: Handle (and ignore) - --rom-directory. - Add -graft-points. - -2012-06-08 Vladimir Serbinenko - - ESCC serial driver for conducting sautomated tests in qemu. - Not tested on real hardware. - - * include/grub/serial.h (grub_serial_port): New field escc_desc. - * grub-core/term/ieee1275/escc.c: New file. - * grub-core/Makefile.core.def (escc): New module. - -2012-06-08 Vladimir Serbinenko - - * grub-core/term/ieee1275/serial.c (do_real_config): Set handle to - invalid on error. - (serial_hw_fetch): Don't read invalid handle. - (serial_hw_put): Don't write into invalid handle. - -2012-06-08 Vladimir Serbinenko - - Add a 1.5 stop bits value. - - * grub-core/term/serial.c (grub_cmd_serial): Handle 1.5. - * include/grub/serial.h (grub_serial_stop_bits_t): Add - GRUB_SERIAL_STOP_BITS_1_5. - -2012-06-08 Vladimir Serbinenko - - * grub-core/commands/wildcard.c (wildcard_expand): Set default return - value rather than let it uninited. - -2012-06-07 Vladimir Serbinenko - - * grub-core/commands/wildcard.c (+check_file): New function. - (wildcard_expand): Don't expand to non-existing files, expand with - suffix and not attempt to expand if not needed. - -2012-06-07 Vladimir Serbinenko - - * grub-core/disk/efi/efidisk.c (name_devices): Don't make disks - out of partitions containing other partitions. - -2012-06-07 Vladimir Serbinenko - - Pass PCIINFO on BIOS to OpenBSD since otherwise it fails to boot - on some qemu versions with GRUB. - - * include/grub/i386/openbsd_bootarg.h (OPENBSD_BOOTARG_PCIBIOS): New - define. - (grub_openbsd_bootarg_pcibios): New struct. - * grub-core/loader/i386/bsd.c (grub_openbsd_boot) [GRUB_MACHINE_PCBIOS]: - Add PCIINFO. - -2012-06-07 Vladimir Serbinenko - - * tests/util/grub-shell.in: Trim firmware output on EFI. - -2012-06-07 Vladimir Serbinenko - - * grub-core/Makefile.core.def (vga_text): Disable on muliboot - and coreboot since it's already in kernel. - -2012-06-07 Vladimir Serbinenko - - * util/getroot.c (grub_util_get_dm_node_linear_info): Moved from here... - * grub-core/kern/emu/hostdisk.c (grub_util_get_dm_node_linear_info): - to here. New return value start. All users updated. - Recursively scan linear mappings. - * include/grub/emu/hostdisk.h (grub_util_get_dm_node_linear_info): New - proto. - * grub-core/kern/emu/hostdisk.c (grub_hostdisk_find_partition_start): - Use grub_util_get_dm_node_linear_info. - * util/getroot.c (convert_system_partition_to_system_disk): Use - grub_util_info rather than grub_dprintf. - (grub_util_biosdisk_get_grub_dev): Add a new grub_util_info. - -2012-06-07 Vladimir Serbinenko - - Move handling of GRUB_QEMU_OPTS to grub-shell so that make check works. - - * Makefile.am: Remove GRUB_QEMU_OPTS handling. - * tests/util/grub-shell.in: Add GRUB_QEMU_OPTS handling. - -2012-06-07 Vladimir Serbinenko - - * include/grub/types.h (grub_set_unaligned64): New function. - * util/grub-setup.c (write_rootdev): Use unaligned access functions. - (setup): Likewise. - -2012-06-06 Vladimir Serbinenko - - * grub-core/disk/ieee1275/ofdisk.c (quiesce): New function. - (grub_ofdisk_fini): Quiesce USB devices. - -2012-06-06 Vladimir Serbinenko - - * grub-core/loader/powerpc/ieee1275/linux.c (grub_linux_boot): Sync - caches. - -2012-06-06 Vladimir Serbinenko - - * util/grub-fstest.c (cmd_crc): Use grub_get_unaligned32 for safety. - -2012-06-06 Vladimir Serbinenko - - * grub-core/disk/pata.c (grub_pata_pio_read) - [GRUB_MACHINE_MIPS_QEMU_MIPS]: Don't byteswap even on mipseb. - (grub_pata_pio_write) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Likewise. - -2012-06-06 Vladimir Serbinenko - - Extend automated tests to qemu-mips. - - * Makefile.am: reorganise tests and enable qemu-mips. - * configure.ac (COND_mipseb), (COND_mipsel): New conditions. - * grub-core/tests/boot/linux.init-mips.S: New file. - * tests/partmap_test.in: Handle ata0 disks. - * tests/util/grub-shell.in: Handle qemu-mips. Make defaults work on - non-pc i386. - -2012-06-06 Vladimir Serbinenko - - * Makefile.util.def (grub-mkrescue) Anable on mips_qemu_mips and - ia64. - * util/grub-mkrescue.in: Handle qemu-mips and ia64. Add missing - quotes while on it. - -2012-06-06 Vladimir Serbinenko - - * grub-core/kern/mips/qemu_mips/init.c (grub_exit): Implement. - (grub_halt): Likewise. - * grub-core/lib/mips/qemu_mips/reboot.c (grub_reboot): Likewise. - -2012-06-06 Vladimir Serbinenko - - * grub-core/term/serial.c (grub_serial_register) - [GRUB_MACHINE_MIPS_QEMU_MIPS]: Don't autostart console in order to bring - the behaviour in line with x86 platforms. - -2012-06-06 Vladimir Serbinenko - - * grub-core/commands/hdparm.c (le16_to_char): Always byte-swap strings. - (grub_ata_strncpy): Likewise. - (grub_ata_identify): Add missing byteswaps. - -2012-06-06 Vladimir Serbinenko - - * grub-core/term/i386/pc/vga_text.c (screen_write_char): Add missing - byte-swap. - (screen_read_char): Likewise. - (grub_vga_text_cls): Likewise. - -2012-06-06 Vladimir Serbinenko - - * grub-core/loader/efi/chainloader.c (copy_file_path): Handle non-ASCII - filenames. - (make_file_path): Likewise. - -2012-06-06 Vladimir Serbinenko - - * grub-core/disk/ieee1275/ofdisk.c (scan): Support vscsi on IBM - machines. - Tested by: Paulo Flabiano Smorigo. - Crucial information about API supplied by: Coleen . - Reviewed by: Coleen . - -2012-06-05 Vladimir Serbinenko - - * util/grub-mkimage.c: Disable -Wcast-align. - -2012-06-05 Vladimir Serbinenko - - * grub-core/genmod.sh.in: Enable objconv errors 2030, 2050 and 2031 - as they are fatal. - -2012-06-05 Vladimir Serbinenko - - * grub-core/Makefile.am (rs_decoder.S): Add missing -ffreestanding. - -2012-06-05 Vladimir Serbinenko - - * util/grub-probe.c (escape_of_path): Fix double free. - -2012-06-05 Vladimir Serbinenko - - * grub-core/commands/videoinfo.c (hook): Show pitch. - -2012-06-05 Vladimir Serbinenko - - * util/grub.d/20_linux_xen.in: Skip xen-syms. - -2012-06-05 Vladimir Serbinenko - - * util/grub-probe.c (escape_of_path): Don't add ieee1275/. - (probe): Add ieee1275 to OFW devices. - -2012-06-04 Vladimir Serbinenko - - * util/ieee1275/ofpath.c (of_path_of_scsi): Fix wrong format specifier. - -2012-06-04 Vladimir Serbinenko - - Handle IBM OFW path. - - * util/ieee1275/ofpath.c (find_obppath): Use devspec if obppath isn't - available. - (of_path_of_scsi): Handle vdevice. - -2012-06-03 Vladimir Serbinenko - - * grub-core/mmap/i386/pc/mmap.c (malloc_hook): - Allocate in multiples of 16 to avoid adding a few bytes free region the - windows bugs upon. - -2012-06-03 Vladimir Serbinenko - - * grub-core/commands/i386/pc/drivemap.c (install_int13_handler): - Allocate in multiples of 16 to avoid adding a few bytes free region the - windows bugs upon. - * grub-core/mmap/i386/pc/mmap.c (malloc_hook): Likewise. - -2012-06-02 Vladimir Serbinenko - - * grub-core/video/efi_gop.c (grub_video_gop_setup): Reject invalid - resolutions. - * grub-core/video/i386/pc/vbe.c (grub_vbe_get_preferred_mode): Likewise. - * grub-core/video/video.c (grub_video_edid_preferred_mode): Likewise. - -2012-06-02 Isao Shimizu - - * util/ieee1275/ofpath.c (check_sas): Fix sas path. - -2012-06-02 Vladimir Serbinenko - - * grub-core/normal/menu_entry.c (print_line): Fix off-by-one error which - resulted in \\ at the end of the line. - -2012-06-02 Vladimir Serbinenko - - * grub-core/kern/parser.c (grub_parser_state_transitions): Handle \t. - (grub_parser_cmdline_state): Likewise. - (grub_parser_split_cmdline): Likewise. - -2012-06-02 Vladimir Serbinenko - - * util/getroot.c (grub_guess_root_devices): Don't canonicalise - /dev/root and /dev/dm-*. - -2012-06-02 Vladimir Serbinenko - - * grub-core/normal/menu_entry.c (update_screen): Fix loop condition to - fix partially stale display. - -2012-06-02 Vladimir Serbinenko - - * grub-core/normal/menu_entry.c (backward_char): Use right line for - substraction. - -2012-06-02 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_write) [__linux__]: - Fix MBR remapping workaround. - (grub_util_biosdisk_read) [__linux__]: Likewise. - -2012-06-01 Vladimir Serbinenko - - * util/grub-install.in: Check for ieee1275 and not ieee1276. - -2012-05-31 Vladimir Serbinenko - - * configure.ac: Bump to beta6. - -2012-05-31 Christer Weinigel - - * grub-core/normal/main.c (grub_file_getline): Fix off-by-one error. - -2012-05-31 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (grub_linux_boot): Use right version. - (grub_cmd_linux): Likewise. - -2012-05-31 Christer Weinigel - - Fix EHCI low-speed. - - * grub-core/bus/usb/ehci.c (GRUB_EHCI_MULT_ONE): Fix the value. - (GRUB_EHCI_MULT_TWO): Likewise. - (GRUB_EHCI_MULT_THREE): Likewise. - (GRUB_EHCI_CMASK_MASK): New enum value. - (GRUB_EHCI_SMASK_MASK): Likewise. - (GRUB_EHCI_CMASK_OFF): Likewise. - (GRUB_EHCI_SMASK_OFF): Likewise. - (grub_ehci_pci_iter): Enable periodic schedule. - (grub_ehci_parse_notrun): Likewise. - (grub_ehci_restore_hw): Likewise. - (grub_ehci_setup_qh): Set flags for low speed transfers. - (grub_ehci_find_qh): Use periodic list for low speed. - (grub_ehci_setup_transfer): Check periodic queue as well. - (grub_ehci_check_transfer): Likewise. - (grub_ehci_cancel_transfer): Cancel periodic transfer. - -2012-05-31 Paulo Flabiano Smorigo - - * util/grub-install.in: Write core.elf in PReP even if the --no-nvram - parameter is used. - -2012-05-31 Peter Jones - - * include/grub/i386/linux.h (linux_kernel_params): Add v206. - * grub-core/loader/i386/linux.c (grub_linux_boot): Use v206. - (grub_cmd_linux) [__x86_64__]: Validate grub_efi_system_table. - -2012-05-31 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (grub_linux_boot): Fix overflow and - uninited variable. Allocate at least setup_sects. - -2012-05-30 Vladimir Serbinenko - - Fix handling of EFI with big memory maps. - - * grub-core/loader/i386/linux.c (GRUB_LINUX_CL_OFFSET): Removed. - (real_mode_mem): Likewise. - (real_mode_target): Likewise. - (real_mode_pages): Likewise. - (prot_mode_pages): Likewise. - (linux_params): New var. - (linux_cmdline): Likewise. - (free_pages): Don't set real mode variables. - (allocate_pages): Don't allocate real mode memory. - (grub_e820_add_region): Remove the limit. - (grub_linux_boot): Allocate and copy real mode memory. - (grub_linux_unload): Free linux_cmdline. - (grub_cmd_linux): Use temporary storage for parameters. - (grub_cmd_initrd): Likewise. - * include/grub/i386/linux.h (GRUB_E820_MAX_ENTRY): Removed. - (linux_kernel_params): Make it 1K big. - -2012-05-30 Vladimir Serbinenko - - * Makefile.util.def: Remove -Wno-format. - * grub-core/Makefile.core.def: Likewise. - -2012-05-30 Vladimir Serbinenko - - * tests/cmp_unit_test.c: Add missing failure message. - * tests/example_unit_test.c: Likewise. - * tests/printf_unit_test.c: Likewise. - -2012-05-30 Vladimir Serbinenko - - * grub-core/commands/gptsync.c (grub_cmd_gptsync): Propagate the - relaxation of protective MBR requirements. - -2012-05-29 Vladimir Serbinenko - - * configure.ac: Add condition for COND_HOST_XNU. - * Makefile.util.def (10_xnu): New script. - * util/grub.d/10_xnu.in: New file, extracted from 30_os_prober.in. - -2012-05-29 Vladimir Serbinenko - - * grub-core/kern/i386/pc/startup.S [__APPLE__]: Add a workaround for - objconv bug. - -2012-05-29 Vladimir Serbinenko - - * grub-core/gdb/i386/machdep.S: Make usable with Apple assembler. - Binary on other platforms stays identical. - -2012-05-28 Vladimir Serbinenko - - * configure.ac: Remove APPLE_CC and add -Wl,-allow_stack_execute on - Apple. - -2012-05-28 Vladimir Serbinenko - - * gentpl.py: Ignore error 2022 in objconv since it's irrelevant for us. - -2012-05-28 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/sys/types.h [__APPLE__]: Include stddef - rather than defining size_t ourselves to avoid conflict. - -2012-05-28 Vladimir Serbinenko - - * grub-core/fs/hfs.c (grub_hfs_dir): Use memset instead of - initialisation to avoid __bzero reference. - -2012-05-28 Vladimir Serbinenko - - * grub-core/boot/i386/pc/startup_raw.S [__APPLE__]: Add Apple assembly - version. - * grub-core/commands/i386/pc/drivemap_int13h.S [__APPLE__]: Likewise. - * grub-core/kern/i386/pc/startup.S [__APPLE__]: Likewise. - * grub-core/lib/i386/relocator16.S [__APPLE__]: Likewise. - * grub-core/lib/i386/relocator_common.S [__APPLE__]: Likewise. - * grub-core/mmap/i386/pc/mmap_helper.S [__APPLE__]: Likewise. - -2012-05-28 Vladimir Serbinenko - - * grub-core/efiemu/runtime/efiemu.c: Replace APPLE_CC with __APPLE__. - * grub-core/kern/misc.c: Likewise. - * grub-core/loader/i386/xnu.c: Likewise. - * include/grub/i386/tsc.h: Likewise. - * include/grub/symbol.h: Likewise. - -2012-05-28 Vladimir Serbinenko - - * include/grub/list.h (grub_bad_type_cast_real): Remove return. - * include/grub/misc.h (ATTRIBUTE_ERROR): Make into noreturn attribute - on older compiler. - -2012-05-28 Vladimir Serbinenko - - * util/getroot.c (grub_util_biosdisk_get_grub_dev) [__APPLE__]: - Implement Apple flavour. - (convert_system_partition_to_system_disk) [__APPLE__]: Likewise. - -2012-05-28 Vladimir Serbinenko - - * include/grub/misc.h (memcmp) [__APPLE__]: Mark as regparm 0. - (memmove) [__APPLE__]: Likewise. - (memcpy) [__APPLE__]: Likewise. - (memset) [__APPLE__]: Likewise. - * grub-core/kern/misc.c (memcmp) [__APPLE__]: Likewise. - (memmove) [__APPLE__]: Likewise. - (memcpy) [__APPLE__]: Likewise. - (memset) [__APPLE__]: Likewise. - -2012-05-28 Vladimir Serbinenko - - * grub-core/genmod.sh.in: Fix a bug in Apple part which caused - dependency discard. - -2012-05-27 Vladimir Serbinenko - - * grub-core/normal/main.c (read_config_file): Provide config_file and - config_directory. - * util/grub.d/41_custom.in: Use config_directoy when available. - -2012-05-27 Vladimir Serbinenko - - * grub-core/fs/bfs.c (iterate_in_b_tree): Add missing NESTED_FUNC_ATTR. - (grub_bfs_dir): Likewise. - -2012-05-27 Peter Jones - - The old code gives arguments to a printf function which can't work - correctly, and the compiler complains. - - * grub-core/tests/example_functional_test.c (example_test): Add - missing text. - * grub-core/tests/lib/test.c (add_failure): Rewrite. - * include/grub/test.h (grub_test_assert_helper): New declaration. - (grub_test_assert): Use grub_test_assert_helper. - -2012-05-27 Vladimir Serbinenko - - * grub-core/Makefile.core.def (example_functional_test): Rename to ... - (exfctest): ... this to avoid overlong filenames. - All users updated. - -2012-05-27 Vladimir Serbinenko - - Handle "." and ".." on squashfs. - - * grub-core/fs/squash4.c (grub_fshelp_node): New field stsize. - Make inode numbers into stack. - (grub_squash_read_symlink): Use stack. - (grub_squash_iterate_dir): Use stack. Create "." and ".." nodes. - (make_root_node): Fill stack. - (grub_squash_open): Use stack. - -2012-05-27 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (open_device): Set dest->dev to 0 after - freeing. - -2012-05-27 Vladimir Serbinenko - - * util/grub-mkconfig_lib.in (print_option_help): Properly redirect - stderr on test calls. - -2012-05-27 Vladimir Serbinenko - - * grub-core/fs/jfs.c (grub_jfs_find_file): Handle "." and "..". - -2012-05-27 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (list_file): Set mtime to correct value. - -2012-05-27 Vladimir Serbinenko - - * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Don't skip "." and - "..". - -2012-05-27 Vladimir Serbinenko - - * grub-core/fs/hfsplus.c (grub_hfsplus_catfile): New field parentid. - (grub_hfsplus_iterate_dir): Add "." and "..". - -2012-05-27 Vladimir Serbinenko - - * grub-core/fs/cpio.c (canonicalize): Handle "..". - (grub_cpio_find_file) [MODE_USTAR]: Handle hardlinks. - -2012-05-27 Vladimir Serbinenko - - * grub-core/fs/btrfs.c (GRUB_BTRFS_ITEM_TYPE_INODE_REF): New enum value. - (find_path): Handle "." and "..". - -2012-05-27 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_file): New field hardlink. - (GRUB_AFFS_FILETYPE_HARDLINK): New enum value. - (grub_affs_iterate_dir): Handle hardlinks. - -2012-05-26 Matthew Garrett - - * grub-core/term/efi/console.c (grub_efi_console_init): Set text mode. - (grub_efi_console_fini): Likewise. - * grub-core/video/efi_gop.c (framebuffer): New field offscreen. - (grub_video_gop_fill_mode_info): Rename to ... - (grub_video_gop_fill_real_mode_info): ... this. - (grub_video_gop_fill_mode_info): New function. - (grub_video_gop_setup): Setup double framebuffer. - (grub_video_gop_get_info_and_fini): Use original framebuffer. - Free offscreen. - (grub_video_gop_swap_buffers): Copy framebuffer. - (grub_video_gop_fini): Free offscreen buffer. - * include/grub/efi/graphics_output.h (grub_efi_gop_blt_operation_t): - New enum. - (grub_efi_gop_blt_pixel): New struct. - -2012-05-26 Vladimir Serbinenko - - * gentpl.py: Remove error disabling for objconv. - -2012-05-26 Vladimir Serbinenko - - * configure.ac: Remove -Wunitialized as it's not available on older - compilers. - -2012-05-26 Vladimir Serbinenko - - Fix extent overflow comparator. - - * grub-core/fs/hfsplus.c (grub_hfsplus_extkey_internal): Add type. - (grub_hfsplus_read_block): Set type. - (grub_hfsplus_cmp_extkey): Compare type. - -2012-05-25 Vladimir Serbinenko - - * util/grub-fstest.c (cmd_cmp): Fix stat'ing of wrong file. - -2012-05-24 Vladimir Serbinenko - - * grub-core/fs/hfsplus.c (grub_hfsplus_label): Use found ptr rather - than 0. - -2012-05-24 Vladimir Serbinenko - - * Makefile.am (starfield_DATA): Add dejavu_bold_14.pf2. - (dejavu_bold_14.pf2): New target. - -2012-05-24 Vladimir Serbinenko - - * configure.ac: Fix djvu font detection. - -2012-05-23 Vladimir Serbinenko - - * grub-core/normal/misc.c (grub_normal_print_device_info): Dsiplay - ext* instead of ext2. - -2012-05-23 Vladimir Serbinenko - - * grub-core/normal/term.c (read_terminal_list): Terminate the terminal - name with \0. - -2012-05-22 Jordan Uggla - - * docs/grub-dev.texi: Remove dot from .png. - -2012-05-22 Vladimir Serbinenko - - * grub-core/partmap/gpt.c (grub_gpt_partition_map_iterate): Accept - protective entry in any slot. - * grub-core/partmap/msdos.c (grub_partition_msdos_iterate): Reject - if protective entry is found in any slot. - - Protective entry in non-first slot make no sense but is a widespread - brain damage. - -2012-05-22 Vladimir Serbinenko - - * grub-core/fs/squash4.c (grub_squash_read_data): Add missing byte-swap. - -2012-05-22 Vladimir Serbinenko - - * grub-core/fs/reiserfs.c (grub_reiserfs_iterate_dir): Fix size byteswap - with old reiserfs. - (grub_reiserfs_open): Don't free root. - -2012-05-22 Vladimir Serbinenko - - * grub-core/fs/fshelp.c (grub_fshelp_find_file): Set currnode to 0 - after freeing for safety. - -2012-05-21 Vladimir Serbinenko - - * grub-core/commands/sleep.c (do_print): Add missing grub_refresh. - Reported by: Jordan Uggla. - -2012-05-21 Jordan Uggla - - * docs/grub.texi Fix documentation of GRUB_HIDDEN_TIMOUNT to match the - actual implementation. Specifically, clarify that the grub menu will - be displayed for GRUB_TIMOUT seconds after the hidden timeout has - passed. - -2012-05-21 Benjamin Herrenschmidt - - * grub-core/kern/powerpc/dl.c (trampoline_template): Use r12 instead - of r0. - -2012-05-21 Vladimir Serbinenko - - Remove unjustified hard dependency of normal.mod on gfxterm. - - * include/grub/term.h (grub_term_output): New member fullscreen. - * include/grub/gfxterm.h (grub_gfxterm_fullscreen): Removed. - * grub-core/term/gfxterm.c (grub_gfxterm_fullscreen): Make static. - (grub_gfxterm): Set .fullscreen. - * grub-core/normal/menu.c (menu_init): Use fullscreen. - * grub-core/gfxmenu/gfxmenu.c (GRUB_MOD_INIT): Likewise. - -2012-05-21 Vladimir Serbinenko - - * docs/grub.texi (Internationalisation/Filesystems): Add precisions - mentioning possible problems with non-ASCII (non-compliant) ISOs. - Mention case-insensitive AFFS, SFS and JFS. - -2012-05-21 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_mtime): Add missing grub_dl_ref. - -2012-05-21 Vladimir Serbinenko - - * grub-core/kern/fs.c (grub_fs_probe): Handle GRUB_ERR_OUT_OF_RANGE as - a bad FS. - -2012-05-18 Vladimir Serbinenko - - * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Mark plain - ISO9660 names as case-insensitive, lowercase it and remove trailing dot. - -2012-05-17 Vladimir Serbinenko - - * grub-core/fs/jfs.c (grub_jfs_data): New field caseins. - (grub_jfs_mount): Fill caseins. - (grub_jfs_find_file): Respect caseins. - -2012-05-17 Vladimir Serbinenko - - * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Don't strrchr - through UTF-16. - -2012-05-17 Vladimir Serbinenko - - * grub-core/fs/fat.c (grub_fat_find_dir): Fix error message. - New argument origpath. All users updated. - -2012-05-15 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (read_data): Prevent overflow. - (read_attr): Ensure that we read start of possibly compressed block. - -2012-05-15 Vladimir Serbinenko - - * include/grub/ntfs.h (grub_ntfs_comp_table_element): New struct. - (grub_ntfs_comp): Use grub_ntfs_comp_table_element for comp_table. - All users updated. - -2012-05-14 Vladimir Serbinenko - - * Makefile.am (starfield_DATA): Replace dejavu.pf2 with dejavu_10.pf2, - dejavu_12.pf2, dejavu_14.pf2 and dejavu_16.pf2. - (dejavu.pf2): Replace with ... - (dejavu_10.pf2), (dejavu_12.pf2), (dejavu_14.pf2), (dejavu_16.pf2): - this. - -2012-05-14 Vladimir Serbinenko - - * util/grub.d/20_linux_xen.in: Add missing line. - -2012-05-14 Vladimir Serbinenko - - * include/grub/charset.h (GRUB_UTF16_UPPER_SURROGATE): Fix mask sizes. - (GRUB_UTF16_LOWER_SURROGATE): Likewise. - (grub_utf16_to_utf8): Likewise. - -2012-05-13 Vladimir Serbinenko - - * grub-core/disk/ieee1275/ofdisk.c (scan): Don't scan device tree if - GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS is set. - * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set - GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS on IBM hardware. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New enum value - GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS. - -2012-05-13 Vladimir Serbinenko - - * grub-core/kern/fs.c (grub_fs_probe): Handle GRUB_ERR_OUT_OF_RANGE as - a bad FS. - -2012-05-13 Vladimir Serbinenko - - * grub-core/fs/udf.c (read_string): Bail out on size=0. - (grub_udf_read_symlink): Handle read_string failure. - -2012-05-12 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (read_device_map): Improve TRANSLATORS - comment. - -2012-05-12 Vladimir Serbinenko - - Fix handling of UDF symlinks. - - * grub-core/fs/udf.c (read_string): New argument outbuf. - All users updated. - (grub_ufs_read_symlink): Rename to ... - (grub_udf_read_symlink): ... this. All users updated. - Handle symlinks with more than one component. - -2012-05-12 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_read_symlink): Fix handling of long - symlinks. Replace leading colon with a slash. - -2012-05-12 Vladimir Serbinenko - - * grub-core/fs/jfs.c (grub_jfs_find_file): Handle multiple slashes in - filename. - -2012-05-12 Vladimir Serbinenko - - * grub-core/fs/bfs.c (find_in_b_tree) [MODE_AFS]: Fix handling of exact - match in inner node. - -2012-05-12 Vladimir Serbinenko - - * grub-core/fs/bfs.c (mount): Improve filesystem detection reliability. - * grub-core/fs/ext2.c (grub_ext2_mount): Likewise. - * grub-core/fs/hfs.c (grub_hfs_mount): Likewise. - * grub-core/fs/hfsplus.c (grub_hfsplus_mount): Likewise. - * grub-core/fs/jfs.c (grub_jfs_mount): Likewise. - * grub-core/fs/minix.c (grub_minix_mount): Likewise. - * grub-core/fs/ntfs.c (grub_ntfs_mount): Likewise. - * grub-core/fs/romfs.c (grub_romfs_mount): Likewise. - * grub-core/fs/xfs.c (grub_xfs_mount): Likewise. - -2012-05-11 Vladimir Serbinenko - - Use grub-probe and not cmp to check that disk is empty. - - * util/grub-install.in: Use grub-probe for zero-check. - * util/grub-probe.c (PRINT_ZERO_CHECK): New enum value. - (probe): Handle PRINT_ZERO_CHECK. - (argp_parser): Handle -t zero_check. - -2012-05-11 Vladimir Serbinenko - - Flush block cache on adding disk to device map. - - * grub-core/kern/emu/hostdisk.c (flush_initial_buffer): New function. - (grub_hostdisk_os_dev_to_grub_drive): Call flush_initial_buffer on - adding. - (read_device_map): Likewise. - (open_device): Flush on opening. - -2012-05-10 Vladimir Serbinenko - - * grub-core/fs/cpio.c (grub_cpio_find_file): Handle prefix. - (handle_symlink): Fix off-by-one error. - Canonicalize the target. - (grub_cpio_dir): Canonicalize the name. - Fix memory leak. - Set directory. - (grub_cpio_open): Canonicalize the name. - -2012-05-10 Vladimir Serbinenko - - * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Fix symlink - handling. - -2012-05-10 Vladimir Serbinenko - - * grub-core/fs/ufs.c (grub_ufs_find_file): Fix handling of double slash. - * grub-core/fs/minix.c (grub_minix_find_file): Likewise. - -2012-05-10 Vladimir Serbinenko - - * util/grub-menulst2cfg.c (main): Check return value of fwrite. - * util/grub-mklayout.c (write_file): Likewise. New argument fname. - All users updated. - -2012-05-10 Vladimir Serbinenko - - * util/grub.d/20_linux_xen.in: Update initrd list based on 10_linux.in - counterpart. - -2012-05-10 Vladimir Serbinenko - - Fix UFS1 big file support. - - * grub-core/fs/ufs.c (INODE): Removed. - (INODE_SIZE): Always use 64-bit byte-swap since size field is always - 64-bit. - (INODE_MODE): Simplify. - (grub_ufs_inode): Use uint64_t for size and not int64_t. - (grub_ufs_lookup_symlink): Don't use INODE. - -2012-05-09 Vladimir Serbinenko - - Fix minixfs with non-power-of-two blocks since it's supported by minix. - - * grub-core/fs/minix.c (GRUB_MINIX_ZONESZ): Use block_size. - (grub_minix_data): Replace log_block_size with block_size. - (grub_minix_read_file): Use block_size but avoid 64-bit division. - (grub_minix_mount): Fill block_size. - -2012-05-09 Vladimir Serbinenko - - * configure.ac: Bump to beta5. - -2012-05-09 Vladimir Serbinenko - - Fix wrapped HFS+ handling. - - * grub-core/fs/fshelp.c (grub_fshelp_read_file): New argument - blocks_start. All users updated. - * grub-core/fs/hfsplus.c (grub_hfsplus_read_block): Don't add - wrapping offset. - (grub_hfsplus_read_file): Pass embedding offset to fshelp_read_file. - -2012-05-09 Vladimir Serbinenko - - Fix long symlinks on reiserfs. - - * grub-core/fs/reiserfs.c (grub_fshelp_node): New field size. - (grub_reiserfs_read_symlink): Use grub_reiserfs_read_real. - (grub_reiserfs_iterate_dir): Save size for non-directories. - (grub_reiserfs_open): Don't reread stat block as we already know the - size. - (grub_reiserfs_read): Split into... - (grub_reiserfs_read_real): ... and ... - (grub_reiserfs_read): ...this. - -2012-05-09 Vladimir Serbinenko - - Fix non-indexed JFS. - - * grub-core/fs/jfs.c (grub_jfs_sblock): New field flags. - (grub_jfs_data): New field namecomponentlen. - (grub_jfs_mount): Fill namecomponentlen. - (grub_jfs_getent): Use namecomponentlen rather than hardcoded 11. - -2012-05-08 Vladimir Serbinenko - - * grub-core/script/yylex.l: Ugly fix for "\\\n ". - * tests/grub_script_echo1.in: Add tests. - -2012-05-08 Vladimir Serbinenko - - * util/grub-install.in: Ignore empty devicetree directory. - -2012-05-08 Bean - - * grub-core/net/ip.c (reassemble): Make asm_buffer into asm_netbuff. - All users updated. - (free_rsm): Free header as well. - (free_old_fragments): Fix memory leak. - * grub-core/net/netbuff.c (grub_netbuff_free): Make return void. - * grub-core/net/tftp.c (tftp_receive): Fix memory leak. - (destroy_pq): Likewise. - * include/grub/net/netbuff.h (grub_netbuff_free): Make return void. - -2012-05-08 Vladimir Serbinenko - - * grub-core/commands/hashsum.c (grub_cmd_hashsum): Align space for - resulting hash as a precaution. - -2012-05-08 Vladimir Serbinenko - - * grub-core/net/bootp.c (set_env_limn_ro): Replace reserved ':' with - '_' in variable names. - * grub-core/net/net.c (grub_net_network_level_interface_register): - Likewise. - -2012-05-08 Vladimir Serbinenko - - Fix AFFS with non-512B blocks. - - * grub-core/fs/affs.c (grub_affs_rblock): Make type uint32_t. - (AFFS_MAX_LOG_BLOCK_SIZE): New definition. - (grub_affs_data): Replace blocksize with log_blocksize. - (grub_affs_read_block): Fix non-512B blocks. - (grub_affs_read_symlink): Likewise. - (grub_affs_iterate_dir): Likewise. Fix freeing corruption. - (grub_affs_read): Fix non-512B blocks. - (grub_affs_label): Likewise. - (grub_affs_mtime): Likewise. - (grub_affs_mount): Fix block detection routine. - -2012-05-08 Vladimir Serbinenko - - Add filesystem mtime to AFFS. - - * grub-core/fs/affs.c (grub_affs_file): Make type unsigned. - (aftime2ctime): New function. - (grub_affs_dir): Use aftime2ctime. - (grub_affs_label): Fix return value. - (grub_affs_mtime): New function. - (grub_affs_fs): Add mtime. - -2012-05-07 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_read_symlink): Convert latin1 into - UTF-8. - -2012-05-07 Vladimir Serbinenko - - * grub-core/fs/sfs.c (grub_sfs_read_symlink): Convert latin1 into - UTF-8. - -2012-05-07 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_iterate_dir): Mark as case insensitive. - -2012-05-07 Vladimir Serbinenko - - * grub-core/fs/sfs.c (grub_sfs_rblock): New fields createtime and - flags. - (FLAGS_CASE_SENSITIVE): New enum value. - (cache_entry): New struct. - (grub_fshelp_node): Add fields cache_off, next_extent, cache_allocated, - cache_size and cache. - (grub_sfs_data): Remove blocksize. All users switched to log_blocksize. - Add log_blocksize and fshelp_flags. - (grub_sfs_read_extent): Handle non-512 blocks. - (grub_sfs_read_block): Add cаche and handle non-512 blocks. - (grub_sfs_read_file): Handle non-512 blocks. - (grub_sfs_mount): Handle non-512 blocks. Fill log_blocksize and - fshelp_flags. - (grub_sfs_read_symlink): Handle non-512 blocks. - (grub_sfs_iterate_dir): Init new fields. Mark as case-insensitive. - (grub_sfs_dir): Free cache. - (grub_sfs_close): Likewise. - -2012-05-06 Vladimir Serbinenko - - * grub-core/fs/bfs.c (read_bfs_file): Fix overflow with over 2TiB - filesystems. - -2012-05-06 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_read_block): Fix theoretical overflow. - -2012-05-06 Vladimir Serbinenko - - * grub-core/commands/ls.c (grub_ls_list_files): Fix overflow. - -2012-05-06 Vladimir Serbinenko - - * grub-core/fs/sfs.c (grub_fshelp_node): Fix types. - (grub_sfs_read_extent): Likewise. - (grub_sfs_read_block): Likewise. - (grub_sfs_mount): Likewise. - (grub_sfs_iterate_dir): Likewise. - (grub_sfs_read_symlink): Use strncpy instead of strcpy. - (grub_sfs_read): Remove unnecessarry and wrong temporary variable. - -2012-05-04 Vladimir Serbinenko - - Fix errors on compressed NTFS with 512B clusters. - - * include/grub/ntfs.h (grub_ntfscomp_func_t): Use appropriately sized - types. - * grub-core/fs/ntfs.c (grub_ntfs_read): Return correct -1 on error and - not 0. - * grub-core/fs/ntfscomp.c (read_block): Use appropriately-sized types. - Relax check for inline extents. - (ntfscomp): Return correct -1 on error and not 0. - -2012-05-04 Vladimir Serbinenko - - * util/grub-install.in: Fix handling of prefix containing spaces. - -2012-05-04 Vladimir Serbinenko - - * grub-core/fs/squash4.c (grub_squash_inode): Fix offset field. - (grub_squash_read_data): Fix offset byte-swapping. - -2012-05-04 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_strcmp): Use unsigned comparison as - per common usage and preffered in several parts of code. - (grub_memcmp): Likewise. - (grub_strncmp): Likewise. - * include/grub/misc.h (grub_strcasecmp): Likewise. - (grub_strncasecmp): Likewise. - * Makefile.util.def (cmp_test): New test. - (grub_script_strcmp): Likewise. - * tests/cmp_unit_test.c: New file. - * tests/grub_script_strcmp.in: Likewise. - * grub-core/fs/hfsplus.c (grub_hfsplus_cmp_catkey): Add a comment. - -2012-05-04 Vladimir Serbinenko - - * include/grub/pci.h: Move enums into no-asm part. - -2012-05-04 Vladimir Serbinenko - - * grub-core/fs/bfs.c (bfs_strcmp) [MODE_AFS]: Use signed comparison. - -2012-05-04 Samuel Thibault - - * util/getroot.c (find_hurd_root_device): Try to make error message - and comments to translators clearer. - -2012-05-04 Vladimir Serbinenko - - * grub-core/commands/menuentry.c: Fix typo in TRANSLATORS comments. - -2012-05-04 Vladimir Serbinenko - - * grub-core/kern/fs.c (grub_fs_probe) [GRUB_UTIL]: Add workaround for - btrfs. - -2012-05-04 Vladimir Serbinenko - - * docs/grub.cfg: Update. - -2012-05-04 Vladimir Serbinenko - - * docs/grub.texi (PXE): Remove not present variables. - -2012-05-04 Vladimir Serbinenko - - * grub-core/net/net.c (defserver_set_env): New function. - (defserver_get_env): Likewise. - (GRUB_MOD_INIT): Register net_default_server and pxe_default_server. - -2012-05-03 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (read_device_map): Skip invalid Fedora - entries. - -2012-05-03 Vladimir Serbinenko - - * grub-core/commands/menuentry.c: Add TRANSLATORS comments. - * grub-core/kern/emu/hostdisk.c: Likewise. - -2012-05-03 Samuel Thibault - - Handle hurd userspace partitions. - - * util/getroot.c (find_hurd_root_device): New function. - (grub_guess_root_devices): Use find_hurd_root_device on Hurd. - -2012-05-03 Vladimir Serbinenko - - * util/getroot.c (convert_system_partition_to_system_disk); Add etherd - names. - Reported by: Bastian Blank. - -2012-05-03 Vladimir Serbinenko - - * grub-core/fs/btrfs.c (grub_btrfs_lzo_decompress): Fix offset when - crossing page boundary. - -2012-05-03 Vladimir Serbinenko - - Fix B-tree search in BFS, especially in presence of non-ASCII - characters. - - * grub-core/fs/bfs.c (bfs_strcmp): New function. - (find_in_b_tree): Use standard bsearch + btree algorithm. - -2012-05-03 Vladimir Serbinenko - - * util/grub-fstest.c (cmd_cmp): Avoid comparing devices, pipes - and so on. - -2012-05-03 Matthew Garrett -2012-05-03 Vladimir Serbinenko - - Suspend broadcom cards in order to stop their DMA. - - * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add pci.h on x86 EFI. - * grub-core/Makefile.core.def (kernel): Add pci.c on x86 EFI. - (pci): Don't build on x86 EFI. - * grub-core/bus/pci.c (grub_pci_find_capability): New function. - * grub-core/kern/efi/mm.c (stop_broadcom) [__i386__ || __x86_64__]: - New function. - (grub_efi_finish_boot_services) [__i386__ || __x86_64__]: Call - stop_broadcom if running on EFI. - * include/grub/pci.h (GRUB_PCI_CLASS_NETWORK): New enum value. - (GRUB_PCI_CAP_POWER_MANAGEMENT): Likewise. - (GRUB_PCI_VENDOR_BROADCOM): Likewise. - (grub_pci_find_capability): New proto. - -2012-05-03 Vladimir Serbinenko - - * docs/grub.texi: Remove dot from the extension as it apparently - doesn't work with some makeinfo versions. - -2012-05-03 Vladimir Serbinenko - - * po/Makefile.in.in: Make msgfmt output in little-endian in accordance - with GRUB expectance. - -2012-05-03 Vladimir Serbinenko - - * util/grub-fstest.c (cmd_cmp): Compare directories recursively. - -2012-05-03 Vladimir Serbinenko - - * grub-core/fs/reiserfs.c (grub_reiserfs_iterate_dir): Put a trailing - zero after directory block since last entry may be not 0-terminated if - it ends on block boundary. Use continue instead of if spanning whole - loop. - -2012-05-03 Vladimir Serbinenko - - Support 4K sectors UDF inline files. - - * grub-core/fs/udf.c (grub_udf_file_entry): Don't specify padding size. - (grub_udf_extended_file_entry): Likewise. - (grub_fshelp_node): Name the anonymous union. Put block at the end. - All users updated. - (get_fshelp_size): New function. - (grub_udf_read_icb): Read whole block. - (grub_udf_iterate_dir): Likewise. - (grub_udf_dir): Likewise. - (grub_udf_open): Likewise. - -2012-05-03 Vladimir Serbinenko - - * grub-core/fs/ufs.c (grub_ufs_get_file_block): Support triple indirect. - -2012-05-03 Vladimir Serbinenko - - * grub-core/fs/ufs.c (grub_ufs_lookup_symlink): Use proper check for - inline symlinks in addition to workaround. - -2012-05-03 Vladimir Serbinenko - - * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Handle read_inode errors. - -2012-05-03 Vladimir Serbinenko - - * grub-core/fs/xfs.c (GRUB_XFS_EXTENT_BLOCK): Fix bitmask. - -2012-05-03 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (nvlist_find_value): Fix return value. - -2012-05-02 Vladimir Serbinenko - - Fix reiserfs big seek times. - - * grub-core/fs/reiserfs.c (grub_reiserfs_get_item): New argument - exact. All users updated. - (grub_reiserfs_read): Use nearest btree search for seeking. - Fix return value on error. - -2012-05-02 Vladimir Serbinenko - - * grub-core/commands/legacycfg.c (legacy_file): Default to restricted - entries. - * grub-core/commands/menuentry.c (grub_cmd_menuentry): Likewise. - * docs/grub.texi: Update menuentry description. - -2012-05-02 Vladimir Serbinenko - - * util/grub-setup.c (setup): Remove duplicate call to embed. Fixes - crash when embedding onto filesystem. - -2012-05-02 Vladimir Serbinenko - - * util/getroot.c (find_root_devices_from_poolname): Handle spaces in the - name. - -2012-05-01 Vladimir Serbinenko - - * grub-core/net/ip.c (handle_dgram): Fix undeclared variable. - -2012-05-01 Vladimir Serbinenko - - * grub-core/normal/autofs.c (read_fs_list): Revert accidental wrong - commit. - -2012-05-01 Vladimir Serbinenko -2012-05-01 Bean - - * grub-core/net/ip.c (handle_dgram): Fix DHCP mac comparison. - -2012-05-01 Vladimir Serbinenko - - * grub-core/kern/file.c (grub_file_read): Read nothing if len = 0. - Special behaviour for len = 0 to read whole file isn't used anywhere and - can cause buffer ovewrflows in several places. - -2012-05-01 Vladimir Serbinenko - - * grub-core/normal/autofs.c (read_fs_list): Fix memory leak. - -2012-05-01 Vladimir Serbinenko - - Handle RAIDZ on non-512B sectors. - - * grub-core/fs/zfs/zfs.c (grub_zfs_device_desc): New member - max_children_ashift. - (fill_vdev_info_real): Fill max_children_ashift. - (read_device): Use max_children_ashift. - -2012-05-01 Vladimir Serbinenko - - * grub-core/fs/fshelp.c (grub_fshelp_find_file): Fix memory leak. - -2012-05-01 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (read_device_map): Reject non-standard - disk names. - * docs/grub.texi: Update device.map parts. - -2012-05-01 Vladimir Serbinenko - - Don't scan into non-diskfilter devices having diskfilter names. - - * grub-core/disk/diskfilter.c (is_valid_diskfilter_name): New function. - (scan_disk): New argument accept_diskfilter. Fix recursion depth - handling. - (scan_disk_hook): New function. - -2012-04-29 Bean - - * grub-core/net/drivers/efi/efinet.c (get_card_packet): Fix buffer - allocation. - -2012-04-29 Mads Kiilerich (tiny) - - * configure.ac: Detect starfield theme font path - /usr/share/fonts/dejavu/DejaVuSans.ttf for Fedora. - -2012-04-26 Vladimir Serbinenko - - * grub-core/term/ieee1275/console.c (grub_console_dimensions): Use 80x24 - geometry on serial consoles. - -2012-04-26 Vladimir Serbinenko - - * grub-core/term/terminfo.c (grub_terminfo_readkey): Increase timeout - because of network consoles. - -2012-04-26 Vladimir Serbinenko - - * grub-core/term/terminfo.c (grub_terminfo_getkey): Fix incorrect queue - handling. - -2012-04-26 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (read_segment): Fix the case when disknr - falls on Q syndrom. - -2012-04-26 Vladimir Serbinenko - - * grub-core/fs/nilfs2.c (grub_nilfs2_palloc_entry_offset_log): - Fix argument to grub_nilfs2_palloc_bitmap_block_offset. - -2012-04-25 Vladimir Serbinenko - - * grub-core/fs/squash4.c (lzo_decompress): Set grub_errno on error. - Allocate at lest 8192 for temporary buffer as required for lzo. - -2012-04-25 Vladimir Serbinenko - - * grub-core/fs/fat.c (grub_fat_mount): Don't add logical_sector_bits - to cluster_bits, since it's already added in. - (grub_fat_read_data): Likewise. - -2012-04-25 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (grub_ntfs_mount): Support 256-byte sectors, - as long as cluster size is multiple of 512 bytes. - -2012-04-23 Vladimir Serbinenko - - * util/grub-mkrescue.in: Fix locale directory. - -2012-04-23 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (map): Make static. - -2012-04-23 Bean - - * util/grub-fstest.c (fstest): Add missing break. - -2012-04-22 Samuel Thibault - - Fix hurd build. - - * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_size) [__GNU__]: Do - not define nr variable. - * util/getroot.c [__GNU__] (strip_extra_slashes, xgetcwd, exec_pipe, - find_root_devices_from_poolname, find_root_devices_from_libzfs, - grub_find_device): Do not define. - -2012-04-21 Vladimir Serbinenko - - Fix kfreebsd compile and behaviour. - - * grub-core/kern/emu/hostdisk.c (grub_util_follow_gpart_up): Fix - format-security. - * util/getroot.c: Fix wait.h include. - (grub_guess_root_devices): Error if grub_find_device fails. - (grub_util_get_geom_abstraction): Fix shadowing and format-security. - (grub_util_get_dev_abstraction): Likewise. - (grub_util_pull_device): Likewise. - (grub_util_get_grub_dev): Likewise. - * util/lvm.c (grub_util_lvm_isvolume): Likewise. - -2012-04-21 Vladimir Serbinenko - - Fix and unify wholedisk detection. - - * util/getroot.c (convert_system_partition_to_system_disk): New argument - is_part. All users updated. - (device_is_wholedisk): Removed. - (grub_util_biosdisk_get_grub_dev): Use is_part. - -2012-04-18 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_write): Fix opening - mode. - -2012-04-18 Vladimir Serbinenko - - * configure.ac: Bump to beta4. - -2012-04-18 Vladimir Serbinenko - - * grub-core/commands/search_wrap.c (grub_cmd_search): Handle old - --fs-uuid --set UUID syntax. - -2012-04-18 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_write): Fix message - disunification. - -2012-04-18 Vladimir Serbinenko - - * conf/Makefile.common (LDFLAGS_PLATFORM): Use explicit -Wl. - -2012-04-18 Mads Kiilerich - - * grub-mkconfig_lib.in: Ignore *.rpmnew and *.rpmsave. - -2012-04-18 Mike Gilbert - - * util/grub.d/10_linux.in: Fix detection of genkernel initramfs. - -2012-04-18 Bean - - * grub-core/disk/ata.c (grub_ata_strncpy): Put terminating zero at right - place. - -2012-04-18 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (open_device): New argument max. All - users updated. - (grub_util_biosdisk_read): Handle Linux partitions not exactly - corresponding to GRUB partitions. - (grub_util_biosdisk_write): Likewise. - -2012-04-18 Vladimir Serbinenko - - Scan mdraid before LVM. - - * include/grub/diskfilter.h (grub_diskfilter_register): Renamed to .. - (grub_diskfilter_register_front): ... this. - (grub_diskfilter_register_back): New function. - All users of grub_diskfilter_register updated. - -2012-04-18 Vladimir Serbinenko - - * util/grub-install.in: Fix an automatic target detection bug. - -2012-04-18 Vladimir Serbinenko - - * util/grub-install.in: New option --efi-directory. - -2012-04-17 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (allocate_pages): Overwrite low memory - boot services if we have no other choice. - -2012-04-14 Vladimir Serbinenko - - * util/grub-mknetdir.in: Rename --override-directory to --directory and - document it. - * tests/util/grub-shell.in: Update to --directory. - -2012-04-13 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c: Disable -Wstrict-aliasing. - -2012-04-13 Vladimir Serbinenko - - * grub-core/fs/minix.c (grub_minix_data): Fix ino type. - (grub_minix_read_file): Likewise. - (grub_minix_read_inode): Likewise. - (grub_minix_find_file): Likewise. - (grub_minix_dir): Likewise. - -2012-04-13 Vladimir Serbinenko - - * util/grub-setup.c (setup): Fix partition handling and blocklist - check. - -2012-04-13 Vladimir Serbinenko - - * grub-core/lib/relocator.c (grub_relocator_alloc_chunk_align): Remove - redundant buggy overlap check. - -2012-04-11 Vladimir Serbinenko - - * tests/util/grub-shell.in: Set pkgdatadir when calling grub-mkrescue - and grub-mknetdir. - -2012-04-11 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (grub_cmd_linux): Avoid accessing - kh.loadflags on pre-2.00 kernels. - -2012-04-11 Vladimir Serbinenko - - Terminate UNDI and PXE before launching the payload to avoid problems - with DMA. - - * grub-core/commands/boot.c (grub_loader_noreturn): Rename to ... - (grub_loader_flags): ... this. All users updated. - (grub_loader_boot): Check for GRUB_LOADER_FLAG_NORETURN. - * grub-core/loader/i386/pc/pxechainloader.c (grub_cmd_pxechain): Mark - loader as GRUB_LOADER_FLAG_PXE_NOT_UNLOAD. - * grub-core/net/drivers/i386/pc/pxe.c (grub_pxe_shutdown): New - function. - (grub_pxe_restore): Likewise. - (fini_hnd): New var. - (GRUB_MOD_INIT): Register shutdown hook. - (GRUB_MOD_FINI): Shutdown and unregister shutdown hook. - * include/grub/loader.h (GRUB_LOADER_FLAG_NORETURN): New const. - (GRUB_LOADER_FLAG_PXE_NOT_UNLOAD): Likewise. - (grub_loader_set): Rename second argument to flags. - -2012-04-07 Vladimir Serbinenko - - * grub-core/normal/charset.c (grub_ucs4_to_utf8): Return number of - written bytes. - (grub_get_num_of_utf8_bytes): New function. - (grub_ucs4_to_utf8_alloc): Use grub_get_num_of_utf8_bytes. - * grub-core/normal/menu_entry.c (run): Convert entry to UTF-8 before - executing it. - * include/grub/charset.h (grub_get_num_of_utf8_bytes): New proto. - (grub_ucs4_to_utf8): Change return type. - -2012-04-07 Vladimir Serbinenko - - * grub-core/commands/usbtest.c (usb_print_str): Silence spurious - warning. - * grub-core/fs/bfs.c (hop_level): Likewise. - * grub-core/net/bootp.c (grub_cmd_bootp): Likewise. - -2012-04-07 Vladimir Serbinenko - - * grub-core/lib/adler32.c: Recode due to license unclearness. - -2012-04-07 Vladimir Serbinenko - - * grub-core/io/lzopio.c (read_block_header): Fix incorrect byte swapping - (test_header): Likewise. - -2012-04-07 Vladimir Serbinenko - - Fix --help formatting. - - * util/grub-mkconfig_lib.in (print_option_help): New function. - (grub_fmt): Likewise. - * util/grub-install.in: Use print_option_help and grub_fmt. - * util/grub-kbdcomp.in: Likewise. - * util/grub-mkconfig.in: Likewise. - * util/grub-mknetdir.in: Likewise. - * util/grub-mkrescue.in: Likewise. - * util/grub-mkstandalone.in: Likewise. - * util/grub-reboot.in: Likewise. - * util/grub-set-default.in: Likewise. - * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. - -2012-04-07 Vladimir Serbinenko - - * linguas.sh: Remove autogenerated *.po. - -2012-04-04 Vladimir Serbinenko - - * po/README: Move language fetcing to ... - * linguas.sh: ... here. - * po/README: Point to linguas.sh. - -2012-04-04 Vladimir Serbinenko - - * po/README: Exclude ko.po due to disclaimer problems. - -2012-04-04 Vladimir Serbinenko - - * grub-core/gettext/gettext.c (grub_gettext_pread): Fix the case when - len = 0. - (grub_gettext_translate_real): Handle 0th string. - (grub_gettext_translate): Ensure that "" isn't translated. - -2012-04-04 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (grub_diskfilter_memberlist): Add - TRANSLATORS comment. - (grub_diskfilter_print_partmap): Propagate changing of error into - warning. - -2012-04-04 Vladimir Serbinenko - - * include/grub/diskfilter.h (grub_diskfilter_vg): Increase extent_size - to uint64_t to prevent overflow. - (grub_diskfilter_lv): Increase start_extent and extent_count - to uint64_t to prevent overflow. - -2012-04-01 Vladimir Serbinenko - - * configure.ac: Increase version. - -2012-04-01 Vladimir Serbinenko - - Introduce en@cyrillic en@hebrew en@arabic and en@greek. - - * po/Rules-translit: New file. - * po/arabic.sed: Likewise. - * po/cyrillic.sed: Likewise. - * po/greek.sed: Likewise. - * po/hebrew.sed: Likewise. - * po/README: Add en@cyrillic en@hebrew en@arabic and en@greek. - * po/Makefile.in.in: Add extra_dist4. - -2012-04-01 Vladimir Serbinenko - - Handle big-endian minixfs (fixes minixfs tests on bigendian). - - * grub-core/fs/minix.c: Replace le with minix. Add necessary defines, - modify names. Introduce MODE_BIGENDIAN. - * grub-core/fs/minix_be.c: New file. - * grub-core/fs/minix2_be.c: Likewise - * grub-core/fs/minix3_be.c: Likewise. - * Makefile.util.def (libgrubmods): Add minix_be, minix2_be and - minix3_be. - * grub-core/Makefile.core.def (minix_be): New module. - (minix2_be): Likewise. - (minix3_be): Likewise. - -2012-04-01 Felix - - * grub-core/loader/efi/appleloader.c (devpath_7): New var. - (devs): Add MBP 2011. - -2012-04-01 Vladimir Serbinenko - - * grub-core/font/font.c (blit_comb): Handle dagesh somewhat. - -2012-04-01 Vladimir Serbinenko - - * grub-core/normal/cmdline.c (print_completion): New field - prompt_len. - (grub_cmdline_get): Handle width properly. - -2012-04-01 Vladimir Serbinenko - - * grub-core/commands/lsacpi.c (options): Add missing terminator. - -2012-03-31 Vladimir Serbinenko - - * include/grub/datetime.h (grub_datetime2unixtime): Fix handling of days - after 29th of February. - -2012-03-31 Vladimir Serbinenko - - Fix exfat endianness handling. - - * grub-core/fs/fat.c (grub_fat_data): Make fat_sector 32-bit. - (grub_fat_mount) [MODE_EXFAT]: Fix bpb.num_reserved_sectors byte-swap. - (grub_fat_iterate_dir) [MODE_EXFAT]: Fix attr byte-swap. - Byte-swap utf16 when necessary. - (grub_fat_label) [MODE_EXFAT]: Byte-swap utf16 when necessary. - -2012-03-31 Anton Blanchard -2012-03-31 Vladimir Serbinenko - - Fix btrfs endianness handling. - - * grub-core/fs/btrfs.c (key_cmp): Use grub_le_to_cpu for clarity. - (lower_bound): Make root uint64_t. Use root in le. - (grub_btrfs_read_logical): Fix template key init. Fix address byteswap. - (find_path): Fix template key init. - (grub_btrfs_dir): Fix mtime byteswap. - * include/grub/types.h (grub_cpu_to_le64_compile_time): New macro. - -2012-03-31 Vladimir Serbinenko - - * grub-core/fs/btrfs.c (grub_btrfs_read_logical): New argument - recursion_depth. Break infinite resursions. All users updated. - -2012-03-31 Vladimir Serbinenko - - * util/getroot.c (convert_system_partition_to_system_disk): Fix use - after free. - Reported by: Peter Jones. - -2012-03-31 Anton Blanchard - - * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Do not byteswap - 8 bit values. - -2012-03-28 Vladimir Serbinenko - - * util/grub-install.in: Fix nvram call for PreP. - -2012-03-28 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (grub_diskfilter_memberlist): Degrade - the error when some elements are missing into a warning. - -2012-03-28 Vladimir Serbinenko - - * grub-core/normal/charset.c (bidi_line_wrap): Fix out-of-range swap. - -2012-03-28 Colin Watson - - * docs/grub.texi (Invoking grub-probe): New section. - Reported by: Filipus Klutiero. Fixes Debian bug #666031. - -2012-03-27 Vladimir Serbinenko - - Fix tab and wide character handling in editor and menu. - - * grub-core/normal/charset.c (grub_unicode_aglomerate_comb): Don't - agglomerate control characters with combining marks. - (bidi_line_wrap): Allow break on tab. - (grub_unicode_get_comb_start): New function. - * grub-core/normal/menu_entry.c: Restructure to handle wide characters - and tab correctly. - * grub-core/normal/menu_text.c (print_entry): Replace \n, \r, \b and \e - with a space. - * grub-core/normal/term.c (print_ucs4_terminal): New argument - fixed_tab_size. All users updated. - * include/grub/term.h (GRUB_TERM_TAB_WIDTH): New const. - (grub_term_getcharwidth): Handle \t. - * include/grub/unicode.h (grub_unicode_glyph_dup): Fix allocation - and copy. - -2012-03-26 Vladimir Serbinenko - - Handle big-endian mdraid. - - * Makefile.util.def (libgrubkern): Add mdraid_linux_be.c. - * grub-core/Makefile.core.def (mdraid09_be): New module. - * grub-core/disk/mdraid_linux.c: Use grub_md_to_cpu* and grub_cpu_to_md* - rather than grub_le_to_cpu* and grub_cpu_to_le*. - * grub-core/disk/mdraid_linux_be.c: New file. - -2012-03-26 Vladimir Serbinenko - - * grub-core/gettext/gettext.c (GRUB_MOD_INIT): Handle errors. - -2012-03-19 Vladimir Serbinenko - - * util/getroot.c (grub_make_system_path_relative_to_its_root): Fix - missing quotes which caused confusion among translators. - -2012-03-19 Vladimir Serbinenko - - * util/grub-mkconfig_lib.in: Fix typo. - -2012-03-19 Vladimir Serbinenko - - * grub-core/script/argv.c (grub_script_argv_split_append): Skip leading - spaces. - * tests/grub_script_leading_whitespace.in: New file. - * Makefile.util.def (grub_script_leading_whitespace): New test. - -2012-03-19 Vladimir Serbinenko - - * grub-core/kern/dl.c (grub_dl_add): Make global in order for gdb_grub - to work. - -2012-03-19 Vladimir Serbinenko - - * grub-core/fs/jfs.c (grub_jfs_label): Use first label if second one - starts with control character. - -2012-03-19 Vladimir Serbinenko - - * grub-core/gdb/cstub.c (grub_gdb_inbuf): Increase the size to avoid - overflow. - (grub_gdb_outbuf): Likewise. - -2012-03-19 Vladimir Serbinenko - - * grub-core/commands/menuentry.c (grub_normal_add_menu_entry): Add - zero terminator. Fixes a crash. - -2012-03-11 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (allocate_pages): Don't allocate - beyond 4 GiB. - (grub_cmd_linux): Use GRUB_LINUX_BZIMAGE_ADDR for non-relocatable - images independently of preffered adderss field. - -2012-03-11 Vladimir Serbinenko - - * grub-core/commands/i386/pc/play.c: Improve TRANSLATORS comments. - * grub-core/commands/regexp.c: Likewise. - * grub-core/loader/i386/linux.c: Likewise. - * grub-core/partmap/msdos.c: Likewise. - * grub-core/script/execute.c: Likewise. - * grub-core/term/gfxterm.c: Likewise. - -2012-03-11 Vladimir Serbinenko - - Add variable parsing in $"..." and fix several mismatches with bash. - - * Makefile.util.def (grub_script_gettext): New test. - * grub-core/script/execute.c (parse_string): New function. - (gettext_append): Likewise. - (grub_script_arglist_to_argv): Use gettext_append. - * grub-core/script/yylex.l: Fix slash and newline handling in $"...". - * tests/grub_script_gettext.in: New file. - -2012-03-11 Vladimir Serbinenko - - Fix handling of leading spaces in scripts. - - * grub-core/normal/cmdline.c (grub_cmdline_get): Don't strip leading - spaces. - * grub-core/normal/main.c (grub_file_getline): Remove all preprocessing - other than skipping \r. All users updated. - * tests/grub_script_echo1.in: Add space-related tests. - * util/grub-menulst2cfg.c (main): Remove useless space skipping. - -2012-03-11 Vladimir Serbinenko - - * grub-core/commands/cat.c (grub_cmd_cat): Fix termination key check. - -2012-03-10 Vladimir Serbinenko - - * configure.ac: Bump up the version to beta2. - -2012-03-10 Vladimir Serbinenko - - Fix gettext reload bugs (e.g. inability to disable gettext - once enabled). - - * grub-core/gettext/gettext.c: Encapsulate all static variables in - main_context and secondary_context. All functions updated. - (grub_gettext_translate): Rename to ... - (grub_gettext_translate_real): ... this. Return NULL on failed - translate. - (grub_gettext_translate): Handle secondary context. - (grub_gettext_delete_list): Close file and zero-out the context. - (grub_mofile_open): Don't call grub_gettext_delete_list. - Don't close file. - (grub_gettext_init_ext): Call grub_gettext_init_ext. Skip loading - if locale="" to avoid pointless error message. - (grub_gettext_env_write_lang): Update lang even if load fails. - Handle secondary context. - (grub_gettext_reread_prefix): New function. - (read_main): Likewise. - (read_secondary): Likewise. - (GRUB_MOD_INIT): Handle secondary context. Hook and export variables. - (GRUB_MOD_FINI): Handle secondary context. Don't close file. - * grub-core/normal/main.c (read_lists): Call grub_gettext_reread_prefix. - * include/grub/normal.h (grub_gettext_reread_prefix): New proto. - -2012-03-10 Vladimir Serbinenko - - * configure.ac: Decrease warning level to avoid spurious warnings and - to be able to compile with GCC 4.2. - * Makefile.util.def: Remove -Wno-error=logical-op. - -2012-03-10 William Bittner - - * util/import_unicode.py: Add missing brackets around string for - python 3 support. - -2012-03-10 Vladimir Serbinenko - - Fix efi chainloader on network root. - - * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Handle - network devices. - * grub-core/net/drivers/efi/efinet.c (grub_efinet_get_device_handle): - New function. - -2012-03-10 Vladimir Serbinenko - - * grub-core/gfxmenu/gui_progress_bar.c (grub_gui_progress_bar): Remove - unused show_text member. - * docs/grub.texi: Document "text" property. - -2012-03-10 Vladimir Serbinenko - - * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Fix format - in dprintf. - -2012-03-10 Vladimir Serbinenko - - Fix IMSM handling on Fedora. - - * util/getroot.c (grub_util_is_imsm): New function. - (grub_util_get_dev_abstraction): Treat IMSM as simple device, not RAID. - -2012-03-10 Vladimir Serbinenko - - * Makefile.am: Strip gold section. - * conf/Makefile.common: Likewise. - * gentpl.py: Likewise. - * grub-core/Makefile.core.def: Likewise. - * grub-core/genmod.sh.in: Likewise. - -2012-03-10 Vladimir Serbinenko - - * util/grub.d/10_linux.in: Use stat if grub-probe on root fails. - * util/grub.d/20_linux_xen.in: Likewise. - Based on Debian patch. - -2012-03-10 Vladimir Serbinenko - - * util/grub.d/10_linux.in: Fix syntax error resulting in - Richard Laager's patch. - * util/grub.d/20_linux_xen.in: Propagate Richard Laager's patch. - -2012-03-10 Vladimir Serbinenko - - * tests/partmap_test.in: Replace qemu-img usage with dd to decrease - dependencies. - -2012-03-10 Richard Laager - - * util/grub.d/10_linux.in: Fix ZFS root passing. - -2012-03-10 Vladimir Serbinenko - - * grub-core/commands/videoinfo.c: Add TRANSLATORS comments. - * grub-core/commands/xnu_uuid.c: Likewise. - * grub-core/loader/efi/appleloader.c: Likewise. - * grub-core/script/execute.c: Likewise. - * grub-core/script/main.c: Likewise. - * util/grub-mkfont.c: Likewise. - -2012-03-10 Vladimir Serbinenko - - * util/grub-mkfont.c (options): Use more appropriate "select" that - "set" for face index. - -2012-03-10 Vladimir Serbinenko - - * util/grub-editenv.c (options): Gettextize command summaries. - -2012-03-10 Vladimir Serbinenko - - * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Use - "out of memory" error messagge. - -2012-03-10 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (grub_diskfilter_memberlist): Add scanning - of diskfilter for diskfilter on diskfilter support. - -2012-03-10 Vladimir Serbinenko - - * util/getroot.c (exec_pipe): Ensure that the child is not localised. - -2012-03-10 Vladimir Serbinenko - - * util/grub-install.in: Check for themes/starfield/theme.txt and not - themes/starfield. - -2012-03-10 Vladimir Serbinenko - - * grub-core/gnulib/regcomp.c (regerror): Fix out-of-range array lookup. - -2012-03-10 Vladimir Serbinenko - - * grub-core/gdb/i386/idt.c (grub_gdb_breakpoint): Remove old debug code. - -2012-03-10 Vladimir Serbinenko - - * grub-core/commands/hashsum.c (grub_cmd_hashsum): Remove dot at the end - of error message. - -2012-03-09 Vladimir Serbinenko - - * util/grub-install.in: Fix install non-PreP IEEE1275 install. - -2012-03-09 Vladimir Serbinenko - - * grub-core/commands/i386/pc/sendkey.c (GRUB_MOD_INIT): Fix confusing - message. - * util/grub-install.in: Fix and gettextize error message. - -2012-03-08 Vladimir Serbinenko - - * util/grub-fstest.c (options): Replace N with NUM and S with STRING. - Gettextize. - * util/grub-mount.c (options): Likewise. - -2012-03-08 Vladimir Serbinenko - - * grub-core/commands/probe.c (options): Replace VAR with VARNAME and - gettextize. - * grub-core/commands/search_wrap.c (options): Likewise. - -2012-03-08 Vladimir Serbinenko - - * grub-core/normal/charset.c (bidi_line_wrap): Fix a spurious warning. - -2012-03-08 Vladimir Serbinenko - - * grub-core/boot/i386/pc/startup_raw.S (multiboot_trampoline): Fix - size calculation. - * grub-core/kern/i386/realmode.S (realidt): Assume default BIOS IDT if - none is known. - -2012-03-08 Vladimir Serbinenko - - * grub-core/net/net.c (grub_net_addr_to_str): Don't translate - "temporary" since it's used in identifier and is limited in space. - -2012-03-08 Vladimir Serbinenko - - * po/POTFILES.in: Regenerate. Include *.h since they contain - translatable strings as well. - -2012-03-08 Vladimir Serbinenko - - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Add missing - byte-swap on big-endian. - Reported by: Lennart Sorensen - -2012-03-07 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (prot_init_space): New variable. - (allocate_pages): Improve dprintf. - (grub_cmd_linux): Fill prot_init_space. Fix improper usage of - code32_start. Fill code32_start and kernel_alignment in params. - (grub_cmd_initrd): Use prot_init_space. - -2012-03-06 Vladimir Serbinenko - - * util/grub-mkstandalone.in: Propagate grub-mkimage.c change. - -2012-03-06 Vladimir Serbinenko - - * util/grub-install.in: Add missing dot at the end of sentence. - -2012-03-06 Vladimir Serbinenko - - * grub-core/commands/videoinfo.c: Add TRANSLATORS comments. - * grub-core/commands/videotest.c: Likewise. - * grub-core/loader/i386/linux.c: Likewise. - -2012-03-06 Vladimir Serbinenko - - * grub-core/commands/acpi.c (options): Fix a dot in the middle of the - sentence. - Reported by: Milo Casagrande. - -2012-03-06 Vladimir Serbinenko - - * grub-core/commands/acpi.c: Add TRANSLATORS comments. - * grub-core/commands/gptsync.c: Likewise. - * grub-core/commands/hashsum.c: Likewise. - * grub-core/commands/i386/pc/sendkey.c: Likewise. - * grub-core/commands/legacycfg.c: Likewise. - * grub-core/io/gzio.c: Likewise. - * grub-core/net/net.c: Likewise. - * grub-core/term/gfxterm.c: Likewise. - * grub-core/term/terminfo.c: Likewise. - * grub-core/tests/test_blockarg.c: Likewise. - * grub-core/video/video.c: Likewise. - * util/grub-install.in: Likewise. - * util/grub-mkfont.c: Likewise. - -2012-03-06 Vladimir Serbinenko - - * util/grub-mkimage.c (help_filter): Add missing capitalisation. - -2012-03-06 Vladimir Serbinenko - - * grub-core/commands/search_wrap.c (options): Fix a typo. - Reported by: David PrĂ©vot. - -2012-03-06 Vladimir Serbinenko - - * util/grub-kbdcomp.in: Change "layout" to "keyboard layout" in - description. - -2012-03-06 Vladimir Serbinenko - - * util/grub-script-check.c (main): Fix a syntax error message which was - unclear. - -2012-03-06 Vladimir Serbinenko - - * util/grub-mkrescue.in (usage): Fix ROM capitalisation. - -2012-03-06 Vladimir Serbinenko - - * grub-core/commands/search_wrap.c (options): Fix wrong copy-paste in - messages. - -2012-03-06 Vladimir Serbinenko - - * util/grub-fstest.c (options): Remove OPTION_ARG_OPTIONAL from options - without argument. - * util/grub-mount.c (options): Likewise. - -2012-03-05 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Unify diskboot.img size message. - -2012-03-05 Vladimir Serbinenko - - * grub-core/net/http.c: Add TRANSLATORS comments. - * grub-core/normal/cmdline.c: Likewise. - * grub-core/normal/misc.c: Likewise. - * grub-core/partmap/msdos.c: Likewise. - * grub-core/parttool/msdospart.c: Likewise. - * grub-core/script/execute.c: Likewise. - * grub-core/script/main.c: Likewise. - * grub-core/term/terminfo.c: Likewise. - * grub-core/video/bitmap.c: Likewise. - * util/grub-install.in: Likewise. - * util/grub-mkimage.c: Likewise. - * util/grub-mklayout.c: Likewise. - * util/grub-setup.c: Likewise. - -2012-03-05 Vladimir Serbinenko - - * util/grub-mount.c (fuse_init): Unify cryptomount and loopback messages - with similar messages in grub-fstest. - -2012-03-05 Vladimir Serbinenko - - * util/grub-install.in: Unify "option requires an argument" message - with similar messages in other files. - * util/grub-mkconfig.in: Likewise. - -2012-03-05 Vladimir Serbinenko - - * util/grub-set-default.in: Replace printf with gettext_printf (the - string in in question is already translated from grub-reboot) - -2012-03-05 Vladimir Serbinenko - - * configure.ac: Bump up the version to beta1. - -2012-03-04 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (allocate_pages): Fix handling of the - case when min_align = 0. - -2012-03-04 Vladimir Serbinenko - - * grub-core/normal/charset.c (bidi_line_wrap): Fix a spurious warning - and fix a case when line_start overflows. - -2012-03-04 Vladimir Serbinenko - - * util/grub-reboot.in (usage): Mention id posibility. - * util/grub-set-default.in (usage): Likewise. - -2012-03-04 Vladimir Serbinenko - - * include/grub/misc.h (ALIGN_UP_OVERHEAD): New define. - * grub-core/loader/i386/linux.c (grub_cmd_initrd): Align initrds at 4. - * grub-core/loader/i386/pc/linux.c (grub_cmd_initrd): Likewise. - * grub-core/loader/ia64/efi/linux.c (grub_cmd_initrd): Likewise. - * grub-core/loader/mips/linux.c (grub_cmd_initrd): Likewise. - * grub-core/loader/powerpc/ieee1275/linux.c (grub_cmd_initrd): Likewise. - * grub-core/loader/sparc64/ieee1275/linux.c (grub_cmd_initrd): Likewise. - -2012-03-04 Vladimir Serbinenko - - * grub-core/commands/menuentry.c (options): Remove - GRUB_ARG_OPTION_REPEATABLE. - Reported by: Andreas Vogel - -2012-03-04 Andreas Vogel - - * grub-core/normal/main.c (grub_normal_free_menu): Fix memory leak. - -2012-03-04 Hideki EIRAKU - - * grub-core/normal/menu_entry.c (kill_line): Fix a crash and off-by-one - error. - -2012-03-04 Vladimir Serbinenko - - Use sort -V by the idea of Georgi Georgiev. - - * util/grub-mkconfig_lib.in (version_sort): New function. - (version_test_numeric): Use version_sort. - -2012-03-04 Vladimir Serbinenko - - Use submenus in grub-mkconfig. - - * util/grub-mkconfig.in: Define GRUB_ACTUAL_DEFAULT. - * util/grub-mkconfig_lib.in (grub_quote): New function. - (gettext_printf): Use gettext and not gettext_quoted to fix several - messages. - * util/grub.d/10_hurd.in: Use submenus. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/10_netbsd.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - * util/grub.d/30_os-prober.in: Likewise. - * util/grub.d/10_illumos.in: Add missing quoting. - * util/grub.d/10_windows.in: Likewise. - -2012-03-04 Vladimir Serbinenko - - Fix menu title instability bug. - - * grub-core/commands/menuentry.c (options): New option --id. - (grub_normal_add_menu_entry): New argument id. All users updated. - (grub_cmd_menuentry): Handle --id. - (grub_menu_init): Accept unknown arguments. - * grub-core/normal/main.c (features): Add feature_menuentry_id and - feature_menuentry_options. - * grub-core/normal/menu.c (grub_menu_execute_entry): Use id for - saved_entry. - (get_entry_number): Match with id as well. - * include/grub/menu.h (grub_menu_entry): New member id. - * util/grub-mkconfig_lib.in (grub_get_device_id): New function. - * util/grub.d/00_header.in: Define menuentry_id_option. - * util/grub.d/10_hurd.in: Define id. - * util/grub.d/10_illumos.in: Likewise. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/10_netbsd.in: Likewise. - * util/grub.d/10_windows.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - * util/grub.d/30_os-prober.in: Likewise. - -2012-03-04 Vladimir Serbinenko - - * grub-core/script/execute.c (grub_script_return): Replace ambiguous - "scope" with "body". - -2012-03-03 Vladimir Serbinenko - - * include/grub/i386/linux.h (linux_kernel_header): Fix init_size type. - * grub-core/loader/i386/linux.c (grub_cmd_linux): Differentiate between - prot_size and prot_file_size. - -2012-03-03 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (is_lv_readable): New argument "easily". - All users updated. If easily=1 require raid-5/-6 to be full. - (is_node_readable): Likewise. - (scan_devices): Scan incomplete but readable LVs at the end. - (grub_diskfilter_memberlist): Pull missing devices. - (insert_array): Skip scanning until device is complete or scan is - done otherwise. - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Fix wrong - check. - * include/grub/diskfilter.h (grub_diskfilter_lv): New member scanned. - * util/raid.c (grub_util_raid_getmembers): Handle "removed" disks. - -2012-03-03 Matthew Garrett -2012-03-03 Vladimir Serbinenko - - Avoid EFI boot services when loading Linux. - - * grub-core/lib/i386/relocator.c (grub_relocator32_boot): New argument - avoid_efi_bootservices. All users updated. - * grub-core/lib/relocator.c (grub_relocator_alloc_chunk_align): New - argument avoid_efi_bootservices. All users updated. - Use grub_efi_mmap_iterate on EFI, grub_mmap_iterate if available. - * grub-core/loader/i386/linux.c (allocate_pages): New arguments - align, min_align, relocatable, prefered_address. All users updated. - Allocate avoiding boot services if kernel is relocatable. - (grub_cmd_linux): Check if kernel is relocatable. - * grub-core/mmap/efi/mmap.c (grub_machine_mmap_iterate): Move most to .. - (grub_efi_mmap_iterate): ... here. New argument avoid_efi_boot_services. - Skip GRUB_EFI_BOOT_SERVICES_DATA and GRUB_EFI_BOOT_SERVICES_CODE if - avoid_efi_boot_services. - (grub_machine_mmap_iterate): Wrap grub_efi_mmap_iterate. - * include/grub/i386/linux.h (linux_kernel_header): Update to 2.10. - (linux_kernel_params): Likewise. - -2012-03-03 Matthew Garrett -2012-03-03 Vladimir Serbinenko - - Use EDID on EFI. - - * grub-core/kern/efi/efi.c (grub_efi_get_variable): New argument - datasize_out. - * grub-core/video/efi_gop.c (check_protocol): Check that GOP has usable - modes. Set gop_handle. - (grub_video_gop_get_edid): New function. - (grub_gop_get_preferred_mode): Likewise. - (grub_video_gop_setup): Use grub_gop_get_preferred_mode. - (grub_video_efi_gop_adapter): Set .get_edid. - * include/grub/efi/edid.h: New file. - * include/grub/efi/efi.h (grub_efi_get_variable): Update proto. - -2012-03-03 Vladimir Serbinenko - - * util/grub-install.in: Load efivars unconditionally. - -2012-03-03 Vladimir Serbinenko - - * po/Rules-piglatin: Change suffix from .po-update-en to - .po-update-en-piglatin. - -2012-03-03 Vladimir Serbinenko - - Add a pig farm. - - * po/piglatin.sed: New file. - * po/en@piglatin.header: Likewise. - * po/Rules-piglatin: Likewise. - * po/README: Add en@piglatin to autogenerated languages. - -2012-03-03 Vladimir Serbinenko - - * grub-core/commands/date.c (GRUB_MOD_INIT): Remove non-uniform - "Command for ...". - * grub-core/commands/hdparm.c (options): Use "Display" rather than - "Check" since we don't check anything. - * grub-core/commands/i386/cpuid.c (options): Clarify that long mode - is 64-bit one. - * grub-core/commands/search_wrap.c (options): Clarify the conditions. - * grub-core/disk/geli.c (grub_md_sha256_real): Fix typo. - (grub_md_sha512_real): Likewise. - -2012-03-03 Vladimir Serbinenko - - * grub-core/commands/gptsync.c: Fix typographic quoting. - * grub-core/commands/ieee1275/suspend.c: Likewise. - * grub-core/commands/parttool.c: Likewise. - * grub-core/commands/search_wrap.c: Likewise. - * grub-core/commands/videoinfo.c: Likewise. - * grub-core/gfxmenu/gui_label.c: Likewise. - * grub-core/hello/hello.c: Likewise. - * grub-core/kern/emu/main.c: Likewise. - * grub-core/net/net.c: Likewise. - * grub-core/normal/menu.c: Likewise. - * grub-core/normal/menu_text.c: Likewise. - * grub-core/normal/misc.c: Likewise. - * util/grub-editenv.c: Likewise. - * util/grub-install.in: Likewise. - * util/grub-kbdcomp.in: Likewise. - * util/grub-mkconfig.in: Likewise. - * util/grub-mknetdir.in: Likewise. - * util/grub-mkrescue.in: Likewise. - * util/grub-mkstandalone.in: Likewise. - * util/grub-reboot.in: Likewise. - * util/grub-set-default.in: Likewise. - * util/grub-setup.c: Likewise. - * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. - -2012-03-02 Vladimir Serbinenko - - * grub-core/commands/acpihalt.c: Add TRANSLATORS comments. - * grub-core/commands/keystatus.c: Likewise. - * grub-core/commands/loadenv.c: Likewise. - * grub-core/commands/probe.c: Likewise. - * grub-core/commands/regexp.c: Likewise. - * grub-core/commands/true.c: Likewise. - * grub-core/commands/videoinfo.c: Likewise. - * grub-core/disk/cryptodisk.c: Likewise. - * grub-core/disk/ldm.c: Likewise. - * grub-core/disk/loopback.c: Likewise. - * grub-core/disk/luks.c: Likewise. - * grub-core/fs/zfs/zfsinfo.c: Likewise. - * grub-core/kern/disk.c: Likewise. - * grub-core/kern/emu/hostdisk.c: Likewise. - -2012-03-02 Vladimir Serbinenko - - * grub-core/fs/zfs/zfsinfo.c (print_vdev_info): Add TRANSLATORS comment. - * util/grub-install.in: Add missing quote in the comment. - -2012-03-02 Vladimir Serbinenko - - * grub-core/commands/i386/pc/drivemap.c: Add TRANSLATORS comments. - * grub-core/commands/lsmmap.c: Likewise. - * grub-core/commands/minicmd.c: Likewise. - * grub-core/commands/mips/loongson/lsspd.c: Likewise. - * grub-core/commands/regexp.c: Likewise. - * grub-core/gdb/gdb.c: Likewise. - * grub-core/term/gfxterm.c: Likewise. - * util/grub-mkconfig.in: Likewise. - * util/grub-mkfont.c: Likewise. - * util/grub-mklayout.c: Likewise. - * util/grub-mknetdir.in: Likewise. - * util/grub-mkrescue.in: Likewise. - * util/grub.d/30_os-prober.in: Likewise. - -2012-03-02 Vladimir Serbinenko - - * grub-core/commands/videoinfo.c (hook): Replace "Direct" - with "Direct color" and "Packed" with "Packed pixel". - (grub_cmd_videoinfo): Simplify legend. - -2012-03-02 Vladimir Serbinenko - - * util/getroot.c (grub_make_system_path_relative_to_its_root): Fix - absolutely unclear error message. - -2012-03-02 Vladimir Serbinenko - - * util/grub-mkstandalone.in: Remove confusing leftover print. - -2012-03-02 Vladimir Serbinenko - - * grub-core/fs/zfs/zfsinfo.c (print_vdev_info): Add TRANSLATORS - comments. - * grub-core/gdb/gdb.c (grub_cmd_gdbstub): Likewise. - (GRUB_MOD_INIT): Likewise. - * grub-core/loader/i386/linux.c (grub_cmd_linux): Clarify that it's - VGA mode. - * grub-core/net/net.c (grub_net_route_address): Add TRANSLATORS - comments. - * util/grub-install.in (usage): Likewise. - Spell ID in whole letters. - Add missing ending dot. - Quote variables. - * util/grub-reboot.in: Fix capitalisation. - * util/grub-set-default.in: Likewise. - -2012-03-02 Vladimir Serbinenko - - * util/getroot.c (strip_extra_slashes) [CYGWIN]: #ifdef-out. - (exec_pipe) [CYGWIN || MINGW32]: Likewise. - (find_root_devices_from_poolname) [CYGWIN || MINGW32]: Likewise. - (find_root_devices_from_libzfs) [CYGWIN || MINGW32]: Likewise. - Disable -Werror for -Wdeprecated-declarations. - (grub_guess_root_devices) [CYGWIN || MINGW32]: #ifdef-out. - (get_dm_uuid) [!HAVE_DEVICE_MAPPER]: Likewise. - (grub_util_get_dm_abstraction) [! __linux__]: #ifdef-out. - (grub_util_get_grub_dev): Make luks handling dependent on - HAVE_DEVICE_MAPPER and not __linux__. - (get_win32_path): Fix format security. - (grub_find_zpool_from_dir) [CYGWIN || MINGW32]: #ifdef-out. - (grub_make_system_path_relative_to_its_root) [CYGWIN || MINGW32]: - Don't try grub_find_zpool_from_dir. - (grub_make_system_path_relative_to_its_root) [!__linux__]: - #ifdef-out paresdir. - -2012-03-02 Vladimir Serbinenko - - * util/grub-pe2elf.c (usage): Add missing noreturn. - (write_section_data): Rename name to shname to avoid shadowing. - (write_symbol_table): Rename name to symname to avoid shadowing. - Fix write_reloc_section call. - -2012-03-02 Vladimir Serbinenko - - * grub-core/boot/i386/pc/startup_raw.S: Move decompressor_end to .bss - to ensure that it's after the last byte of .text. - -2012-03-02 Vladimir Serbinenko - - * util/ieee1275/ofpath.c (my_isdigit): New function. - (trailing_digits): Use my_isdigit. - (strip_trailing_digits): Likewise. - -2012-03-02 Vladimir Serbinenko - - * util/resolve.c (read_dep_list): Use grub_isspace instead of isspace. - * grub-core/kern/emu/hostdisk.c (read_device_map): Likewise. - -2012-03-02 Vladimir Serbinenko - - * grub-core/kern/i386/pc/startup.S: Define __start. - -2012-03-02 Vladimir Serbinenko - - * gentpl.py (kernel): Remove the use of TARGET_OBJ2ELF after strip since - strip already transforms he format. - -2012-03-02 Vladimir Serbinenko - - * conf/i386-pc-cygwin-img-ld.sc: Define also _edata and __edata. - -2012-02-29 Vladimir Serbinenko - - * util/grub-install.in: Add missing gettext init. - * util/grub-kbdcomp.in: Likewise. - * util/grub-mkconfig.in: Likewise. - * util/grub-mknetdir.in: Likewise. - * util/grub-mkrescue.in: Likewise. - * util/grub-mkstandalone.in: Likewise. - * util/grub-reboot.in: Likewise. - * util/grub-set-default.in: Likewise. - * util/grub.d/00_header.in: Likewise. - * util/grub.d/10_hurd.in: Likewise. - * util/grub.d/10_windows.in: Likewise. - * util/grub.d/30_os-prober.in: Likewise. - * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. - -2012-02-29 Vladimir Serbinenko - - * po/Rules-swiss: Fix header comment. - -2012-02-29 Andreas Vogel - - * grub-core/kern/misc.c (grub_xvasprintf): Fix an exit path which - resulted in leak of arguments. - -2012-02-29 Vladimir Serbinenko - - * grub-core/boot/i386/pc/startup_raw.S: Use separate - reed_solomon_size const definition instead of computing it since - Apple assembler doesn't support the later. - -2012-02-29 Vladimir Serbinenko - - * gentpl.py (kernel): Rewrite Apple part. - -2012-02-29 Vladimir Serbinenko - - * include/grub/kernel.h (FOR_MODULES): Check module magic. - -2012-02-29 Vladimir Serbinenko - - * util/grub-mkimagexx.c (locate_sections): Support non-standard - ELF section gap. - (load_image): Likewise. - -2012-02-29 Vladimir Serbinenko - - * configure.ac: Fix a typo in previous commit. - -2012-02-29 Vladimir Serbinenko - - Don't add -Wl,-N on Apple platform. - - * configure.ac (TARGET_LDFLAGS_OLDMAGIC): New subst. - * conf/Makefile.common: Use TARGET_LDFLAGS_OLDMAGIC instead of -Wl,-N - -2012-02-29 Vladimir Serbinenko - - * grub-core/Makefile.core.def (lzma_decompress): Use - TARGET_IMG_BASE_LDOPT rather than hardcoding -Wl,-Ttext. - -2012-02-29 Vladimir Serbinenko - - * grub-core/genmod.sh.in: Rewrite the Apple part. - -2012-02-29 Vladimir Serbinenko - - * grub-core/loader/machoXX.c (grub_macho_load): Fix signed vs unsigned - comparison. - -2012-02-29 Vladimir Serbinenko - - * acinclude.m4 (grub_CHECK_PIC): New test. - * configure.ac: Add -fno-PIC to TARGET_CFLAGS if -fPIC is default. - -2012-02-29 Vladimir Serbinenko - - * include/grub/libgcc.h (__STDC_VERSION__): Define if it's not yet so - to avoid the warning. - -2012-02-29 Vladimir Serbinenko - - * grub-core/boot/i386/pc/diskboot.S (firstlist): Rename to ... - (LOCAL(firstlist)): ... this. Move it before the firstlist and not - after. All users updated. - -2012-02-29 Vladimir Serbinenko - - Use the common size routine in hostfs so we can read disks as well. - - * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors): Rename to .. - (grub_util_get_fd_size): ... this. Return size in bytes. - All users updated. - * grub-core/kern/emu/hostfs.c (grub_hostfs_open): Use - grub_util_get_fd_size. - -2012-02-29 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors) [__APPLE__]: - Add blocksize retrieval. - -2012-02-29 Vladimir Serbinenko - - * configure.ac: Restore CFLAGS after efiemu check. - -2012-02-29 Vladimir Serbinenko - - * configure.ac: Move -fnested-functions to CPPFLAGS to workaround - Apple bug. - -2012-02-29 Vladimir Serbinenko - - * grub-core/Makefile.am (MACHO2IMG): Add missing variable. - -2012-02-29 Vladimir Serbinenko - - * grub-core/commands/i386/pc/halt.c (grub_halt): Add noreturn attribute. - (grub_cmd_halt): Likewise. - -2012-02-29 Vladimir Serbinenko - - * grub-core/lib/i386/relocator16.S: Declare LOCAL(relocator16_end) - for local arithmetics. - Break %sp init into 2 instructions. - Add 0 byte at the end. - -2012-02-29 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (read_segment): Initialise err - before loops. - -2012-02-29 Vladimir Serbinenko - - * grub-core/lib/xzembed/xz_dec_stream.c (hash_validate): Use void * - for context. - -2012-02-29 Vladimir Serbinenko - - * grub-core/disk/ldm.c (make_vg): Init part.name. - (grub_ldm_detect): Silence spurious warning. - (grub_util_is_ldm): Likewise. - -2012-02-29 Vladimir Serbinenko - - * grub-core/loader/i386/xnu.c (grub_xnu_boot): Init fsbfreq to - sane value to avoid a spurious warning. - -2012-02-29 Vladimir Serbinenko - - * include/grub/dl.h: Switch from APPLE_CC to __APPLE__. - (GRUB_MOD_LICENSE) [ASM_FILE]: Make into macro. All users updated. - -2012-02-29 Vladimir Serbinenko - - * include/grub/symbol.h (EXT_C) [!ASM_FILE]: Redefine with strings. - * grub-core/lib/i386/backtrace.c (grub_backtrace): Use EXT_C. - -2012-02-29 Vladimir Serbinenko - - * grub-core/gdb/i386/machdep.S: Use VARIABLE and EXT_C instead of - hardcoding the relevant info. - -2012-02-29 Vladimir Serbinenko - - * grub-core/gnulib/argp-fmtstream.c (__argp_get_display_len): Add - missing const qualifiers. - * grub-core/gnulib/argp-fmtstream.h (__argp_get_display_len): Likewise. - -2012-02-29 Vladimir Serbinenko - - * util/getroot.c [__APPLE__]: Add missing includes. - (grub_util_biosdisk_is_floppy): Fix usage of undefined variable. - -2012-02-29 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Silence spurious warning. - -2012-02-29 Vladimir Serbinenko - - * util/ieee1275/ofpath.c: Rename devname to sys_devname everywhere to - avoid conflicts. - -2012-02-29 Vladimir Serbinenko - - * util/ieee1275/grub-ofpathname.c: Add missing config.h include. - -2012-02-29 Vladimir Serbinenko - - * util/grub-setup.c (setup) [!__linux__]: Add missing file declaration - and grub_file_close call. - -2012-02-29 Vladimir Serbinenko - - Add LZSS Mach-O support (needed for new xnu kernelcache). - - * grub-core/Makefile.core.def (xnu): Add file lzss.c - * grub-core/loader/lzss.c: New file. - * grub-core/loader/xnu.c (grub_xnu_load_driver): Close binaryfile - on Mach-O open failure. - * grub-core/loader/macho.c (grub_macho_close): Free uncompressedXX. - Don't free cmdsXX in uncompressedXX is set. - (grub_macho_file): Init new fields. - New argument is_64bit. All users updated. - Handle compressed. Error out if no suitable architecture is found. - Don't close file. - (grub_macho_open): New argument is_64bit. All users updated. - * grub-core/loader/macho32.c: Add defines for new fields. - * grub-core/loader/macho64.c: Likewise. - * grub-core/loader/machoXX.c (grub_macho_contains_macho): Make static. - (grub_macho_parse): Handle compressed. - Defer actual processing if compressed. - (grub_macho_cmds_iterate): Decompress if compressed. New argument - "filename". All users updated. - (grub_macho_size): New argument "filename". All users updated. - (grub_macho_get_entry_point): Likewise. - (grub_macho_load): Handle compressed. - * include/grub/macho.h (grub_macho_lzss_header): New struct. - (GRUB_MACHO_LZSS_OFFSET): New define. - (grub_decompress_lzss): New proto. - * include/grub/machoload.h (grub_macho_file): New fields to handle - compressed. - (grub_macho_contains_macho64): Remove proto. - (grub_macho_contains_macho32): Likewise. - * util/grub.d/30_os-prober.in: Use kernel cache if available. - -2012-02-29 Vladimir Serbinenko - - * grub-core/disk/pata.c (grub_pata_readwrite): Fix ATAPI protocol error. - -2012-02-28 Vladimir Serbinenko - - Fix make dist. - - * Makefile.am (starfield_theme_files): New var. - (starfield_DATA): Use starfield_theme_files. - (EXTRA_DIST): Add starfield_theme_files. Add starfield source files. - Add bootcheck-related files. - * conf/Makefile.extra-dist (EXTRA_DIST): Add several missing files. - * docs/Makefile.am (EXTRA_DIST): Add font_char_metrics.png - and font_char_metrics.txt. - * grub-core/Makefile.core.def (kernel): Update extra_dist. - (setjmp): Add lib/ia64/longjmp.S. - * po/Makefile.in.in (DISTFILES): Add POTFILES-shell.in and grub.d.sed. - * po/POTFILES.in: Regenerate. - * po/Rules-swiss: use DISTFILES.common.extra2 and not - DISTFILES.common.extra1. - * util/devicemap.c: Removed. - * grub-core/lib/i386/relocator_backward.S: Likewise. - * util/import_gcry.py: Remove unused files. Add extra_dist for - ChangeLog. - -2012-02-28 Vladimir Serbinenko - - * grub-core/gettext/gettext.c (grub_mofile_open): Call - grub_gettext_delete_list before changing grub_gettext_max to avoid - running out of array bounds. - -2012-02-28 Vladimir Serbinenko - - * grub-core/term/i386/pc/vga_text.c: Add GRUB_MACHINE_MULTIBOOT to - grub_vga_text_init/grub_vga_text_fini. - -2012-02-28 Vladimir Serbinenko - - * grub-core/loader/i386/xnu.c (grub_xnu_boot): Fix format specification. - -2012-02-27 Vladimir Serbinenko - - * configure.ac: Bump to 2.00~beta0. - -2012-02-27 Vladimir Serbinenko - - * util/getroot.c (grub_find_root_devices_from_btrfs): Add - missing initialisation. - -2012-02-27 Vladimir Serbinenko - - * grub-core/partmap/msdos.c (message_warn): Clarify messages. - -2012-02-27 Vladimir Serbinenko - - Support v2 xnu boot arguments. - - * grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devicetree): - New argument fsbfreq_out. - (grub_xnu_set_video): Receive an argument grub_xnu_boot_params_common. - (grub_xnu_boot): Support v2 arguments. Disable PIC so that APIC can - be used. - * grub-core/loader/machoXX.c (grub_macho_load): New argument - darwin_version. - * grub-core/loader/xnu.c (grub_xnu_darwin_version): New variable. - * include/grub/i386/xnu.h (grub_xnu_boot_params_common): New struct. - (grub_xnu_boot_params): Rename to ... - (grub_xnu_boot_params_v1): ...this. Use grub_xnu_boot_params_common. - (grub_xnu_boot_params_v2): New struct. - -2012-02-27 Vladimir Serbinenko - - * grub-core/efiemu/prepare.c (grub_efiemu_crc): Add missing - zeroing of CRC field before computing CRC. - -2012-02-27 Vladimir Serbinenko - - * grub-core/lib/relocator.c (malloc_in_range): Fix memory leak. - Change order of allocations to decrease fragmentation. - -2012-02-27 Vladimir Serbinenko - - * Makefile.util.def (grub-ofpathname): Enable on all platforms. - -2012-02-27 Colin Watson - - Use write-combining MTRR to speed up video with buggy BIOSes. - - * grub-core/video/i386/pc/vbe.c (framebuffer): New member mtrr. - (cpuid): New define. - (rdmsr): Likewise. - (wrmsr): Likewise. - (mtrr_base): Likewise. - (mtrr_mask): Likewise. - (grub_vbe_enable_mtrr_entry): New function. - (grub_vbe_enable_mtrr): Likewise. - (grub_vbe_disable_mtrr): Likewise. - (grub_vbe_bios_set_display_start): Disable mtrr when handing the - control off to BIOS. - (grub_video_vbe_init): Fill mtrr. - (grub_video_vbe_fini): Disable mtrr. - (grub_video_vbe_get_info_and_fini): Likewise. - (grub_video_vbe_setup): Enable mtrr. - -2012-02-27 Colin Watson - - * include/grub/partition.h (grub_partition_map): Change prototype of - embed to take a maximum value for nsectors. - * include/grub/emu/hostdisk.h (grub_util_ldm_embed): Likewise. - * include/grub/fs.h (grub_fs): Likewise. - * grub-core/partmap/msdos.c (embed_signatures): New array. - (pc_partition_map_embed): Check for and avoid sectors matching any - of the signatures in embed_signatures, up to max_nsectors. - * grub-core/partmap/gpt.c (gpt_partition_map_embed): Restrict - returned sector map to max_nsectors. - * grub-core/disk/ldm.c (grub_util_ldm_embed): Likewise. - * grub-core/fs/btrfs.c (grub_btrfs_embed): Likewise. - * grub-core/fs/zfs/zfs.c (grub_zfs_embed): Likewise. - * util/grub-setup.c (setup): Allow for the embedding area being - split into multiple blocklists. Tell dest_partmap->embed the - maximum number of sectors we care about. - -2012-02-27 Vladimir Serbinenko - - * include/grub/fs.h (grub_fs) [GRUB_UTIL]: Add blocklist_install field. - Specify blocklist_install and reserver_first_sector for all fs. - * util/grub-setup.c (setup): Use FIBMAP/FIEMAP on Linux. Check resulting - blocklists. - -2012-02-27 Vladimir Serbinenko - - * util/grub-install.in: Clarify strings. - Fix source dir check. - -2012-02-27 Richard Laager - - * util/getroot.c (grub_find_root_devices_from_mountinfo): Handle - "zfs" and "fuse.zfs" as synonyms. - -2012-02-27 Vladimir Serbinenko - - * configure.ac: Put platform and target_cpu substitutions back since - they are used for directories. - -2012-02-27 Richard Laager -2012-02-27 Vladimir Serbinenko - - * util/grub.d/10_linux.in: Add ZFS-related arguments. - * util/grub.d/20_linux_xen.in: Likewise. - -2012-02-27 Richard Laager - - * util/getroot.c (find_root_devices_from_poolname): Handle vdevs - with full paths. - -2012-02-27 Richard Laager - - * util/getroot.c (grub_find_root_devices_from_mountinfo): Add missing - unescape. - -2012-02-27 Vladimir Serbinenko - - Don't use insecure popen in getroot. - - * util/getroot.c (get_mdadm_uuid): Move pipe logic to ... - (exec_pipe): ... here. - (find_root_devices_from_poolname): Use exec_pipe. - -2012-02-27 Vladimir Serbinenko - - Remove platform and target_cpu replacement. - - * configure.ac: Remove platform and target_cpu substitutions. - * tests/util/grub-shell.in: Use modinfo. - * util/powerpc/ieee1275/grub-mkrescue.in: Specify powerpc-ieee1275 - explicitly. - -2012-02-27 Vladimir Serbinenko - - Autodetect platform in grub-install but allow override. - - * util/grub-install.in: Autodetect platform. Support --target and - --directory. Read platform from modinfo.sh. - -2012-02-27 Vladimir Serbinenko - - Support btrfs multi-volume probe. - - * util/getroot.c (btrfs_ioctl_dev_info_args) [__linux__]: New struct. - (btrfs_ioctl_fs_info_args) [__linux__]: Likewise. - (BTRFS_IOC_DEV_INFO) [__linux__]: New define. - (BTRFS_IOC_FS_INFO) [__linux__]: Likewise. - (grub_find_root_devices_from_btrfs) [__linux__]: New function. - (grub_find_root_devices_from_mountinfo) [__linux__]: Use - grub_find_root_devices_from_btrfs if on btrfs. - -2012-02-27 Vladimir Serbinenko - - Remove any awareness of *.c util files about target. - - * Makefile.util.def (grub-setup): Split to ... - (grub-bios-setup): ... and this. - (grub-sparc64-setup): ... and this. - * configure.ac: Don't add machine_CPPFLAGS into HOST_CPPFLAGS. - * docs/man/grub-setup.h2m: Split into ... - * docs/man/grub-sparc64-setup.h2m: ... this. - * docs/man/grub-bios-setup.h2m: ... and this. - * include/grub/dl.h (grub_dl) [GRUB_UTIL]: Remove struct. - * include/grub/elf.h (Elf_*) [GRUB_UTIL]: Remove types. - (GRUB_TARGET_WORDSIZE) [GRUB_UTIL]: Remove. - (grub_target_addr_t): Remove. - (grub_target_size_t): Remove. - (grub_target_ssize_t): Remove. - * util/grub-install.in: Use new grub-*-setup. - * util/grub-mkimagexx.c (Elf_Word): New define. - (Elf_Half): Likewise. - (Elf_Section): Likewise. - (ELF_ST_TYPE): Likewise. - * util/grub-setup.c: Switch from GRUB_MACHINE_SPARC64 to - GRUB_SETUP_SPARC64 and from GRUB_MACHINE_PCBIOS to GRUB_SETUP_BIOS. - -2012-02-27 Vladimir Serbinenko - - Replace grub_target_addr with more appropriate types. - - * grub-core/commands/efi/fixvideo.c (scan_card): Replace - grub_target_addr with grub_addr. - * grub-core/commands/iorw.c (grub_cmd_read): Replace - grub_target_addr with grub_port. - (grub_cmd_write): Likewise. - * grub-core/commands/memrw.c (grub_cmd_read): Replace - grub_target_addr with grub_addr. - (grub_cmd_write): Likewise. - * grub-core/video/efi_uga.c (find_line_len): Likewise. - -2012-02-27 Vladimir Serbinenko - - * include/grub/efi/api.h (grub_efi_runtime_services): Add missing - const qualifier for vendor_guid. - -2012-02-27 Vladimir Serbinenko - - * grub-core/efiemu/runtime/efiemu.c (efiemu_get_variable): Add missing - const qualifier. - (efiemu_memequal): Likewise. - (find_variable): Likewise. - -2012-02-27 Vladimir Serbinenko - - Fix missing console prototype on qemu-mips. - - * include/grub/mips/qemu_mips/console.h: New file. - -2012-02-27 Matthew Garrett -2012-02-27 Vladimir Serbinenko - - * grub-core/kern/efi/efi.c (grub_efi_get_variable): Add new function. - * include/grub/efi/efi.h: Likewise. - * include/grub/efi/api.h: Add guid for EFI-specified variables. - * include/grub/charset.h (GRUB_MAX_UTF16_PER_UTF8): New definition. - * grub-core/normal/charset.c (grub_utf8_process): Move from here ... - * include/grub/charset.h (grub_utf8_process): ... to here. Inline. - * grub-core/normal/charset.c (grub_utf8_to_utf16): Move from here ... - * include/grub/charset.h (grub_utf8_to_utf16): ... to here. Inline. - -2012-02-27 Matthew Garrett - - * include/grub/efi/pci.h: New file to define EFI PCI protocols. - -2012-02-27 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (grub_diskfilter_iterate): Fix off-by-one - error. - -2012-02-27 Vladimir Serbinenko - - * configure.ac: Remove inappropriate use of program_transform_name - on grubdir and bootdir but allow explicit specification of those - variables. - -2012-02-27 Vladimir Serbinenko - - * util/grub-mknetdir.in (grub_prefix): Removed. - (subdir): Use @bootdirname@ and @grubdirname@. - -2012-02-27 Vladimir Serbinenko - - Replace PACKAGE_TARNAME with PACKAGE in pkglibdir and pkgdatadir. - -2012-02-27 Vladimir Serbinenko - - * po/POTFILES.in: Regenerated. - -2012-02-27 Vladimir Serbinenko - - Remove improper use of program_transform_name on pkglibrootdir. - - * configure.ac (pkglibrootdir): Removed. - (grub-mkimage): Replace PKGLIBROOTDIR with PKGLIBDIR. - * util/grub-mkimage.c: Likewise. - -2012-02-27 Vladimir Serbinenko - - * grub-core/normal/menu_text.c (grub_print_message_indented_real): Fix a - warning. - -2012-02-27 Vladimir Serbinenko - - * util/grub-install.in: Use file identifier if no UUID is available - or user explicitly prompted for it. - -2012-02-27 Navdeep Parhar - - * grub-core/loader/i386/bsd.c (freebsd_zfsguid): New variable. - (freebsd_get_zfs): New function. - (grub_freebsd_boot): Pass zfs UUID. - (grub_cmd_freebsd): Set zfs UUID. - -2012-02-27 Vladimir Serbinenko - - * conf/Makefile.common (platformdir): Base on pkglibdir and not - pkglibrootdir. - -2012-02-27 Mike Gilbert - - Add configure flag to control libzfs integration. - - * configure.ac: Add AC_ARG_ENABLE(libzfs ...) and associated logic. - -2012-02-26 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (insert_array): Choose the smallest - device. - * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Reject too - small devices. - -2012-02-26 Vladimir Serbinenko - - Remove grub_{modname}_init and grub_{modname}_fini. They should never - be used directly if it's really a module and GRUB_MOD_INIT shouldn't - be used on non-modules. - - * grub-core/commands/boot.c (GRUB_MOD_INIT) [LOONGSON || QEMU_MIPS]: - Rename to grub_boot_init. - (GRUB_MOD_FINI) [LOONGSON || QEMU_MIPS]: Rename to grub_boot_fini. - * grub-core/commands/keylayouts.c (GRUB_MOD_INIT) - [LOONGSON || QEMU_MIPS]: Rename to grub_keylayouts_init. - (GRUB_MOD_FINI) [LOONGSON || QEMU_MIPS]: Rename to grub_keylayouts_fini. - * grub-core/font/font_cmd.c (GRUB_MOD_INIT) - [LOONGSON || QEMU_MIPS]: Rename to grub_font_init. - (GRUB_MOD_FINI) [LOONGSON || QEMU_MIPS]: Rename to grub_font_fini. - * grub-core/kern/mips/loongson/init.c: Replace explicit protos with - includes. - (grub_machine_init): Remove empty inits. - * grub-core/kern/mips/qemu_mips/init.c: Replace explicit protos with - includes. - (grub_machine_init): Remove empty inits. - * grub-core/term/arc/console.c: Remove explicit proto. - * grub-core/term/at_keyboard.c (GRUB_MOD_INIT) - [LOONGSON || QEMU_MIPS]: Rename to grub_at_keyboard_init. - (GRUB_MOD_FINI) [LOONGSON || QEMU_MIPS]: Rename to - grub_at_keyboard_fini. - * grub-core/term/gfxterm.c (GRUB_MOD_INIT) - [LOONGSON || QEMU_MIPS]: Rename to grub_gfxterm_init. - (GRUB_MOD_FINI) [LOONGSON || QEMU_MIPS]: Rename to - grub_gfxterm_fini. - * grub-core/term/i386/pc/vga_text.c (GRUB_MOD_INIT) - [LOONGSON || QEMU_MIPS]: Rename to grub_vgatext_init. - (GRUB_MOD_FINI) [LOONGSON || QEMU_MIPS]: Rename to - grub_vgatext_fini. - * grub-core/term/ieee1275/console.c: Remove explicit proto. - * grub-core/term/serial.c (GRUB_MOD_INIT) - [LOONGSON || QEMU_MIPS]: Rename to grub_serial_init. - (GRUB_MOD_FINI) [LOONGSON || QEMU_MIPS]: Rename to - grub_serial_fini. - * grub-core/term/terminfo.c (GRUB_MOD_INIT) - [LOONGSON || QEMU_MIPS]: Rename to grub_terminfo_init. - (GRUB_MOD_FINI) [LOONGSON || QEMU_MIPS]: Rename to - grub_terminfo_fini. - * grub-core/video/bitmap.c (GRUB_MOD_INIT): Removed. - (GRUB_MOD_FINI): Likewise. - * grub-core/video/radeon_fuloong2e.c (GRUB_MOD_INIT) - [LOONGSON]: Rename to grub_video_radeon_fuloong2e_init. - (GRUB_MOD_FINI) [LOONGSON]: Rename to - grub_video_radeon_fuloong2e_fini. - * grub-core/video/sis315pro.c (GRUB_MOD_INIT) - [LOONGSON]: Rename to grub_video_sis315pro_init. - (GRUB_MOD_FINI) [LOONGSON]: Rename to - grub_video_sis315pro_fini. - * grub-core/video/sm712.c (GRUB_MOD_INIT) - [LOONGSON]: Rename to grub_video_sm712_init. - (GRUB_MOD_FINI) [LOONGSON]: Rename to - grub_video_sm712_fini. - * include/grub/at_keyboard.h (grub_at_keyboard_init): New proto. - (grub_at_keyboard_fini): Likewise. - * include/grub/dl.h (GRUB_MOD_INIT) [!GRUB_UTIL && !EMU]: - Don't declare grub_{modname}_init. - (GRUB_MOD_INIT) [!GRUB_UTIL && !EMU]: Don't declare grub_{modname}_fini. - * include/grub/keyboard_layouts.h (grub_keylayouts_init) [!EMU]: - New proto. - (grub_keylayouts_fini) [!EMU]: Likewise. - * include/grub/serial.h (grub_serial_init) [!EMU]: - New proto. - (grub_serial_fini) [!EMU]: Likewise. - * include/grub/terminfo.h (grub_terminfo_init) [!EMU]: - New proto. - (grub_terminfo_fini) [!EMU]: Likewise. - * include/grub/video.h (grub_font_init) [!EMU]: - New proto. - (grub_font_fini) [!EMU]: Likewise. - (grub_gfxterm_init) [!EMU]: Likewise. - (grub_gfxterm_fini) [!EMU]: Likewise. - (grub_video_sm712_init) [!EMU]: Likewise. - (grub_video_sm712_fini) [!EMU]: Likewise. - (grub_video_sis315pro_init) [!EMU]: Likewise. - (grub_video_sis315pro_fini) [!EMU]: Likewise. - (grub_video_radeon_fuloong2e_init) [!EMU]: Likewise. - (grub_video_radeon_fuloong2e_fini) [!EMU]: Likewise. - -2012-02-26 Vladimir Serbinenko - - Make nand a prefix for nand devices. - - * grub-core/disk/ieee1275/nand.c (grub_nand_open): Use prefix nand. - -2012-02-26 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_stpcpy): Move from here ... - * include/grub/misc.h (grub_stpcpy): ... to here. Inlined. - -2012-02-26 Vladimir Serbinenko - - * include/grub/env.h (grub_env_find): Remove prototype. - * grub-core/kern/env.c (grub_env_find): Make static. - (grub_env_set): Remove useless set. - -2012-02-26 Vladimir Serbinenko - - * grub-core/kern/i386/realmode.S: Remove useless align. - -2012-02-26 Vladimir Serbinenko - - * include/grub/dl.h (grub_dl_load_file): Don't export. - -2012-02-26 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (grub_diskfilter_open): Remove useless - grub_dprintf. - -2012-02-26 Vladimir Serbinenko - - * grub-core/disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Remove useless - grub_errors. - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Simplify by - not reloading whole superblock but only the part which is really needed. - Remove useless grub_errors. - * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Remove useless - grub_errors. - -2012-02-26 Vladimir Serbinenko - - Don't export grub_get_rtc. - - * include/grub/i386/pc/time.h (grub_get_rtc): Don't export. - * grub-core/commands/i386/pc/play.c (play): Use grub_get_time_ms. - -2012-02-26 Vladimir Serbinenko - - * grub-core/genmod.sh.in: Add -R .note.GNU-stack to strip. - -2012-02-26 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (insert_array): Remove scanner_name - argument since it can be deduced from diskfilter. All users updated. - -2012-02-26 Vladimir Serbinenko - - Remove prio_list. - - * include/grub/list.h (grub_prio_list): Removed. - (GRUB_PRIO_LIST_PRIO_MASK): Removed. All users switched to - GRUB_COMMAND_PRIO_MASK. - (GRUB_PRIO_LIST_FLAG_ACTIVE): Removed. All users switched to - GRUB_COMMAND_FLAG_ACTIVE. - (grub_prio_list_insert): Removed. - (grub_prio_list_remove): Likewise. - (GRUB_AS_PRIO_LIST): Likewise. - (GRUB_AS_PRIO_LIST_P): Likewise. - * include/grub/command.h (GRUB_COMMAND_PRIO_MASK): New define. - (GRUB_COMMAND_FLAG_ACTIVE): Likewise. - * grub-core/kern/list.c (grub_prio_list_insert): Remove. - * grub-core/kern/command.c (grub_register_command_prio): Inline - the prio_list code. - (grub_unregister_command): Likewise. - -2012-02-26 Vladimir Serbinenko - - Fix interrupt mixup from previous commit. - - * include/grub/i386/pc/int.h (grub_i386_idt): New struct. - (grub_realidt): New var. - * grub-core/lib/i386/relocator16.S (grub_relocator16_idt): New variable - Load idt. - * grub-core/lib/i386/relocator.c (grub_relocator16_idt): - New declaration. - (grub_relocator16_boot): Set grub_relocator16_idt. - * grub-core/kern/i386/realmode.S (realidt): Renamed to ... - (LOCAL(realidt)): ... this. - * grub-core/boot/i386/pc/startup_raw.S: Pass pointer to realidt in eax. - * grub-core/kern/i386/pc/startup.S: Save pointer to realidt. - (grub_realidt): New variable. - -2012-02-26 Vladimir Serbinenko - - * grub-core/lib/i386/backtrace.c (grub_cmd_backtrace): Move from ... - * grub-core/lib/backtrace.c (grub_cmd_backtrace): ... to here. - * grub-core/lib/i386/backtrace.c (GRUB_MOD_INIT): Move from ... - * grub-core/lib/backtrace.c (GRUB_MOD_INIT): ... to here. - Gettextize. - * grub-core/lib/i386/backtrace.c (GRUB_MOD_FINI): Move from ... - * grub-core/lib/backtrace.c (GRUB_MOD_FINI): ... to here. - * po/POTFILES.in: Regenerate. - -2012-02-26 Vladimir Serbinenko - - * grub-core/commands/probe.c (grub_cmd_probe): Gettextise UUID and label - errors. - -2012-02-26 Vladimir Serbinenko - - * grub-core/gnulib/argp-fmtstream.c (__argp_get_display_len): Stop on - \0. - (add_length): Likewise. - -2012-02-26 Vladimir Serbinenko -2012-02-26 Lubomir Kundrak - - GDB serial and backtrace support. - - * grub-core/kern/i386/realmode.S (real_to_prot): Reload IDT. - (prot_to_real): Likewise. - * grub-core/kern/i386/int.S (grub_bios_interrupt): Remove IDT reload. - * grub-core/Makefile.core.def (backtrace): New module. - (gdb): Likewise. - * grub-core/gdb/cstub.c: New file. - * grub-core/gdb/gdb.c: Likewise. - * grub-core/gdb/i386/idt.c: Likewise. - * grub-core/gdb/i386/machdep.S: Likewise. - * grub-core/gdb/i386/signal.c: Likewise. - * grub-core/lib/i386/backtrace.c: Likewise. - * grub-core/lib/backtrace.c: Likewise. - * include/grub/backtrace.h: Likewise. - * include/grub/gdb.h: Likewise. - * include/grub/i386/gdb.h: Likewise. - -2012-02-26 Vladimir Serbinenko - - * grub-core/gnulib/argp-fmtstream.c (__argp_get_display_len): - New function. - (add_length): Likewise. - (__argp_fmtstream_update): Handle strings with non-ASCII chars. - * grub-core/gnulib/argp-fmtstream.h (__argp_get_display_len): New - proto. - * grub-core/gnulib/argp-help.c (argp_args_usage): Use - __argp_get_display_len. - -2012-02-26 Vladimir Serbinenko - - $"..." support in scripts. - - * grub-core/script/execute.c (grub_script_arglist_to_argv): Handle - GRUB_SCRIPT_ARG_TYPE_GETTEXT. - * grub-core/script/yylex.l: Likewise. - * include/grub/script_sh.h (GRUB_SCRIPT_ARG_TYPE_GETTEXT): New enum - value. - -2012-02-26 Vladimir Serbinenko - - * gentpl.py: Remove obsolete pkglib_DATA handling. - -2012-02-26 Vladimir Serbinenko - - Don't transform PACKAGE_TARNAME following a discussion on autoconf - mailing list. - - * util/grub-install.in: Don't transform PACKAGE_TARNAME. - * util/grub-kbdcomp.in: Likewise. - * util/grub-mkconfig.in: Likewise. - * util/grub-mkconfig_lib.in: Likewise. - * util/grub-mknetdir.in: Likewise. - * util/grub-mkrescue.in: Likewise. - * util/grub-mkstandalone.in: Likewise. - * util/grub-reboot.in: Likewise. - * util/grub-set-default.in: Likewise. - * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. - -2012-02-26 Vladimir Serbinenko - - Remove GRUB_PREFIX. - - * util/grub-mkconfig.in: Remove GRUB_PREFIX. - * util/grub.d/00_header.in: Compute prefix in the only place it's still - used for backward compatibility. - -2012-02-26 Vladimir Serbinenko - - Add new all_video module. - - * grub-core/Makefile.am (moddep.lst): Make dependent on video.lst. - * grub-core/Makefile.core.def (all_video): New module. - * grub-core/genmoddep.awk: Generate dependency of all_video from - video.lst. - * grub-core/lib/fake_module.c: New file. - * grub-core/normal/main.c (features): Add feature_all_video_module. - * util/grub.d/00_header.in: Define locale_dir based on $prefix and - don't do explicit search again. - insmod all_video in load_video if available. - -2012-02-26 Vladimir Serbinenko - - Another round of string clarification and adding TRANSLATORS comments. - -2012-02-26 Vladimir Serbinenko - - * util/grub-mknetdir.in: Remove erroneous reference to install_device. - -2012-02-26 Vladimir Serbinenko - - * grub-core/normal/charset.c (grub_utf8_to_ucs4_alloc): Fix return type - to grub_ssize_t. - * grub-core/normal/main.c (grub_normal_init_page): Fix msg_len type. - * include/grub/charset.h (grub_utf8_to_ucs4_alloc): Fix prototype. - -2012-02-26 Vladimir Serbinenko - - * grub-core/normal/menu_text.c (grub_print_message_indented_real): Add - trailing newline implicitly. All users updated. - -2012-02-26 Vladimir Serbinenko - - Implement serial on IEEE1275 and EFI. - - * docs/grub.texi (Platform-specific limitations): Fix the columen video - on emu. Mention arc and emu as the only platforms without serial - support. - * grub-core/Makefile.core.def (serial): Enable on all terminfomodule and - ieee1275 platforms. - * grub-core/term/efi/serial.c: New file. - * grub-core/term/ieee1275/serial.c: Likewise. - * grub-core/term/serial.c (grub_serial_find): Disable direct port - specification if no ns8250 driver is available. - (grub_cmd_serial): Likewise. - (GRUB_MOD_INIT) [GRUB_MACHINE_IEEE1275]: Init ofserial. - (GRUB_MOD_INIT) [GRUB_MACHINE_EFI]: Init efiserial. - * include/grub/efi/api.h (GRUB_EFI_SERIAL_IO_GUID): New define. - (grub_efi_parity_type_t): New type. - (grub_efi_stop_bits_t): Likewise. - (grub_efi_serial_io_interface): New struct. - * include/grub/serial.h (grub_serial_port): Make 'broken' field - available for all interfaces. - Add EFI and IEEE1275 fields. - (grub_ofserial_init): New proto. - (grub_efiserial_init): Likeiwse. - * util/grub.d/00_header.in: Don't check for the presence of serial - module. - -2012-02-26 Vladimir Serbinenko - - * grub-core/disk/ieee1275/ofdisk.c (scan): Fix improper use of device - name as if it was an alias. - -2012-02-25 Vladimir Serbinenko - - * grub-core/commands/lsacpi.c (options): Fix typo. - -2012-02-25 Vladimir Serbinenko - - Convert grub-emu to argp. - - * grub-core/Makefile.core.def (kernel): Add kern/emu/argp_common.c on - emu. - * util/argp_common.c: Rename to ... - * grub-core/kern/emu/argp_common.c: ... this. All users updated. - Add missing includes. - * grub-core/kern/emu/main.c: Convert to argp. - * po/POTFILES.in: Regenerate. - * util/grub-install.in (usage): Make first letter lowcase in messages - for uniformity. - * util/grub-setup.c (options): Likewise. - -2012-02-24 Vladimir Serbinenko - - * grub-core/gfxmenu/gui_progress_bar.c (progress_bar_set_property): - Put back accidently commented-out code. - -2012-02-24 Vladimir Serbinenko - - * grub-core/fs/hfsplus.c (grub_hfsplus_btree_iterate_node): Add btree - loop check using Brent algorithm. - (grub_hfsplus_btree_search): Likewise. - -2012-02-24 Vladimir Serbinenko - - * util/grub-install.in: Fix usage of wrong device for PreP install. - -2012-02-24 Vladimir Serbinenko - - * conf/Makefile.common (CFLAGS_GNULIB): Add - -Wno-unsafe-loop-optimizations. - * configure.ac: Remove -Wmissing-declarations and -Wmissing-prototypes - on tools. - * grub-core/commands/legacycfg.c: Add pragma to skip - -Wunsafe-loop-optimizations. - (check_password_md5_real): Fix loop counter type. - * grub-core/commands/testload.c (grub_cmd_testload): Fix over the EOF - reading. - * grub-core/disk/ldm.c (grub_util_get_ldm): Fix logic error. - * grub-core/fs/zfs/zfs_sha256.c (zio_checksum_SHA256): Add safety - loop condition. - * grub-core/io/gzio.c: Add pragma to skip -Wunsafe-loop-optimizations. - * grub-core/lib/LzmaEnc.c (GetOptimum): Avoid possible infinite loop. - * grub-core/net/net.c (grub_net_route_address): Add safety loop - condition. - * grub-core/normal/charset.c (bidi_line_wrap): Likewise. - * grub-core/normal/cmdline.c (grub_set_history): Fix loop types and - avoid possible infinite loops. - * grub-core/script/parser.y: Add pragma to skip -Wmissing-declarations - and -Wunsafe-loop-optimizations. - * grub-core/script/yylex.l: Likewise. - * util/grub-mkfont.c: Add pragma to skip -Wunsafe-loop-optimizations. - (print_glyphs): Avoid infinite loops. - * util/grub-mkimage.c (compress_kernel_xz): Fix format security. - -2012-02-24 GrĂ©goire Sutre - - * grub-core/commands/lsacpi.c (disp_acpi_xsdt_table): Fix loop condition - to avoid infinite loop. - (disp_acpi_rsdt_table): Likewise. - -2012-02-24 Vladimir Serbinenko - - * grub-core/font/font.c (grub_font_load): Add support for default - path for fonts ($prefix/fonts). - * grub-core/kern/corecmd.c (grub_core_cmd_insmod): Unify condition - for checking if string is a path. - * grub-core/normal/main.c (features): Add feature_default_font_path. - * util/grub-mkconfig.in: Skip mangling of GRUB_FONT into GRUB_FONT_PATH. - * util/grub.d/00_header.in: Use default directory if possible. - * util/grub-install.in: Install unicode.pf2. - -2012-02-24 Vladimir Serbinenko - - * po/README: Add de_CH and en@quot to po/LINGUAS generation command. - * po/Rules-swiss: New file. - * po/swiss.sed: Likewise. - -2012-02-23 Vladimir Serbinenko - - * grub-core/fs/btrfs.c (find_device): Fix typos. - * grub-core/fs/zfs/zfs.c (read_device): Likewise. - * util/grub-mkrelpath.c (argp_parser): Likewise. - Reported by: Yuri Chornoivan. - -2012-02-23 Dalet Omega - - * grub-core/gfxmenu/gui_label.c (label_set_property): Add template - for usual informative messages. - -2012-02-23 Dalet Omega - - Starfield theme. - - * Makefile.am: Define starfield_DATA and dejavu.pf2 generation. - * conf/Makefile.common: Define starfielddir. - * configure.ac: Configure starfield. - * themes/starfield/COPYING.CC-BY-SA-3.0: New file. - * themes/starfield/README: Likewise. - * themes/starfield/blob_w.png: Likewise. - * themes/starfield/boot_menu_c.png: Likewise. - * themes/starfield/boot_menu_e.png: Likewise. - * themes/starfield/boot_menu_n.png: Likewise. - * themes/starfield/boot_menu_ne.png: Likewise. - * themes/starfield/boot_menu_nw.png: Likewise. - * themes/starfield/boot_menu_s.png: Likewise. - * themes/starfield/boot_menu_se.png: Likewise. - * themes/starfield/boot_menu_sw.png: Likewise. - * themes/starfield/boot_menu_w.png: Likewise. - * themes/starfield/slider_c.png: Likewise. - * themes/starfield/slider_n.png: Likewise. - * themes/starfield/slider_s.png: Likewise. - * themes/starfield/src/blob_nw.xcf: Likewise. - * themes/starfield/src/bootmenu/: Likewise. - * themes/starfield/src/bootmenu/center.xcf: Likewise. - * themes/starfield/src/bootmenu/corner.xcf: Likewise. - * themes/starfield/src/bootmenu/side.xcf: Likewise. - * themes/starfield/src/slider_c.xcf: Likewise. - * themes/starfield/src/slider_n.xcf: Likewise. - * themes/starfield/src/slider_s.xcf: Likewise. - * themes/starfield/src/terminalbox/: Likewise. - * themes/starfield/src/terminalbox/center.xcf: Likewise. - * themes/starfield/src/terminalbox/corner.xcf: Likewise. - * themes/starfield/src/terminalbox/side.xcf: Likewise. - * themes/starfield/starfield.png: Likewise. - * themes/starfield/terminal_box_c.png: Likewise. - * themes/starfield/terminal_box_e.png: Likewise. - * themes/starfield/terminal_box_n.png: Likewise. - * themes/starfield/terminal_box_ne.png: Likewise. - * themes/starfield/terminal_box_nw.png: Likewise. - * themes/starfield/terminal_box_s.png: Likewise. - * themes/starfield/terminal_box_se.png: Likewise. - * themes/starfield/terminal_box_sw.png: Likewise. - * themes/starfield/terminal_box_w.png: Likewise. - * themes/starfield/theme.txt: Likewise. - -2012-02-23 Vladimir Serbinenko - - * util/grub.d/00_header.in: Add missing export theme. - -2012-02-22 Vladimir Serbinenko - - * util/ieee1275/ofpath.c: Remove include of malloc.h since stdlib is - already included. - Reported by: Eren D. - -2012-02-22 Vladimir Serbinenko - - * conf/Makefile.common (grubdatadir): Removed. - (Makefile.am): Move eveything grubdata to pkgdata. - -2012-02-22 Vladimir Serbinenko - - * grub-core/commands/acpihalt.c (get_sleep_type): - Remove unused variable. - -2012-02-22 Vladimir Serbinenko - - * include/grub/acpi.h (GRUB_ASCII_OPCODE): Add - GRUB_ACPI_OPCODE_STRING_CONST, GRUB_ACPI_OPCODE_BUFFER, - GRUB_ACPI_OPCODE_CREATE_WORD_FIELD - and GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD. - * grub-core/commands/acpihalt.c [GRUB_DSDT_TEST]: Replace include of - i18n with gettext no-op. - (skip_data_ref_object): Support GRUB_ACPI_OPCODE_BUFFER and - GRUB_ACPI_OPCODE_STRING_CONST. - (get_sleep_type): Support GRUB_ACPI_OPCODE_CREATE_WORD_FIELD and - GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD. Add handling of unknown opcodes. - -2012-02-22 Vladimir Serbinenko - - * po/POTFILES.in: Regenerate. - -2012-02-22 Vladimir Serbinenko - - * Makefile.util.def (libgrubmods.a): Add -Wno-error=logical-op - -Wno-error=missing-noreturn. - -2012-02-22 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_read_block): Avoid <= in loop - condition to avoid possibly infinite loops. - * grub-core/lib/pbkdf2.c (grub_crypto_pbkdf2): Likewise. - * grub-core/lib/xzembed/xz_dec_bcj.c (bcj_powerpc): Likewise. - -2012-02-22 Vladimir Serbinenko - - * grub-core/normal/charset.c (bidi_line_wrap): Avoid <= in loop - condition to avoid possibly infinite loops. - -2012-02-22 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (read_device_map): Add missing noreturn - on show_error. - -2012-02-22 Vladimir Serbinenko - - * grub-core/kern/disk.c (grub_disk_write): Add missing const qualifier. - -2012-02-22 Vladimir Serbinenko - - * grub-core/kern/corecmd.c (grub_core_cmd_ls): Add missing var init. - -2012-02-22 Vladimir Serbinenko - - * util/bin2h.c (usage): Add missing attribute noreturn. - -2012-02-22 Vladimir Serbinenko - - * grub-core/commands/testload.c (grub_cmd_testload): Fix overflow - if the size isn't divisible by 512. - -2012-02-22 Vladimir Serbinenko - - Make list_push and list_remove functions rather than inline functions - to decrease size and avoid aliasing violations. - - * include/grub/list.h (grub_list_push): Move to ... - * grub-core/kern/list.c (grub_list_push): ... here. Don't inline. - * include/grub/list.h (grub_list_remove): Move to ... - * grub-core/kern/list.c (grub_list_remove): ... here. Don't inline. - -2012-02-22 Vladimir Serbinenko - - * configure.ac: Disable for now -Wstack-protector, -Wunreachable-code - and -Wunused-result. - -2012-02-21 Vladimir Serbinenko - - * grub-core/net/net.c (grub_cmd_deladdr): Fix index. - Reported by: Seth Goldberg - -2012-02-21 Vladimir Serbinenko - - * configure.ac: Add -fno-builtin-gettext on host if NLS is disabled. - -2012-02-19 Samuel Thibault - - * util/grub-mkconfig.in (GRUB_CMDLINE_GNUMACH): Export variable. - * util/grub.d/10_hurd.in: Include GRUB_CMDLINE_GNUMACH in gnumach - command line. - * docs/grub.texi (Simple configuration): Document - GRUB_CMDLINE_GNUMACH. - -2012-02-18 Vladimir Serbinenko - - * conf/Makefile.common (platform_SCRIPTS): New variable. - (platform_PROGRAMS): Likewise. - * gentpl.py: Mark *,module and *.image for install. - * grub-core/gdb_grub.in: Add a notice of expected environment. - * grub-core/Makefile.core.def (gdb_grub): Mark for install. - (gmodule.pl): Likewise. - -2012-02-18 Vladimir Serbinenko - - Replace grub_checkkey with grub_getkey_noblock. - - * grub-core/kern/term.c (grub_checkkey): Replaced with ... - (grub_getkey_noblock): ... this. All users updated. - -2012-02-18 Vladimir Serbinenko - - * grub-core/kern/emu/console.c: Move to ... - * grub-core/term/emu/console.c: ...here. - (grub_ncurses_getkey): Fix return value if no key is detected. - -2012-02-12 Vladimir Serbinenko - - * include/grub/test.h (grub_unit_test_init): Add missing prototype. - (grub_unit_test_fini): Likewise. - * tests/lib/unit_test.c (main): Remove extra nested external prototype. - -2012-02-12 Vladimir Serbinenko - - * include/grub/test.h (GRUB_UNIT_TEST) - -2012-02-12 Vladimir Serbinenko - - * grub-core/script/execute.c (grub_script_break): Clarify logic. - Better error handling. - (grub_script_return): Likewise. - * grub-core/script/lexer.c (grub_script_lexer_yywrap): Likewise. - -2012-02-12 Vladimir Serbinenko - - * grub-core/lib/libgcrypt_wrap/cipher_wrap.h (__GNU_LIBRARY__): Avoid - rimplicit redifinition. - -2012-02-12 Vladimir Serbinenko - - * docs/grub.texi (Internationalisation): Detail (lack of) collation in - GRUB. - -2012-02-12 Vladimir Serbinenko - - * grub-core/normal/cmdline.c (grub_cmdline_get): Don't gettext prompt. - * grub-core/normal/main.c (grub_normal_read_line_real): Gettext - prompt here. - -2012-02-12 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (zfs_fetch_nvlist): Mark unknown member here - as GRUB_ERR_BUG. Don't malloc if no device is available. - -2012-02-12 Vladimir Serbinenko - - * grub-core/term/terminfo.c (grub_terminfo_output_unregister): - Mark calling with invalid term as GRUB_ERR_BUG. - -2012-02-12 Vladimir Serbinenko - - * grub-core/net/tftp.c (tftp_receive): Silently discard too short - packets rather than raising an error. - -2012-02-12 Vladimir Serbinenko - - * grub-core/loader/xnu.c (grub_xnu_writetree_toheap_real): Avoid set - in if. - -2012-02-12 Vladimir Serbinenko - - * grub-core/loader/efi/appleloader.c (grub_cmd_appleloader): Move - diagnostic to dprintf. - * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Likewise. - -2012-02-12 Vladimir Serbinenko - - * grub-core/kern/corecmd.c (grub_core_cmd_ls): Handle error in parsing - device name. - -2012-02-12 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (locate_attr): Avoid set in if. - (grub_ntfs_iterate_dir): Likewise. - -2012-02-12 Vladimir Serbinenko - - Efiemu stylistic fixes and gettext. - - * grub-core/efiemu/i386/loadcore32.c - (grub_arch_efiemu_relocate_symbols32): Avoid set in if. - * grub-core/efiemu/i386/loadcore64.c - (grub_arch_efiemu_relocate_symbols64): Likewise. - * grub-core/efiemu/i386/pc/cfgtables.c - (grub_machine_efiemu_init_tables): Likewise. - * grub-core/efiemu/loadcore.c (grub_efiemu_resolve_symbols): Likewise. - (grub_efiemu_loadcore_initXX): Add a filename argument. - All users updated. - Improved error message. - * grub-core/efiemu/loadcore_common.c (grub_efiemu_loadcore_init): - Add a filename argument. - All users updated. - * grub-core/efiemu/symbols.c (grub_efiemu_set_virtual_address_map): - Reclassify double relocation as GRUB_ERR_BUG. - -2012-02-12 Vladimir Serbinenko - - * grub-core/commands/i386/pc/play.c (grub_cmd_play): Improve error - handling. - -2012-02-12 Vladimir Serbinenko - - * grub-core/commands/hdparm.c (grub_cmd_hdparm): Allow running - on partition. - -2012-02-12 Vladimir Serbinenko - - * include/grub/misc.h (grub_error_save): Fix cleaning grub_errno. - -2012-02-12 Vladimir Serbinenko - - Improve string. Gettextize. - -2012-02-11 Vladimir Serbinenko - - * configure.ac: Remove -Winline altogether and -Wmissing-prototypes on - utils. - * util/import_gcry.py: Add -Wno-strict-aliasing on checked modules. - -2012-02-11 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (grub_diskfilter_print_partmap) - [GRUB_UTIL]: New function. - (insert_array) [GRUB_UTIL]: Store partmaps. - * include/grub/diskfilter.h (grub_diskfilter_pv) [GRUB_UTIL]: New member - partmaps. - (grub_diskfilter_print_partmap) [GRUB_UTIL]: New proto. - * util/grub-probe.c (probe_partmap): Call grub_diskfilter_print_partmap. - (probe_abstraction): Print diskfilter and not raid. - Reported by: Lennart Sorensen - -2012-02-11 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Explicitly init decompress_size. - * util/grub-mkimagexx.c (MASK3): New define. - (add_value_to_slot_20b): Use MASK3. - (add_value_to_slot_21): Likewise. - (relocate_addresses): Fix format specification. - (load_image): Explicitly init symtab_section. - -2012-02-11 Vladimir Serbinenko - - * util/getroot.c (grub_find_root_devices_from_mountinfo): Fix types. - (grub_util_biosdisk_get_grub_dev): Fix format specification. - -2012-02-11 Vladimir Serbinenko - - * grub-core/kern/emu/full.c (grub_arch_dl_get_tramp_got_size): Enable - on powerpc. - Reported by: Lennart Sorensen - -2012-02-11 Vladimir Serbinenko - - * gentpl.py: Add missing license header. - * docs/grub.texi: Update copyright year. - -2012-02-10 GrĂ©goire Sutre - - Source grub-mkconfig_lib from the build directory at build time. - Suggested by: Vladimir Serbinenko. - - * gentpl.py (manpage): Set pkgdatadir to $(builddir) on help2man call. - * util/grub-install.in: Define pkgdatadir if not already set, and source - grub-mkconfig_lib from there. - * util/grub-kbdcomp.in: Likewise. - * util/grub-mkconfig.in: Likewise. - * util/grub-mknetdir.in: Likewise. - * util/grub-mkrescue.in: Likewise. - * util/grub-mkstandalone.in: Likewise. - * util/grub-reboot.in: Likewise. - * util/grub-set-default.in: Likewise. - * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. - -2012-02-10 Vladimir Serbinenko - - Increase warning level. - - * conf/Makefile.common (CFLAGS_GNULIB): Add -Wno-redundant-decls - -Wno-unreachable-code -Wno-conversion -Wno-old-style-definition. - * configure.ac (HOST_CFLAGS): Add bunch of -W arguments. - (TARGET_CFLAGS): Likewise. - (HOST_CFLAGS): Add -Werror unless --disable-werror is activated. - * grub-core/Makefile.core.def (decompressor_xz): Add - -Wno-unreachable-code. - (normal): Add -Wno-redundant-decls. - (xzio): Add -Wno-unreachable-code. - (lzopio): Add -Wno-redundant-decls -Wno-error. - * grub-core/commands/acpi.c: Add exception to -Wcast-align. - * grub-core/commands/lsacpi.c: Add exception to -Wcast-align. - * grub-core/gensymlist.sh: Add exception to -Wmissing-format-attribute. - * grub-core/kern/dl.c: Add exception to -Wcast-align. - * grub-core/kern/efi/efi.c (grub_efi_modules_addr): Likewise. - * grub-core/kern/i386/coreboot/init.c: Add exception to - -Wsuggest-attribute=noreturn. - * grub-core/kern/ia64/dl.c: Add exception to -Wcast-align. - * grub-core/kern/ia64/dl_helper.c: Likewise. - * grub-core/kern/mips/dl.c: Likewise. - * grub-core/kern/sparc64/dl.c: Likewise. - * grub-core/lib/LzmaEnc.c: Add exception to -Wshadow. - * grub-core/lib/libgcrypt_wrap/cipher_wrap.h (memcpy): Likewise. - (memcmp): Likewise. - * grub-core/lib/pbkdf2.c: Add exception to -Wunreachable-code. - * grub-core/loader/ia64/efi/linux.c: Add exception to -Wcast-align. - * grub-core/loader/mips/linux.c: Likewise. - * grub-core/loader/multiboot_elfxx.c: Likewise. - * grub-core/script/parser.y: Add exception to -Wunreachable-code. - * grub-core/video/sm712.c: Add exception to -Wcast-align. - * util/import_gcry.py: Add -Wno-cast-align to modules checked by hand. - * grub-core/font/font.c (grub_font_loader_init): Add explicit cast and - fixme. - * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Likewise. - * grub-core/kern/i386/multiboot_mmap.c (grub_machine_mmap_init): - Fix prototype. - -2012-02-10 Vladimir Serbinenko - - * grub-core/lib/i386/relocator16.S: Fix incorrect use of absolute - address. - -2012-02-10 Vladimir Serbinenko - - * grub-core/commands/legacycfg.c (grub_cmd_legacy_kernel): - Avoid improper use of strings. - (grub_cmd_legacy_initrdnounzip): Likewise. - -2012-02-10 Vladimir Serbinenko - - * include/grub/emu/misc.h (grub_util_warn): Add missing format - attribute. - (grub_util_info): Likewise. - (grub_util_error): Likewise. - -2012-02-10 Vladimir Serbinenko - - * util/grub-mount.c (fuse_init): Avoid improper use of strings. - * util/grub-fstest.c (fstest): Likewise. - -2012-02-10 Vladimir Serbinenko - - * grub-core/disk/geli.c (grub_md_sha256_real): Respect format security. - (grub_md_sha512_real): Likewise. - (grub_util_get_geli_uuid): Likewise. - * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors): Likewise. - (grub_util_biosdisk_open): Fix format specification. - Respect format security. - * grub-core/kern/emu/misc.c (xmalloc): Respect format security. - (xrealloc): Likewise. - (xasprintf): Likewise. - -2012-02-10 Vladimir Serbinenko - - * util/import_gcry.py: Include grub/crypto.h in init.c. - -2012-02-10 Vladimir Serbinenko - - * util/grub-mkimage.c (compress_kernel_lzma): Respect format security. - (generate_image): Make prefix a const char *. - Fix format specifications. Respect format security. - Avoid void * arithmetics. - Avoid shadowing. - (argp_parser): Remove unused variable. Respect format security. - * util/grub-mkimagexx.c (relocate_symbols): Avoid shadowing. - (count_funcs) [!MKIMAGE_ELF64]: #if-out. - (count_funcs): Remove unused variable. - (relocate_addresses): Fix format specification. - Disable x86-64 with elf32. Remove unused variables. - (add_fixup_entry): Avoid shadowing. - (make_reloc_section): Fix format specification. - Use assert. - (locate_sections): Fix format specifications. - (load_image): Avoid shadowing. - -2012-02-10 Vladimir Serbinenko - - * util/grub-setup.c (setup): Remove unused variable. Avoid shadowing. - Fix format specifications. Respect format security. - Don't translate already translated grub_errmsg. - (argp_parser): Remove unused variable - -2012-02-10 Vladimir Serbinenko - - * util/grub-mkrelpath.c (argp_parser): Remove unused variable. - -2012-02-10 Vladimir Serbinenko - - * util/grub-mkpasswd-pbkdf2.c (argp_parser): Remove unused variable. - (main): Likewise. Use xmalloc. Respect format security. - -2012-02-10 Vladimir Serbinenko - - * util/grub-mklayout.c (console_grub_equivalence): Make "layout" - a const char *. - (argp_parser): Remove unused variable. - -2012-02-10 Vladimir Serbinenko - - * util/grub-mkfont.c (grub_font_info): Make name a const char *. - (add_pixel): Make static. - (add_font): Likewise. - (write_string_section): Make name and str a const char *. - (write_be16_section): Make name a const char *. - (print_glyphs): Make static. - (write_font_ascii_bitmap): Likewise. - (write_font_width_spec): Likewise. - (write_font_pf2): Likewise. - (argp_parser): Remove unused variable. - Respect format security. - (main): Avoid shadowing. Respect format security. - -2012-02-10 Vladimir Serbinenko - - * util/grub-editenv.c (argp_parser): Make static. - (create_envblk_file): Use xmalloc. - (open_envblk_file): Likewise. - Resepect format security. - (set_variables): Respect format security. - -2012-02-10 Vladimir Serbinenko - - * util/getroot.c (grub_find_device): Respect format security. - (get_mdadm_uuid): Remove unused variable. - (grub_util_pull_device): Dont call gettext on already translated - grub_errmsg. - (find_system_device): Remove unused variable. - (grub_util_get_grub_dev): Likewise. - (grub_make_system_path_relative_to_its_root): Respect format security. - -2012-02-10 Vladimir Serbinenko - - * util/grub-fstest.c (execute_command): Make first argument - a const char *. - (read_file): Avoid shadowing. - Reuse underlying error message if device open fails. - (cmd_cmp): Respect format security. - (root): Make const char *. - (fstest): Remove args argument and use global copy. - Respect format security. - (argp_parser): Make static. - (main): Make default_root const char *. - -2012-02-10 Vladimir Serbinenko - - * util/grub-mount.c (root): Make const char *. - (execute_command): Make first argument a const char *. - (fuse_init): Respect format security. - (argp_parser): Make static. Remove unused variable. - (main): Make default_root a const char *. - Respect format security. - -2012-02-10 Vladimir Serbinenko - - * util/grub-probe.c (probe): Don't call gettext on already translated - grub_errmsg. - Remove unused variables. - (argp_parser): Remove unused variable. - -2012-02-10 Vladimir Serbinenko - - * util/grub-script-check.c (argp_parser): Remove unused variable. - (main): Rename read to curread to avoid shadowing. - -2012-02-10 Vladimir Serbinenko - - * util/misc.c (grub_util_write_image_at): Fix format specification. - (grub_util_write_image): Likewise. - (grub_script_execute_argument_to_string): Removed (unused). - (grub_script_execute_menuentry): Likewise. - (grub_putchar): Likewise. - -2012-02-10 Vladimir Serbinenko - - * include/grub/symbol.h (EXT_C) [GRUB_UTIL]: Removed. - (FUNCTION) [GRUB_UTIL]: Likewise. - (VARIABLE) [GRUB_UTIL]: Likewise. - -2012-02-10 Vladimir Serbinenko - - * include/grub/misc.h: Avoid evaluationg NEED_ENABLE_EXECUTE_STACK and - NEED_REGISTER_FRAME_INFO in GRUB_UTIL. - -2012-02-10 Vladimir Serbinenko - - * grub-core/partmap/bsdlabel.c (iterate_real): Fix freeing of static - buffer. - -2012-02-10 Vladimir Serbinenko - - * grub-core/lib/LzmaEnc.c (LzmaEnc_FastPosInit): Made static. - (LzmaEnc_SaveState): Removed (unused). - (LzmaEnc_RestoreState): Likewise. - (LzmaEnc_InitPriceTables): Made static. - (LzmaEnc_Construct): Likewise. - (LzmaEnc_FreeLits): Likewise. - (LzmaEnc_Destruct): Likewise. - (LzmaEnc_Init): Likewise. - (LzmaEnc_InitPrices): Likewise. - (LzmaEnc_Finish): Likewise. - (LzmaEnc_PrepareForLzma2): Removed (unused). - (LzmaEnc_MemPrepare): Likewise. - (LzmaEnc_GetNumAvailableBytes): Likewise. - (LzmaEnc_GetCurBuf): Likewise. - (LzmaEnc_CodeOneMemBlock): Likewise. - -2012-02-10 Vladimir Serbinenko - - * grub-core/disk/ldm.c (grub_util_get_ldm): Remove unused variables. - (grub_util_ldm_embed): Likewise. - -2012-02-10 Vladimir Serbinenko - - * util/grub-editenv.c (print_var): Rename name to varname to - avoid shadowing. - (main): Rename index to curindex to avoid shadowing. - Make filename a const char *. - -2012-02-10 Vladimir Serbinenko - - * grub-core/script/lexer.c (grub_script_lexer_init): Rename getline - to arg_getline to avoid shadowing. - -2012-02-10 Vladimir Serbinenko - - * grub-core/partmap/gpt.c (gpt_partition_map_embed): Rename disk to - disk_ to avoid shadowing. - -2012-02-10 Vladimir Serbinenko - - * grub-core/lib/LzFind.c (MatchFinder_GetIndexByte): Rename index to - curindex to avoid shadowing. - Make static. - (MatchFinder_GetNumAvailableBytes): Make static. - -2012-02-10 Vladimir Serbinenko - - * grub-core/fs/squash4.c (direct_read): Rename read to curread to - avoid shadowing. - -2012-02-10 Vladimir Serbinenko - - * grub-core/disk/cryptodisk.c (grub_cryptodisk_endecrypt): Rename - argument from encrypt to do_encrypt to avoid shadowing. - -2012-02-09 Vladimir Serbinenko - - * grub-core/loader/multiboot_elfxx.c (grub_multiboot_load_elf): Fix - incorrect nesting of #if's. - -2012-02-09 Vladimir Serbinenko - - * grub-core/commands/lsacpi.c (disp_acpi_xsdt_table): #if'-out the - checks which are always false on some platforms. - (grub_cmd_lsacpi): Likewise. - * grub-core/kern/misc.c (grub_strtoul): Likewise. - * grub-core/loader/multiboot.c (grub_multiboot_set_video_mode): - Likewise. - -2012-02-09 Vladimir Serbinenko - - * grub-core/disk/diskfilter.c (read_segment): Renome unreachable code. - * grub-core/net/ip.c (grub_net_recv_ip4_packets): Likewise. - -2012-02-09 Vladimir Serbinenko - - * grub-core/gnulib/regex.h (re_pattern_buffer): Declare buffer as - re_dfa_t to avoid breaking alignment invariants. - * grub-core/gnulib/regex_internal.h (re_dfa_t): Moved to ... - * grub-core/gnulib/regex.h (re_dfa_t): ... here. - -2012-02-09 Vladimir Serbinenko - - * grub-core/loader/i386/xnu.c (grub_xnu_boot): Fix printf. - * grub-core/loader/ia64/efi/linux.c (grub_cmd_fpswa): Likewise. - -2012-02-09 Vladimir Serbinenko - - * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_init): - Fix declaration. - -2012-02-09 Vladimir Serbinenko - - * grub-core/bus/usb/ehci.c (grub_ehci_ehcc_read32): Restructure to - conserve alignment invariants. - (grub_ehci_ehcc_read16): Likewise. - (grub_ehci_oper_read32): Likewise. - (grub_ehci_oper_write32): Likewise. - (grub_ehci_pci_iter) [!GRUB_HAVE_UNALIGNED_ACCESS]: Check alignment. - Conserve alignment invariants. - -2012-02-09 Vladimir Serbinenko - - * grub-core/kern/emu/full.c (grub_emu_post_init): Remove raid reinit. - * include/grub/disk.h [GRUB_MACHINE_EMU]: Remove now useless LVM/RAID - declarations. - -2012-02-09 Vladimir Serbinenko - - * grub-core/kern/emu/hostfs.c (grub_hostfs_close): - Remove unused variable. - -2012-02-09 Vladimir Serbinenko - - * grub-core/efiemu/loadcore_common.c (grub_efiemu_loadcore_load): - Remove set in if. - -2012-02-09 Vladimir Serbinenko - - * include/grub/net.h: Remove double declarations. - -2012-02-09 Vladimir Serbinenko - - Remove "payload" command in ia64 Linux loader since I couldn't - find any evidence of it being used for anything. - Replace "relocate" command with an environment variable - - * grub-core/loader/ia64/efi/linux.c (ia64_boot_param): Remove extra - fields. - (ia64_boot_payload): Removed. - (last_payload): Likewise. - (RELOCATE_OFF): Likewise. - (RELOCATE_ON): Likewise. - (RELOCATE_FORCE): Likewise. - (relocate): Likewise. - (free_pages): Don't free payloads. - (grub_load_elf64): Use common error messages. - Use "linux_relocate" variable. - Increase the space after boot_params. - (grub_cmd_payload): Removed. - (grub_cmd_relocate): Likewise. - (grub_cmd_fpswa): Improve messages. - (cmd_payload): Removed. - (cmd_relocate): Likewise. - (GRUB_MOD_INIT): Don't register "payload" and "relocate". - (GRUB_MOD_FINI): Don't unregister "payload" and "relocate". - -2012-02-09 Vladimir Serbinenko - - Convert UHCI to DMA framework. - - * grub-core/bus/usb/uhci.c (grub_uhci): Add chunk and phys members. - (grub_uhci_pci_iter): Fill new members - (grub_alloc_td): Use P2V and V2P functions. - (grub_free_queue): Likewise. - (grub_alloc_qh): Likewise. - (grub_uhci_setup_transfer): Likewise. - (grub_uhci_check_transfer): Likewise. - -2012-02-09 Vladimir Serbinenko - - * grub-core/video/colors.c (grub_video_parse_color): Fix error message. - Remove assignment in if while on it. - -2012-02-09 Vladimir Serbinenko - - * util/grub-mkstandalone.in: Fix modules directory. - -2012-02-09 Vladimir Serbinenko - - * util/grub-mkimage.c (image_targets): Set default_compression to lzma - on i386-pc target. - (argp_parser): Accept "auto" as compression specification. - -2012-02-09 Vladimir Serbinenko - - Fix `help' with unloaded modules. - - * include/grub/normal.h (grub_dyncmd_get_cmd): New proto. - * grub-core/normal/dyncmd.c (grub_dyncmd_get_cmd): New function. - (grub_dyncmd_dispatcher): Small stylistic fix. - * grub-core/commands/help.c (grub_cmd_help): Load missing modules when - explicit help is requested. - -2012-02-09 Vladimir Serbinenko - - * grub-core/fs/cpio.c (grub_cpio_dir): Fix a bug with multiple listing. - Explicitly init restart while on it. - -2012-02-09 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/wchar.h (mbrtowc): Set pwc to zero to avoid - uninited variable. - -2012-02-08 Vladimir Serbinenko - - * util/grub-mknetdir.in: Use . rather than source for POSIX - compatibility. - -2012-02-08 Vladimir Serbinenko - - * util/grub-probe.c (main): Fix trailing space in compatibility hint. - -2012-02-08 Vladimir Serbinenko - - * grub-core/kern/partition.c (grub_partition_get_name): Fix uninited - variable. - -2012-02-08 Vladimir Serbinenko - - * grub-core/commands/hdparm.c (grub_cmd_hdparm): Accept device name - without quotes. - -2012-02-08 Vladimir Serbinenko - - * grub-core/net/net.c (GRUB_MOD_INIT): Don't register netfs. - -2012-02-08 Vladimir Serbinenko - - * grub-core/kern/partition.c (grub_partition_get_name): Fix reverse - iteration of partitions. - -2012-02-08 Vladimir Serbinenko - - Improve gettext support. Stylistic fixes and error handling fixes while - on it. - -2012-02-07 Vladimir Serbinenko - - * grub-core/lib/i386/relocator16.S: Revert moving A20 code into PM - part. Instead setup the correct stack in RM. - * grub-core/lib/i386/relocator.c (grub_relocator16_boot): Reserve place - for stack. - * include/grub/i386/relocator_private.h: New file. - -2012-02-05 Vladimir Serbinenko - - * grub-core/commands/minicmd.c (GRUB_MOD_INIT): Add missing SIZE - argument. - * util/grub-fstest.c (options): Add missing DEVICE part. - -2012-02-05 Vladimir Serbinenko - - Clarify and unify messages. - - * grub-core/commands/hashsum.c (options): Unify messages. - * grub-core/commands/keystatus.c (GRUB_MOD_INIT): Don't mark a - literal-only message as translatable. - * grub-core/commands/lsacpi.c (GRUB_MOD_INIT): Likewise. - * grub-core/loader/ia64/efi/linux.c (GRUB_MOD_INIT): Likewise. - * grub-core/commands/legacycfg.c (GRUB_MOD_INIT): Add quoting around - commands. - * grub-core/commands/menuentry.c (options): Clarify that it's a keyboard - key, not the key used to unlock. Clarify what it's used for. - * grub-core/kern/emu/hostdisk.c (read_device_map): Unify error message. - * grub-core/loader/xnu.c (grub_xnu_load_driver): Remove erroneous colon. - * grub-core/script/main.c (GRUB_MOD_INIT): Clarify [n] to be [NUM]. - * util/grub-editenv.c (options): Unify "verbose" message. - * util/grub-fstest.c (read_file): Unify error message. - (fstest): Add quotes around commands. - (options): Unify "verbose" message. - * util/grub-install.in: Add quotes around variable name. - * util/grub-kbdcomp.in: Unify error message. - * util/grub-mkfont.c (main): Likewise. - * util/grub-mkrescue.in: Likewise. - * util/grub-mklayout.c (options): Unify "verbose" message. - * util/grub-mkstandalone.in: Unify help and verbose messages. - * util/grub-mount.c (options): Unify "verbose" message. - * util/grub-probe.c (options): Likewise. - * util/grub-script-check.c (options): Likewise. - * util/grub-setup.c (setup): Unify no-terminator message. - (options): Use DEVICE and not DEV. - Unify "verbose" message. - * util/ieee1275/ofpath.c (xrealpath): Unify error message. - -2012-02-05 Vladimir Serbinenko - - Improve and unify messages. - - * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors): Add argument - name. All users updated. - Print filename in error. - (read_device_map): Print filename in error. - * util/getroot.c (grub_guess_root_devices): Print filename in error. - (grub_util_get_os_disk): Likewise. - (grub_util_biosdisk_get_grub_dev): Likewise. - (grub_util_check_block_device): Likewise. - (grub_util_check_char_device): Likewise. - (grub_make_system_path_relative_to_its_root): Likewise. - * util/grub-editenv.c (create_envblk_file): Likewise. - (open_envblk_file): Likewise. - (write_envblk): Likewise. - * util/grub-fstest.c (cmd_cp): Likewise. - (cmd_cat): Likewise. - (cmd_cmp): Likewise. - * util/grub-menulst2cfg.c (main): Likewise. - * util/grub-mkfont.c (write_font_ascii_bitmap): Likewise. - (write_font_width_spec): Likewise. - (write_font_pf2): Likewise. - * util/grub-mkimage.c (generate_image): New argument outname. - All users updated. - Remove unreacheable message. - (options): Unify messages. - (help_filter): Likewise. - * util/grub-mklayout.c (usage): Removed (unused). - (main): Print filename in error. - * util/grub-mkrescue.in: Fix wrong quoting. - * util/grub-setup.c (setup): Print filename in error. - * util/ieee1275/ofpath.c (vendor_is_ATA): Likewise. - (check_sas): Likewise. - * util/misc.c (grub_util_get_fp_size): Removed. - (grub_util_get_image_size): Print filename in error. - (grub_util_read_at): Removed. - (grub_util_read_image): Print filename in error. - (grub_util_load_image): Likewise. - (grub_util_write_image_at): New argument filename. All users updated. - Print filename in error. - (grub_util_write_image): New argument filename. All users updated. - Print filename in error. - * util/raid.c (grub_util_raid_getmembers): Print filename in error. - * util/resolve.c (grub_util_resolve_dependencies): Likewise. - -2012-02-05 Vladimir Serbinenko - - * grub-core/Makefile.core.def (pxechain): New module. - * grub-core/loader/i386/pc/pxechainloader.c: New file. - * grub-core/net/drivers/i386/pc/pxe.c (grub_pxe_get_cached): New - function. - (grub_pc_net_config_real): Use grub_pxe_get_cached. - * include/grub/i386/pc/pxe.h (grub_pxe_get_cached): New proto. - -2012-02-05 Vladimir Serbinenko - - * grub-core/kern/err.c (GRUB_MAX_ERRMSG): Move to ... - * include/grub/err.h (GRUB_MAX_ERRMSG): ... here. - * include/grub/err.h (grub_error_saved): New struct. - (grub_errmsg): Make array size explicit. - * include/grub/misc.h (grub_error_save): New function. - (grub_error_load): Likewise. - * grub-core/kern/err.c (grub_error_stack_items): Use grub_error_saved. - (grub_error_push): Update `errno' member name. - (grub_error_pop): Likewise - * grub-core/net/tftp.c (tftp_data): New member save_err. - (tftp_receive): Save error. - (tftp_open): Restore error. - -2012-02-05 Vladimir Serbinenko - - * grub-core/lib/i386/relocator16.S (grub_relocator16_start): Move switch - to real mode down to execute A20-related code in protected mode as - intended. - -2012-02-05 GrĂ©goire Sutre - - * grub-core/disk/diskfilter.c (grub_diskfilter_make_raid): Return - NULL when the argument `level' has an unexpected value. - -2012-02-04 Vladimir Serbinenko - - Move platform-dependent files from $prefix to $prefix/$platform. - - * config.h.in (GRUB_TARGET_CPU): New definition. - (GRUB_PLATFORM): Likewise. - * configure.ac: Define GRUB_TARGET_CPU and GRUB_PLATFORM. - * grub-core/commands/parttool.c (grub_cmd_parttool): Update dir. - * grub-core/efiemu/main.c (grub_efiemu_autocore): Likewise. - * grub-core/kern/dl.c (grub_dl_load): Likewise. - * grub-core/normal/autofs.c (read_fs_list): Likewise. - * grub-core/normal/crypto.c (read_crypto_list): Likewise. - * grub-core/normal/dyncmd.c (read_command_list): Likewise. - * grub-core/normal/term.c (read_terminal_list): Likewise. - * grub-core/gettext/gettext.c (grub_mofile_open_lang): Use - $prefix/locale. - (grub_gettext_init_ext): Likewise. - * grub-core/normal/main.c (GRUB_MOD_INIT): Define grub_cpu and - grub_platform. - * util/grub-install.in: Update directories. - * util/grub-mknetdir.in: Likewise. - * util/grub-mkrescue.in: Likewise. - -2012-02-04 Vladimir Serbinenko - - * grub-core/kern/ieee1275/openfw.c (grub_claimmap): Change to - grub_error framework. All users updated. - -2012-02-04 Vladimir Serbinenko - - * grub-core/gettext/gettext.c: Mostly rewritten to avoid using - lists (by always binsearching), improve caching (cache strings - used for binsearch, not only results), improve - maintainability (by using more structured binary search) and correct - error handling. - -2012-02-04 Vladimir Serbinenko - - * grub-core/script/execute.c (grub_script_return): Fix warning. - -2012-02-04 Vladimir Serbinenko - - * grub-core/script/execute.c (grub_script_return): Fix potential - NULL-dereference. - Reported by: Jim Meyering. - -2012-02-03 Vladimir Serbinenko - - * po/POTFILES.in: Regenerate. - * util/grub-install.in: Gettextize the strings missed in first pass. - -2012-02-03 Vladimir Serbinenko - - * Makefile.util.def (grub-mkdevicemap): Removed. - * include/grub/emu/hostdisk.h (grub_util_get_os_disk): New proto. - * include/grub/util/deviceiter.h: Removed. - * util/deviceiter.c: Likewise. - * util/getroot.c (grub_util_get_os_disk): New function. - * util/grub-install.in: Remove grub-mkdevicemap. Use -t disk as - replacement for EFI. - * util/grub-mkdevicemap.c: Removed. - * util/grub-probe.c (probe): Handle PRINT_DISK. - (argp_parser): Handle -t disk. - -2012-02-03 Vladimir Serbinenko - - * util/grub-mkfont.c: Migrate to argp. - * util/grub-mklayout.c: Likewise. - * util/grub-mkpasswd-pbkdf2.c: Likewise. - * util/grub-mkrelpath.c: Likewise. - * util/grub-probe.c: Likewise. - * util/grub-script-check.c: Likewise. - -2012-02-03 Vladimir Serbinenko - - * util/grub-reboot.in: Add missing datarootdir. - Add missing newline. - * util/grub-set-default.in: Add missing datarootdir. - * util/powerpc/ieee1275/grub-mkrescue.in: Add missing newline. - * util/grub-mkrescue.in: Likewise. - -2012-02-03 Vladimir Serbinenko - - * util/grub.d/30_os-prober.in: Fix TRANSLATORS comment. - -2012-02-03 Vladimir Serbinenko - - * util/grub-kbdcomp.in: Add decent help and gettextize. - * docs/man/grub-kbdcomp.h2m: New file. - -2012-02-03 Vladimir Serbinenko - - Migrate grub-mkimage.c to argp. - - * Makefile.util.def (grub-mkimage): Add util/argp_common.c. - (grub-setup): Likewise. - * util/grub-setup.c (print_version): Move to ... - * util/argp_common.c (print_version): ... here. - * util/grub-setup.c (argp_program_version_hook): Move to ... - * util/argp_common.c (argp_program_version_hook): ... here. - * util/grub-setup.c (argp_parser): Add exit (1) on fatal error for - safety. - * util/grub-mkimage.c (main): Migrate to argp. - -2012-02-03 Vladimir Serbinenko - - * util/grub-mkrescue.in: Use same message as - util/powerpc/ieee1275/grub-mkrescue.in with %s in place of command - for better translations. - -2012-02-03 Vladimir Serbinenko - - * util/powerpc/ieee1275/grub-mkrescue.in: Gettextize. Unify the command - options with generic grub-mkrescue.in with the goal of future - merge. - -2012-02-03 Vladimir Serbinenko - - * grub-core/kern/mm.c: Add missing include of i18n.h - * grub-core/lib/relocator.c: Likewise. - -2012-02-03 Vladimir Serbinenko - - * grub-core/loader/ia64/efi/linux.c (find_mmap_size): Replace fatal with - error. - (allocate_pages): Check return value. - Replace fatal with error. - (grub_linux_boot): Replace printf with dprintf. - Check find_mmap_size return value. - Replace fatal with error. - Don't call grub_machine_fini. - (grub_load_elf64): Replace printf with dprintf. - (grub_cmd_linux): Likewise. - (grub_cmd_initrd): Likewise. - (grub_cmd_payload): Likewise. - -2012-02-03 Vladimir Serbinenko - - * grub-core/loader/i386/xnu.c (grub_cmd_devprop_load): Fix error - message. - * grub-core/video/radeon_fuloong2e.c - (grub_video_radeon_fuloong2e_setup): Likewise. - * grub-core/video/sis315pro.c (grub_video_sis315pro_setup): Likewise. - * grub-core/video/video.c (grub_video_set_mode): Don't override - standard out of memory message. - -2012-02-03 GrĂ©goire Sutre - - NetBSD disk wedge support. - - * grub-core/kern/emu/hostdisk.c (grub_hostdisk_find_partition_start) - [__NetBSD__]: Handle NetBSD disk wedges. - * util/getroot.c (convert_system_partition_to_system_disk) - [__NetBSD__]: Likewise. - -2012-02-03 Mark Wooding - - * util/grub-mkconfig.in: Use umask rather than chmod to create - grub.cfg.new to avoid insecure grub.cfg. - -2012-02-03 Vladimir Serbinenko - - * grub-core/commands/ls.c: Gettextize. - * grub-core/commands/setpci.c: Likewise. - * grub-core/commands/videotest.c: Likewise. - * grub-core/disk/geli.c: Likewise. - * grub-core/kern/mm.c: Likewise. - * grub-core/lib/relocator.c: Likewise. - * grub-core/loader/efi/appleloader.c: Likewise. - * grub-core/loader/i386/xnu.c: Likewise. - * grub-core/loader/ia64/efi/linux.c: Likewise. - * grub-core/loader/xnu.c: Likewise. - * grub-core/net/dns.c: Likewise. - * grub-core/net/net.c: Likewise. - * grub-core/script/lexer.c: Likewise. - * grub-core/script/parser.y: Likewise. - * grub-core/script/yylex.l: Likewise. - * util/getroot.c: Likewise. - * util/grub-setup.c: Likewise. - -2012-02-03 Vladimir Serbinenko - - * grub-core/fs/reiserfs.c (grub_reiserfs_get_item): Use proper error - number. - -2012-02-03 Vladimir Serbinenko - - * grub-core/disk/ldm.c (grub_util_ldm_embed): Correct error message. - -2012-02-03 Vladimir Serbinenko - - * grub-core/commands/search_file.c (SEARCH_TARGET): Remove obsolete - macro. - * grub-core/commands/search_label.c (SEARCH_TARGET): Likewise. - * grub-core/commands/search_uuid.c (SEARCH_TARGET): Likewise. - -2012-02-03 Vladimir Serbinenko - - * util/grub-mkstandalone.in: Fix help messages. Gettextize. - * util/grub-install.in: Gettextize. - * util/grub-mkconfig.in: Likewise. - * util/grub-mkconfig_lib.in: Replace gettext with echo -n and not echo - if not available. - (grub_warn): Gettextize. - * util/grub-mknetdir.in: Gettextize. - * util/grub-mkrescue.in: Likewise. - * util/grub-mkstandalone.in: Likewise. - * util/grub-reboot.in: Likewise. - * util/grub-set-default.in: Likewise. - * util/grub.d/00_header.in: Likewise. - * util/grub.d/10_hurd.in: Likewise. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/10_netbsd.in: Likewise. - * util/grub.d/10_windows.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - * util/grub.d/30_os-prober.in: Likewise. - * po/POTFILES-shell.in: Regenerate. - -2012-02-03 Richard Laager - - * util/grub-mkimage.c (main): Fix format-security warning. - * util/grub-mkrelpath.c (main): Likewise. - * util/grub-probe.c (main): Likewise. - -2012-02-03 Richard Laager - - * util/grub-probe.c (probe): Don't crash on canonicalize_file_name - failure. - Put back lost PRINT_DRIVE. - -2012-02-03 Richard Laager - - * util/getroot.c (find_root_devices_from_libzfs): Fix compilation error. - (grub_guess_root_devices): Replace strlen with sizeof. - Avoid crash. - (find_root_devices_from_poolname): Remove unused variable. - Handle raidzN. - -2012-02-03 Vladimir Serbinenko - - Support install on multi-device filesystems. - - * include/grub/emu/getroot.h (grub_guess_root_device): Renamed to ... - (grub_guess_root_devices): ...this. Return char **. All users updated. - * include/grub/emu/misc.h (grub_find_root_device_from_mountinfo): - Removed. - * util/getroot.c (find_root_device_from_libzfs): Moved pool logic to ... - (find_root_devices_from_poolname): ... here. - (grub_find_root_devices_from_mountinfo): Return char **. Make static. - Support zfs-fuse. - (grub_guess_root_device): Rename to ... - (grub_guess_root_devices): ... this. Return char **. All users updated. - * util/grub-install.in: Handle multi-device filesystems. - * util/grub-probe.c (probe). Make device_names a char **. Add delim - argument. All users updated. - Handle multi-device filesystems. - Use 'delim' as separator. - Remove device check to allow filesystems on file. - (main): Support -0 argument. Handle multi-device. - * util/grub-setup.c (setup): Remove root argument. Handle multi-device. - Fix a cross-device check while on it. - (arguments): Remove root_dev. - (argp_parser): Remove -r. - (main): Remove root_dev. - -2012-02-01 Vladimir Serbinenko - - * grub-core/fs/zfs/zfscrypt.c: Add link to documentation. - -2012-02-01 Vladimir Serbinenko - - * grub-core/commands/videotest.c (grub_cmd_videotest): Fix subset - symbol. - Reported by: NODA, Kai . - -2012-02-01 Vladimir Serbinenko - - Fix ehci on amd64. - - * grub-core/bus/usb/usbhub.c (grub_usb_hub_add_dev): Use %p to print - pointers. - * grub-core/bus/usb/ehci.c (grub_ehci_pci_iter): Likewise. - (grub_ehci_setup_qh): Likewise. - (grub_ehci_find_qh): Likewise. - (grub_ehci_transaction): Likewise. - (grub_ehci_setup_transfer): Likewise. - (grub_ehci_check_transfer): Likewise. - (grub_ehci_portstatus): Likewise. - (grub_ehci_detect_dev): Likewise. - (grub_ehci_transfer_controller_data): New field td_last_phys. - (grub_ehci_setup_transfer): Fill td_last_phys. - (grub_ehci_check_transfer): Use td_last_phys. - -2012-02-01 Seth Goldberg - - * grub-core/normal/context.c (grub_env_extractor_close): Don't crash - if no submenu is present. - -2012-02-01 AleÅ¡ Nesrsta - - CBI support. - - * include/grub/usb.h (grub_usbms_protocol_t): New values - GRUB_USBMS_PROTOCOL_CB and GRUB_USBMS_PROTOCOL_CBI. - * grub-core/disk/usbms.c (GRUB_USBMS_CBI_CMD_SIZE): New define. - (GRUB_USBMS_CBI_ADSC_REQ): Likewise. - (grub_usbms_dev): Add subclass, protocol and intrpt. - Remove in_maxsz and out_maxsz. - (grub_usbms_reset): Rename to ... - (grub_usbms_bo_reset): .. this. - (grub_usbms_cbi_cmd): New function. - (grub_usbms_cbi_reset): Likewise. - (grub_usbms_reset): Likewise. - (grub_usbms_attach): Recognize cbi. Same subclass and protocol. - (grub_usbms_transfer): Rename to ... - (grub_usbms_transfer_bo): ... this. - (grub_usbms_transfer_cbi): Likewise. - (grub_usbms_transfer): Likewise. - -2012-02-01 AleÅ¡ Nesrsta -2012-02-01 Vladimir Serbinenko - - EHCI support. All of the credit goes to AleÅ¡ Nesrsta. I've just added - the support for the CS5536 modification thereos and few bugfixes. - - * grub-core/Makefile.core.def (ehci): New module. - * grub-core/bus/usb/ehci.c: New file. - * grub-core/bus/usb/usbhub.c (grub_usb_hub_add_dev): New arguments - port and hubaddr. All users updated. - Save port and hubaddr into dev structure. - * include/grub/cs5536.h (GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE): New - define. - * include/grub/pci.h (grub_dma_phys2virt): New function. - (grub_dma_virt2phys): Likewise. - * include/grub/usb.h (grub_usb_device): New members port and hubaddr. - -2012-01-31 Vladimir Serbinenko - - * grub-core/fs/fat.c (grub_fat_mount) [!MODE_EXFAT]: Remove fstype - check as some mkfs implementations omit it. - -2012-01-31 Vladimir Serbinenko - - * docs/grub.texi (Unicode): Mention identifier and space limitations. - -2012-01-31 Vladimir Serbinenko - - * grub-core/fs/jfs.c (grub_jfs_sblock): Make volname a char array. - Add new member volname2. - (grub_jfs_label): Use volname2 if available. - -2012-01-31 Vladimir Serbinenko - - * grub-core/fs/nilfs2.c (grub_nilfs2_super_block): Expand volume_name - over last_mounted as seen in image generated by mkfs.nilfs2. - (grub_nilfs2_label): Use sizeof for the size of s_volume_name. - -2012-01-31 Vladimir Serbinenko - - * grub-core/fs/fat.c (grub_fat_dir_entry) [MODE_EXFAT]: Expand label - to 15 UTF-16 characters as seen in FS generated by mkexfatfs. - (grub_fat_label) [MODE_EXFAT]: Use macros for size. - -2012-01-31 Vladimir Serbinenko - - * grub-core/fs/romfs.c (grub_romfs_mount): Fix a bug with labels going - over the sector. - -2012-01-31 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (get_filesystem_dnode): Support space in - subvolume name (by removing a bogus and useless check). - -2012-01-31 Vladimir Serbinenko - - * grub-core/fs/ext2.c (grub_ext2_label): Fix field size. Change to - sizeof while on it. - -2012-01-30 Vladimir Serbinenko - - * grub-core/disk/scsi.c (grub_scsi_read_capacity): Renamed to ... - (grub_scsi_read_capacity10): ... this. - (grub_scsi_read_capacity16): New function. - (grub_scsi_open): Use read_capacity16 if read_capacity10 returned - 0xffffffff. - Fix off-by-one error. - * include/grub/scsi.h (grub_scsi): Rename size to last_block and make it - 64-bit unsigned. - * include/grub/scsicmd.h (grub_scsi_read_capacity): Rename to ... - (grub_scsi_read_capacity10): ... this. - (grub_scsi_read_capacity_data): Rename to ... - (grub_scsi_read_capacity10_data): ... this. Rename size to last_block. - (grub_scsi_read_capacity16): New struct. - (grub_scsi_read_capacity16_data): Likewise. - (grub_scsi_cmd_t): Rename grub_scsi_cmd_read_capacity to - grub_scsi_cmd_read_capacity10. - New command grub_scsi_cmd_read_capacity16. - -2012-01-30 Vladimir Serbinenko - - SCSI >2TiB support. - - * grub-core/disk/scsi.c (grub_scsi_read16): New function. - (grub_scsi_write16): Likewise. - (grub_scsi_read): Use read16 when necessary. - (grub_scsi_write): Likewise. - * include/grub/scsicmd.h (grub_scsi_read16): New struct. - (grub_scsi_write16): Likewise. - (grub_scsi_cmd_t): Add READ16 and WRITE16. - -2012-01-30 Vladimir Serbinenko - - SCSI write support (for usbms mainly). - - * grub-core/disk/scsi.c (grub_scsi_write10): Uncomment. Make buffer - a const pointer. - (grub_scsi_write): Implement. - * include/grub/scsi.h (grub_scsi_dev): Make write buffer a const pointer - -2012-01-30 Vladimir Serbinenko - - * grub-core/io/lzopio.c (uncompress_block): Fix use of incorrect - variable. - -2012-01-29 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/string.h (memchr): New function. - -2012-01-29 Vladimir Serbinenko - - * po/POTFILES.in: Regenerate. - -2012-01-29 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/assert.h (assert_real): Replace grub_fatal - with grub_printf to avoid unnecessary fatal failure. - -2012-01-29 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/limits.h (SHRT_MAX): New define. - (INT_MAX): Likewise. - * grub-core/lib/posix_wrap/stdio.h (snprintf): New function. - * grub-core/lib/posix_wrap/stdlib.h (abs): Likewise. - * grub-core/lib/posix_wrap/string.h (memcmp): Likewise. - (strcpy): Likewise. - (strstr): Likewise. - (strchr): Likewise. - (strncpy): Likewise. - (strcat): Likewise. - (strncat): Likewise. - (strcoll): Likewise. - * include/grub/types.h (GRUB_SHRT_MAX): New define. - (GRUB_INT_MAX): Likewise. - -2012-01-29 Vladimir Serbinenko - - * grub-core/gnulib/regcomp.c (regerror): Don't use abort on - unexpected error. - (optimize_utf8): Likewise. - * grub-core/lib/posix_wrap/stdlib.h (abort): Removed. - -2012-01-29 Vladimir Serbinenko - - * grub-core/boot/i386/pc/lnxboot.S: Use - GRUB_DECOMPRESSOR_MAX_DECOMPRESSOR_SIZE. - * grub-core/boot/i386/pc/startup_raw.S: Ensure about boot_dev - location. - * include/grub/offsets.h (GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE): New - definition. - (GRUB_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE): Likewise. - -2012-01-29 Vladimir Serbinenko - - * util/getroot.c (grub_util_get_dm_node_linear_info): Fix memory leak. - * grub-core/disk/cryptodisk.c (cryptodisk_cleanup): Disable for - now to avoid double free. - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_dev): Rename to - hostdisk. - * include/grub/disk.h (grub_disk_dev_id): New id HOSTDISK. - * util/grub-probe.c (escape_of_path): Always return a new copy. - (print_full_name): Escape path. - (probe): Don't call grub_util_devname_to_ofpath on NULL. - Fix hints on abstractions. - -2012-01-29 Vladimir Serbinenko - - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): - Don't add "root" line if no compatibility hont is available. - Suggested by: Seth Goldberg. - -2012-01-29 Vladimir Serbinenko - - * include/grub/ata.h (grub_ata): Add a new element maxbuffer. - * grub-core/disk/ata.c (grub_ata_readwrite): Limit to ata->maxbuffer. - * grub-core/disk/pata.c (grub_pata_open): Set ata->maxbuffer. - * grub-core/disk/ahci.c (grub_ahci_open): Likewise. - -2012-01-29 Vladimir Serbinenko - - * include/grub/zfs/dnode.h (DN_MIN_INDBLKSHIFT): Removed. - -2012-01-29 Vladimir Serbinenko - - * util/grub-pe2elf.c (ehdr): Make static. - (shdr): Likewise. - (num_sections): Likewise. - (offset): Likewise. - -2012-01-29 Vladimir Serbinenko - - Eliminate ofpath limits and possible overflows. - - * util/ieee1275/ofpath.c (grub_util_info) [STANDALONE]: New function. - (OF_PATH_MAX): Removed. - (MAX_DISK_CAT): New const. - (find_obppath): Use allocated rather than preallocated buffer. - Return result. Argument of_path removed. All users updated. - Add missing fdstat. - (xrealpath): New function. - (block_device_get_sysfs_path_and_link): Remove sysfs argument. - Allocate rather than use preallocated buffer. All users updated. - (__of_path_common): Use allocated rather than preallocatecd buffer. - Return result. Argument of_path removed. All users updated. - (vendor_is_ATA): Read only needed part form the file. - (check_sas): Allocate depending on contents rather than fixed. - (main) [STANDALONE]: Handle NULL result. - -2012-01-29 Vladimir Serbinenko - - * grub-core/normal/completion.c (iterate_dev): Close the disk. - -2012-01-29 Vladimir Serbinenko - - Cryptodisk write support. - - * grub-core/disk/cryptodisk.c (grub_crypto_pcbc_encrypt): New function. - (grub_cryptodisk_decrypt): Moved logic to ... - (grub_cryptodisk_endecrypt): ...this. New argument "encrypt". - (grub_cryptodisk_write): Implement. - * grub-core/kern/emu/hostdisk.c (nwrite): Rename to ... - (grub_util_fd_write): ... this. Make global. - * include/grub/emu/hostdisk.h (grub_util_fd_write): New proto. - -2012-01-29 Vladimir Serbinenko - - * include/grub/list.h (grub_list_remove): Don't crash if element is - removed twice. - -2012-01-29 Vladimir Serbinenko - - Rename ofconsole to console. - - * grub-core/commands/terminal.c (handle_command): Handle ofconsole - as sysnonym to console. - * grub-core/term/ieee1275/ofconsole.c: Renamed to .. - * grub-core/term/ieee1275/console.c: ... this. All users updated. - Rename grub_ofconsole_ to grub_console_. All users updated - (grub_console_term_output): Rename "ofconsole" to "console". - * grub-core/term/terminfo.c (grub_cmd_terminfo): Handle "ofconsole" - as "console". - -2012-01-29 Vladimir Serbinenko - - * grub-core/loader/i386/pc/plan9.c (grub_cmd_plan9): Remove PXE - handling. - * include/grub/disk.h (grub_disk_dev_id): Remove obsolete - GRUB_DISK_DEVICE_UUID_ID, GRUB_DISK_DEVICE_PXE_ID and - GRUB_DISK_DEVICE_FILE_ID. - -2012-01-29 Vladimir Serbinenko - - * grub-core/kern/partition.c (grub_partition_get_name): Simplify logic - and improve performance. - -2012-01-29 Vladimir Serbinenko - - * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_encode_devname): Fix - missing ieee1275/ prefix on whole disk. - -2012-01-29 Vladimir Serbinenko - - * include/grub/powerpc/ieee1275/util/biosdisk.h: Remove. - * include/grub/powerpc/ieee1275/biosdisk.h: Likewise. - -2012-01-29 Vladimir Serbinenko - - * grub-core/fs/cpio.c (handle_symlink): Fix a bug. - -2012-01-29 Vladimir Serbinenko - - Merge common RAID and LVM logic to an abstract diskfilter. - Add LDM support using the same framework. - - * Makefile.util.def (libgrubkern): Add grub-core/disk/ldm.c, - grub-core/disk/diskfilter.c and grub-core/partmap/gpt.c. - (libgrubmods): Remove grub-core/disk/raid.c and - grub-core/partmap/gpt.c. - * grub-core/Makefile.core.def (ldm): New module. - (raid): Renamed to diskfilter. All users updated. - * grub-core/disk/raid.c: Moved to ... - * grub-core/disk/diskfilter.c: ... here. - * grub-core/disk/diskfilter.c: Rename grub_raid_ to grub_diskfilter_. - (lv_num): New var. - (find_array): Renamed to ... - (find_lv): ... this. Support multi-LV. Skip nameless LVs - (grub_is_array_readable): Renamed to ... - (grub_is_lv_readable): ... this. Support multinode hierarchy. - (insert_array): New argument id. - (is_node_readable): New function. - (scan_device): Rename to ... - (scan_disk): .. this. Restrict to one disk. - (scan_devices): New function. - (grub_diskfilter_iterate): Support multi-LV. - Skip invisible and nameless LVs. - (grub_diskfilter_memberlist): Support multi-LV. - (grub_diskfilter_read_node): New function. - (grub_raid_read): Most of logic moved to ... - (read_segment): ... here - (read_lv): New function. - (grub_diskfilter_get_vg_by_uuid): New function. - (grub_diskfilter_make_raid): Likewise. - * grub-core/disk/ldm.c: New file. - * grub-core/disk/lvm.c (vg_list): Removed. - (lv_count): Likewise. - (scan_depth): Likewise. - (is_lv_readable): Likewise. - (grub_lvm_getvalue): Advance pointer past the number. - (find_lv): Removed. - (do_lvm_scan): Refactored into ... - (grub_lvm_detect): ... this. Support raid. - (grub_lvm_iterate): Removed. - (grub_lvm_memberlist): Likewise. - (grub_lvm_open): Likewise. - (grub_lvm_close): Likewise. - (read_lv): Likewise. - (read_node): Likewise. - (is_node_readable): Likewise. - (is_lv_readable): Likewise. - (grub_lvm_read): Likewise. - (grub_lvm_write): Likewise. - (grub_lvm_dev): Use diskfilter - (GRUB_MOD_INIT): Likewise. - (GRUB_MOD_FINI): Likewise. - * grub-core/disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Use - new interface. - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Likewise. - * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Likewise. - * grub-core/disk/raid5_recover.c (grub_raid5_recover): Use - grub_diskfilter_read_node. - Fix a bug with xor. - * grub-core/disk/raid6_recover.c (grub_raid6_recover): Use - grub_diskfilter_read_node. - Support GRUB_RAID_LAYOUT_MUL_FROM_POS. - * grub-core/kern/disk.c (grub_disk_dev_list): Make global. - (grub_disk_dev_iterate): Move from here... - * include/grub/disk.h (grub_disk_dev_iterate): ... to here. Inlined. - * grub-core/kern/emu/hostdisk.c (grub_hostdisk_find_partition_start): - Make global. - (grub_hostdisk_find_partition_start): Likewise. - (grub_hostdisk_os_dev_to_grub_drive): New function. - (grub_util_biosdisk_get_osdev): Check that disk is biosdisk. - * grub-core/kern/emu/hostdisk.c (make_device_name): Move to ... - * util/getroot.c (make_device_name): ... here. - * grub-core/kern/emu/hostdisk.c (grub_util_get_dm_node_linear_info): - Move to ... - * util/getroot.c (grub_util_get_dm_node_linear_info): ...here. - * grub-core/kern/emu/hostdisk.c - (convert_system_partition_to_system_disk): Move to ... - * util/getroot.c (convert_system_partition_to_system_disk): ...here. - * grub-core/kern/emu/hostdisk.c (device_is_wholedisk): Move to ... - * util/getroot.c (device_is_wholedisk): ... here. - * grub-core/kern/emu/hostdisk.c (find_system_device): Move to ... - * util/getroot.c (find_system_device): ... here. - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_present): - Move to ... - * util/getroot.c (grub_util_biosdisk_is_present): ...here. - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev): - Move to ... - * util/getroot.c (grub_util_biosdisk_get_grub_dev): ... here. - Handle LDM. - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): - Move to ... - * util/getroot.c (grub_util_biosdisk_is_floppy): ... here. - * grub-core/partmap/gpt.c (grub_gpt_partition_map_iterate): Made global. - * include/grub/disk.h (grub_disk_dev_id): Replaced RAID and LVM with - DISKFILTER. - * include/grub/raid.h: Renamed to ... - * include/grub/diskfilter.h: ... this. - * include/grub/diskfilter.h: Rename grub_raid_* to grub_diskfilter_* - (GRUB_RAID_LAYOUT_*): Make into array. - (GRUB_RAID_LAYOUT_MUL_FROM_POS): New value. - (grub_diskfilter_vg): New struct. - (grub_diskfilter_pv_id): Likewise. - (grub_raid_member): Removed. - (grub_raid_array): Likewise. - (grub_diskfilter_pv): New struct. - (grub_diskfilter_lv): Likewise. - (grub_diskfilter_segment): Likewise. - (grub_diskfilter_node): Likewise. - (grub_diskfilter_get_vg_by_uuid): New proto. - (grub_raid_register): Inline. - (grub_diskfilter_unregister): Likewise. - (grub_diskfilter_make_raid): New proto. - (grub_diskfilter_vg_register): Likewise. - (grub_diskfilter_read_node): Likewise. - (grub_diskfilter_get_pv_from_disk) [GRUB_UTIL]: Likewise. - * include/grub/emu/hostdisk.h (grub_util_get_ldm): New proto. - (grub_util_is_ldm): Likewise. - (grub_util_ldm_embed) [GRUB_UTIL]: Likewise. - (grub_hostdisk_find_partition_start): Likewise. - (grub_hostdisk_os_dev_to_grub_drive): Likewise. - * include/grub/gpt_partition.h (GRUB_GPT_PARTITION_TYPE_LDM): - New definition. - (grub_gpt_partition_map_iterate): New proto. - * include/grub/lvm.h (grub_lvm_vg): Removed. - (grub_lvm_pv): Likewise. - (grub_lvm_lv): Likewise. - (grub_lvm_segment): Likewise. - (grub_lvm_node): Likewise. - * util/getroot.c [...] - * util/grub-probe.c (probe_raid_level): Handle diskfilter. - (probe_abstraction): Likewise. - * util/grub-setup.c (setup): Remove must_embed. Support LDM. - (main): Remove dead logic. - -2012-01-28 Vladimir Serbinenko - - Simplify root device discover and don't fail when trying to open - incorrect devices. - - * grub-core/disk/efi/efidisk.c (get_diskname_from_path_real): New - function. - (get_diskname_from_path): Likewise. - (grub_efidisk_get_device_name): Use get_diskname_from_path instead - of iterating. - -2012-01-27 Vladimir Serbinenko - - * grub-core/Makefile.core.def (setpci): Enable on all PCI platforms. - -2012-01-27 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (nvlist_find_value): Check that we don't go - pastthe end. - -2012-01-27 Vladimir Serbinenko - - * util/grub-install.in: Add missing \. - Reported by: gentoofan - -2012-01-26 Vladimir Serbinenko - - * grub-core/fs/squash4.c (xz_decompress): Fix return value. - (direct_read): Use correct compressed size. - (grub_squash_read_data): Likewise. - -2012-01-26 Vladimir Serbinenko - - * docs/grub.texi (Platform limitations): New section. - (Platform-specific operations): Likewise. - * docs/grub-dev.texi (Porting): Likewise. - -2012-01-25 Vladimir Serbinenko - - IEEE1275 disk write support. - - * grub-core/kern/ieee1275/ieee1275.c (grub_ieee1275_write): Make buffer - const void *. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_write): Likewise. - * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_read): Move open - and seek loginc to ... - (grub_ofdisk_prepare): ... here. - (grub_ofdisk_write): Implement. - -2012-01-25 Vladimir Serbinenko - - ARC disk write support. - - * grub-core/disk/arc/arcdisk.c (handle_writable): New var. - (reopen): New argument writable. All users updated. - Handle required access mode. - (grub_arcdisk_write): Implement. - * include/grub/arc/arc.h (grub_arc_file_access): New enum. - (grub_arc_firmware_vector): Make buffer to write a const buffer. - -2012-01-25 Vladimir Serbinenko - - * grub-core/fs/btrfs.c (grub_btrfs_device): New field size. - (read_sblock): Don't attempt to read superblocks outside the disk size. - -2012-01-25 Vladimir Serbinenko - - * grub-core/fs/nilfs2.c (grub_nilfs2_load_sb): Use device size from - first superblock to find the second one when possible. - -2012-01-25 Vladimir Serbinenko - - * util/grub-install.in: Fix an ARC bug. - Print a warning if no platform-specific setup is available. - -2012-01-24 Vladimir Serbinenko - - Use static allocation rather than scratch pointer in reed_solomon. - It decreases its size significantly and avoids a variable in .text. - - * grub-core/lib/reed_solomon.c (scratch): Removed. - (chosenstat): New const or static array. - (sigma): Likewise. - (errpot): Likewise. - (errpos): Likewise. - (sy): Likewise. - (mstat): Likewise. - (errvals): Likewise. - (eqstat): Likewise. - (pol_evaluate): Replace x with log_x argument. All users updated. - (syndroms): Removed. - (gauss_solve): Use statically allocated arrays. - (rs_recover): Likewise. - Calculate syndroms directly. - (decode_block): Use statically allocated arrays. - (grub_reed_solomon_add_redundancy) [TEST]: Fix -DTEST compilation. - (main) [TEST]: Allow -DTEST -DSTANDALONE. - -2012-01-24 Vladimir Serbinenko - - Eliminate fixed limit on reed solomon decoder length. - - * grub-core/boot/i386/pc/lnxboot.S: Scan for multiboot signature - rather than hardcoding the address. - * grub-core/boot/i386/pc/startup_raw.S: Add new data field - no_reed_solomon_length. - Move gate_a20 to no-reed-solomon part. - Don't force a particular size of no reed-solomon part. - * include/grub/offsets.h (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): - Removed. - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH): New define. - * util/grub-setup.c (setup): Read no_rs_length from the image itself. - -2012-01-24 Vladimir Serbinenko - - * grub-core/commands/wildcard.c (match_files): Handle filenames - without explicit device. - (wildcard_expand): Don't add explicit device if not already present. - * tests/grub_script_echo1.in: Add a new expansion test. - -2012-01-24 Vladimir Serbinenko - - Replace single-linked with double-linked lists. It results in more - compact and more efficient code. - - * grub-core/kern/list.c (grub_list_push): Moved from here ... - * include/grub/list.h (grub_list_push): ... to here. Set prev. - (grub_list_remove): Moved from here ... - * include/grub/list.h (grub_list_remove): ... here. Use and set prev. - (grub_prio_list_insert): Set prev. - * include/grub/list.h (grub_list): Add prev. All users updated. - -2012-01-24 Vladimir Serbinenko - - Handle newer autotools. Add some missing quotes while on it. - - * Makefile.am (pkglib_DATA): Remove update-grub_lib. - (pkglib_DATA): Move grub-mkconfig_lib from here ... - (pkgdata_DATA): ... here. - * Makefile.util.def (update-grub_lib): Removed. - * conf/Makefile.common (pkglib_DATA): Removed. - (pkglib_SCRIPTS): Likewise. - (pkgdata_DATA): New variable. - * tests/util/grub-shell-tester.in: Replace pkglib with pkgdata where - needed. - Add missing quotes. - Remove unused variable while on it. - * tests/util/grub-shell.in: Likewise. - * util/grub-install.in: Likewise. - * util/grub-mkconfig.in: Likewise. - * util/grub-mknetdir.in: Likewise. - * util/grub-mkrescue.in: Likewise. - * util/grub-mkstandalone.in: Likewise. - * util/grub.d/00_header.in: Likewise. - * util/grub.d/10_hurd.in: Likewise. - * util/grub.d/10_illumos.in: Likewise. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/10_netbsd.in: Likewise. - * util/grub.d/10_windows.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - * util/grub.d/30_os-prober.in: Likewise. - * util/update-grub_lib.in: Removed. - -2012-01-24 Seth Goldberg - - * grub-core/net/drivers/i386/pc/pxe.c (grub_pxe_recv): Relax checks as - a workaround for intel problem. - -2012-01-23 Paulo de Rezende Pinatti -2012-01-23 Vladimir Serbinenko -2012-01-23 pfsmorigo - - * util/grub-install.in: Support dd'in into PreP partition. - * util/grub-probe.c (probe): Support discovering partition type. - (main): Support -t msdos_parttype. - -2012-01-23 Vladimir Serbinenko - - * grub-core/normal/crypto.c (grub_crypto_autoload): Prevent - infinite recursion using counter. - * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_init): Defer s->crc32 - init to skip it if the magic check fails. - (dec_stream_header): Init s->crc32. - -2012-01-22 Vladimir Serbinenko -2012-01-22 Zachary Bedell -2012-01-22 Richard Laager - - * grub-core/fs/zfs/zfs.c (uberblock_verify): New parameter size. - All users updated. - (find_bestub): Determine correct size. - (fill_vdev_info_real): Fill ashift. New argument. All users updated. - (scan_disk): Align the size down. - Call check pool before find_bestub to have ashift. - -2012-01-22 Vladimir Serbinenko - - * grub-core/lib/relocator.c (malloc_in_range): Remove couple of - dprintf in no-malloc zone. - -2012-01-22 Mario Limonciello - - * configure.ac: Add back in test for limits.h. - -2012-01-20 Vladimir Serbinenko - - Support 4K-sector NTFS. - - * include/grub/ntfs.h (GRUB_NTFS_MAX_MFT): Increase to 8. - (grub_ntfs_data): Remove blocksize. - * grub-core/fs/ntfs.c (fixup): Fix size comparison. - Remove data argument. All users updated. - -2012-01-20 Vladimir Serbinenko - - * grub-core/kern/mips/arc/init.c (grub_total_modules_size): Mark as - being in .text to avoid dprel references. - * include/grub/mips/loongson/kernel.h (grub_arch_machine): Likewise. - * include/grub/mips/loongson/memory.h (grub_arch_memsize): Likewise. - (grub_arch_highmemsize): Likewise. - * include/grub/mips/loongson/time.h (grub_arch_busclock): Likewise. - * include/grub/mips/qemu_mips/memory.h (grub_arch_memsize): Likewise. - * include/grub/mips/time.h (grub_arch_cpuclock): Likewise. - -2012-01-18 Vladimir Serbinenko - - Support powerpc with GCC that defines __PPC__ but not __powerpc__. - - * config.h.in (__powerpc__) [__PPC__ && !__powerpc__]: New definition. - * grub-core/lib/setjmp.S: Treat __PPC__ as equivalent to __powerpc__. - -2012-01-18 Vladimir Serbinenko - - * include/grub/datetime.h (grub_get_datetime_cmos): Don't define in - GRUB_UTIL. - (grub_set_datetime_cmos): Likewise. - -2012-01-18 Vladimir Serbinenko - - Make XZ compression parameters dependent on target and not host CPU. - - * configure.ac: Define GRUB_TARGET_CPU_XYZ series. - * grub-core/lib/xzembed/xz_config.h: Use GRUB_TARGET_CPU_XYZ. - -2012-01-18 Vladimir Serbinenko - - * grub-core/kern/powerpc/dl.c (grub_arch_dl_get_tramp_got_size): Remove - set but not used variable. - -2012-01-14 Vladimir Serbinenko - - * grub-core/fs/reiserfs.c (grub_reiserfs_uuid): Reject 0-uuid as - created when no uuid support is compiled into mkfs.reiser. - -2012-01-14 Vladimir Serbinenko - - * grub-core/fs/hfs.c (macroman_to_utf8): Convert / to :. - (utf8_to_macroman): Do the opposite. - * grub-core/fs/hfsplus.c (grub_hfsplus_iterate_dir): Convert / to :. - -2012-01-14 Vladimir Serbinenko - - * configure.ac: Refise build qemu_mips w/o unifont. - -2012-01-14 Vladimir Serbinenko - - Eliminate grub_min/grub_max prone to overflow usage. - - * grub-core/bus/usb/usbhub.c (grub_usb_add_hub): Eliminate grub_min. - (poll_nonroot_hub): Likewise. - * grub-core/fs/affs.c (grub_affs_iterate_dir): Likewise. - (grub_affs_label): Likewise. - * grub-core/fs/btrfs.c (grub_btrfs_lzo_decompress): Likewise. - * grub-core/fs/hfs.c (grub_hfs_dir): Likewise. - (grub_hfs_label): Likewise. - * grub-core/fs/hfsplus.c (grub_hfsplus_cmp_catkey): Likewise. - * grub-core/fs/zfs/zfs.c (MIN): Remove. - (zap_leaf_array_equal): Use grub_size. Remove MIN. - (zap_leaf_array_get): Likewise. - (dnode_get_path): Likewise. - * grub-core/io/lzopio.c (grub_lzopio_read): Eliminate grub_min. - * grub-core/io/xzio.c (grub_xzio_read): Likewise. - * grub-core/script/execute.c (grub_script_break): Likewise. - * grub-core/script/lexer.c (grub_script_lexer_record): Eliminate - grub_max. - * grub-core/script/yylex.l (grub_lexer_yyrealloc): Likewise. - * include/grub/misc.h (grub_min): Removed. - (grub_max): Likewise. - -2012-01-14 Samuel Thibault - - * grub-core/fs/ext2.c (grub_ext2_iterate_dir): Ignore entries with - direct.inode = 0. - -2012-01-14 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/wctype.h (CHARCLASS_NAME_MAX): New define. - -2012-01-14 Vladimir Serbinenko - - * include/grub/datetime.h (grub_datetime2unixtime): Fix offset. - -2012-01-14 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/stdlib.h (MB_CUR_MAX): Moved from here ... - * grub-core/lib/posix_wrap/wchar.h (MB_CUR_MAX): ... here. Value fixed. - -2012-01-14 Vladimir Serbinenko - - * grub-core/fs/fshelp.c (grub_fshelp_find_file): Use grub_strcasecmp - rather than a hack for grub_strncasemap. - -2012-01-14 Vladimir Serbinenko - - Support multiple initrds - Note: part of this was accidently committed in r3739. - - * grub-core/loader/i386/linux.c (grub_cmd_initrd): Support multiple - initrd. - * grub-core/loader/i386/pc/linux.c (grub_cmd_initrd): Likewise. - * grub-core/loader/ia64/efi/linux.c (grub_cmd_initrd): Likewise. - * grub-core/loader/mips/linux.c (grub_cmd_initrd): Likewise. - * grub-core/loader/powerpc/ieee1275/linux.c (grub_cmd_initrd): Likewise. - * grub-core/loader/sparc64/ieee1275/linux.c (grub_cmd_initrd): Likewise. - -2012-01-14 Vladimir Serbinenko - - * grub-core/disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Skip - disks with unknown size. - * grub-core/disk/raid.c (scan_devices): Allow disks with unknown sizes. - -2012-01-14 Vladimir Serbinenko - - Remove defines pertaining to arbitrary limits not affecting GRUB - anymore. - - * grub-core/fs/ext2.c (EXT2_PATH_MAX): Removed. - (EXT2_MAX_SYMLINKCNT): Likewise. - * grub-core/fs/nilfs2.c (NILFS_BTREE_LEVEL_MAX): Likewise. - * grub-core/net/tftp.c (TFTP_MAX_PACKET): Likewise. - * include/grub/i386/pc/pxe.h (GRUB_PXE_MIN_BLKSIZE): Likewise. - (GRUB_PXE_MAX_BLKSIZE): Likewise. - * include/grub/normal.h (GRUB_MAX_CMDLINE): Likewise. - * include/grub/zfs/dnode.h (DN_MAX_INDBLKSHIFT): Likewise. - (DN_MAX_OBJECT_SHIFT): Likewise. - (DN_MAX_OFFSET_SHIFT): Likewise. - (DN_MAX_OBJECT): Likewise. - (DNODES_PER_LEVEL_SHIFT): Likewise. - * include/grub/zfs/spa.h (SPA_MAXBLOCKSHIFT): Likewise. - (SPA_MAXBLOCKSIZE): Likewise. - (SPA_BLOCKSIZES): Likewise. - * include/grub/zfs/zap_impl.h (MZAP_MAX_BLKSHIFT): Likewise. - (MZAP_MAX_BLKSZ): Likewise. - -2012-01-14 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (grub_zfs_read): Remove useless alloc and - handle NULL appropriately. - Remove MIN. - -2012-01-13 Vladimir Serbinenko - - Fix efiemu. - - * grub-core/efiemu/runtime/efiemu.c: explicitly include right - cpu/types.h. - (efiemu_set_virtual_address_map): Remove UINT_TO_PTR. - * configure.ac: Fix efiemu check. - -2012-01-13 Vladimir Serbinenko - - * util/grub.d/30_os-prober.in: Fix occurence of grub-probe instead of - grub_probe. - Reported by: adamwill - -2012-01-12 Seth Goldberg - - * grub-core/lib/arg.c (grub_arg_parse): Fix NULL pointer dereference. - -2012-01-12 Vladimir Serbinenko - - Fix handling of wide characters in gfxterm. - - * grub-core/term/gfxterm.c (grub_colored_char): Remove width and index. - (clear_char): Likewise. - (paint_char): Skip code == NULL chars. - (grub_gfxterm_putchar): Set code = NULL on "shadowed" positions. - -2012-01-12 Vladimir Serbinenko - - * grub-core/normal/charset.c: Move comment to right place. - -2012-01-11 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_bblock): Revert flags. - (GRUB_AFFS_FLAG_FFS): Put back where it was. - (grub_affs_mount): Revert the correct version checking. - -2012-01-11 Vladimir Serbinenko - - * docs/grub.texi (Unicode): Mention several other unsupported features. - -2011-12-26 Vladimir Serbinenko - - * grub-core/fs/squash4.c (squash_mount): Mark endian conversion in - case statements as compile-time one. - (direct_read): Prevent spurious warnings. - (grub_squash_read_data): Likewise. - -2011-12-26 Vladimir Serbinenko - - Various squash4 fixes and LZO and XZ support. - - * Makefile.util.def (libgrubmods.a): Add xzembed directory to cppflags. - Add xzembed source files. - * grub-core/Makefile.core.def (squash4): Add xzembed and minilzo flags. - * grub-core/fs/squash4.c (grub_squash_super): New field compression. - (grub_squash_inode): New subtype long_dir. - (SQUASH_TYPE_LONG_DIR): New inode type. - (COMPRESSION): New enum. - (XZBUFSIZ): New const. - (grub_squash_data): New fields blksz, decompress, xzdec, xzbuf. - (read_chunk): Use data->decompress. - (zlib_decompress): New function. - (lzo_decompress): Likewise. - (xz_decompress): Likewise. - (squash_mount): Set new data fields. - (grub_squash_iterate_dir): Handle long dir. - (squash_unmount): Free xzdec and xzbuf. - (grub_squash_open): Check ino type. - (direct_read): Stylistic fixes. Use data->decompress. - (grub_squash_read_data): Likewise. - * grub-core/io/gzio.c (grub_gzio): Remove disk_input. - (get_byte): Likewise. - (grub_zlib_disk_read): Removed. - * grub-core/lib/posix_wrap/sys/types.h (ssize_t): New type. - (GRUB_POSIX_BOOL_DEFINED): New define. - * grub-core/lib/posix_wrap/unistd.h: Include sys/types.h. - * grub-core/lib/xzembed/xz.h: Addmissing includes. - [!GRUB_POSIX_BOOL_DEFINED]: Define bool. - * include/grub/deflate.h (grub_zlib_disk_read): Removed. - -2011-12-26 Vladimir Serbinenko - - Don't override more informative errors. - - * grub-core/commands/acpi.c (grub_cmd_acpi): Don't override errors. - * grub-core/font/font.c (open_section): Likewise. - * grub-core/loader/i386/bsd.c (grub_bsd_load_aout): New argument - filename. Don't override errors. - (grub_cmd_openbsd_ramdisk): Don't override errors. - * grub-core/loader/i386/linux.c (grub_cmd_linux): Likewise. - (grub_cmd_initrd): Likewise. - * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Likewise. - (grub_cmd_initrd): Likewise. - * grub-core/loader/ia64/efi/linux.c (grub_load_elf64): Likewise. - (grub_cmd_linux): Likewise. - (grub_cmd_initrd): Likewise. - (grub_cmd_payload): Likewise. - * grub-core/loader/mips/linux.c (grub_cmd_initrd): Likewise. - * grub-core/loader/multiboot.c (grub_cmd_multiboot): Likewise. - (grub_cmd_module): Likewise. - * grub-core/loader/powerpc/ieee1275/linux.c (grub_cmd_initrd): Likewise. - * grub-core/loader/sparc64/ieee1275/linux.c (grub_cmd_initrd): Likewise. - * grub-core/loader/xnu.c (grub_xnu_load_driver): Likewise. - (grub_cmd_xnu_mkext): Likewise. - (grub_cmd_xnu_ramdisk): Likewise. - (grub_xnu_check_os_bundle_required): Likewise. - (grub_xnu_load_kext_from_dir): Likewise. - (grub_cmd_xnu_kextdir): Likewise. - * grub-core/loader/xnu_resume.c (grub_xnu_resume): Likewise. - -2011-12-25 Vladimir Serbinenko - - * grub-core/fs/minix.c (grub_minix_mount) [MODE_MINIX3]: Treat 0xffff - as 1024 in block size field. Found on one of my test images. - Small optimisation while on it. - -2011-12-25 Vladimir Serbinenko - - * docs/grub.texi (Filesystems): Mention SFS as Latin1 filesystem. - * grub-core/fs/sfs.c (grub_sfs_mount): Fix a memory leak while on it. - (grub_sfs_iterate_dir): Convert Latin1 to UTF8. Stylistic and - performance fixes while on it. - (grub_sfs_close): Fix memory leak while on it. - (grub_sfs_label): Convert Latin1 to UTF-8. - -2011-12-25 Vladimir Serbinenko - - * grub-core/fs/hfs.c (grub_hfs_dir): Cap keylen to actually available - space to avoid overflows. - (grub_hfs_label): Convert from macroman to UTF-8. - -2011-12-25 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_label): Interpret label as latin1. - -2011-12-25 Vladimir Serbinenko - - * grub-core/normal/menu.c (menu_init): Don't stop menu init at gfxterm. - -2011-12-25 Vladimir Serbinenko - - * unicode: Import Unicode 6.0 data. - -2011-12-25 Vladimir Serbinenko - - * grub-core/term/gfxterm.c (grub_gfxterm_putchar): Don't set values - outside of range. - -2011-12-25 Vladimir Serbinenko - - Avoid cutting in the middle of UTF-8 character. - - * include/grub/charset.h (grub_getend): New function. - * grub-core/script/function.c (grub_script_function_find): Use - grub_getend. - * grub-core/normal/completion.c (add_completion): Likewise. - -2011-12-25 Vladimir Serbinenko - - * grub-core/normal/charset.c (grub_ucs4_to_utf8): Small stylistic fix. - (grub_bidi_line_logical_to_visual): Skip tags. They are deprecated. - * include/grub/unicode.h (GRUB_UNICODE_TAG_START): New enum value. - (GRUB_UNICODE_TAG_END): Likewise. - (GRUB_UNICODE_LAST_VALID): Likewise. - -2011-12-25 Vladimir Serbinenko - - * include/grub/unicode.h (grub_unicode_compact_range): Replace end with - len and make it smaller. All users updated. - * util/import_unicode.py: Put length and not end character. - Check length. - -2011-12-25 Vladimir Serbinenko - - Make better Unicode-compliant and unify some UTF-8 code pathes. - - * grub-core/normal/charset.c (grub_utf8_to_utf16): Don't eat possibly - valid character. - (grub_is_valid_utf8): Use grub_utf8_process. - Check resulting code range. - (grub_utf8_to_ucs4): Use grub_utf8_process. - * include/grub/charset.h (grub_utf16_to_utf8): Don't eat up a possibly - valid character. - -2011-12-25 Vladimir Serbinenko - - * grub-core/io/bufio.c (grub_bufio_read): Fix handling of corner cases. - -2011-12-25 Vladimir Serbinenko - - * docs/grub.texi (Filesystems): Mention AFS. - -2011-12-25 Vladimir Serbinenko - - * docs/grub.texi (Filesystems): Clarify restrictions. - (Regexp): Mention non-Unicode regexp behaviour. - (Other): Mention non-Unicode matching behaviour. - -2011-12-24 Vladimir Serbinenko - - Make HFS implementation use MacRoman. - - * grub-core/fs/hfs.c (MAX_UTF8_PER_MAC_ROMAN): New define. - (macroman): New const array. - (macroman_to_utf8): New function. - (utf8_to_macroman): Likewise. - (grub_hfs_find_dir): Use utf8_to_macroman. - (grub_hfs_dir): Use macroman_to_utf8. - Set case_insensitive. - -2011-12-24 Vladimir Serbinenko - - * docs/grub.texi (Filesystems): Add IEEE1275 full-path example. - -2011-12-24 Vladimir Serbinenko - - Integrate hints into autogeneration scripts. - - * docs/grub.texi (Filesystems): Add a hostdisk example. - * Makefile.util.def (grub-mkdevicemap): Remove ofpath. - (grub-probe): Add ofpath. - * gentpl.py: Remove group nosparc64. - * grub-core/commands/search.c (cache_entry): New struct. - (cache): New var. - (FUNC_NAME): Use and save cache. Fix handling of trailing comma. - * grub-core/commands/search_wrap.c (options): Add platform-specific - hint options. - (grub_cmd_search): Handle platform-specific hints. - (GRUB_MOD_INIT): Declare grub_cmd_search as accept_dash. - * grub-core/kern/emu/hostdisk.c (map): New field device_map. - (grub_util_biosdisk_data): Likewise. - (grub_util_biosdisk_open): Set device_map. - (read_device_map): Handle "" as indication of no map. - Set device_map. - (find_system_device): Add hostdisk/ prefix for autogenerated entries. - (grub_util_biosdisk_get_compatibility_hint): New function. - * grub-core/normal/main.c (features): Add feature_platform_search_hint. - * include/grub/emu/hostdisk.h - (grub_util_biosdisk_get_compatibility_hint): New proto. - * util/grub-install.in: Don't call grub-mkdevicemap. - Add platform-specific hint to load.cfg. - * util/grub-mkconfig.in: Don't call grub-mkdevicemap. - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Add - hints. Set root preliminary to compatibility hint, not to OS name. - * util/grub-probe.c (PRINT_*): Add hints. - (print): Make static. - (escape_of_path): New function. - (guess_bios_drive): Likewise. - (guess_efi_drive): Likewise. - (guess_baremetal_drive): Likewise. - (print_full_name): Likewise. - (probe): Handle hints. - (main): Likewise. - * util/ieee1275/devicemap.c: Removed. - * util/ieee1275/ofpath.c (find_obppath): Allow to fail. All users - updated. - (grub_util_devname_to_ofpath): Return NULL on failure. - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev): Fix - resource leak. - * util/getroot.c (grub_util_pull_device): Fix memory leak. - - * po/POTFILES.in: Regenerated. - - Allow purely long options - - * grub-core/lib/arg.c (SHORT_ARG_HELP): Removed. - (SHORT_ARG_USAGE): Likewise. - (grub_arg_show_help): Compare opt with help_options. - (parse_option): Receive opt as argument. If makes big simplificatons. - All users updated - -2011-12-24 Vladimir Serbinenko - - * grub-core/lib/libgcrypt_wrap/cipher_wrap.h (WORDS_BIGENDIAN): - Restructure to avoid warning. - -2011-12-24 Vladimir Serbinenko - - * util/grub-install.in: Account for possible escaped comma in device - name. - -2011-12-24 Vladimir Serbinenko - - * util/ieee1275/ofpath.c (of_path_of_ide): Fix address for secondary - channel. - -2011-12-24 Vladimir Serbinenko - - * grub-core/kern/ieee1275/openfw.c (grub_devalias_iterate): Fix - allocation and zero-setting. - (grub_ieee1275_get_devname): Check that alias is complete. - -2011-12-24 Vladimir Serbinenko - - * grub-core/kern/disk.c (grub_disk_read): Fix hook calling for - unaligned segments. - -2011-12-24 Vladimir Serbinenko - - * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): Add ieee1275/ - prefix. - (grub_ofdisk_open): Check and discard ieee1275 prefix. - * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_encode_devname): - Add ieee1275 prefix. - -2011-12-23 Vladimir Serbinenko - - * docs/grub.texi (Filesystems): Update. - -2011-12-23 Vladimir Serbinenko - - Support odc, newc and bigendian cpio formats. - - * Makefile.util.def (libgrubmods): Add odc.c, newc.c and cpio_be.c. - * grub-core/Makefile.core.def (newc): New module. - (odc): Likewise. - (cpio_be): Likewise. - * grub-core/fs/cpio.c (ALIGN_CPIO): New macro. - (MAGIC): Likewise. - (MAGIC2): Likewise. - (head) [MODE_ODC]: Adapt for the format. - (head) [MODE_NEWC]: Likewise. - (head) [!MODE_*]: Write fields of interest as arrays. - (MAGIC_USTAR): Removed. - (read_number) [MODE_NEWC]: Change to hex. - (read_number) [!MODE_*]: Parse binary arrays. - (grub_cpio_find_file): Factor out the code for better structure and - always use read_number. - (grub_cpio_mount): Use MAGIC and MAGIC2. - (grub_cpio_dir): Exit on first hook non-0 return. - (grub_cpio_fs) [MODE_ODC]: Set name to odc. - (grub_cpio_fs) [MODE_NEWC]: Set name to newc. - (GRUB_MOD_INIT) [MODE_ODC]: Set name to odc. - (GRUB_MOD_INIT) [MODE_NEWC]: Set name to newc. - (GRUB_MOD_FINI) [MODE_ODC]: Set name to odc. - (GRUB_MOD_FINI) [MODE_NEWC]: Set name to newc. - * grub-core/fs/newc.c: New file. - * grub-core/fs/odc.c: Likewise. - * grub-core/fs/cpio_be.c: Likewise. - -2011-12-23 Vladimir Serbinenko - - Fix handling of tar numbers occupying the whole field. - - * grub-core/fs/cpio.c (read_number): New function. - (grub_cpio_find_file): Use read_number instead of strtoull. - -2011-12-23 Vladimir Serbinenko - - * grub-core/fs/cpio.c (grub_cpio_find_file): Fix handling of names - occupying the whole field size. - -2011-12-23 Lukas Anzinger - - * util/grub-mkconfig_lib.in (version_test_gt): Fix variable names. - -2011-12-23 Vladimir Serbinenko - - * grub-core/net/net.c (grub_cmd_delroute): Add missing out condition. - -2011-12-23 Seth Goldberg - - * grub-core/Makefile.core.def (lzma_decompress): Add missing - TARGET_IMG_LDFLAGS. - -2011-12-23 Vladimir Serbinenko - - * util/getroot.c (ESCAPED_PATH_MAX): New define. - (mountinfo_entry): Increase the field size to take escaping into - account. - (find_root_device_from_libzfs): Add one byte to size of strings for - security. - -2011-12-23 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c (grub_reed_solomon_add_redundancy): Add - an assert. - * util/grub-setup.c (setup): Likewise. - -2011-12-23 Vladimir Serbinenko - - * grub-core/boot/i386/pc/startup_raw.S: Add missing argument for - _LzmaDecodeA. - -2011-12-22 Vladimir Serbinenko - - * docs/grub.texi (Internationalisation): New section. - -2011-12-22 Vladimir Serbinenko - - * docs/grub.texi (Loopback booting): New section. - -2011-12-22 Keshav P R - - * util/grub-mkstandalone.in: Fix minor typo errors. - -2011-12-20 Vladimir Serbinenko - - IPv6, TCP, HTTP, ICMP and DNS support. Several cleanups and bugfixes. - - * grub-core/Makefile.core.def (net): Add net/dns.c, net/tcp.c, - net/icmp.c and net/icmp6.c. - (http): New module. - (priority_queue): Likewise. - * grub-core/io/bufio.c: Rewritten. - * grub-core/lib/legacy_parse.c (legacy_command): New argument type - TYPE_WITH_CONFIGFILE_OPTION. - (legacy_commands): Add bootp and dhcp. - (is_option): Handle TYPE_WITH_CONFIGFILE_OPTION. - (grub_legacy_parse): Likewise. - * grub-core/lib/priority_queue.c: New file. - * grub-core/net/arp.c: Add missing license header. - (arp_find_entry): Removed. - (arp_find_entry): Likewise. - (grub_net_arp_resolve): Rename to ... - (grub_net_arp_send_request): ...this. - (grub_net_arp_receive): New card argument. - * grub-core/net/bootp.c (parse_dhcp_vendor): Clean up. - Set router and DNS server. - (grub_net_configure_by_dhcp_ack): Handle routing information. - (grub_cmd_bootp): Set checksum. - (grub_bootp_init): Remove net_dhcp. - * grub-core/net/dns.c: New file. - * grub-core/net/drivers/efi/efinet.c (send_card_buffer): Wait for - completion. - (get_card_packet): Handle allocation. - (grub_efinet_findcards): Set mtu. - * grub-core/net/drivers/emu/emunet.c: Add missing license header. - (get_card_packet): Handle allocation. - (emucard): Set mtu. - * grub-core/net/drivers/i386/pc/pxe.c (grub_pxe_recv): Handle allocation - (GRUB_MOD_INIT): Set mtu. - * grub-core/net/drivers/ieee1275/ofnet.c (grub_ofnetcard_data): Remove - mtu. - (get_card_packet): Handle allocation. - (grub_ofnet_findcards): Set mtu. - * grub-core/net/ethernet.c (send_ethernet_packet): Add compile time - assert. - (grub_net_recv_ethernet_packet): Handle IPv6. - * grub-core/net/http.c: New file. - * grub-core/net/icmp.c: Likewise. - * grub-core/net/icmp6.c: Likewise. - * grub-core/net/ip.c (ip6addr): New type. - (ip6hdr): Likewise. - (reassemble): Likewise. - (cmp): New function. - (reassembles): New variable. - (grub_net_ip_chksum): Handle 0xffff sum and unaligned buffers. - (id): New variable. - (send_fragmented): New function. - (grub_net_send_ip_packet): Rename to ... - (grub_net_send_ip4_packet): ... this. Send fragmented if needed. - Handle non-UDP. - (grub_net_recv_ip_packets): Rename to ... - (handle_dgram): ... this. Check checksum. Handle non-UDP. - (free_rsm): New function. - (free_old_fragments): Likewise. - (grub_net_recv_ip4_packets): New function. - (grub_net_send_ip6_packet): Likewise. - (grub_net_send_ip_packet): Likewise. - (grub_net_recv_ip6_packets): Likewise. - (grub_net_recv_ip_packets): Likewise. - * grub-core/net/net.c (grub_net_link_layer_entry): New struct. - (LINK_LAYER_CACHE_SIZE): New const. - (link_layer_find_entry): New function. - (grub_net_link_layer_add_address): Likewise. - (grub_net_link_layer_resolve_check): Likewise. - (grub_net_link_layer_resolve): Likewise. - (grub_net_ipv6_get_slaac): Likewise. - (grub_net_ipv6_get_link_local): Likewise. - (grub_cmd_ipv6_autoconf): Likewise. - (parse_ip): Handle one number representation. - (parse_ip6): New functoion. - (match_net): Handle IPv6. - (grub_net_resolve_address): Handle IPv6 and DNS. - (grub_net_resolve_net_address): Handle IPv6. - (route_cmp): New function. - (grub_net_route_address): Find best route. - (grub_net_addr_to_str): Handle IPv6. - (grub_net_addr_cmp): New function. - (grub_net_add_addr): Register local route. - (print_net_address): Handle net address. - (grub_net_poll_cards): Retransmit TCP. - (grub_net_poll_cards_idle_real): Likewise. - (have_ahead): New function. - (grub_net_seek_real): Use underlying seek. - (GRUB_MOD_INIT): Register net_ipv6_autoconf and init dns. - * grub-core/net/tcp.c: New file. - * grub-core/net/tftp.c (tftp_data): Add priority_queue. - (cmp): New function. - (ack): Likewise. - (tftp_receive): Handle unordered input. - (destroy_pq): New function. - (tftp_close): Close pq. - * grub-core/net/udp.c: Put missing license header. - (grub_net_udp_socket): New function. - (udp_socket_register): Likewise. - (grub_net_udp_close): Likewise. - (grub_net_recv_udp_packet): Check checksum. - * include/grub/efi/api.h (grub_efi_simple_network): Add status. - * include/grub/misc.h (grub_memchr): New function. - * include/grub/net.h (GRUB_NET_*_SIZE): New enum. - (grub_net_card_driver): Return buf in recv. - (grub_net_slaac_mac_list): New struct. - (grub_network_level_protocol_id): Add ipv6. - (grub_net_network_level_addr): Likewise. - (grub_net_network_level_net_addr): Likewise. - (grub_net_app_protocol): Add seek. - (grub_net_socket): Removed. - (grub_net_sockets): Likewise. - (grub_net_socket_register): Likewise. - (grub_net_socket_unregister): Likewise. - (FOR_NET_SOCKETS): Likewise. - (grub_net_add_addr): Add const. - (GRUB_NET_BOOTP_*): New enum. - (grub_net_addr_cmp): New proto. - (GRUB_NET_MAX_STR_ADDR_LEN): Take IPV6 into account. - (GRUB_NET_MAX_STR_HWADDR_LEN): New define. - (grub_net_hwaddr_to_str): NEw proto. - (FOR_NET_NETWORK_LEVEL_INTERFACES): New macro. - (FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE): Handle NULL. - (grub_dns_init): New proto. - (grub_dns_fini): Likewise. - (grub_net_tcp_retransmit): Likewise. - (grub_net_link_layer_add_address): Likewise. - (grub_net_link_layer_resolve_check): Likewise. - (grub_net_link_layer_resolve): Likewise. - (grub_net_dns_lookup): Likewise. - (grub_net_add_dns_server): Likewise. - (grub_net_remove_dns_server): Likewise. - (GRUB_NET_TRIES): New const. - (GRUB_NET_INTERVAL): Likewise. - * include/grub/net/arp.h: Mostly rewritten. - * include/grub/net/ethernet.h (grub_net_ethertype_t): New enum. - * include/grub/net/ip.h: Mostly rewritten. - * include/grub/net/netbuff.h: Indent. - * include/grub/net/tcp.h: New file. - * include/grub/net/udp.h: Mostly rewritten. - * include/grub/priority_queue.h: New file. - * include/grub/types.h (PRIdGRUB_SSIZE): New define. - (grub_swap_bytes64_compile_time): Likewise. - (grub_cpu_to_be16_compile_time): Likewise. - (grub_cpu_to_be32_compile_time): Likewise. - (grub_cpu_to_be64_compile_time): Likewise. - (grub_be_to_cpu64_compile_time): Likewise. - -2011-12-16 Vladimir Serbinenko - - * grub-core/commands/i386/pc/drivemap.c (int13slot): Replace - UINT_TO_PTR with cast. - -2011-12-15 Vladimir Serbinenko - - * util/import_gcry.py: Skip _gcry_rmd160_mixblock and serpent_test. We - don't use them. - -2011-12-15 Vladimir Serbinenko - - * util/import_gcry.py: Don't add include camellia.h to camellia.c. It's - already there. - -2011-12-15 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Clean multiboot header to avoid - confusing ipxe. - -2011-12-15 Vladimir Serbinenko - - * grub-core/lib/libgcrypt/cipher/md4.c (transform) [WORDS_BIGENDIAN]: - Add missing const attribute. - * grub-core/lib/libgcrypt/cipher/md5.c (transform) [WORDS_BIGENDIAN]: - Likewise. - * grub-core/lib/libgcrypt/cipher/rmd160.c (transform) [WORDS_BIGENDIAN]: - Likewise. - -2011-12-15 Vladimir Serbinenko - - * grub-core/lib/libgcrypt/cipher/serpent.c (serpent_key_prepare): Fix - misaligned access. - (serpent_setkey): Likewise. - (serpent_encrypt_internal): Likewise. - (serpent_decrypt_internal): Likewise. - (serpent_encrypt): Don't put an alignment-increasing cast. - (serpent_decrypt): Likewise. - (serpent_test): Likewise. - -2011-12-15 Vladimir Serbinenko - - * grub-core/loader/multiboot.c (grub_cmd_module): Fix target address. - -2011-12-15 Vladimir Serbinenko - - Replace UINT_TO_PTR and PTR_TO_UINT with explicit grub_addr_t casts. - - * include/grub/types.h (UINT_TO_PTR): Removed. All users switched to - grub_addr_t casts. - (PTR_TO_UINT64): Likewise. - (PTR_TO_UINT32): Likewise. - -2011-12-15 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Decrease the higher limit - because of stack. - * util/grub-setup.c (setup): Don't add redundancy past the higher load - limit. - -2011-12-15 Vladimir Serbinenko - - * grub-core/gfxmenu/gui_label.c (label_paint): Handle the case - text_width > available width a bit more gracefully. - -2011-12-15 Vladimir Serbinenko - - * grub-core/loader/i386/bsdXX.c (grub_freebsd_load_elfmodule): Fix - current address calculation. - -2011-12-15 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c (decode_block): Allocate on heap and not - stack. - (encode_block): Likewise. - -2011-12-15 Vladimir Serbinenko - - * grub-core/boot/i386/pc/startup_raw.S: Clear direction flag for - certainety. - -2011-12-15 Vladimir Serbinenko - - * grub-core/boot/i386/pc/startup_raw.S: Move realmode routines to - non-RS part to avoid RS messing with GDT. - * include/grub/offsets.h (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): - Increase to suit in realmode routines. - -2011-12-15 Vladimir Serbinenko - - * grub-core/kern/i386/realmode.S: Increase alignment. - * grub-core/boot/i386/pc/startup_raw.S: Likewise. - -2011-12-14 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c (init_powx): Set gf_powx_inv[0] just to - be deterministic. - (syndroms): Compute 0 syndrom. - (rs_recover): Use 0 syndrom. - -2011-12-14 Vladimir Serbinenko - - * include/grub/kernel.h (FOR_MODULES): Make it a bit faster. - -2011-12-14 Vladimir Serbinenko - - * include/grub/types.h (GRUB_PROPERLY_ALIGNED_ARRAY): Add missing - brackets. - -2011-12-14 Vladimir Serbinenko - - * grub-core/gfxmenu/widget-box.c (get_left_pad): Take corners into - account. - (get_top_pad): Likewise. - (get_right_pad): Likewise. - (get_bottom_pad): Likewise. - -2011-12-14 Vladimir Serbinenko - - * grub-core/gfxmenu/gui_list.c (draw_menu): Don't use assignment in if. - -2011-12-14 Vladimir Serbinenko - - * include/grub/efi/api.h (grub_efi_memory_descriptor): Add packed - attribute as the structure isn't guaranteed to be properly aligned. - (grub_efi_pci_device_path): Likewise. - (grub_efi_pccard_device_path): Likewise. - (grub_efi_memory_mapped_device_path): Likewise. Additionaly explicitly - specify the size of `memory_type'. - (grub_efi_vendor_device_path): Likewise. - (grub_efi_controller_device_path): Likewise. - (grub_efi_acpi_device_path): Likewise. - (grub_efi_expanded_acpi_device_path): Likewise. - (grub_efi_atapi_device_path): Likewise. - (grub_efi_scsi_device_path): Likewise. - (grub_efi_fibre_channel_device_path): Likewise. - (grub_efi_1394_device_path): Likewise. - (grub_efi_usb_device_path): Likewise. - (grub_efi_usb_class_device_path): Likewise. - (grub_efi_i2o_device_path): Likewise. - (grub_efi_mac_address_device_path): Likewise. - (grub_efi_ipv4_device_path): Likewise. - (grub_efi_ipv6_device_path): Likewise. - (grub_efi_infiniband_device_path): Likewise. - (grub_efi_uart_device_path): Likewise. - (grub_efi_vendor_messaging_device_path): Likewise. - (grub_efi_hard_drive_device_path): Likewise. - (grub_efi_cdrom_device_path): Likewise. - (grub_efi_vendor_media_device_path): Likewise. - (grub_efi_file_path_device_path): Likewise. - (grub_efi_protocol_device_path): Likewise. - (grub_efi_piwg_device_path): Likewise. - (grub_efi_bios_device_path): Likewise. - -2011-12-14 Vladimir Serbinenko - - * include/grub/charset.h (grub_utf16_to_utf8): Make src a const pointer. - (grub_ucs4_to_utf8_alloc): Likewise. - (grub_ucs4_to_utf8): Likewise. - * grub-core/normal/charset.c (grub_ucs4_to_utf8): Likewise. - (grub_ucs4_to_utf8_alloc): Likewise. - -2011-12-14 Vladimir Serbinenko - - AFFS never uses unicode. - - * include/grub/charset.h (GRUB_MAX_UTF8_PER_LATIN1): New const. - (grub_latin1_to_utf8): New inline function. - * grub-core/fs/affs.c (grub_affs_iterate_dir): Convert latin1 to UTF8. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/romfs.c (grub_romfs_mount): Fix pointer comparison - overflow. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/squash4.c (grub_squash_inode): Fix field sizes. - (grub_squash_dirent_header): Likewise. - (read_chunk): Don't double swap. - (grub_squash_iterate_dir): Fix swap sizes. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/jfs.c (grub_jfs_getent): Handle UTF16 endianness. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/hfs.c (grub_hfs_find_node): Handle unaligned keys. - (grub_hfs_iterate_dir): Likewise. - -2011-12-13 Vladimir Serbinenko - - Fix video on platforms where unaligned access is forbidden. - Make several optimisations while on it. - - * grub-core/video/fb/fbblit.c (grub_video_fbblit_replace_directN): - Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. - (grub_video_fbblit_replace_32bit_1bit): Likewise. - (grub_video_fbblit_replace_24bit_1bit) [!GRUB_HAVE_UNALIGNED_ACCESS]: - Disable. - (grub_video_fbblit_replace_16bit_1bit): - Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. - (grub_video_fbblit_replace_8bit_1bit): Likewise. - (grub_video_fbblit_replace_BGRX8888_RGBX8888): Likewise. - (grub_video_fbblit_replace_BGRX8888_RGB888): Likewise. - (grub_video_fbblit_replace_BGR888_RGBX8888): Likewise. - (grub_video_fbblit_replace_BGR888_RGBX8888): Likewise. - (grub_video_fbblit_replace_BGR888_RGB888): Likewise. - (grub_video_fbblit_replace_RGBX8888_RGB88): Likewise. - (grub_video_fbblit_replace_RGB888_RGBX888): Likewise. - (grub_video_fbblit_replace_RGB888_RGBX8888): Likewise. - (grub_video_fbblit_replace_index_RGBX8888): Likewise. - (grub_video_fbblit_replace_index_RGB888): Likewise. - (grub_video_fbblit_blend_BGRA8888_RGBA8888): Likewise. - (grub_video_fbblit_blend_BGR888_RGBA8888): Likewise. - (grub_video_fbblit_blend_RGBA8888_RGBA8888): Likewise. - (grub_video_fbblit_blend_RGB888_RGBA8888): Likewise. - (grub_video_fbblit_blend_index_RGBA8888): Likewise. - (grub_video_fbblit_blend_XXXA8888_1bit): Likewise. - (grub_video_fbblit_blend_XXX888_1bit) [!GRUB_HAVE_UNALIGNED_ACCESS]: - Disable. - (grub_video_fbblit_blend_XXX565_1bit): - Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. - * grub-core/video/fb/fbfill.c (grub_video_fbfill_direct32): Likewise. - * grub-core/video/fb/fbutil.c (grub_video_fb_get_video_ptr): Return - void *. - * grub-core/video/fb/video_fb.c (common_blitter) - [!GRUB_HAVE_UNALIGNED_ACCESS]: Skip disabled blitters. - (grub_video_fb_create_render_target_from_pointer) - [!GRUB_HAVE_UNALIGNED_ACCESS]: Check alignment. - * include/grub/fbutil.h (grub_video_fb_get_video_ptr): Return void *. - * include/grub/i386/types.h (GRUB_HAVE_UNALIGNED_ACCESS): New - definition. - * include/grub/x86_64/types.h (GRUB_HAVE_UNALIGNED_ACCESS): Likewise. - -2011-12-13 Vladimir Serbinenko - - * grub-core/kern/sparc64/dl.c (grub_arch_dl_relocate_symbols): Support - HH22 and HM10 relocations. - -2011-12-13 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_vsnprintf_real): Fix fmt2 parsing. - -2011-12-13 Vladimir Serbinenko - - * grub-core/commands/videotest.c (grub_cmd_videotest): Check that - allocation succeeded. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/iso9660.c (grub_iso9660_convert_string): Make first - argument a u8 pointer. All users updated. - Handle unaligned buffers. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Force inlining of - add_part to workaround compiler bug. - -2011-12-13 Vladimir Serbinenko - - * include/grub/kernel.h (FOR_MODULES): Preserve alignment invariants. - -2011-12-13 Vladimir Serbinenko - - * grub-core/loader/multiboot_mbi2.c (grub_multiboot_add_elfsyms): - Reserve alignment invariants. - (grub_multiboot_load): Likewise. - (retrieve_video_parameters): Likewise. - (grub_multiboot_make_mbi): Likewise. - -2011-12-13 Vladimir Serbinenko - - * grub-core/loader/i386/xnu.c (grub_xnu_devprop_remove_property): Fix - incorrect pointer. - -2011-12-13 Vladimir Serbinenko - - * grub-core/disk/pata.c (grub_pata_pio_read): Handle unaligned buffer. - (grub_pata_pio_write): Likewise. - -2011-12-13 Vladimir Serbinenko - - Add noreturn attributes and remove unreachable code. - - * grub-core/bus/cs5536.c (grub_cs5536_smbus_wait): Remove unreachable - code. - * grub-core/commands/halt.c (grub_cmd_halt): Remove unreachable - code. Mark as noreturn. - * grub-core/commands/minicmd.c (grub_mini_cmd_exit): Likewise. - * grub-core/commands/reboot.c (grub_cmd_reboot): Likewise. - * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Remove - unreachable code. - * grub-core/kern/main.c (grub_main): Mark as noreturn. - * grub-core/kern/rescue_reader.c (grub_rescue_run): Likewise. - * grub-core/lib/posix_wrap/stdlib.h (abort): Likewise. - * grub-core/normal/menu.c (run_menu): Remove unreachable code. - * include/grub/kernel.h (grub_main): Mark as noreturn. - * include/grub/reader.h (grub_rescue_run): Likewise. - -2011-12-13 Vladimir Serbinenko - - * include/grub/i386/qemu/memory.h (grub_machine_mmap_init): Remove - redundant declaration. - -2011-12-13 Vladimir Serbinenko - - * include/grub/net.h (grub_net_network_level_interfaces): Remove - redundant declaration. - (FOR_NET_NETWORK_LEVEL_INTERFACES): Move to appropriate place. - -2011-12-13 Vladimir Serbinenko - - * grub-core/commands/hdparm.c (le16_to_char): Make src and dest uint16 * - to ensure alignment. - (grub_hdparm_print_identify): Make argument uint16 * to ensure - alignment. Ensure tmp alignment. - (grub_cmd_hdparm): Ensure buf alignment. - * grub-core/disk/ata.c (grub_ata_strncpy): Make src and dest uint16 * - to ensure alignment. - (grub_ata_dumpinfo): Ensure text alignment. - (grub_atapi_identify): Preserve alignment invariant. - (grub_ata_identify): Likewise. Use grub_get_unaligned32 when necessary. - -2011-12-13 Vladimir Serbinenko - - * include/grub/emu/misc.h (xasprintf): Add missing format attribute. - * include/grub/mips/kernel.h (grub_halt): Remove redundant declaration. - * include/grub/mips/qemu_mips/kernel.h (grub_halt): Likewise. - * include/grub/misc.h (grub_reboot) - [GRUB_MACHINE_EMU || GRUB_MACHINE_QEMU_MIPS]: Export. - (grub_halt) [__mips__]: Likewise. - -2011-12-13 Vladimir Serbinenko - - * include/grub/efi/memory.h (grub_machine_mmap_iterate): - Remove redundant declaration. - (grub_mmap_get_post64): Likewise. - (grub_mmap_get_upper): Likewise. - (grub_mmap_get_lower): Likewise. - -2011-12-13 Vladimir Serbinenko - - * grub-core/partmap/dvh.c (grub_dvh_is_valid): Make argument - uint32_t * to ensure alignment. - (dvh_partition_map_iterate): Make `block' a union to ensure alignment. - -2011-12-13 Vladimir Serbinenko - - * grub-core/partmap/sunpc.c (grub_sun_is_valid): Make argument - uint16_t * to ensure alignment. - (sun_pc_partition_map_iterate): Make `block' a union to ensure - alignment. - -2011-12-13 Vladimir Serbinenko - - * grub-core/partmap/sun.c (grub_sun_is_valid): Make argument uint16_t * - to ensure alignment. - (sun_partition_map_iterate): Make `block' a union to ensure alignment. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (u16at): Make into inline function. - Handle unaligned pointers. - (u32at): Likewise. - (u64at): Likewise. - (fixup): Use byte access instead of v16at. - (find_attr): Fix imporper usage of v32at. - (read_data): Likewise. - (list_file): Handle byte-swapping and unaligned strings. - (grub_ntfs_label): Likewise. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/udf.c (grub_udf_partmap): Add packed attribute - as it's not necessarily aligned. - -2011-12-13 Vladimir Serbinenko - - * grub-core/kern/mips/qemu_mips/init.c (grub_at_keyboard_init): Remove - redundant declaration. - (grub_serial_init): Likewise. - (grub_terminfo_init): Likewise. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (DVA_OFFSET_TO_PHYS_SECTOR): Make into inline - function. - (ZAP_HASH_IDX): Likewise. - (ZAP_LEAF_HASH_SHIFT): Likewise. - (ZAP_LEAF_HASH_NUMENTRIES): Likewise. - (LEAF_HASH): Likewise. - (ZAP_LEAF_NUMCHUNKS): Likewise. - (ZAP_LEAF_CHUNK): Likewise. Changed pointer arithmetic to preserve - alignment invariants. Return pointer. All users updated. - (ZAP_LEAF_ENTRY): Make into inline function. - (NBBY): Removed. - (xor): LIkewise. - (xor_out): Use grub_crypto_xor. - (dnode_get_path): Use grub_get_unaligned. - (nvlist_find_value): Likewise. - (grub_zfs_nvlist_lookup_uint64): Likewise. - (grub_zfs_nvlist_lookup_string): Likewise. - (get_nvlist_size): Likewise. - (grub_zfs_open): Likewise. - (fill_fs_info): Likewise. - (grub_zfs_dir): Likewise. - * include/grub/zfs/zap_leaf.h (zap_leaf_phys): Adapt to preserve - alignment invariants. - * include/grub/zfs/zio.h (zio_eck_t): Mark as packed as it's not - necessarily aligned. - -2011-12-13 Vladimir Serbinenko - - * grub-core/net/netbuff.c (grub_netbuff_alloc): Ensure proper alignment. - -2011-12-13 Vladimir Serbinenko - - * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Change pointer - arithmetic to conserve alignment invariants. - -2011-12-13 Vladimir Serbinenko - - * include/grub/efiemu/efiemu.h (grub_efiemu_get_memory_map): Remove - redundant declaration. - (grub_efiemu_mm_obtain_request): Likewise. - (grub_efiemu_prepare): Likewise. - -2011-12-13 Vladimir Serbinenko - - * include/grub/list.h: Explicitly cast return of grub_bad_type_cast - to match types. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/hfsplus.c (grub_hfsplus_btree_recoffset): Handle the - case of aunaligned recptr. - (grub_hfsplus_read_block): Declare extoverflow as key to ensure - alignment. - (grub_hfsplus_btree_search): Handle unaligned index. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Use grub_get_unaligned16 - to get freetag and skip. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/nilfs2.c (grub_nilfs2_btree_node): Add zero-size keys - array. - (grub_nilfs2_btree_node_dkeys): Ensure return pointer alignment. - (grub_nilfs2_btree_lookup): Ensure buffer alignment. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/romfs.c (grub_romfs_iterate_dir): Properly align - name for checksum and fix allocation algorithm. - -2011-12-13 Vladimir Serbinenko - - * include/grub/types.h (grub_properly_aligned_t): New type. - (GRUB_PROPERLY_ALIGNED_ARRAY): New macro. - (grub_get_unaligned16): Add explicit casts. - (grub_get_unaligned32): Likewise. - (grub_get_unaligned64): Likewise. - (grub_set_unaligned16): New function. - (grub_set_unaligned32): Likewise. - -2011-12-13 Vladimir Serbinenko - - * grub-core/normal/datetime.c (grub_weekday_names): Make const. - -2011-12-13 Vladimir Serbinenko - - * grub-core/fs/udf.c (read_string): Macroify GRUB_MAX_UTF8_PER_UTF16. - * grub-core/fs/jfs.c (grub_jfs_diropen): Likewise. - * grub-core/fs/fat.c (grub_fat_iterate_dir): Likewise. - -2011-12-13 Vladimir Serbinenko - - * grub-core/term/at_keyboard.c (set_scancodes): Fix preprocessor - conditionals. - -2011-12-13 Vladimir Serbinenko - - * grub-core/kern/emu/main.c (main): Add missing const qualifier. - * grub-core/loader/efi/appleloader.c (devdata): Likewise. - -2011-12-13 Vladimir Serbinenko - - Unify and improve RAID and crypto xor. - - * grub-core/disk/raid.c (grub_raid_block_xor): Removed. All users - changed to grub_crypto_xor - * grub-core/lib/crypto.c (grub_crypto_xor): Moved from here ... - * include/grub/crypto.h (grub_crypto_xor): ... here. Inlined. - Use bigger types when possible. - -2011-12-13 Vladimir Serbinenko - - * grub-core/disk/raid.c (scan_devices): Fix condition. - -2011-12-13 Vladimir Serbinenko - - * grub-core/net/drivers/ieee1275/ofnet.c (bootp_response_properties): - Make name a const ptr. - -2011-12-13 Vladimir Serbinenko - - * grub-core/kern/ieee1275/ieee1275.c (grub_ieee1275_finddevice): Make - first argument a const pointer. - * grub-core/kern/ieee1275/openfw.c (grub_children_iterate): Likewise. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_finddevice): Update - proto. - (grub_children_iterate): Likewise. - (grub_machine_mmap_iterate): Remove redundant declaration. - -2011-12-13 Vladimir Serbinenko - - * grub-core/commands/acpi.c (grub_acpi_create_ebda) [!x86]: Disable. - (grub_cmd_acpi) [!x86]: Disable EBDA. - -2011-12-13 Vladimir Serbinenko - - Enable UTF8 in gnulib regexp. - - * config.h.in (RE_ENABLE_I18N) [!GRUB_UTIL]: New define. - * grub-core/lib/posix_wrap/ctype.h (islower): Use grub_islower. - (isupper): Use grub_isupper. - (isascii): New inline function. - * grub-core/lib/posix_wrap/wchar.h: Replace dummy with real contents. - * grub-core/lib/posix_wrap/wctype.h: Likewise. - * grub-core/normal/charset.c (grub_utf8_process): New function. - (grub_utf8_to_utf16): Use grub_utf8_process. - (grub_encode_utf8_character): New function. - (grub_ucs4_to_utf8): Use grub_encode_utf8_character. - * include/grub/charset.h (grub_utf8_process): New declaration. - (grub_encode_utf8_character): Likewise. - * include/grub/misc.h (grub_islower): New inline function. - (grub_isupper): Likewise. - (grub_strchrsub): Moved down to fix the definitions. - -2011-12-13 Vladimir Serbinenko - - * grub-core/bus/usb/ohci.c (grub_ohci_check_transfer): Add an unsigned - specification. - -2011-12-13 Vladimir Serbinenko - - * include/grub/loader.h (grub_loader_register_preboot_hook): - Use struct preboot * and not void * for handle. All users updated. - (grub_loader_unregister_preboot_hook): Likewise. - -2011-12-12 Vladimir Serbinenko - - * include/grub/charset.h (GRUB_MAX_UTF8_PER_UTF16): New const. - * grub-core/fs/hfsplus.c (grub_hfsplus_catkey_internal): Change to - UTF-16-BE. All users updated. - (grub_hfsplus_cmp_catkey): Fix unicode handling. - (grub_hfsplus_iterate_dir): Likewise. - (grub_hfsplus_label): Likewise. - -2011-12-12 Vladimir Serbinenko - - * grub-core/disk/ahci.c (grub_ahci_pciinit): Fix compat condition. - -2011-11-30 Vladimir Serbinenko - - Add missing const qualifiers. - - * grub-core/commands/i386/pc/sendkey.c (keysym): Add missing const. - * grub-core/commands/lspci.c (grub_pci_classname): Likewise. - * grub-core/commands/menuentry.c (hotkey_aliases): Likewise. - * grub-core/disk/lvm.c (grub_lvm_getvalue): Likewise. - (grub_lvm_check_flag): Likewise. - * grub-core/efiemu/i386/coredetect.c - (grub_efiemu_get_default_core_name): Likewise - * grub-core/efiemu/main.c (grub_efiemu_autocore): Likewise. - * grub-core/fs/hfsplus.c (grub_hfsplus_catkey_internal): Likewise. - * grub-core/fs/ntfs.c (fixup): Likewise. - * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Likewise. - * grub-core/fs/zfs/zfs.c (decomp_entry): Likewise. - (fzap_lookup): Likewise. - (zap_lookup): Likewise. - * grub-core/gnulib/regcomp.c (init_dfa): Likewise. - * grub-core/lib/legacy_parse.c (check_option): Likewise. - * grub-core/lib/posix_wrap/langinfo.h (nl_langinfo): Likewise. - * grub-core/loader/i386/bsd.c (grub_bsd_add_meta): Likewise. - (grub_freebsd_add_meta_module): Likewise. - (grub_cmd_freebsd_module): Likewise. - * grub-core/loader/i386/xnu.c (tbl_alias): Likewise. - * grub-core/loader/xnu.c (grub_xnu_register_memory): Likewise. - (grub_xnu_writetree_get_size): Likewise. - (grub_xnu_writetree_toheap_real): Likewise. - (grub_xnu_find_key): Likewise. - (grub_xnu_create_key): Likewise. - (grub_xnu_create_value): Likewise. - (grub_xnu_register_memory): Likewise. - (grub_xnu_check_os_bundle_required): Likewise. - (grub_xnu_scan_dir_for_kexts): Likewise. - (grub_xnu_load_kext_from_dir): Likewise. - * grub-core/normal/color.c (color_list): Likewise. - * grub-core/normal/completion.c (current_word): Likewise. - * grub-core/normal/menu_entry.c (insert_string): Likewise. - * grub-core/term/serial.c (grub_serial_find): Likewise. - * grub-core/term/tparm.c (grub_terminfo_tparm): Likewise. - * include/grub/efiemu/efiemu.h (grub_efiemu_get_default_core_name): - Likewise. - * include/grub/i386/bsd.h (grub_bsd_add_meta): Likewise. - (grub_freebsd_add_meta_module): Likewise. - * include/grub/lib/arg.h (grub_arg_option): Likewise. - * include/grub/net.h (grub_net_card_driver): Likewise. - (grub_net_card): Likewise. - (grub_net_app_protocol): Likewise. - * include/grub/parttool.h (grub_parttool_argdesc): Likewise. - * include/grub/serial.h (grub_serial_find): Likewise. - * include/grub/tparm.h (grub_terminfo_tparm): Likewise. - * include/grub/xnu.h (grub_xnu_create_key): Likewise. - (grub_xnu_create_value): Likewise. - (grub_xnu_find_key): Likewise. - (grub_xnu_scan_dir_for_kexts): Likewise. - (grub_xnu_load_kext_from_dir): Likewise. - - * include/grub/zfs/zio_checksum.h (zio_checksum_t): Moved from here ... - * grub-core/fs/zfs/zfs.c (zio_checksum_t): ...here. - * include/grub/zfs/zio_checksum.h (zio_checksum_info): - Moved from here ... - * grub-core/fs/zfs/zfs.c (zio_checksum_info): ... here. Added missing const. - -2011-11-28 Colin Watson - - * util/getroot.c (find_root_device_from_libzfs): Use xasprintf. - -2011-11-27 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (recovery): Fix spelling. - (read_device): Fix size calculation. - -2011-11-25 Robert Millan - - * util/getroot.c [HAVE_LIMITS_H]: Include `'. - (find_root_device_from_libzfs): Add zpool output parser to be used - as fallback when libzfs isn't available. - -2011-11-25 Seth Goldberg - - * po/Makefile.in.in: Add missing escape-continuation. - -2011-11-25 Vladimir Serbinenko - - * grub-core/fs/cpio.c (grub_cpio_dir): Handle subdirs correctly. - -2011-11-16 Vladimir Serbinenko - - * grub-core/kern/dl.c (grub_dl_load_segments): Fix alignment handling. - -2011-11-16 Vladimir Serbinenko - - * grub-core/kern/dl.c (grub_dl_unload): Fix freeing segments. - -2011-11-16 Vladimir Serbinenko - - * grub-core/kern/x86_64/efi/callwrap.S: Fix the comment. - -2011-11-14 Vladimir Serbinenko - - * grub-core/lib/adler32.c: Add missing license specification. - * grub-core/lib/crc64.c: Likewise. - * grub-core/loader/i386/pc/plan9.c: Likewise. - * grub-core/partmap/plan.c: Likewise. - -2011-11-13 Lubomir Kundrak - - Add facility to debug GRUB with gdb under qemu. - - * grub-core/gdb_grub.in: New file. - * grub-core/gmodule.pl.in: Likewise. - * grub-core/Makefile.core.def (gmodule.pl): New script. - (gdb_grub): Likewise. - -2011-11-13 Vladimir Serbinenko - - * util/grub-mount.c (argp_parser): Accept relative pathes. - * util/grub-fstest.c (argp_parser): Likewise. - -2011-11-13 Vladimir Serbinenko - - Plan9 support. - - * Makefile.util.def (libgrubmods): Add - grub-core/partmap/plan.c. - * docs/grub.texi: Notice Plan9 support. - * grub-core/Makefile.core.def (plan9): New module. - (part_plan): Likewise. - * grub-core/loader/i386/pc/plan9.c: New file. - * grub-core/partmap/plan.c: Likewise. - * include/grub/msdos_partition.h (GRUB_PC_PARTITION_TYPE_PLAN9): New - define. - (GRUB_PC_PARTITION_TYPE_LINUX_SWAP): Likewise. - * include/grub/mm.h (grub_extend_alloc): New inline function. - -2011-11-13 Vladimir Serbinenko - - Make Reed-Solomon faster by using power of generator representation of - GF(256)*. - - * grub-core/lib/reed_solomon.c (grub_uint16_t) [TEST]: Removed. - (gf_double_t): Likewise. - (gf_invert): Removed. - (gf_powx): New array. - (gf_powx_inv): Likewise. - (scratch): Move higher. - (gf_reduce): Removed. - (gf_mul): Use powx. - (gf_invert): Likewise. - (init_inverts): Replaced with ... - (init_powx): ...this. All users updated. - (pol_evaluate): Replace multiplications with additions. - (rs_encode): Likewise. - (gauss_eliminate): Call gf_invert. - (grub_reed_solomon_add_redundancy): Call init_powx. - (grub_reed_solomon_recover): Call init_powx unconditionally. - -2011-11-12 Vladimir Serbinenko - - * grub-core/partmap/gpt.c (gpt_partition_map_embed): Fix spelling. - -2011-11-12 Vladimir Serbinenko - - * grub-core/partmap/gpt.c (gpt_partition_map_embed): Restore - disk->partiton for safety. - -2011-11-12 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev): - Fix a memory leak. - (grub_util_biosdisk_get_grub_dev): Add a useful debug info. - -2011-11-12 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (find_system_device): Fix a memory leak. - -2011-11-12 Vladimir Serbinenko - - * include/grub/lvm.h (grub_lvm_pv): Correct start type. - -2011-11-12 Vladimir Serbinenko - - Fix spaces handling in proc/self/mountinfo. - - * util/getroot.c (unescape): New function. - (grub_find_root_device_from_mountinfo): Use unescape. - -2011-11-12 Vladimir Serbinenko - - Support ZFS embedding. - - * grub-core/fs/zfs/zfs.c (grub_zfs_embed): New function. - (grub_zfs_fs): Register grub_zfs_embed. - -2011-11-12 Vladimir Serbinenko - - Fix MIPS compilation. - - * grub-core/boot/mips/startup_raw.S: Use GRUB_DECOMPRESSOR_* - * include/grub/offsets.h: Rename decompressor fields from - GRUB_KERNEL_* to GRUB_DECOMPRESSOR_*. - * util/grub-mkimage.c (image_targets): Use new names. - -2011-11-12 Vladimir Serbinenko - - Defer multiboot device parsing until we're in compressed part. - - * grub-core/boot/i386/pc/lnxboot.S: Remove setting dos_part and - bsd_part. setdevice has fallen into disuse. - * grub-core/boot/i386/pc/startup_raw.S (dos_part): Removed. - (bsd_part): Likewise. - (boot_dev): New variable. - (multiboot_trampoline): Don't parse multiboot device. - Pass multiboot device in %edx. - * grub-core/disk/i386/pc/biosdisk.c (GRUB_MOD_INIT): Parse - grub_boot_device. - * grub-core/kern/i386/pc/init.c (grub_machine_get_bootlocation): - Likewise. - * grub-core/kern/i386/pc/startup.S: Save edx. - (grub_boot_drive): Removed. - (grub_install_dos_part): Likewise. - (grub_install_bsd_part): Likewise. - (grub_boot_device): New variable. - * include/grub/i386/pc/kernel.h (grub_install_dos_part): Removed. - (grub_install_bsd_part): Likewise. - (grub_boot_drive): Likewise. - (grub_boot_device): New variable. - * include/grub/offsets.h (GRUB_KERNEL_I386_PC_INSTALL_DOS_PART): - Removed. - (GRUB_KERNEL_I386_PC_INSTALL_BSD_PART): Likewise. - (GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY): Moved lower. - (GRUB_KERNEL_MACHINE_INSTALL_BSD_PART): Removed. - (GRUB_KERNEL_MACHINE_INSTALL_DOS_PART): Likewise. - * util/grub-install.in: Remove redundant condition. - -2011-11-12 Vladimir Serbinenko - - Fix bug introduced by previous commit. - - * grub-core/boot/i386/pc/startup_raw.S: Compute RS start correctly. - -2011-11-12 Vladimir Serbinenko - - Use decompressors framework on i386-pc. It increases core size - by 46 bytes but improves compatibility and maintainability. - - * grub-core/Makefile.core.def (lzma_decompress): New image. - (kernel): Add i386_pc_ldflags. - * grub-core/kern/i386/pc/startup.S: Move intial part to .. - * grub-core/boot/i386/pc/startup_raw.S: ... here. Pass pointers - to real_to_prot, prot_to_real and device info. - * include/grub/offsets.h: Renamed decompressor offsets. - * util/grub-mkimage.c (grub_compression_t): New cmpression lzma. - (image_target_desc): Remove raw_size and rename decompressor fields. - (compress_kernel): Handle lzma. - (generate_image): Handle decompressors on i386-pc. - -2011-11-12 Vladimir Serbinenko - - * configure.ac: Add -fno-asynchronous-unwind-tables. - -2011-11-12 Vladimir Serbinenko - - Move assembly code to C by using intwrap. It increases core size - by 88 bytes but improves compatibility and maintainability. - - * grub-core/kern/i386/pc/startup.S (grub_console_putchar): Moved to ... - * grub-core/term/i386/pc/console.c (grub_console_putchar_real): - ... here. Translated to C. - * grub-core/kern/i386/pc/startup.S (grub_console_getkey): Moved to ... - * grub-core/term/i386/pc/console.c (grub_console_getkey): - ... here. Translated to C. - * grub-core/kern/i386/pc/startup.S (grub_console_getxy): Moved to ... - * grub-core/term/i386/pc/console.c (grub_console_getxy): - ... here. Translated to C. - * grub-core/kern/i386/pc/startup.S (grub_console_gotoxy): Moved to ... - * grub-core/term/i386/pc/console.c (grub_console_gotoxy): - ... here. Translated to C. - * grub-core/kern/i386/pc/startup.S (grub_console_cls): Moved to ... - * grub-core/term/i386/pc/console.c (grub_console_cls): - ... here. Translated to C. - * grub-core/kern/i386/pc/startup.S (grub_console_setcursor): Moved to .. - * grub-core/term/i386/pc/console.c (grub_console_setcursor): - ... here. Translated to C. - * grub-core/kern/i386/pc/startup.S (grub_get_rtc): Moved to .. - * grub-core/kern/i386/pc/init.c (grub_get_rtc): ... here. - Translated to C. - * grub-core/term/i386/pc/console.c (int10_9): New function. - (grub_console_putchar): Likewise. - * include/grub/i386/pc/console.h: Removed the not anymore shared - functions. - -2011-11-12 Vladimir Serbinenko - - Move grub_chainloader_real_boot out of the kernel. - - * grub-core/Makefile.am: Remove machine/loader.h. - * grub-core/kern/i386/pc/startup.S (grub_chainloader_real_boot): - Removed. - * grub-core/lib/i386/relocator.c (grub_relocator16_esi): New extern - variable. - (grub_relocator16_keep_a20_enabled): Likewise. - (grub_relocator16_boot): Fill new variables. - * grub-core/lib/i386/relocator16.S: Add gate a20 handling. - * grub-core/loader/i386/pc/chainloader.c (grub_chainloader_boot): Use - relocator. - (grub_chainloader_unload): Likewise. - (grub_chainloader_cmd): Likewise. - * include/grub/i386/pc/loader.h: Removed. - * include/grub/i386/relocator.h (grub_relocator16_state): Add a20 - and esi. All initialisers updated. - -2011-11-12 Vladimir Serbinenko -2011-11-12 Colin Watson - - * Makefile.util.def (grub-mount): New util. - * .bzrignore: Add grub-mount. - * configure.ac: Check for fuse and enable grub-mount if available. - * docs/man/grub-mount.h2m: New file. - * util/grub-mount.c: Likewise. - -2011-11-11 Vladimir Serbinenko - - * grub-core/commands/efi/fixvideo.c: Gettextize. - * grub-core/commands/hashsum.c: Likewise. - * grub-core/commands/i386/cmostest.c: Likewise. - * grub-core/commands/i386/pc/drivemap.c: Likewise. - * grub-core/commands/i386/pc/lsapm.c: Likewise. - * grub-core/commands/i386/pc/sendkey.c: Likewise. - * grub-core/commands/lsmmap.c: Likewise. - * grub-core/commands/menuentry.c: Likewise. - * grub-core/commands/mips/loongson/lsspd.c: Likewise. - * grub-core/commands/setpci.c: Likewise. - * grub-core/loader/i386/bsd.c: Likewise. - * grub-core/loader/i386/linux.c: Likewise. - * util/getroot.c: Likewise. - * util/grub-editenv.c: Likewise. - * util/grub-fstest.c: Likewise. - * util/grub-mkfont.c: Likewise. - * util/grub-mkimage.c: Likewise. - * util/grub-mkpasswd-pbkdf2.c: Likewise. - * util/grub-pe2elf.c: Likewise. - * util/grub-probe.c: Likewise. - * util/grub-setup.c: Likewise. - * util/ieee1275/ofpath.c: Likewise. - * util/misc.c: Likewise. - * util/raid.c: Likewise. - -2011-11-11 Robert Millan - - * util/getroot.c (grub_util_get_geom_abstraction): Remove - __attribute__((unused)) from `os_dev', which *is* being used. - -2011-11-11 Vladimir Serbinenko - - * include/grub/dl.h (GRUB_ARCH_DL_TRAMP_SIZE) [__ia64__]: Add back - forgotten define. - (GRUB_ARCH_DL_GOT_ALIGN) [__ia64__]: Redefine in terms of - GRUB_IA64_DL_GOT_ALIGN. - (GRUB_ARCH_DL_TRAMP_ALIGN) [__ia64__]: Redefine in terms of - GRUB_IA64_DL_TRAMP_ALIGN. - -2011-11-11 Vladimir Serbinenko - - Replace grub_fatal with normal errors in i386 linux loader. - - * grub-core/loader/i386/linux.c (find_efi_mmap_size): Return 0 on error. - (allocate_pages): Check find_efi_mmap_size return value. - (grub_e820_add_region): Return error. - (grub_linux_boot): Check mmap return value. - -2011-11-11 Vladimir Serbinenko - - * grub-core/commands/acpihalt.c: Gettextized. - * grub-core/commands/cacheinfo.c: Likewise. - * grub-core/commands/cmp.c: Likewise. - * grub-core/commands/efi/loadbios.c: Likewise. - * grub-core/commands/gptsync.c: Likewise. - * grub-core/commands/ieee1275/suspend.c: Likewise. - * grub-core/commands/legacycfg.c: Likewise. - * grub-core/commands/memrw.c: Likewise. - * grub-core/commands/minicmd.c: Likewise. - * grub-core/commands/parttool.c: Likewise. - * grub-core/commands/time.c: Likewise. - * grub-core/commands/videoinfo.c: Likewise. - * grub-core/disk/geli.c: Likewise. - * grub-core/disk/i386/pc/biosdisk.c: Likewise. - * grub-core/disk/luks.c: Likewise. - * grub-core/disk/lvm.c: Likewise. - * grub-core/font/font_cmd.c: Likewise. - * grub-core/fs/zfs/zfscrypt.c: Likewise. - * grub-core/fs/zfs/zfsinfo.c: Likewise. - * grub-core/gfxmenu/view.c: Likewise. - * grub-core/kern/emu/hostdisk.c: Likewise. - * grub-core/kern/emu/main.c: Likewise. - * grub-core/kern/emu/misc.c: Likewise. - * grub-core/kern/emu/mm.c: Likewise. - * grub-core/kern/mips/arc/init.c: Likewise. - * grub-core/kern/mips/loongson/init.c: Likewise. - * grub-core/kern/partition.c: Likewise. - * grub-core/lib/i386/halt.c: Likewise. - * grub-core/lib/mips/arc/reboot.c: Likewise. - * grub-core/lib/mips/loongson/reboot.c: Likewise. - * grub-core/loader/i386/pc/chainloader.c: Likewise. - * grub-core/loader/i386/xnu.c: Likewise. - * grub-core/loader/multiboot.c: Likewise. - * grub-core/net/bootp.c: Likewise. - * grub-core/net/net.c: Likewise. - * grub-core/normal/term.c: Likewise. - * grub-core/partmap/bsdlabel.c: Likewise. - * grub-core/parttool/msdospart.c: Likewise. - * grub-core/term/gfxterm.c: Likewise. - * grub-core/term/terminfo.c: Likewise. - * grub-core/video/i386/pc/vbe.c: Likewise. - * util/grub-menulst2cfg.c: Likewise. - * util/grub-mkdevicemap.c: Likewise. - * util/grub-mklayout.c: Likewise. - * util/grub-mkrelpath.c: Likewise. - * util/grub-script-check.c: Likewise. - * util/ieee1275/grub-ofpathname.c: Likewise. - * util/resolve.c: Likewise. - -2011-11-11 Vladimir Serbinenko - - Support %1$d syntax. - - * tests/printf_unit_test.c: New file. - * Makefile.util.def (printf_test): New test. - * grub-core/kern/misc.c (grub_vsnprintf_real): Support %1$d syntax. - -2011-11-11 Vladimir Serbinenko - - * grub-core/hook/datehook.c (grub_read_hook_datetime): Small stylistic - fix. - -2011-11-11 Vladimir Serbinenko - - * grub-core/efiemu/mm.c (grub_efiemu_mmap_fill): Change printf into - dprintf. - * grub-core/font/font.c (grub_font_load): Likewise. - -2011-11-11 Vladimir Serbinenko - - * util/grub-macho2img.c: Add comment concerning gettext. - * grub-core/lib/legacy_parse.c: Likewise. - -2011-11-11 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_vprintf): Add missing va_end. - (grub_xvasprintf): Likewise. - -2011-11-11 Vladimir Serbinenko - - Add const keyword to grub_env_get and gettextize week days. - - * grub-core/hook/datehook.c (grub_datetime_names): Make const. - (grub_read_hook_datetime): Return const char *. - * grub-core/kern/env.c (grub_env_get): Return const char *. All users - updated. - * grub-core/normal/datetime.c (grub_weekday_names): Make const. - Mark for gettext. - (grub_get_weekday_name): Return const char *. Call gettext. - * grub-core/script/argv.c (grub_script_argv_append): Receive const - char * and len as the argument. All users updated. - (grub_script_argv_split_append): Receive const char *. - * include/grub/datetime.h (grub_get_weekday_name): Update proto. - * include/grub/env.h (grub_env_get): Likewise. - (grub_env_read_hook_t): Return const char *. - * include/grub/script_sh.h (grub_script_argv_append): Update proto. - (grub_script_argv_split_append): Likewise. - -2011-11-11 Vladimir Serbinenko - - * grub-core/normal/main.c (grub_normal_execute): Remove leftover call. - -2011-11-11 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_strstr): Moved from here ... - * include/grub/misc.h (grub_strstr): ... here. Make static and inline. - -2011-11-11 Vladimir Serbinenko - - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_set_property): - Fix prototype. - -2011-11-11 Vladimir Serbinenko - - Fix mips compilation. - - * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec): Restrict hash_id to - normal decoder. - (hashes): Use in embed decoder as well (for sizes). - (dec_stream_header): Fix embed decompressor logic. - (dec_stream_footer): Likewise. - -2011-11-11 Vladimir Serbinenko - - * grub-core/kern/x86_64/dl.c (grub_arch_dl_relocate_symbols): Issue - an error and not a fatal on unrecognised relocation types. - -2011-11-11 Vladimir Serbinenko - - * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): - Issue error rather than printf on unknown arguments. - -2011-11-11 Vladimir Serbinenko - - * grub-core/kern/ieee1275/ieee1275.c (grub_ieee1275_set_property): - Make buf a const. - -2011-11-11 Vladimir Serbinenko - - * grub-core/fs/zfs/zfscrypt.c (GRUB_MOD_INIT), (GRUB_MOD_FINI): - Fix module name. - -2011-11-11 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (grub_ntfs_read_symlink): Stylistic fix. Remove - leftover debug printf. - -2011-11-11 Vladimir Serbinenko - - * grub-core/fs/btrfs.c (grub_btrfs_embed): Spelling fix. - -2011-11-11 Vladimir Serbinenko - - * grub-core/efiemu/main.c (grub_efiemu_register_configuration_table): - A stylistic fix. - -2011-11-11 Vladimir Serbinenko - - * grub-core/commands/probe.c (grub_cmd_probe): Fix error message. - -2011-11-10 Shea Levy - - Allow all modules to perform serial IO - - * grub-core/term-serial.c (grub_serial_find): Remove static qualifier - * include/grub/serial.h (grub_serial_port_configure): New inline - function. - (grub_serial_port_fetch): Likewise. - (grub_serial_port_put): Likewise. - (grub_serial_port_fini): Likewise. - (grub_serial_find): New proto. - -2011-11-10 Vladimir Serbinenko - - Put symlink at the end of the node and fix a potential - memory corruption. - - * grub-core/fs/iso9660.c (grub_fshelp_node): New field have_symlink. - Make symlink into an array. - (set_rockridge): Set have_symlink and alloc_dirents. - (grub_iso9660_read_symlink): Use new layout. - (grub_iso9660_iterate_dir): Fix memory corruption. - Use new layout. - (grub_iso9660_dir): Set have_symlink. - (grub_iso9660_open): Likewise. - -2011-11-10 Vladimir Serbinenko - - Remove local keyword. - - * util/grub-mkconfig_lib.in (version_test_numeric): Remove local. - (version_test_gt): Likewise. - (version_find_latest): Likewise. - (gettext_printf): Likewise. - * util/grub.d/10_windows.in (get_os_name_from_boot_ini): Likewise. - -2011-11-10 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (zfs_mount): Fix spurious warning. - -2011-11-10 Vladimir Serbinenko - - Fix ZFS memory and resource leaks. - - * grub-core/fs/zfs/zfs.c (fill_vdev_info_real): New paramter inserted. - All users updated. - Free type on exit. - (fill_vdev_info): New parameter inserted. All users updated. - (check_pool_label): Likewise. - (scan_disk): Likewise. - (scan_devices): Close non-inserted disks. - (fzap_iterate): Free l. - (unmount_device): Free children descripto memory. - -2011-11-10 Vladimir Serbinenko - - * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Fix grub_strncat - argument (access out of bounds). - -2011-11-10 Vladimir Serbinenko - - * grub-core/fs/btrfs.c (grub_btrfs_read_logical): Fix RAID10 logic for - >= 6 drives. - -2011-11-10 Vladimir Serbinenko - - * include/grub/i386/netbsd_bootinfo.h (grub_netbsd_btinfo_bootwedge): - Fix declaration. - -2011-11-09 Vladimir Serbinenko - - Fix several memory leaks. - - * grub-core/fs/btrfs.c (grub_btrfs_dir): Fix memory leak. - * grub-core/fs/cpio.c (grub_cpio_find_file): Likewise. - (grub_cpio_dir): Likewise. - * grub-core/fs/fat.c (grub_fat_label): Likewise. - * grub-core/fs/jfs.c (grub_jfs_label): Likewise. - * grub-core/fs/romfs.c (grub_romfs_close): Likewise. - (grub_romfs_label): Likewise. - * grub-core/fs/squash4.c (squash_mount): Use zalloc for safety. - (squash_unmount): New function. - (grub_squash_dir): Fix memory leak. - (grub_squash_open): Likewise. - (grub_squash_read): Likewise. - (grub_squash_mtime): Likewise. - * grub-core/fs/xfs.c (grub_xfs_open): Likewise. - * grub-core/fs/zfs/zfs.c (check_pool_label): Likewise. - * util/grub-fstest.c (fstest): Likewise. - -2011-11-09 Vladimir Serbinenko - - * include/grub/misc.h (grub_strncat): Fix the order of conditionals to - avoid accessing beyond the array. - -2011-11-09 Vladimir Serbinenko - - * configure.ac: Add missing -mXX to TARGET_CPPFLAGS. - -2011-11-09 Vladimir Serbinenko - - Several AFFS fixes. - - * grub-core/fs/affs.c (grub_affs_bblock): Replace flags with version. - (GRUB_AFFS_FLAG_FFS): Removed. - (GRUB_AFFS_SYMLINK_SIZE): Likewise. - (GRUB_AFFS_FILETYPE_DIR): Make positive and unsigned. - (GRUB_AFFS_FILETYPE_DIR), (GRUB_AFFS_FILETYPE_REG): Fix a mix-up. - (grub_fshelp_node): Make block 32-bit. - Add block_cache and last_block_cache. - (grub_affs_read_block): Fill and use block cache. - (grub_affs_read_file): Removed. - (grub_affs_mount): Zero-fill node. Fix version check. Don't reread - boot block. - (grub_affs_read_symlink): Fix symlink size. Add a \0 at the end for - safety. - (grub_affs_iterate_dir): Use more appropriate types. Zero-fill allocated - space. - (grub_affs_close): Free block cache. - (grub_affs_read): Use grub_fshelp_read_file directly. - -2011-11-08 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (read_dva): Issue an error if read failed - with no error set. - -2011-11-08 Vladimir Serbinenko - - * grub-core/lib/LzmaEnc.c (LzmaEnc_CodeOneBlock): Remove set but not - used variable. - * grub-core/kern/ia64/dl_helper.c (grub_ia64_dl_get_tramp_got_size): - Likewise. - -2011-11-08 Vladimir Serbinenko - - Fix potential problem with calling zfs_to_cpu and cpu_to_be in a row. - - * grub-core/fs/zfs/zfscrypt.c (grub_zfs_decrypt_real): Use explicit - byteswap when needed. - -2011-11-08 Vladimir Serbinenko - - Fix FreeBSD compilation. - - * grub-core/disk/geli.c (GRUB_MD_SHA256) [GRUB_UTIL]: Redefine in a way - to avoid circular dependency. - (GRUB_MD_SHA512) [GRUB_UTIL]: Likewise. - * util/getroot.c (grub_util_follow_gpart_up): Move from here... - * grub-core/kern/emu/hostdisk.c (+grub_util_follow_gpart_up): ... here. - -2011-11-08 Vladimir Serbinenko - - Fix ZFS crypto error types. - - * grub-core/fs/zfs/zfscrypt.c (grub_ccm_decrypt): Fix return type. - (grub_gcm_decrypt): Likewise. - (grub_zfs_load_key_real): Fix error code type. Handle possible error - from PBKDF2. - -2011-11-08 Vladimir Serbinenko - - Illumos support. - - * Makefile.util.def (10_illumos): New script. - * configure.ac: Set COND_HOST_ILLUMOS. - * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors) [__sun__]: - Support Illumos calls. - (find_partition_start) [__sun__]: Likewise. - (convert_system_partition_to_system_disk) [__sun__]: Likewise. - (device_is_wholedisk) [__sun__]: Handle Illumos naming scheme. - (grub_util_biosdisk_get_grub_dev) [__sun__]: Handle Illumos. - * util/getroot.c (find_root_device_from_libzfs) [__sun__]: Return raw - device. - * util/grub-probe.c (probe) [__sun__]: Do character check. - * util/grub.d/10_illumos.in: New file. - -2011-11-08 Vladimir Serbinenko - - Support escaped commas in hostdisk. - - * grub-core/kern/emu/hostdisk.c (unescape_cmp): New function. - (find_grub_drive): Use unescape_cmp. - (make_device_name): Escape commas. - -2011-11-08 Vladimir Serbinenko - - * util/grub.d/10_kfreebsd.in: Use ${grub_mkrelpath} not grub-mkrelpath. - -2011-11-08 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (zap_iterate): Remove set but not used - variable. - -2011-11-08 Vladimir Serbinenko - - Support trampoline jumps on powerpc. - - * grub-core/kern/dl.c (grub_dl_load_segments) [__powerpc__]: Follow - __ia64__ path. - (grub_dl_load_segments): Set mod->sz. - (grub_dl_flush_cache): Flush whole space occupied by module, not just - segments. - * grub-core/kern/ia64/dl.c (nopm): Make const while on it. - (jump): Likewise. - * grub-core/kern/powerpc/dl.c (grub_arch_dl_get_tramp_got_size): New - function. - (trampoline): New struct. - (trampoline_template): New const. - (grub_arch_dl_relocate_symbols): Create trampolines on overflow. - * include/grub/dl.h (grub_dl): Add sz element. - [__powerpc__]: Follow __ia64__. - (GRUB_ARCH_DL_TRAMP_ALIGN): Define on ppc. - (GRUB_ARCH_DL_GOT_ALIGN): Likewise. - (GRUB_ARCH_DL_TRAMP_SIZE): Likewise. - (grub_arch_dl_get_tramp_got_size) [__powerpc__]: New proto. - -2011-11-06 Vladimir Serbinenko - - ZFS crypto support. - - * Makefile.util.def (libgrubmods): Add grub-core/fs/zfs/zfscrypt.c. - * grub-core/Makefile.core.def (zfscrypt): New module. - * grub-core/fs/zfs/zfs.c (subvolume): New structure. - (grub_zfs_data): Replace mdn with subvol. Put case_insensitivity inside - it. All users updated. - (grub_zfs_decrypt): New var. - (grub_zfs_load_key): Likewise. - (zio_checksum_functions): Add SHA256+MAC. - (zio_checksum_verify): Handle incomplete comparison due to MAC. - (zio_read): Handle encrypted blocks. - (zap_verify): Remove incorrect check. - (fzap_iterate): Handle non-standard fzap. - (zap_iterate): Likewise. - (zap_iterate_u64): New function. - (dnode_get_fullpath): Load keys. - * grub-core/fs/zfs/zfscrypt.c: New file. - * grub-core/lib/crypto.c (grub_crypto_cipher_close): Removed. - (grub_crypto_ecb_encrypt): Make input const. - * include/grub/crypto.h (grub_crypto_cipher_close): Inline. - (grub_crypto_ecb_encrypt): Make input const. - (GRUB_CIPHER_AES): New macro. - * include/grub/zfs/dmu.h (dmu_object_type): Add DMU_OT_DSL_KEYCHAIN. - * include/grub/zfs/dsl_dir.h (dsl_dir_phys): Add keychain. - * include/grub/zfs/spa.h (grub_zfs_endian): Moved from here ... - * include/grub/zfs/zfs.h (grub_zfs_endian): ... here. Added GURB_ZFS_ - prefix. All users updated. - (grub_zfs_add_key): New proto. - (grub_zfs_decrypt): Likewise. - (grub_zfs_load_key): Likewise. - * include/grub/zfs/zio.h (zio_checksum): Add SHA256+MAC. - * util/grub-fstest.c (options): Add -K option. - (argp_parser): Likewise. - -2011-11-05 Vladimir Serbinenko - - Support zle compression on ZFS. - - * grub-core/fs/zfs/zfs.c (zle_decompress): New function. - (decomp_table): Add zle. - * include/grub/zfs/zio.h (zio_compress): Add zle. - -2011-11-05 Vladimir Serbinenko - - Support BtrFS embedding. - - * grub-core/fs/btrfs.c (grub_btrfs_embed) [GRUB_UTIL]: New function. - (grub_btrfs_fs) [GRUB_UTIL]: Set embed. - * include/grub/fs.h (grub_fs) [GRUB_UTIL]: New field embed. - * util/grub-setup.c (setup): Use fs embedding if available. - Add additional sanity check. - -2011-11-05 Vladimir Serbinenko - - * util/grub-install.in: Fix condition for config_opt. - -2011-11-04 Vladimir Serbinenko - - Support third redundancy strip on raidz3. - - * grub-core/fs/zfs/zfs.c (recovery): Add Gauss for general case. - Return error on singularity. All users updated. - (read_device): Don't stop on 3rd failure on raidz3. - -2011-11-04 Vladimir Serbinenko - - Support case-insensitive ZFS subvolumes. - - * grub-core/fs/zfs/zfs.c (mzap_lookup): New parameter case_insensitive. - All users updated. - (zap_hash): Likewise. - (name_cmp): New function. - (zap_leaf_array_equal): New parameter case_insensitive. - All users updated. - (zap_leaf_lookup): Likewise. - (fzap_lookup): Likewise. - (zap_lookup): Likewise. - (dnode_get_path): New parameter case_insensitive. Retrieve case - sensitiviness of a volume. All users updated. - (dnode_get_fullpath): New parameter case_insensitive. - All users updated. - (grub_zfs_dir): Set info.case_insensitiveness. - -2011-11-04 Vladimir Serbinenko - - Support second redundancy strip on raidz(2,3). - - * grub-core/fs/zfs/zfs.c (powx): New array. - (powx_inv): Likewise. - (poly): New const. - (xor_out): New function. - (gf_mul): Likewise. - (recovery): Likewise. - (read_device): Use second redundancy strip. - -2011-11-04 Vladimir Serbinenko - - Use a power of generator representation of GF(256) multiplication group - to save space time and complexity. - - * grub-core/disk/raid6_recover.c (raid6_table1): Removed. - (raid6_table2): Likewise. - (powx): New array. - (powx_inv): Likewise. - (poly): New const. - (grub_raid_block_mul): Replace with ... - (grub_raid_block_mulx): ...this. - (grub_raid6_init_table): Rewritten. - (grub_raid6_recover): Use power of generator representation. - -2011-11-04 Vladimir Serbinenko - - * grub-core/disk/raid6_recover.c (grub_raid6_recover): Get start_sector - for the right device. - -2011-11-04 Vladimir Serbinenko - - * include/grub/kernel.h (grub_module_header): Make type into uint32 as - expected by grub-mkimage and it's more clear since there is no implicit - padding. - -2011-11-04 Vladimir Serbinenko - - * grub-core/disk/raid.c (scan_devices): Don't derference NULL on whole - disk. - * grub-core/disk/lvm.c (do_lvm_scan): Likewise. - -2011-11-03 Philipp Matthias Hahn - - * util/grub-mkrescue.in: Fix handling xorriso option. - -2011-11-03 Vladimir Serbinenko - - * grub-core/gettext/gettext.c (grub_gettext_init_ext): Exit if local is - NULL. - -2011-11-03 crocket - - * util/grub.d/10_linux.in: Add Slackware initrd naming. - -2011-11-03 Vladimir Serbinenko - - XZ CRC64 and SHA256 support. - - * Makefile.util.def (libgrubmods): Add crc64.c. - * grub-core/Makefile.core.def (crc64): New module. - * grub-core/lib/crc64.c: New file. - * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_hash) - [!GRUB_EMBED_DECOMPRESSOR]: Rename crc32_context to hash_context. - Fix the type. - (MAX_HASH_SIZE): New define. - (xz_dec) [!GRUB_EMBED_DECOMPRESSOR]: Add generic hash fields. - (dec_block) [!GRUB_EMBED_DECOMPRESSOR]: Handle non-crc32 hashes. - (index_update) [!GRUB_EMBED_DECOMPRESSOR]: Likewise. - (dec_index) [!GRUB_EMBED_DECOMPRESSOR]: Likewise. - (crc32_validate) [!GRUB_EMBED_DECOMPRESSOR]: Rename to ... - (hash_validate) [!GRUB_EMBED_DECOMPRESSOR]: ... this. - Handle non-crc32 hashes. - (hashes) [!GRUB_EMBED_DECOMPRESSOR]: New variable. - (dec_stream_header): Handle non-crc32 hashes. - (dec_stream_footer): Likewise. - (dec_block_header): Likewise. - (dec_main): Likewise. - (xz_dec_init): Likewise. - (xz_dec_reset): Likewise. - (xz_dec_end): Likewise. - * util/import_gcry.py: Add CRC64 line. - -2011-11-03 Vladimir Serbinenko - - * grub-core/fs/ufs.c (grub_ufs_mtime) [MODE_UFS2]: Check mtime field - as well. - -2011-11-03 Vladimir Serbinenko - - Make reiserfs label retrieval similar to other *_label functions. - - * grub-core/fs/reiserfs.c (grub_reiserfs_superblock): New field label. - (REISERFS_MAX_LABEL_LENGTH): Removed. - (REISERFS_LABEL_OFFSET): Likewise. - (grub_reiserfs_label): Rewritten. - -2011-11-03 Vladimir Serbinenko - - * grub-core/fs/nilfs2.c (grub_nilfs2_mtime): Use correct superblock - field. - -2011-11-03 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (read_device): Support raidz3. - -2011-11-02 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (read_device): Add ability to sustain a single - drive failure on both raidz and raidz2. - -2011-11-02 Vladimir Serbinenko - - Fix RAIDZ(2) for >= 5 devices. - - * grub-core/fs/zfs/zfs.c (read_device): Fix length formula. Remove - asize argument. All users updated. - -2011-11-01 Vladimir Serbinenko - - Fix RAIDZ(2). - - * grub-core/fs/zfs/zfs.c (grub_zfs_device_desc): New member ashift. - (fill_vdev_info_real): Set ashift. - (read_device): Rewrite RAIDZ part based on reverse engineering. - -2011-10-31 Vladimir Serbinenko - - * grub-core/fs/btrfs.c (grub_btrfs_extent_read): Add sanity check and - don't report potentially unavialiable fields in debug output. - (find_path): Fix double-free and memory leak. - -2011-10-31 Vladimir Serbinenko - - Read label on UFS1. - - * grub-core/fs/ufs.c (grub_ufs_label): Remove MODE_UFS2 condition. - (grub_ufs_fs): Always set .label. - -2011-10-31 Vladimir Serbinenko - - Use shifts in UFS. - - * grub-core/fs/ufs.c (UFS_LOG_BLKSZ): New macro. - (grub_ufs_data): New field log2_blksz. - (grub_ufs_read_file): Use shifts. - (grub_ufs_mount): Check block size and logarithm it. - -2011-10-31 Vladimir Serbinenko - - * grub-core/fs/ufs.c (grub_ufs_lookup_symlink): Fix handling of - long symlinks. - -2011-10-30 Vladimir Serbinenko - - Handle symlinks and long names on tar and cpio. - - * grub-core/fs/cpio.c (ATTR_TYPE): New definition. - (ATTR_FILE): Likewise. - (ATTR_DIR): Likewise. - (ATTR_LNK): Likewise. - (grub_cpio_data) [MODE_USTAR]: New fields linkname and linkname_alloc. - (grub_cpio_find_file): Fill mode, handle linkname field as well as - L and K entries. - (grub_cpio_mount): Zero-fill data. - (handle_symlink): New function. - (grub_cpio_dir): Handle symlinks. - (grub_cpio_open): Likewise. - (grub_cpio_close) [MODE_USTAR]: Free linkname. - -2011-10-30 Vladimir Serbinenko - - Fix iso9660 filename limitations and fix memory leaks. - - * grub-core/fs/iso9660.c (set_rockridge): Free sua at the end. - (grub_iso9660_iterate_dir): Fix slash handling in symlinks. - -2011-10-30 Vladimir Serbinenko - - Fix JFS file name length limitations. - - * grub-core/fs/jfs.c (grub_jfs_inode): Fix in-place symlink length. - (grub_jfs_diropen): Fix maximum filename length. - (grub_jfs_getent): Fix filename length. - (grub_jfs_lookup_symlink): Fix size checks. - -2011-10-30 Vladimir Serbinenko - - * grub-core/loader/mips/linux.c (loongson_machtypes): Fix fuloong type - string. - -2011-10-30 Vladimir Serbinenko - - Leverage BFS implementation to read AFS. - - * Makefile.util.def (libgrubmods): Add afs.c. - * grub-core/Makefile.core.def (afs): New module - * grub-core/fs/afs.c: New file. - * grub-core/fs/bfs.c [MODE_AFS]: Adapt for AFS. - -2011-10-30 Vladimir Serbinenko - - * grub-core/fs/bfs.c: Macroify and add some necessary sanity checks. - -2011-10-30 Vladimir Serbinenko - - * grub-core/fs/bfs.c: Run indent. - -2011-10-30 Vladimir Serbinenko - - BFS implementation based on the specification. - - * grub-core/fs/bfs.c: New file. - * Makefile.util.def (libgrubmods): Add bfs.c. - * grub-core/Makefile.core.def (bfs): New module. - -2011-10-30 Vladimir Serbinenko - - * util/grub-fstest.c (cmd_cp): Clarify error message. - (cmd_cmp): Likewise. - -2011-10-30 Yves Blusseau - - * po/POTFILES.in: Regenerate because of the removal of afs, afs_be, befs - and befs_be. - -2011-10-29 Vladimir Serbinenko - - Remove afs and befs because of copyright problem. - - * grub-core/fs/afs.c: Removed. - * grub-core/fs/afs_be.c: Removed. - * grub-core/fs/befs.c: Removed. - * grub-core/fs/befs_be.c: Removed. - * Makefile.util.def (libgrubkern): Remove afs, afs_be, befs and befs_be. - * grub-core/Makefile.core.def (afs): Removed. - (afs_be): Likewise. - (befs): Likewise. - (befs_be): Likewise. - -2011-10-28 Vladimir Serbinenko - - Prefer rockridge over Joliet. - - * grub-core/fs/iso9660.c (grub_iso9660_mount): Move rockridge detection - to ... - (set_rockridge): ... here. - (grub_iso9660_mount): Check rockridge on the primary label when - discovering. Ignore Joliet if Rockridge is present. - -2011-10-28 Vladimir Serbinenko - - Use shifts in nilfs2. - - * grub-core/fs/nilfs2.c (LOG_INODE_SIZE): New definition. - (LOG_NILFS_DAT_ENTRY_SIZE): Likewise. - (grub_nilfs2_palloc_entries_per_group): Replace with ... - (grub_nilfs2_log_palloc_entries_per_group): ... this. - (grub_nilfs2_palloc_group): Use shifts and bitmasks. - (grub_nilfs2_entries_per_block): Replaced with ... - (grub_nilfs2_log_entries_per_block_log): ... this. - (grub_nilfs2_blocks_per_group): Replaced with ... - (grub_nilfs2_blocks_per_group_log): ... this. - (grub_nilfs2_blocks_per_desc_block): Replaced with ... - (grub_nilfs2_blocks_per_desc_block_log): ... this. - (grub_nilfs2_palloc_desc_block_offset): Replaced with ... - (grub_nilfs2_palloc_desc_block_offset_log): ... this. - (grub_nilfs2_palloc_entry_offset): Replaced ... - (grub_nilfs2_palloc_entry_offset_log): ... this. Use shifts. - (grub_nilfs2_dat_translate): Use shifts. - (grub_nilfs2_read_inode): Likewise. - (GRUB_MOD_INIT): Ensure that logs are correct. - -2011-10-28 Vladimir Serbinenko - - Use shifts in minix filesystem. - - * grub-core/fs/minix.c (GRUB_MINIX_ZONESZ): Use log_block_size. - (GRUB_MINIX_ZONE2SECT): Likewise. - (grub_minix_data): Replace block_size with log_block_size. - (grub_minix_read_file): Use shifts. - (grub_minix_mount): Check block size and take a logarithm. - -2011-10-28 Vladimir Serbinenko - - Use shifts in squash4. - - * grub-core/fs/squash4.c (grub_squash_data): New field log2_blksz. - (squash_mount): Check block size and take logarithm. - (direct_read): Use shifts. - -2011-10-28 Vladimir Serbinenko - - Correct befs block counting logic. - - * grub-core/fs/afs.c (GRUB_AFS_BLOCKS_PER_DI_RUN): Replaced with... - (GRUB_AFS_LOG_BLOCKS_PER_DI_RUN): ... this. - (GRUB_AFS_BLOCKRUN_LOG_SIZE): New definition. - (grub_afs_read_inode): Use block_shift. - (RANGE_SHIFT): New definition. - (grub_afs_read_block): Account for RANGE_SHIFT, emit errors on - unexpected conditions, use shifts and appropriate types. - (GRUB_MOD_INIT): Check the value of GRUB_AFS_BLOCKRUN_LOG_SIZE. - -2011-10-28 Vladimir Serbinenko - - * grub-core/disk/raid.c (scan_devices): Check partition. - * grub-core/disk/lvm.c (do_lvm_scan): Likewise. - -2011-10-27 Vladimir Serbinenko - - Support BFS (befs) UUID. - - * grub-core/fs/afs.c (grub_afs_inode): Make small_data zero-size. - (grub_afs_small_data_element_header): New struct. - (grub_afs_read_inode): Read complete inode. Fix ino type while on it. - (grub_afs_read_attribute) [MODE_BFS]: New function. - (grub_afs_iterate_dir): Allocate for complete inode. - (grub_afs_mount): Likewise. - (grub_afs_uuid) [MODE_BFS]: New function. - (grub_afs_fs) [MODE_BFS]: Add .uuid. - -2011-10-27 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (read_device): Silence spurious warning. - (zfs_unmount): Fix memory leak. - -2011-10-26 Vladimir Serbinenko - - Support NTFS reparse points. - - * grub-core/fs/ntfs.c (list_file): Set symlink type when appropriate. - (symlink_descriptor): New struct. - (grub_ntfs_read_symlink): New function. - (grub_ntfs_iterate_dir): Use grub_ntfs_read_symlink. - (grub_ntfs_open): Likewise. - -2011-10-26 Vladimir Serbinenko - - * include/grub/ntfs.h: Add GRUB_NTFS_ prefix. All users updated. - -2011-10-26 Vladimir Serbinenko - - fstest xnu_uuid subcommand. - - * grub-core/commands/xnu_uuid.c (libgrubkrn): Add - grub-core/commands/xnu_uuid.c. - * util/grub-fstest.c (CMD_XNU_UUID): New enum value. - (fstest): Handle xnu_uuid. - (options): Document xnu_uuid. - (argp_parser): Parse xnu_uuid. - -2011-10-26 Vladimir Serbinenko - - * grub-core/commands/xnu_uuid.c (grub_cmd_xnu_uuid): Support - -l argument. Add newline at the end if printing. - (GRUB_MOD_INIT): Document -l. - -2011-10-26 Vladimir Serbinenko - - * grub-core/fs/nilfs2.c (grub_nilfs2_uuid): Add missing field length. - -2011-10-26 Vladimir Serbinenko - - ZFS multi-device and version 33 support. - - * Makefile.util.def (libgrubkern): Add grub-core/fs/zfs/zfsinfo.c. - * grub-core/fs/zfs/zfs.c (grub_zfs_device_desc): New struct. - (grub_zfs_data): Add multidev-ice-related fields. - (zio_checksum_verify): Zero-pad printed values. Print checksum name. - (dva_get_offset): Make dva const. - (zfs_fetch_nvlist): New function. - (fill_vdev_info_real): Likewise. - (fill_vdev_info): Likewise. - (check_pool_label): Likewise. - (scan_disk): Likewise. - (scan_devices): Likewise. - (read_device): Likewise. - (read_dva): Likewise. - (zio_read_gang): Use read_dva. - (zio_read_data): Likewise. - (zap_leaf_lookup): Add missing endian conversion. - (zap_verify): Add missing endian conversion. All users updated. - (fzap_lookup): Likewise. - (fzap_iterate): Likewise. - (dnode_get_path): Handle SA bonus. - (nvlist_find_value): Make input const. All users updated. - (unmount_device): New function. - (zfs_unmount): Use unmount_device. - (zfs_mount): Use scan_disk. - (zfs_mtime): New function. - (grub_zfs_open): Handle system attributes. - (fill_fs_info): Likewise. - (grub_zfs_dir): Likewise. - (grub_zfs_fs): Add mtime. - * grub-core/fs/zfs/zfsinfo.c (print_vdev_info): Add missing return. - * include/grub/zfs/sa_impl.h (SA_TYPE_OFFSET): New definition. - (SA_MTIME_OFFSET): Likewise. - (SA_SYMLINK_OFFSET): Likewise. - * include/grub/zfs/zfs.h (SPA_VERSION): Increase to 33. - * util/grub-fstest.c (CMD_ZFSINFO): New enum value. - (fstest): Support zfsinfo. - (argp_parser): Likewise. - -2011-10-26 Vladimir Serbinenko - - * include/grub/datetime.h (grub_datetime2unixtime): Fix off-by-one - error. - -2011-10-26 Vladimir Serbinenko - - ZFS fixes. - - * grub-core/fs/zfs/zfs.c (fzap_iterate): Fix handling of indexes - sharing the same block. Iterate over correct number of indices. - (dnode_get_path): Handle symlinks correctly. - -2011-10-25 Vladimir Serbinenko - - * grub-core/fs/jfs.c (grub_jfs_sblock): Fix offset to volname. - -2011-10-25 Vladimir Serbinenko - - Read label on HFS+. - - * grub-core/fs/hfsplus.c (grub_hfsplus_cmp_catkey_id): New function. - (grub_hfsplus_btree_search): Fix types. - (grub_hfsplus_label): Implement. - -2011-10-25 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (grub_ntfs_uuid): Fix a memory leak. - -2011-10-25 Vladimir Serbinenko - - * grub-core/fs/fat.c (grub_fat_uuid): Make uppercase to match Linux. - -2011-10-25 Vladimir Serbinenko - - Fix symlink handling on iso9660. - - * grub-core/fs/iso9660.c (grub_fshelp_node): Remove dir_off. Add symlink - All users updated. - (grub_iso9660_susp_iterate): Accept zero-size iterate. - (grub_iso9660_read_symlink): Moved most of code ... - (grub_iso9660_iterate_dir): ... here. Fill node->symlink. - -2011-10-25 Vladimir Serbinenko - - * grub-core/loader/i386/bsd.c (grub_netbsd_add_boot_disk_and_wedge): - Use union to avoid breaking strict-aliasing rules. - -2011-10-25 Vladimir Serbinenko - - Support multi-extent iso files. - - * grub-core/fs/iso9660.c (grub_iso9660_data): Remove first_sector. - Add node. - (grub_fshelp_node): Revamp. All users updated. - (FLAG_*): New enum. - (read_node): New function. - (grub_iso9660_susp_iterate): Use read_node. Receive a node as argument. - All users updated. - (grub_iso9660_mount): Don't attempt to read sua when there is none. - (get_node_size): New function. - (grub_iso9660_iterate_dir): Use read_node. Agglomerate multi-extent - entries. - Fix memory leak on . and .. - (grub_iso9660_read): Use read_node. - (grub_iso9660_close): Free node. - -2011-10-25 Vladimir Serbinenko - - Fix tar 4G limit and handle paths containing dot. - - * grub-core/fs/cpio.c (grub_cpio_data): Use grub_off_t for offsets. - (canonicalize): New function. - (grub_cpio_find_file): Use canonicalize. Store offs in - grub_disk_addr_t. - (grub_cpio_dir): Use grub_disk_addr_t. - (grub_cpio_open): Likewise. - -2011-10-25 Vladimir Serbinenko - - Fix handling of uncompressed blocks on squashfs and break 4G limit. - - * grub-core/fs/squash4.c (grub_squash_super): Add block_size. Remove - unused flags. - (grub_squash_inode): Add long_file and block_size. - (grub_squash_cache_inode): New struct. - (grub_squash_dirent): Make types into enum. - (SQUASH_TYPE_LONG_REGULAR): New type. - (grub_squash_frag_desc): Add field size. - (SQUASH_BLOCK_FLAGS): New enum. - (grub_squash_data): Use grub_squash_cache_inode. - (grub_fshelp_node): Make ino_chunk 64-bit. - (read_chunk): Minor argument change. All users updated. - (squash_mount): Use correct le_to_cpu. - (grub_squash_open): Handle LONG_REGULAR. - (direct_read): New function. - (grub_squash_read_data): Handle blocks correctly. - -2011-10-25 Vladimir Serbinenko - - * grub-core/kern/disk.c (grub_disk_read_small): Fix memory leak. - -2011-10-25 Vladimir Serbinenko - - * grub-core/fs/romfs.c (grub_romfs_open): Add missing return. - -2011-10-24 Vladimir Serbinenko - - Fix 2G limit on ZFS. - - * grub-core/fs/zfs/zfs.c (zio_checksum_verify): Use more appropriate - types. - (uberblock_verify): Likewise. - (dmu_read): Likewise. - (grub_zfs_read): Likewise. Remove invalid cast. - -2011-10-24 Vladimir Serbinenko - - * grub-core/fs/jfs.c (grub_jfs_blkno): Use more appropriate types. - (grub_jfs_blkno): Fix incorrect shift. - (grub_jfs_read_file): Use more appropriate types. - -2011-10-24 Vladimir Serbinenko - - Support triple indirect on minix2 and minix3. - - * grub-core/fs/minix.c (grub_minix_inode) [MODE_MINIX2 || MODE_MINIX3]: - Declare triple_indir_zone. - (grub_minix_get_file_block) [MODE_MINIX2 || MODE_MINIX3]: Handle triple - indirect. - -2011-10-24 Vladimir Serbinenko - - Minix FS fixes. - - * grub-core/fs/minix.c (GRUB_MINIX_INODE_SIZE): Size is always 32-bit. - (grub_minix_inode) [!MODE_MINIX2 && !MODE_MINIX3]: Make size 32-bit. - Rename ctime to mtime. All users updated. - (grub_minix_get_file_block): Fix types and double indirect computations. - -2011-10-23 Vladimir Serbinenko - - * grub-core/fs/fat.c (grub_fat_label) [MODE_EXFAT]: Set *label to 0 - if no label is found. - (grub_fat_iterate_dir): Fix file size type. - (grub_fat_iterate_dir): Likewise. - -2011-10-23 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c (gf_invert): Declare as const and - save some space. - * include/grub/offsets.h (GRUB_KERNEL_I386_PC_RAW_SIZE): Decrease. - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): Likewise. - -2011-10-23 Vladimir Serbinenko - - * util/import_gcry.py: Automatically fix camellia.c and camellia.h. - -2011-10-23 Vladimir Serbinenko - - * util/import_gcry.py: Accept space between # and include. - -2011-10-23 Vladimir Serbinenko - - * grub-core/lib/setjmp.S [__ia64__]: Include ./ia64/longjmp.S. - -2011-10-23 Vladimir Serbinenko - - Fine grainely disable warnings on lexer. Remove Wno-error on it. - - * grub-core/Makefile.core.def (normal): Remove -Wno-error. - * grub-core/script/lexer.c: Declare yytext_ptr to avoid having - yylex_strncpy. - * grub-core/script/yylex.l: Add fine-grained #pragma. - -2011-10-23 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/string.h (memcpy) [GRUB_UTIL]: - New inline function. - * grub-core/lib/libgcrypt_wrap/cipher_wrap.h (memcpy) [GRUB_UTIL]: - Likewise. - (memset) [GRUB_UTIL]: Likewise. - (memcmp) [GRUB_UTIL]: Likewise. - -2011-10-23 Vladimir Serbinenko - - * include/grub/misc.h (grub_memcpy): Declare grub_memcpy with static - inline function rather than a define. - -2011-10-23 Vladimir Serbinenko - - * util/grub-setup.c: Add missing include. - -2011-10-23 Vladimir Serbinenko - - * util/ieee1275/grub-ofpathname.c: Add missing include. - -2011-10-23 Vladimir Serbinenko - - * grub-core/kern/i386/pc/startup.S (grub_exit): Add missing zeroing-out. - * grub-core/lib/i386/reboot_trampoline.S (grub_reboot_start): - Likewise. - -2011-10-23 Vladimir Serbinenko - - * grub-core/io/lzopio.c (test_header): Fix incorrect memcmp instead of - grub_memcmp usage. - -2011-10-23 Vladimir Serbinenko - - * util/grub-install.in: Add datarootdir as per automake manual - suggestion. - * util/grub-mknetdir.in: Likewise. - -2011-10-23 Vladimir Serbinenko - - * util/grub.d/10_hurd.in: Add datarootdir as per automake manual - suggestion. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/10_netbsd.in: Likewise. - * util/grub.d/10_windows.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - -2011-10-20 Vladimir Serbinenko - - Remove redundant grub_kernel_image_size. - - * grub-core/kern/i386/coreboot/init.c (grub_machine_init): Use - _edata and _start. - * grub-core/kern/i386/coreboot/startup.S: Move multiboot header after - the small code. It moves it only by few bytes but simplifies the code. - * grub-core/kern/i386/pc/init.c (grub_machine_init): Use _edata and - _start. - * grub-core/kern/i386/pc/startup.S: Use _edata and _start. - (grub_kernel_image_size): Removed. - * grub-core/kern/i386/qemu/startup.S: Use _edata and _start. - (grub_kernel_image_size): Removed. - [APPLE_CC]: Remove apple compiler support. i386-qemu port can't be - compiled with Apple toolchain. - * grub-core/kern/sparc64/ieee1275/crt0.S: Remove leftover fields. - * include/grub/i386/pc/kernel.h (grub_kernel_image_size): Removed. - * include/grub/i386/qemu/kernel.h (grub_kernel_image_size): Removed. - (grub_total_module_size): Likewise. - * include/grub/offsets.h (GRUB_KERNEL_I386_PC_KERNEL_IMAGE_SIZE): - Removed. - (GRUB_KERNEL_I386_PC_COMPRESSED_SIZE): Put it lower. - (GRUB_KERNEL_I386_PC_INSTALL_DOS_PART): Likewise. - (GRUB_KERNEL_I386_PC_INSTALL_BSD_PART): Likewise. - (GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY): Likewise. - (GRUB_KERNEL_I386_QEMU_KERNEL_IMAGE_SIZE): Removed. - (GRUB_KERNEL_SPARC64_IEEE1275_KERNEL_IMAGE_SIZE): Likewise. - (GRUB_KERNEL_SPARC64_IEEE1275_COMPRESSED_SIZE): Likewise. - * include/grub/sparc64/ieee1275/kernel.h (grub_kernel_image_size): - Removed. - (grub_total_module_size): Removed. - * util/grub-mkimage.c (image_target_desc): Remove image_size. - (image_targets): Likewise. - Set .compressed_size to no field on sparc. - (generate_image): Remove kernel_image_size handling. - -2011-10-19 Szymon Janc - - * grub-core/bus/usb/uhci.c (grub_uhci_setup_transfer): Fix possible - NULL pointer dereference. - -2011-10-19 Vladimir Serbinenko - - Removed unused GRUB_BOOT_VERSION. Check for kernel version is better - done with a dedicated section. - - * grub-core/boot/sparc64/ieee1275/boot.S: Remove GRUB_BOOT_VERSION. - Ensure the correct position of boot_path. - * grub-core/kern/i386/efi/startup.S: Remove GRUB_BOOT_VERSION. - * grub-core/kern/i386/pc/startup.S: Likewise. Ensure correct position of - other fields. - * grub-core/kern/x86_64/efi/startup.S: Remove GRUB_BOOT_VERSION. - * include/grub/boot.h: Removed. All references removed. - * include/grub/sparc64/ieee1275/boot.h (GRUB_BOOT_MACHINE_VER_MAJ): - Removed. - (GRUB_BOOT_MACHINE_BOOT_DEVPATH): Make it lower. - -2011-10-19 Vladimir Serbinenko - - * util/grub-install.in: Declare IEEE1275 as able to find out the disk - name. - -2011-10-19 Vladimir Serbinenko - - * grub-core/kern/main.c (grub_set_prefix_and_root): Init prefix. - -2011-10-19 Vladimir Serbinenko - - * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_encode_devname): - Don't add the bogus brackets. - -2011-10-19 Vladimir Serbinenko - - ExFAT support. - - * Makefile.util.def (libgrubmods.a): Add grub-core/fs/exfat.c. - * grub-core/Makefile.core.def (exfat): New module. - * grub-core/fs/exfat.c: New file. - * grub-core/fs/fat.c (GRUB_FAT_DIR_ENTRY_SIZE): Removed. - (GRUB_FAT_ATTR_*): Make into an enum. - (GRUB_FAT_ATTR_LONG_NAME) [MODE_EXFAT]: Removed. - (GRUB_FAT_ATTR_VALID) [MODE_EXFAT]: Remove GRUB_FAT_ATTR_VOLUME_ID. - (GRUB_FAT_ATTR_VOLUME_ID) [MODE_EXFAT]: Removed. - (GRUB_FAT_MAXFILE): Removed. - (grub_exfat_bpb) [MODE_EXFAT]: New struct. - (grub_current_fat_bpb_t): New type. - (grub_fat_dir_entry) [MODE_EXFAT]: New struct. - (grub_fat_dir_node) [MODE_EXFAT]: New struct. - (grub_fat_dir_node_t): New type. - (grub_fat_data) [MODE_EXFAT]: Remove root_sector and num_root_sectors. - (fat_log2) [MODE_EXFAT]: Removed. - (grub_fat_mount): Use grub_current_fat_bpb_t. Add some sanity checks. - (grub_fat_mount) [MODE_EXFAT]: Handle ExFAT. - (grub_fat_iterate_dir) [MODE_EXFAT]: New function. - (grub_fat_find_dir) [MODE_EXFAT]: Handle ExFAT. - (grub_fat_label) [MODE_EXFAT]: New function. - (grub_fat_fs) [MODE_EXFAT]: Set name to "exfat" and - reserved_first_sector to 0. - -2011-10-19 Vladimir Serbinenko - - Move grub_reboot out of the kernel. - - * grub-core/Makefile.core.def (reboot): Add platform-specific files. - * grub-core/kern/efi/efi.c (grub_reboot): Moved to ... - * grub-core/lib/efi/reboot.c: ... here. - * grub-core/kern/i386/efi/startup.S: Remove including of realmode.S. - * grub-core/kern/i386/ieee1275/startup.S: Likewise. - * grub-core/kern/i386/pc/startup.S (grub_exit): Inline cold_reboot. - * grub-core/kern/i386/realmode.S (grub_reboot): Moved to... - * grub-core/lib/i386/reboot_trampoline.S: ... here. - * grub-core/kern/ieee1275/openfw.c (grub_reboot): Moved to... - * grub-core/lib/ieee1275/reboot.c: ... here. - * grub-core/kern/mips/arc/init.c (grub_reboot): Moved to... - * grub-core/lib/mips/arc/reboot.c: ... here. - * grub-core/kern/mips/loongson/init.c (grub_reboot): Moved to... - * grub-core/lib/mips/loongson/reboot.c: ...here. - * grub-core/kern/mips/qemu_mips/init.c (grub_reboot): Moved to... - * grub-core/lib/mips/qemu_mips/reboot.c: ... here. - * include/grub/emu/misc.h (grub_reboot): New function declaration. - * include/grub/i386/reboot.h: New file. - * include/grub/mips/loongson/ec.h: Fix includes. - * include/grub/mips/qemu_mips/kernel.h (grub_reboot): Removed. - * include/grub/misc.h (grub_reboot): Don't mark as kernel function. - * grub-core/lib/i386/reboot.c: New file. - -2011-10-18 Vladimir Serbinenko - - Make grub_prefix into module to fix the arbitrary limit and save - some space. - - * grub-core/kern/emu/main.c (grub_prefix): Removed. - * grub-core/kern/i386/coreboot/startup.S (grub_prefix): Likewise. - * grub-core/kern/i386/efi/startup.S (grub_prefix): Likewise. - * grub-core/kern/i386/ieee1275/startup.S (grub_prefix): Likewise. - * grub-core/kern/i386/pc/startup.S (grub_prefix): Likewise. - * grub-core/kern/i386/qemu/startup.S (grub_prefix): Likewise. - * grub-core/kern/ia64/efi/startup.S (grub_prefix): Likewise. - * grub-core/kern/mips/startup.S (grub_prefix): Likewise. - * grub-core/kern/powerpc/ieee1275/startup.S (grub_prefix): Likewise. - * grub-core/kern/sparc64/ieee1275/crt0.S (grub_prefix): Likewise. - * grub-core/kern/x86_64/efi/startup.S (grub_prefix): Likewise. - * include/grub/ia64/efi/kernel.h: Removed. - * include/grub/kernel.h: New module type OBJ_TYPE_PREFIX. - (grub_prefix): Removed. - * include/grub/offsets.h (GRUB_KERNEL_I386_PC_PREFIX): Removed. - (GRUB_KERNEL_I386_PC_PREFIX_END): Likewise. - (GRUB_KERNEL_I386_QEMU_PREFIX): Likewise. - (GRUB_KERNEL_I386_QEMU_PREFIX_END): Likewise. - (GRUB_KERNEL_SPARC64_IEEE1275_PREFIX): Likewise. - (GRUB_KERNEL_SPARC64_IEEE1275_PREFIX_END): Likewise. - (GRUB_KERNEL_POWERPC_IEEE1275_PREFIX): Likewise. - (GRUB_KERNEL_POWERPC_IEEE1275_PREFIX_END): Likewise. - (GRUB_KERNEL_MIPS_LOONGSON_PREFIX): Likewise. - (GRUB_KERNEL_MIPS_LOONGSON_PREFIX_END): Likewise. - (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX): Likewise. - (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END): Likewise. - (GRUB_KERNEL_MIPS_ARC_PREFIX): Likewise. - (GRUB_KERNEL_MIPS_ARC_PREFIX_END): Likewise. - (GRUB_KERNEL_I386_EFI_PREFIX): Likewise. - (GRUB_KERNEL_I386_EFI_PREFIX_END): Likewise. - (GRUB_KERNEL_IA64_EFI_PREFIX): Likewise. - (GRUB_KERNEL_IA64_EFI_PREFIX_END): Likewise. - (GRUB_KERNEL_X86_64_EFI_PREFIX): Likewise. - (GRUB_KERNEL_X86_64_EFI_PREFIX_END): Likewise. - (GRUB_KERNEL_I386_COREBOOT_PREFIX): Likewise. - (GRUB_KERNEL_I386_COREBOOT_PREFIX_END): Likewise. - (GRUB_KERNEL_I386_MULTIBOOT_PREFIX): Likewise. - (GRUB_KERNEL_I386_MULTIBOOT_PREFIX_END): Likewise. - (GRUB_KERNEL_I386_IEEE1275_PREFIX): Likewise. - (GRUB_KERNEL_I386_IEEE1275_PREFIX_END): Likewise. - (GRUB_KERNEL_MACHINE_PREFIX): Likewise. - (GRUB_KERNEL_MACHINE_PREFIX_END): Likewise. - * grub-core/kern/main.c (grub_set_prefix_and_root): Retrieve grub_prefix - from module. - * util/grub-mkimage.c (image_target_desc): Removed prefix and - prefix_end. - (image_targets): Likewise. - (generate_image): Put prefix as a module. - -2011-10-16 Vladimir Serbinenko - - Replace grub_module_iterate with FOR_MODULES. - - * grub-core/disk/memdisk.c (GRUB_MOD_INIT): Switched to new interface. - * grub-core/kern/efi/efi.c (grub_arch_modules_addr): Renamed to... - (grub_efi_modules_addr): ...this. - * grub-core/kern/efi/init.c (grub_modbase): New variable. - (grub_efi_init): Set grub_modbase. - * grub-core/kern/emu/main.c (grub_arch_modules_addr): Removed. - (grub_modbase): New variable. - * grub-core/kern/i386/coreboot/init.c (grub_arch_modules_addr): Removed. - (grub_modbase): New variable. - (grub_machine_init): Set grub_modbase. - * grub-core/kern/i386/pc/init.c (grub_arch_modules_addr): Removed. - (grub_modbase): New variable. - (grub_machine_init): Set grub_modbase. - * grub-core/kern/ieee1275/init.c (grub_arch_modules_addr): Removed. - (grub_modbase): New variable. - (grub_machine_init): Set grub_modbase. - * grub-core/kern/main.c (grub_module_iterate): Remove. - (grub_modules_get_end): Use grub_modbase. - (grub_load_modules): Use FOR_MODULES. - (grub_load_config): Likewise. - * grub-core/kern/mips/arc/init.c (grub_arch_modules_addr): Removed. - (grub_modbase): New variable. - (grub_machine_init): Set grub_modbase. - * grub-core/kern/mips/loongson/init.c (grub_arch_modules_addr): Removed. - (grub_modbase): New variable. - (grub_machine_init): Set grub_modbase. - * grub-core/kern/mips/qemu_mips/init.c (grub_arch_modules_addr): - Removed. - (grub_modbase): New variable. - (grub_machine_init): Set grub_modbase. - * include/grub/efi/efi.h (grub_efi_modules_addr): New declaration. - * include/grub/kernel.h (grub_arch_modules_addr): Removed. - (grub_module_iterate): Likewise. - (grub_modbase): New variable declaration. - (FOR_MODULES): New macro. - -2011-10-16 Vladimir Serbinenko - - * configure.ac: Check for __ctzdi2 and __ctzsi2. - * include/grub/libgcc.h: Include __ctzdi2 and __ctzsi2 if present. - -2011-10-16 Vladimir Serbinenko - - Fix few obvious type discrepancies. - - * grub-core/fs/affs.c (grub_affs_read_file): Use grub_off_t for offset. - * grub-core/fs/afs.c (grub_afs_read_file): Likewise. - * grub-core/fs/fshelp.c (grub_fshelp_find_file): Remove leftover - variable. - * grub-core/fs/hfs.c (grub_hfs_read_file): Use grub_off_t for offset - and connected types. - * grub-core/fs/nilfs2.c (grub_nilfs2_read_file): Use grub_off_t for - offset. - (grub_nilfs2_iterate_dir): Use grub_off_t for fpos. - * grub-core/fs/sfs.c (grub_sfs_read_file): Use grub_off_t for offset. - * grub-core/fs/ufs.c (grub_ufs_read_file): Use grub_off_t for offset - and connected types. - -2011-10-16 Vladimir Serbinenko - - Fix python 3.x incompatibilities. - - * gentpl.py: Put brackets around print strings. - * util/import_gcry.py: Open explicitly as utf-8. - Use in instead of has_key. - -2011-10-16 Vladimir Serbinenko - - * grub-core/fs/xfs.c (grub_xfs_inode): New field fork_offset. - (GRUB_XFS_INO_AGBITS): Make into inline function. - (GRUB_XFS_INO_INOINAG): Likewise. - (GRUB_XFS_INO_AG): Likewise. - (GRUB_XFS_FSB_TO_BLOCK): Likewise. - (GRUB_XFS_EXTENT_OFFSET): Likewise. - (GRUB_XFS_EXTENT_BLOCK): Likewise. - (GRUB_XFS_EXTENT_SIZE): Likewise. - (GRUB_XFS_ROUND_TO_DIRENT): Likewise. - (GRUB_XFS_NEXT_DIRENT): Likewise. - (grub_xfs_read_block): Rewrite the btree parsing. Fixes invalid BMAP. - (grub_xfs_read_file): Fix offset type. - -2011-10-15 Robert Millan - - * util/getroot.c (grub_util_get_grub_dev): Fix OS selection #ifdefs. - -2011-10-15 Robert Millan - - Fix build problem on FreeBSD and GNU/kFreeBSD. - - * util/getroot.c [__FreeBSD_kernel__]: Include `'. - -2011-10-14 Vladimir Serbinenko - - Fix overflow with >2GiB file on HFS+. >4GiB wasn't tested. - - * grub-core/fs/hfsplus.c (grub_hfsplus_btree): Use more appropriate - types. - (grub_hfsplus_btree_recoffset): Likewise. - (grub_hfsplus_btree_recptr): Likewise. - (grub_hfsplus_find_block): Likewise. - (grub_hfsplus_btree_search): Likewise. - (grub_hfsplus_read_block): Likewise. - (grub_hfsplus_read_file): Likewise. - (grub_hfsplus_mount): Likewise. - (grub_hfsplus_btree_iterate_node): Likewise. - (grub_hfsplus_btree_search): Likewise. - (grub_hfsplus_iterate_dir): Likewise. - (grub_hfsplus_read): A small code simplification. - -2011-10-14 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c - (convert_system_partition_to_system_disk): Don't assume that children - of mapper nodes are mapper nodes. - -2011-10-14 Vladimir Serbinenko - - * grub-core/lib/posix_wrap/ctype.h (isxdigit): Use grub_isxdigit. - * include/grub/misc.h (grub_isxdigit): New function. - * grub-core/video/colors.c (my_isxdigit): Removed. All users - switched to grub_isxdigit. - * grub-core/term/serial.c (grub_serial_find): Fix in case of port - number starting with a letter. - -2011-10-09 Robert Millan - - LVM support for FreeBSD and GNU/kFreeBSD. - - * util/lvm.c (grub_util_lvm_isvolume): Enable on FreeBSD and - GNU/kFreeBSD. - (LVM_DEV_MAPPER_STRING): Move from here ... - * include/grub/util/lvm.h (LVM_DEV_MAPPER_STRING): ... to here. - * util/getroot.c: Include `'. - (grub_util_get_dev_abstraction): Enable - grub_util_biosdisk_is_present() on FreeBSD and GNU/kFreeBSD. - Check for LVM abstraction on FreeBSD and GNU/kFreeBSD. - (grub_util_get_grub_dev): Replace "/dev/mapper/" with - `LVM_DEV_MAPPER_STRING'. Enable LVM and mdRAID only on platforms that - support it. - * util/grub-setup.c (main): Check for LVM also on FreeBSD and - GNU/kFreeBSD. - * util/grub.d/10_kfreebsd.in: Load `geom_linux_lvm' kernel module - when LVM abstraction is required for ${GRUB_DEVICE}. - -2011-10-06 Szymon Janc - - Add support for LZO compression in GRUB: - - import of minilzo library, - - LZO decompression for btrfs, - - lzop files decompression. - - * grub-core/io/lzopio.c: New file. - * grub-core/lib/adler32.c: Likewise. - * grub-core/lib/minilzo/lzoconf.h: Likewise. - * grub-core/lib/minilzo/lzodefs.h: Likewise. - * grub-core/lib/minilzo/minilzo.c: Likewise. - * grub-core/lib/minilzo/minilzo.h: Likewise. - * Makefile.util.def (libgrubmods.a): Add grub-core/io/lzopio.c, - grub-core/lib/adler32.c, grub-core/io/lzopio.c, - grub-core/lib/minilzo/minilzo.c to common. - * Makefile.util.def (libgrubmods.a): Add flags required by minilzo to - cflags in cppflags. - * grub-core/Makefile.core.def (btrfs): Likewise. - * grub-core/Makefile.core.def (lzopio): New module. - (adler32): Likewise. - * grub-core/fs/btrfs.c: Include minilzo.h. - (GRUB_BTRFS_COMPRESSION_LZO): New define. - (GRUB_BTRFS_LZO_BLOCK_SIZE): Likewise. - (GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE): Likewise. - (grub_btrfs_lzo_decompress): New function. - (grub_btrfs_extent_read): Add support for LZO compression type. - * include/grub/types.h (GRUB_UCHAR_MAX): New define. - (GRUB_USHRT_MAX): Likewise. - (GRUB_UINT_MAX): Likewise. - * grub-core/lib/posix_wrap/limits.h (USHRT_MAX): Likewise. - (UINT_MAX): Likewise. - (CHAR_BIT): Likewise. - * grub-core/lib/posix_wrap/sys/types.h (ULONG_MAX): Moved to - grub-core/lib/posix_wrap/limits.h - (UCHAR_MAX): Likewise. - * include/grub/file.h (grub_file_filter_id): New compression filter - GRUB_FILE_FILTER_LZOPIO. - * include/grub/file.h (grub_file_filter_id): Set - GRUB_FILE_FILTER_LZOPIO as GRUB_FILE_FILTER_COMPRESSION_LAST. - * include/grub/types.h (grub_get_unaligned16): New function. - (grub_get_unaligned32): Likewise. - (grub_get_unaligned64): Likewise. - * util/import_gcry.py (cryptolist): Add adler32. - -2011-10-05 Vladimir Serbinenko - - * grub-core/Makefile.core.def: Eliminate rarely used emu_condition. This - in perspective decreases the complexity of build system and fixes - compilation right now. - -2011-10-01 Ales Nesrsta - - * grub-core/bus/usb/uhci.c: Changes made by Rock Cui - thanks! - (fixed problem related to using UHCI with coreboot). - -2011-08-25 BVK Chaitanya - - * gentpl.py: Use Autogen macros so that the output template file - (Makefile.tpl) size is reduced. - -2011-09-29 Mads Kiilerich - - * grub-core/Makefile.core.def (kernel): Add kern/i386/int.S to - extra_dist. - -2011-09-29 Mario Limonciello - - * util/misc.c (grub_util_get_disk_size) [__MINGW32__]: Strip trailing - slashes on PHYSICALDRIVE%d paths when making Windows CreateFile calls. - -2011-09-29 Mario Limonciello - - * grub-core/kern/emu/misc.c (canonicalize_file_name) [__MINGW32__]: Use - _fullpath. - -2011-09-29 Mario Limonciello - - Remove extra declaration of sleep for mingw32. - - * util/misc.c (sleep) [__MINGW32__]: Removed. - * include/grub/util/misc.h (sleep) [__MINGW32__]: Likewise. - -2011-09-28 GrĂ©goire Sutre - - * include/grub/bsdlabel.h (grub_partition_bsd_disk_label): Add fields - type and packname. - * include/grub/i386/netbsd_bootinfo.h (NETBSD_BTINFO_BOOTDISK): - Resurrected. - (NETBSD_BTINFO_BOOTWEDGE): New definition. - (grub_netbsd_btinfo_bootwedge): New struct. - * grub-core/loader/i386/bsd.c (grub_netbsd_add_boot_disk_and_wedge): - New function. - (grub_cmd_netbsd): Call grub_netbsd_add_boot_disk_and_wedge. - -2011-09-28 Thomas Haller - - * grub-core/loader/multiboot_elfxx.c (Elf_Shdr): Set according to - loader. - -2011-09-28 Andreas Born - - Fix incorrect identifiers in bash-completion. - - * util/bash-completion.d/grub-completion.bash.in - (_grub_mkpasswd-pbkdf2): Rename to ... - (_grub_mkpasswd_pbkdf2): ... this. All users updated. - (_grub_script-check): Rename to ... - (_grub_script_check): ... this. All users updated. - -2011-09-28 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): - Return 0 if disk isn't biosdisk. - -2011-09-17 GrĂ©goire Sutre - - * Makefile.util.def (grub-mkrelpath): Add LIBUTIL for getrawpartition(3) - on NetBSD. - * Makefile.util.def (grub-fstest): Likewise. - -2011-09-17 GrĂ©goire Sutre - - * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors) [__NetBSD__]: - Get sector size from disk label. - -2011-09-05 Colin Watson - - * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Return 1 for - */README* as well as README*. - Reported by: Axel Beckert. - -2011-08-23 Vladimir Serbinenko - - * grub-core/kern/mips/loongson/init.c (grub_machine_init): Handle the - case of less than 256 MiB of RAM. - -2011-08-23 Vladimir Serbinenko - - * grub-core/commands/wildcard.c (make_regex): Handle @. - -2011-08-23 Vladimir Serbinenko - - * util/grub-install.in: Move cryptodisk logic to appropriate place. - -2011-08-21 Szymon Janc - - * acinclude.m4: Use AC_LANG_PROGRAM macro to generate source code for - AC_LANG_CONFTEST macros. - -2011-08-20 Szymon Janc - - Add grub-fstest option to uncompress data for commands. - - * util/grub-fstest.c (uncompress): New var. - (options): New option -u. - -2011-08-20 Szymon Janc - - * grub-core/loader/i386/linux.c (grub_linux_setup_video): Add - GRUB_VIDEO_DRIVER_RADEON_FULOONG2E to switch case statement. - -2011-08-20 Szymon Janc - - * grub-core/io/gzio.c (grub_gzio_open): Always return original io if - file type was not recognized correctly (not gzip or corrupted). - -2011-08-19 Vladimir Serbinenko - - * grub-core/kern/mips/loongson/init.c (grub_reboot): Reboot Fuloong. - * include/grub/cs5536.h (GRUB_CS5536_MSR_DIVIL_RESET): New definition. - -2011-08-19 Vladimir Serbinenko - - * grub-core/Makefile.core.def (kernel): Add video/radeon_fuloong2e.c on - loongson. - * grub-core/kern/mips/loongson/init.c (grub_machine_init): Init - video_radeon_fuloong2e. - * grub-core/video/radeon_fuloong2e.c: New file. - * include/grub/video.h (grub_video_id_t): Add new ID - GRUB_VIDEO_DRIVER_RADEON_FULOONG2E. - -2011-08-19 Vladimir Serbinenko - - * include/grub/mips/loongson.h (GRUB_CPU_LOONGSON_COP0_PRID): New - define. - * grub-core/kern/mips/loongson/init.c (grub_machine_init): Check - that PRID matches the detected subplatform and reset the subplatform - if it doesn't. - -2011-08-19 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_vprintf): Fix a bug on malloc failure. - -2011-08-19 Vladimir Serbinenko - - Fix PCI iterating on functions >= 4. - - * grub-core/bus/pci.c (grub_pci_iterate): Remove useless ghost skipping. - * include/grub/mips/loongson/pci.h (GRUB_LOONGSON_OHCI_GHOST_FUNCTION): - Removed. - (GRUB_LOONGSON_EHCI_GHOST_FUNCTION): Likewise. - (grub_pci_read): Fix bitmask. - (grub_pci_read_word): Likewise. - (grub_pci_read_byte): Likewise. - (grub_pci_write): Likewise. - (grub_pci_write_word): Likewise. - (grub_pci_write_byte): Likewise. - -2011-08-19 Vladimir Serbinenko - - * configure.ac: Don't impose march=loongson2f on loongson platform. (It - can still be specified in TARGET_CFLAGS) - -2011-08-19 Vladimir Serbinenko - - Rename Fuloong into Fuloong 2F. Add new ID for Fuloong2E. - - * grub-core/Makefile.core.def (fwstart_fuloong): Rename fwstart_fuloong - into fwstart_fuloong2f. Use boot/mips/loongson/fuloong2f.S. - * grub-core/boot/mips/loongson/fuloong.S: Rename to ... - * grub-core/boot/mips/loongson/fuloong2f.S: ... this. - (FULOONG): Rename to ... - (FULOONG2F): ... this. All users updated. - * grub-core/boot/mips/startup_raw.S (machtype_fuloong_str): Rename to - (machtype_fuloong2f_str): ... this. - (machtype_fuloong2e_str): New string. - Check for machtype_fuloong2e_str. - * grub-core/loader/mips/linux.c (loongson_machtypes) - [GRUB_MACHINE_MIPS_LOONGSON]: Add GRUB_ARCH_MACHINE_FULOONG2E. - * grub-core/term/serial.c (loongson_defserial) - [GRUB_MACHINE_MIPS_LOONGSON]: New array. - (grub_serial_register) [GRUB_MACHINE_MIPS_LOONGSON]: Use - loongson_defserial. - * include/grub/mips/loongson/kernel.h (GRUB_ARCH_MACHINE_FULOONG): - Rename to ... - (GRUB_ARCH_MACHINE_FULOONG2F): ... this. - (GRUB_ARCH_MACHINE_FULOONG2E): New const. - * util/grub-mkimage.c (image_target_desc): Rename IMAGE_FULOONG_FLASH - to IMAGE_FULOONG2F_FLASH. All users updated. - (image_targets): Rename images. - * util/grub-mkstandalone.in: Accept fuloong2f and fuloong2e. - -2011-08-19 Szymon Janc - - Make enable of disk cache statistics code configurable. - - * configure.ac: --enable-cache-stats added. - * config.h.in (DISK_CACHE_STATS): New define. - * grub-core/Makefile.core.def (cacheinfo): New command. - * include/grub/disk.h(grub_disk_cache_get_performance): New function. - * grub-core/commands/cacheinfo.c: New file. - * grub-core/commands/minicmd.c (grub_rescue_cmd_info): Updated and - moved to cacheinfo.c. - * grub-core/kern/disk.c: Use DISK_CACHE_STATS to disable disk cache - debug code. - * include/grub/disk.h: Likewise. - -2011-08-19 Szymon Janc - - * Makefile.am (AUTOMAKE_OPTIONS): = Added -Wno-portability flag. - * grub-core/Makefile.am: Likewise. - -2011-08-16 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_iterate): Skip with - non-zero pull. - -2011-08-16 Vladimir Serbinenko - - * grub-core/fs/jfs.c (grub_jfs_read_file): New parameter ino. - All users updated. - (grub_jfs_lookup_symlink): Use correct starting inode. - -2011-08-16 Vladimir Serbinenko - - * util/grub-setup.c (main): Add missing gcry initialisation. - -2011-08-16 Vladimir Serbinenko - - Don't accept text modes on EFI when booting Linux. - - * grub-core/loader/i386/linux.c (ACCEPTS_PURE_TEXT): New define. - (grub_linux_boot) [!ACCEPTS_PURE_TEXT]: Restrict to graphics modes. - -2011-08-15 Mario Limonciello -2011-08-15 Colin Watson - - * util/grub-probe.c (probe): Canonicalise the path argument, fixing - use of "/path/.." as in grub-install for EFI as well as handling - symlinks correctly. - Fixes Debian bug #637768. - -2011-08-15 Colin Watson - - * util/grub-probe.c: Remove duplicate #include. - -2011-08-10 Robert Millan - - Detect LSI MegaRAID SAS (`mfi') devices on GNU/kFreeBSD. - - * util/deviceiter.c [__FreeBSD_kernel__] (get_mfi_disk_name): New - function. - [__FreeBSD_kernel__] (grub_util_iterate_devices): Scan for mfi - (/dev/mfid[0-9]+) devices using get_mfi_disk_name(). - -2011-08-03 Robert Millan - - * include/grub/zfs/zap_leaf.h (typedef union zap_leaf_chunk): Mark - la_array as packed. - Reported by: Zachary Bedell - -2011-07-26 Colin Watson - - * configure.ac: The Loongson port requires grub-mkfont due to its - use of -DUSE_ASCII_FAILBACK. Raise an error if it is not going to - be built. - -2011-07-26 Colin Watson - - * util/grub-install.in: Don't source grub-mkconfig_lib until after - processing arguments (otherwise help2man fails when GRUB has not yet - been installed). - -2011-07-25 Vladimir Serbinenko - - New script grub-mkstandalone. - - * Makefile.util.def (grub-mkstandalone): New script. - * docs/man/grub-mkstandalone.h2m: New file. - * util/grub-mkstandalone.in: Likewise. - -2011-07-25 Vladimir Serbinenko - - Support ATA disks with 4K sectors. - - * include/grub/ata.h (grub_ata): New member log_sector_size. - * grub-core/disk/ata.c (grub_ata_dumpinfo): Show sector size. - (grub_ata_identify): Read sector size. - (grub_ata_readwrite): Use log_sector_size rather than hardcoded value. - -2011-07-25 Vladimir Serbinenko - - * util/grub-install.in: Don't use uhci outside of x86. - -2011-07-25 Vladimir Serbinenko - - * util/grub-mkrescue.in: Add missing quotes. - -2011-07-25 Vladimir Serbinenko - - * grub-core/normal/menu.c (grub_menu_execute_entry): Fix NULL - dereference. - -2011-07-23 Vladimir Serbinenko - - * grub-core/disk/pata.c (grub_pata_readwrite): Add missing wait. - -2011-07-23 Vladimir Serbinenko - - * include/grub/video.h: add missing EXPORT_FUND on - grub_video_edid_checksum and grub_video_edid_preferred_mode. - -2011-07-23 Vladimir Serbinenko - - * include/grub/mips/kernel.h: Fix define conflict. - -2011-07-23 Vladimir Serbinenko - - * grub-core/kern/mips/cache_flush.S [GRUB_MACHINE_MIPS_LOONGSON]: Flush - all four ways. - -2011-07-21 Colin Watson - - Preferred resolution detection for VBE. - - * grub-core/video/video.c (grub_video_edid_checksum): New function. - (grub_video_edid_preferred_mode): Likewise. Try EDID followed by - the Flat Panel extension, in line with the X.org VESA driver. - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): - New function. - (grub_vbe_bios_get_ddc_capabilities): Likewise. - (grub_vbe_bios_read_edid): Likewise. - (grub_vbe_get_preferred_mode): Likewise. - (grub_video_vbe_setup): When the mode is "auto", try to get the - preferred mode from VBE, and use the largest mode that is no larger - than the preferred mode (some BIOSes expose a preferred mode that is - not in their mode list!). If this fails, fall back to 640x480 as a - safe conservative choice. - (grub_video_vbe_get_edid): New function. - (grub_video_vbe_adapter): Add get_edid. - * include/grub/video.h (struct grub_vbe_edid_info): New structure. - (struct grub_video_adapter): Add get_edid. - (grub_video_edid_checksum): Add prototype. - (grub_video_edid_preferred_mode): Likewise. - * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New - structure. - - * grub-core/commands/videoinfo.c (print_edid): New function. - (grub_cmd_videoinfo): Print EDID if available. - - * util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This - is more appropriate on a wider range of platforms than 640x480. - * docs/grub.texi (Simple configuration): Update GRUB_GFXMODE - documentation. - -2011-07-10 Vladimir Serbinenko - - * util/grub-install.in: Recognize ESP mounted at /boot/EFI. - -2011-07-10 Vladimir Serbinenko - - * po/POTFILES.in: Regenerate. - -2011-07-10 Vladimir Serbinenko - - * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Fix - incorrect memory usage. - -2011-07-10 Vladimir Serbinenko - - * util/grub-install.in: Source grub-mkconfig_lib. - -2011-07-08 Vladimir Serbinenko - - Remove getroot.c from core on emu platform. - - * grub-core/Makefile.core.def (kernel): Remove kern/emu/getroot.c and - kern/emu/raid.c. - * grub-core/kern/emu/main.c (main): Don't try to guess root device. It's - useless. - * grub-core/kern/emu/misc.c (get_win32_path): Moved from here... - * util/getroot.c (get_win32_path): ... here. - * grub-core/kern/emu/misc.c (fini_libzfs): Moved from here... - * util/getroot.c (fini_libzfs): ... here. - * grub-core/kern/emu/misc.c (grub_get_libzfs_handle): Moved from here... - * util/getroot.c (grub_get_libzfs_handle): ... here. - * grub-core/kern/emu/misc.c (grub_find_zpool_from_dir): - Moved from here... - * util/getroot.c (grub_find_zpool_from_dir): ... here. - * grub-core/kern/emu/misc.c - (grub_make_system_path_relative_to_its_root): Moved from here... - * util/getroot.c (grub_make_system_path_relative_to_its_root): ... here. - * grub-core/kern/emu/getroot.c: Moved from here ... - * util/getroot.c: ... here. All users updated. - * grub-core/kern/emu/raid.c: Moved from here ... - * util/raid.c: ... here. All users updated. - -2011-07-08 Vladimir Serbinenko - - * po/POTFILES.in: Regenerate. - -2011-07-07 Vladimir Serbinenko - - Fix compilation on GNU/Linux. - - * grub-core/kern/emu/getroot.c (grub_util_pull_device) [!FreeBSD]: - Disable geli. - (grub_util_get_grub_dev) [!FreeBSD]: Likewise. - (grub_util_pull_device) [HAVE_DEVICE_MAPPER]: Fix const and func name. - * grub-core/disk/cryptodisk.c (grub_cryptodisk_open): Fix proto. - -2011-07-07 Vladimir Serbinenko -2011-07-07 Michael Gorven -2011-07-07 Clemens Fruhwirth - - LUKS and GELI support. - - * Makefile.util.def (libgrubkern.a): Add grub-core/lib/crypto.c, - grub-core/disk/luks.c, grub-core/disk/geli.c, - grub-core/disk/cryptodisk.c, grub-core/disk/AFSplitter.c, - grub-core/lib/pbkdf2.c, grub-core/commands/extcmd.c, - grub-core/lib/arg.c. - (libgrubmods.a): Remove gcrypts cflags and cppflags. - Remove grub-core/commands/extcmd.c, grub-core/lib/arg.c, - grub-core/lib/crypto.c, grub-core/lib/libgcrypt-grub/cipher/sha512.c, - grub-core/lib/libgcrypt-grub/cipher/crc.c and grub-core/lib/pbkdf2.c. - (grub-bin2h): Add libgcry.a. - (grub-mkimage): Likewise. - (grub-mkrelpath): Likewise. - (grub-script-check): Likewise. - (grub-editenv): Likewise. - (grub-mkpasswd-pbkdf2): Likewise. - (grub-pe2elf): Likewise. - (grub-fstest): Likewise. - (grub-mkfont): Likewise. - (grub-mkdevicemap): Likewise. - (grub-probe): Likewise. - (grub-ofpath): Likewise. - (grub-mklayout): Likewise. - (example_unit_test): Likewise. - (grub-menulst2cfg): Likewise. - * autogen.sh (UTIL_DEFS): Add Makefile.utilgcry.def. - * grub-core/Makefile.core.def (cryptodisk): New module. - (luks): Likewise. - (geli): Likewise. - * grub-core/disk/AFSplitter.c: New file. - * grub-core/disk/cryptodisk.c: Likewise. - * grub-core/disk/geli.c: Likewise. - * grub-core/disk/luks.c: Likewise. - * grub-core/kern/emu/getroot.c (get_dm_uuid): New function based on - grub_util_is_lvm. - (grub_util_get_dm_abstraction): New function. - (grub_util_follow_gpart_up): Likewise. - (grub_util_get_geom_abstraction): Likewise. - (grub_util_get_dev_abstraction): Use new functions. - (grub_util_pull_device): Pull GELI and LUKS. - (grub_util_get_grub_dev): Handle LUKS and GELI. - * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors): New function. - (grub_util_biosdisk_open): Use grub_util_get_fd_sectors. - (follow_geom_up): Removed. - (grub_util_fd_seek): New function. - (open_device): Use grub_util_fd_seek. - (nread): Rename to .. - (grub_util_fd_read): ... this. All users updated. - * grub-core/lib/crypto.c (grub_crypto_ecb_decrypt): A better prototype. - (grub_crypto_cbc_decrypt): Likewise. - (grub_crypto_hmac_write): Likewise. - (grub_crypto_hmac_buffer): Likewise. - (grub_password_get): Extend to util. - * include/grub/crypto.h (gcry_cipher_spec) [GRUB_UTIL]: - New member modname. - (gcry_md_spec) [GRUB_UTIL]: Likewise. - * include/grub/cryptodisk.h: New file. - * include/grub/disk.h (grub_disk_dev_id): Rename LUKS to CRYPTODISK. - * include/grub/emu/getroot.h (grub_dev_abstraction_types): Add - LUKS and GELI. - (grub_util_follow_gpart_up): New proto. - * include/grub/emu/hostdisk.h (grub_util_fd_seek): Likewise. - (grub_util_fd_read): Likewise. - (grub_cryptodisk_cheat_mount): Likewise. - (grub_util_cryptodisk_print_uuid): Likewise. - (grub_util_get_fd_sectors): Likewise. - * util/grub-fstest.c (mount_crypt): New var. - (fstest): Mount crypto if requested. - (options): New option -C. - (argp_parser): Parse -C. - (main): Init and fini gcry. - * util/grub-install.in: Support cryptodisk install. - * util/grub-mkconfig.in: Export GRUB_ENABLE_CRYPTODISK. - * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Support - cryptodisk. - (prepare_grub_to_access_device): Likewise. - * util/grub-mkpasswd-pbkdf2.c (main): Use grub_password_get. - * util/grub-probe.c (probe_partmap): Support cryptodisk UUID probe. - (probe_cryptodisk_uuid): New function. - (probe_abstraction): Likewise. - (probe): Use new functions. - * util/import_gcry.py: Create Makefile.utilgcry.def. - Add modname member. - -2011-07-07 Vladimir Serbinenko - - Lazy device scanning. - - * Makefile.util.def (libgrubkern.a): Add grub-core/kern/emu/raid.c. - (grub-setup): Remove util/raid.c. - * grub-core/Makefile.core.def (kernel): Add kern/emu/raid.c on emu. - * grub-core/disk/lvm.c (scan_depth): New variable. - (grub_lvm_iterate): Rescan if necessary. - (find_lv): New function based on grub_lvm_open. - (grub_lvm_open): Use find_lv. Rescan on error. - (is_node_readable): New function. - (is_lv_readable): Likewise. - (grub_lvm_scan_device): Skip already found disks. - (do_lvm_scan): New function. Move grub_lvm_scan_device inside of it. - Stop if searched device is found and readable. - * grub-core/disk/raid.c (inscnt): New variable. - (scan_depth): Likewise. - (scan_devices): New function based on grub_raid_register. Abort if - looked for device is found. - (grub_raid_iterate): Rescan if needed. - (find_array): NEw function based on -grub_raid_open. - (grub_raid_open): Use find_array and rescan. - (insert_array): Set became_readable_at. - * grub-core/kern/disk.c (grub_disk_dev_iterate): Iterate though "pull. - * grub-core/kern/emu/getroot.c (grub_util_open_dm) [HAVE_DEVICE_MAPPER]: - New function. - (grub_util_is_lvm) [HAVE_DEVICE_MAPPER]: Use grub_util_open_dm. - (grub_util_pull_device): New function. - (grub_util_get_grub_dev): Call grub_util_pull_device. - * util/raid.c: Moved to .. - * grub-core/kern/emu/raid.c: ... here. - (grub_util_raid_getmembers): New parameter "bootable". - All users updated. Support 1.x. - * include/grub/ata.h (grub_ata_dev): Change iterate prototype. - All users updated. - * include/grub/disk.h (grub_disk_pull_t): New enum. - (grub_disk_dev): Change iterate prototype. - All users updated. - * include/grub/emu/getroot.h (grub_util_raid_getmembers) [__linux__]: - New proto. - * include/grub/emu/hostdisk.h (grub_util_pull_device): Likewise. - * include/grub/lvm.h (grub_lvm_lv): New members fullname and compatname. - * include/grub/raid.h (grub_raid_array): New member became_readable_at. - * include/grub/scsi.h (grub_scsi_dev): Change iterate prototype. - All users updated. - * include/grub/util/raid.h: Removed. - -2011-07-06 Vladimir Serbinenko - - * po/POTFILES.in: Regenerate. - -2011-07-06 Vladimir Serbinenko - - Unify sparc init with other ieee1275. - - * grub-core/Makefile.core.def (kernel): Use kern/ieee1275/init.c - instead of kern/sparc64/ieee1275/init.c. - * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options) - [__sparc__]: Set GRUB_IEEE1275_FLAG_NO_PARTITION_0. - * grub-core/kern/ieee1275/init.c [__sparc__]: Include - grub/machine/kernel.h. - (grub_ieee1275_original_stack) [__sparc__]: New variable. - (grub_claim_heap) [__sparc__]: Use sparc version. - (grub_machine_init): Moved args parsing to - (grub_parse_cmdline): ...this. - * grub-core/kern/sparc64/ieee1275/init.c: Removed. - * include/grub/offsets.h (GRUB_KERNEL_SPARC64_IEEE1275_MOD_GAP): - New definition. - (GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN): Likewise. - - Move BOOTP to separate file. - - * grub-core/Makefile.core.def (net): Add net/bootp.c. - * grub-core/net/net.c: Move all BOOTP functions to - * grub-core/net/bootp.c: ... here. - - Use frame interface on PXE. - - * grub-core/Makefile.core.def (pxecmd): Removed. - (pxe): Use net/drivers/i386/pc/pxe.c rather than net/i386/pc/pxe.c. - * grub-core/commands/i386/pc/pxecmd.c: Removed. - * grub-core/i386/pc/pxe.c: Moved from here ... - * grub-core/net/i386/pc/pxe.c: ... here. Rewritten. - * grub-core/net/net.c (grub_net_open_real): Handle old pxe syntax. - * include/grub/i386/pc/pxe.h (grub_pxe_unload): Removed. - - EFI network support. - - * grub-core/Makefile.core.def (efinet): New module. - * grub-core/disk/efi/efidisk.c (compare_device_paths): Moved from - here... - * grub-core/kern/efi/efi.c (grub_efi_compare_device_paths): ... here. - All users updated. - * grub-core/kern/efi/init.c (grub_efi_net_config): New variable. - (grub_machine_get_bootlocation): Call grub_efi_net_config if needed. - * grub-core/kern/x86_64/efi/callwrap.S (efi_wrap_7): New function. - * grub-core/net/drivers/efi/efinet.c: New file. - * include/grub/efi/efi.h (grub_efi_compare_device_paths): New proto. - (grub_efi_net_config): New extern var. - - Various cleanups and bugfixes. - - * grub-core/disk/efi/efidisk.c (grub_efidisk_open): Fix off-by-one - error. - (grub_efidisk_get_device_name): Unify similar codepaths. Accept whole - disk declared as partition. - * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_open): Fix memory - leak on failure. - * grub-core/kern/dl.c (grub_dl_load_file): Fix memory leak. - * grub-core/kern/mm.c (grub_debug_malloc): Don't use unsupported %zx. - (grub_debug_zalloc): Likewise. - (grub_debug_realloc): Likewise. - (grub_debug_memalign): Likewise. - * grub-core/net/arp.c (grub_net_arp_receive): IPv4 is 4-byte wide. - Check that target is IPv4. - * grub-core/net/drivers/ieee1275/ofnet.c (grub_ofnet_findcards): Use - local-mac-address as fallback. - * grub-core/net/ethernet.c (grub_net_recv_ethernet_packet): Prevent - memory leak. - * grub-core/net/ip.c (ipchksum): Rename to ... - (grub_net_ip_chksum): ... this. All users updated. - (grub_net_recv_ip_packets): Special handling for DHCP. - * util/grub-mkimage.c (generate_image): Zero-out aout header. - - Unify prefix handling - - * grub-core/kern/efi/init.c (grub_efi_set_prefix): Revamped into ... - (grub_machine_get_bootlocation): ... this. - * grub-core/kern/emu/main.c (grub_machine_set_prefix): Revamped into ... - (grub_machine_get_bootlocation): ... this. - (grub_prefix): New variable. - (prefix): Removed. - (root_dev): New variable. - (dir): Likewise. - (main): Use new variables. - * grub-core/kern/i386/coreboot/init.c (grub_machine_set_prefix): - Revamped into ... - (grub_machine_get_bootlocation): ... this. - * grub-core/kern/i386/efi/init.c (grub_machine_set_prefix): Removed. - * grub-core/kern/i386/pc/init.c (make_install_device): Revamped into ... - (grub_machine_get_bootlocation): ... this. - (grub_machine_set_prefix): Removed. - * grub-core/kern/ia64/efi/init.c (grub_machine_set_prefix): Removed. - * grub-core/kern/ieee1275/init.c (grub_machine_set_prefix): - Revamped into ... - (grub_machine_get_bootlocation): ... this. - * grub-core/kern/main.c (grub_set_root_dev): Revamped into ... - (grub_set_prefix_and_root): ... this. All users updated. - * grub-core/kern/mips/init.c (grub_machine_set_prefix): - Revamped into ... - (grub_machine_get_bootlocation): ... this. - * include/grub/kernel.h (grub_machine_set_prefix): Removed. - (grub_machine_get_bootlocation): New proto. - * include/grub/i386/pc/kernel.h (grub_pc_net_config): New var. - - Less intrusive and more reliable seek on network implementation. - - * grub-core/kern/file.c (grub_file_net_seek): Removed. - (grub_file_seek): Don't call grub_file_net_seek. - * grub-core/net/net.c (grub_net_fs_read): Renamed to ... - (grub_net_fs_read_real): .. this. - (grub_net_seek_real): Use net->offset. - (grub_net_fs_read): Seek if necessary. - - Unify IEEE1275 netwotk config with the other platforms. - - * grub-core/kern/ieee1275/init.c (grub_ieee1275_net_config): - New variable. - (grub_machine_get_bootlocation): Support network. - * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): - Support type and device parsing. - (grub_ieee1275_get_device_type): New function. - * grub-core/net/drivers/ieee1275/ofnet.c (grub_getbootp_real): Revamped - into ... - (grub_ieee1275_net_config_real): ... this. - (grub_ofnet_probecards): Removed. - * grub-core/Makefile.am (KERNEL_HEADER_FILES): Remove ofnet.h. - * include/grub/ieee1275/ofnet.h: Removed. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_net_config): NEw - extern var. - (grub_ieee1275_get_device_type): New function. - - Unify network device closing across platforms and make more robust. - - * grub-core/kern/ieee1275/init.c (grub_machine_fini): Don't call - grub_grubnet_fini. - * grub-core/net/ethernet.c (send_ethernet_packet): Open card if it isn't - already. - * grub-core/net/net.c (grub_net_network_level_interface_register): - Update num_ifaces. - (grub_net_card_unregister): Close all interfaces. - (receive_packets): Don't poll if no iterfaces are registered. - Open if necessary. - (grub_net_fini_hw): New function. - (grub_net_restore_hw): Likewise. - (fini_hnd): New variable. - (GRUB_MOD_INIT): Register preboot hook. - (GRUB_MOD_FINI): Run and unregister preboot hook. - - Poll network cards when idle. - - * grub-core/kern/term.c (grub_net_poll_cards_idle): New variable. - (grub_checkkey): Call grub_net_poll_cards_idle if it's not NULL. - * grub-core/net/net.c (receive_packets): Save last poll time. - (grub_net_poll_cards_idle_real): New function. - (GRUB_MOD_INIT): Register grub_net_poll_cards_idle. - (GRUB_MOD_FINI): Unregister grub_net_poll_cards_idle. - * include/grub/kernel.h (grub_poll_cards_idle): New extern variable. - - Rename ofnet interfaces. - - * grub-core/net/drivers/ieee1275/ofnet.c (find_alias): New function. - (grub_ofnet_findcards): Use ofnet_%s names. - - * util/grub-mknetdir.in: Support for EFI and IEEE1275. - - Cleanup socket opening. - - * grub-core/net/net.c (grub_net_fs_open): Rewritten. - (grub_net_fs_close): Likewise. - (grub_net_fs_read_real): Use eof member. - * include/grub/net/udp.h (+grub_net_udp_open): New proto. - (+grub_net_udp_close): New inline function. - - * include/grub/net/tftp.h: Moved to the top of ... - * grub-core/net/tftp.c: ... here. - * include/grub/net/ip.h: Moved mostly to the top of ... - * grub-core/net/ip.c: ... here. - * include/grub/net/ethernet.h: Moved mostly to the top of ... - * grub-core/net/ethernet.c: ... here. - - * grub-core/kern/device.c (grub_device_close): Free device->net->server. - - * grub-core/commands/probe.c (grub_cmd_probe): Use protocol name for - FS name. - - * include/grub/net/ip.h (ipv4_ini): Removed. - (ipv4_fini): Likewise. - - * include/grub/net/ip.h (grub_net_recv_ip_packets): New proto. - (grub_net_send_ip_packets): Likewise. - -2011-07-05 Vladimir Serbinenko - - * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_init): Use new - grub_read_cmos prototype. - -2011-07-05 Vladimir Serbinenko - - VGA text support in qemu-mips - - * grub-core/Makefile.core.def (kernel): Add term/i386/pc/vga_text.c, - term/i386/vga_common.c and kern/vga_init.c on qemu-mips. - * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init vga - text. - * grub-core/kern/i386/qemu/init.c: Renamed to ... - * grub-core/kern/vga_init.c: ... this. - * grub-core/kern/vga_init.c (VGA_ADDR) [__mips__]: Adjust. - (grub_qemu_init_cirrus) [__mips__]: Skip PCI and adjust the I/O base. - * grub-core/term/i386/pc/vga_text.c (VGA_TEXT_SCREEN) [__mips__]: - Adjust. - * include/grub/vga.h [GRUB_MACHINE_MIPS_QEMU_MIPS]: Declare - GRUB_MACHINE_PCI_IO_BASE. - -2011-07-05 Vladimir Serbinenko - - MIPS qemu flash support. - - * grub-core/boot/mips/startup_raw.S [GRUB_MACHINE_MIPS_QEMU_MIPS]: Check - magic. - * grub-core/kern/mips/qemu_mips/init.c (probe_mem): New function. - (grub_machine_init): Probe memory if its size isn't known. - * util/grub-mkimage.c (image_targets): Add flash targets. - (generate_image): Handle flash targets. - -2011-07-05 Vladimir Serbinenko - - MIPS qemu at_keyboard support. - - * gentpl.py (videoinkernel): Add qemu-mips. - * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add necessary headers. - * grub-core/Makefile.core.def (kernel): Add at_keyboard and layout. - * grub-core/kern/mips/qemu_mips/init.c (grub_machine_init): Init new - modules. - * grub-core/term/at_keyboard.c (grub_keyboard_controller_init) - [GRUB_MACHINE_MIPS_QEMU_MIPS]: Don't consider original set. - * grub-core/term/serial.c (grub_serial_register) - [GRUB_MACHINE_MIPS_QEMU_MIPS]: Make com0 explicitly active. - -2011-07-05 Vladimir Serbinenko - - CMOS support on sparc. - - * gentpl.py (cmos): Add powerpc and sparc. - * grub-core/Makefile.core.def (datetime): Add lib/ieee1275/cmos.c on - powerpc and sparc. - * grub-core/lib/cmos_datetime.c (grub_get_datetime) - [__powerpc__ || __sparc__]: Rename to grub_get_datetime_cmos. - (grub_set_datetime) [__powerpc__ || __sparc__]: Likewise to - grub_set_datetime_cmos. - * grub-core/lib/ieee1275/cmos.c: New file. - * grub-core/lib/ieee1275/datetime.c (no_ieee1275_rtc): New vaiable. - (find_rtc): Set no_ieee1275_rtc on error. - (grub_get_datetime): Call grub_get_datetime_cmos on error. - (grub_set_datetime): Call grub_set_datetime_cmos on error. - * include/grub/cmos.h (grub_cmos_read): Return grub_err_t since it may - fail. Move value to argument. All users updated - (grub_cmos_write): Likewise. - (grub_cmos_read) [__powerpc__ || __sparc__]: Rewritten. - (grub_cmos_write) [__powerpc__ || __sparc__]: Likewise. - * include/grub/datetime.h [__powerpc__ || __sparc__]: Declare - grub_get_datetime_cmos and grub_set_datetime_cmos. - -2011-07-02 GrĂ©goire Sutre - - * util/grub-mkconfig.in: Use @PACKAGE@ instead of hardcoded name when - sourcing grub-mkconfig_lib. - * util/update-grub_lib.in: Likewise. - * util/grub.d/00_header.in: Likewise. - * util/grub.d/10_hurd.in: Likewise. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/10_netbsd.in: Likewise. - * util/grub.d/10_windows.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - * util/grub.d/30_os-prober.in: Likewise. - -2011-06-28 Colin Watson - - * grub-core/term/gfxterm.c (grub_virtual_screen_setup): Use - default_bg_color rather than black. - (grub_gfxterm_fullscreen): Likewise. - (grub_gfxterm_background_color_cmd): Save new background color in - default_bg_color. - -2011-06-27 Vladimir Serbinenko - - * grub-core/Makefile.core.def (chain): Fix coreboot filename. - -2011-06-27 Vladimir Serbinenko - - * grub-core/disk/pata.c (grub_pata_initialize) [QEMU_MIPS]: Fix a - mismerge. - -2011-06-27 Vladimir Serbinenko - - Chainloading on coreboot support. - - * grub-core/Makefile.core.def (chain): Add coreboot. - * grub-core/loader/i386/coreboot/chainloader.c: New file. - -2011-06-27 Vladimir Serbinenko - - * grub-core/loader/i386/bsd.c (grub_bsd_load): Handle relocator failure - if it happens. - -2011-06-27 Vladimir Serbinenko - - Implement time command. - - * grub-core/Makefile.core.def (time): New module. - * grub-core/commands/time.c: New file. - * grub-core/script/parser.y: Remove "time" keyword. - * grub-core/script/yylex.l: Likewise. - -2011-06-27 Vladimir Serbinenko - - * include/grub/loader.h (grub_loader_unregister_preboot_hook): Export. - -2011-06-27 Vladimir Serbinenko - - * grub-core/lib/relocator.c (malloc_in_range): Fix a memory corruption - when handling leftovers. - -2011-06-27 Vladimir Serbinenko - - * util/ieee1275/grub-ofpathname.c (main): Handle --help and --version - so that help2man doesn't fail. - -2011-06-27 Vladimir Serbinenko - - * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer) Use right - type in pointers on sparc64. - (get_card_packet): Likewise. - -2011-06-27 Colin Watson - - * grub-core/commands/videoinfo.c (hook): Indicate current video mode - with `*'. - (grub_cmd_videoinfo): Fetch current video mode. - -2011-06-27 Vladimir Serbinenko - - * grub-core/disk/scsi.c (grub_scsi_read): Limit SCSI reads to 32K - because of underlying system restrictions. - -2011-06-27 Vladimir Serbinenko - - * util/grub-mkrescue.in: Rename "ata" to "pata" and add ahci when - necessary. - -2011-06-27 Vladimir Serbinenko - - Coreboot video support. - - * grub-core/Makefile.core.def (vga): Extend to coreboot and multiboot. - (vbe): Likewise. - * grub-core/kern/i386/coreboot/startup.S: Include int.S. - * grub-core/kern/i386/pc/startup.S (grub_bios_interrupt): Moved from - here ... - * grub-core/kern/i386/int.S: ... here. - * grub-core/video/i386/pc/vbe.c: Updated includes. - * grub-core/video/i386/pc/vga.c: Likewise. - * include/grub/i386/coreboot/memory.h - (GRUB_MEMORY_MACHINE_SCRATCH_ADDR): New definition. - (GRUB_MEMORY_MACHINE_SCRATCH_SEG): Likewise. - (GRUB_MEMORY_MACHINE_SCRATCH_SIZE): Likewise. - * include/grub/i386/pc/int.h (GRUB_CPU_INT_FLAGS_DEFAULT) [!PCBIOS]: - Disable interrupts. - * include/grub/i386/pc/vga.h: Removed. All users updated. - -2011-06-27 Vladimir Serbinenko - - * grub-core/disk/ahci.c (grub_ahci_readwrite_real): Use proper - definitions for dprintf. - * grub-core/disk/pata.c (grub_pata_readwrite): Likewise. - -2011-06-27 Vladimir Serbinenko - - * grub-core/net/drivers/ieee1275/ofnet.c (send_card_buffer): Fix - prototype. - (get_card_packet): Likewise. - -2011-06-26 Yves Blusseau - - Display the path of the file when file is not found - - * grub-core/fs/fat.c: Display the filename when file is not found. - * grub-core/fs/fshelp.c: Likewise. - * grub-core/fs/hfs.c: Likewise. - * grub-core/fs/jfs.c: Likewise. - * grub-core/fs/minix.c: Likewise. - * grub-core/fs/ufs.c: Likewise. - * grub-core/fs/btrfs.c: Likewise. - * grub-core/commands/i386/pc/play.c: Likewise. - -2011-06-26 Szymon Janc - - * grub-core/commands/cmp.c (grub_cmd_cmp): Remove unnecessary NULL - pointer checks before calling grub_free(). - * grub-core/commands/wildcard.c (match_devices): Likewise. - * grub-core/commands/wildcard.c (match_files): Likewise. - * grub-core/fs/cpio.c (grub_cpio_dir): Likewise. - * grub-core/fs/cpio.c (grub_cpio_open): Likewise. - * grub-core/fs/udf.c (grub_udf_read_block): Likewise. - * grub-core/fs/xfs.c (grub_xfs_read_block): Likewise. - * grub-core/loader/efi/chainloader.c (grub_cmd_chainloader): Likewise. - * grub-core/normal/cmdline.c (grub_cmdline_get): Likewise. - * grub-core/script/yylex.l (grub_lexer_unput): Likewise. - * grub-core/video/readers/jpeg.c (grub_video_reader_jpeg): Likewise. - * grub-core/video/readers/png.c (grub_png_output_byte): Likewise. - -2011-06-25 Patrick - - * grub-core/kern/main.c (grub_load_normal_mode): Correct the comment. - -2011-06-25 Vladimir Serbinenko - - * grub-core/net/i386/pc/pxe.c (grub_pxe_recv): Fix declaration. - (grub_pxe_send): Likewise. - (GRUB_MOD_INIT): Fix types. - -2011-06-24 Szymon Janc - - * grub-core/io/xzio.c: Fix code style issues - -2011-06-24 Vladimir Serbinenko -2011-06-24 Manoel Rebelo Abranches - - Network infrastructure. - The ARP protocol was made by Paulo Pinatti - - * include/grub/net/arp.h: New file. - * include/grub/net/device.h: Likewise. - * include/grub/net/ethernet.h: Likewise. - * include/grub/net/ip.h: Likewise. - * include/grub/net/netbuff.h: Likewise. - * include/grub/net/tftp.h: Likewise. - * include/grub/net/udp.h: Likewise. - * include/grub/ieee1275/ofnet.h: Likewise. - * include/grub/emu/export.h: Likewise. - * include/grub/net.h: Likewise. - * grub-core/net/arp.c: Likewise. - * grub-core/net/ethernet.c: Likewise. - * grub-core/net/ip.c: Likewise. - * grub-core/net/udp.c: Likewise. - * grub-core/net/tftp.c: Likewise. - * grub-core/net/netbuff.c: Likewise. - * grub-core/net/net.c: Likewise. - * grub-core/net/drivers/emu/emunet.c: Likewise. - * grub-core/net/drivers/ieee1275/ofnet.c: Likewise. - * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add net.h, ofnet.h and - export.h. - * grub-core/Makefile.core.def (net): New module. - (tftp): Likewise. - (ofnet): Likewise. - (emunet): Likewise. - * grub-core/commands/ls.c (grub_ls_list_devices) [!GRUB_UTIL]: List - network protocols. - * grub-core/kern/device.c (grub_net_open) : New variable. - (grub_device_open): Handle network device. - (grub_device_close): Likewise. - * grub-core/kern/file.c (grub_file_net_seek) : New variable. - (grub_grubnet_fini): Likewise. - (grub_file_seek): Seek in network device. - * grub-core/kern/fs.c (grub_fs_probe): Handle network devices. - * grub-core/kern/ieee1275/init.c (grub_machine_set_prefix): Handle - network root. - (grub_machine_fini): Call grub_grubnet_fini. - * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_parse_args): Handle - network. - (grub_ieee1275_get_aliasdevname): New function. - * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_get_mbi_size): - Add unofficial Solaris network info. - (grub_multiboot_make_mbi): Likewise. - * grub-core/fs/i386/pc/pxe.c: Moved from here ... - * grub-core/net/i386/pc/pxe.c: ...here. Adapted for new design. - * include/grub/device.h (grub_fs): Removed. - * include/grub/err.h (grub_err_t): Add network-related values. - * include/grub/i386/pc/pxe.h: Removed bootp parts. - * include/grub/ieee1275/ieee1275.h (grub_ofnetcard_data): New struct. - (grub_ieee1275_get_aliasdevname): New proto. - * include/grub/net.h: Rewritten. - -2011-06-24 Vladimir Serbinenko - - * grub-core/disk/raid.c (insert_array): Ensure uniqueness of readable - names. - -2011-06-24 Vladimir Serbinenko - - * grub-core/commands/wildcard.c (match_files): Add a useful dprintf. - (wildcard_expand): Don't stop on nonregexp parts after regexp ones since - it truncates the output. - Reported by: Ximin Luo. - -2011-06-24 Vladimir Serbinenko - - * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Skip . and .. - -2011-06-24 Vladimir Serbinenko - - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Load - partmap before abstraction. - -2011-06-24 Alexander Kurtz - - * util/grub-mkconfig_lib.in: Add missing quotes. - -2011-06-24 Vladimir Serbinenko - - * grub-core/kern/emu/getroot.c (grub_guess_root_device): Revert to - old method if mountinfo would return /dev/root and /dev/root doesn't - exist. - -2011-06-24 Vladimir Serbinenko - - ZFS zlib support - - * grub-core/fs/zfs/zfs.c (zlib_decompress): New function. - (decomp_table): Add zlib entries. - (zio_read): USe 8 bits for compression function rather than 3. - * include/grub/zfs/zio.h (zio_compress): Add zlib values. - -2011-06-24 Vladimir Serbinenko - - * grub-core/disk/ahci.c: Add missing license statements. - * grub-core/fs/romfs.c: Likewise. - * grub-core/lib/ia64/setjmp.S: Likewise. - * grub-core/loader/i386/pc/freedos.c: Likewise. - * grub-core/loader/ia64/efi/linux.c: Likewise. - * grub-core/video/colors.c: Likewise. - * include/grub/dl.h (GRUB_MOD_DEP): New macro. - -2011-06-23 Vladimir Serbinenko - - AHCI support. - - * grub-core/Makefile.core.def (ata_pthru): Removed. - (ahci): New module. - (pata): Likewise. - * grub-core/bus/usb/ohci.c (GRUB_MOD_FINI): Unregister preboot hook - on unload. - * grub-core/commands/hdparm.c (grub_hdparm_do_ata_cmd): Use ATA - readwrite. - (grub_hdparm_do_check_powermode_cmd): Likewise. - (grub_hdparm_do_smart_cmd): Likewise. - (grub_hdparm_set_val_cmd): Likewise. - (grub_cmd_hdparm): Likewise. Check thta we have an ATA device. - * grub-core/disk/ahci.c: New file. - * grub-core/disk/ata.c: Factor out the low-level part into ... - * grub-core/disk/pata.c: ... here. - * grub-core/disk/ata_pthru.c: Contents moved to ... - * grub-core/disk/pata.c: ... here. - * grub-core/disk/scsi.c (grub_scsi_names): New array. - (grub_scsi_iterate): Use grub_scsi_names. - (grub_scsi_open): Likewise. - * grub-core/kern/disk.c (grub_disk_ata_pass_through): Removed. - * include/grub/ata.h (grub_ata_commands): Add DMA commands. - (grub_ata_regs_t): New struct. - (grub_disk_ata_pass_through_parms): Likewise. - (grub_ata_device): Renamed to ... - (grub_ata): ... this. - (grub_ata_dev): New struct. - Removed all low-level inline functions. - * include/grub/scsi.h: Add PATA and AHCI subsystems. - (grub_scsi_dev): Removed 'name' and 'id'. Added 'id' parameter to - iterate hooks and open. All users updated. - * util/grub-install.in: Handle AHCI disk module. - -2011-06-23 Szymon Janc - - Add support for DRI and RSTn markers in JPEG files. - - * grub-core/video/readers/jpeg.c (JPEG_MARKER_DRI): New define. - (JPEG_MARKER_RST0): Likewise. - (JPEG_MARKER_RST1): Likewise. - (JPEG_MARKER_RST2): Likewise. - (JPEG_MARKER_RST3): Likewise. - (JPEG_MARKER_RST4): Likewise. - (JPEG_MARKER_RST5): Likewise. - (JPEG_MARKER_RST6): Likewise. - (JPEG_MARKER_RST7): Likewise. - (grub_jpeg_data): New fields dri, r1, bitmap_ptr. - (grub_jpeg_decode_dri): New function. - (grub_jpeg_decode_sos): Move image data related part into - grub_jpeg_decode_data function. - (grub_jpeg_decode_data): New function. - (grub_jpeg_reset): New function. - (grub_jpeg_decode_jpeg): Handle new markers. - -2011-06-23 Vladimir Serbinenko - - * util/ieee1275/ofpath.c (check_sas): Close fd. - (main): Free of_path. - Reported by: David Volgyes . - -2011-06-23 Vladimir Serbinenko - - * util/grub-mkpasswd-pbkdf2.c (main): Don't double-close. - Reported by: David Volgyes . - -2011-06-23 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Close - file after stat. - Reported by: David Volgyes . - -2011-06-23 Vladimir Serbinenko - - * util/raid.c (grub_util_raid_getmembers): Close fd before returning. - - Reported by: David Volgyes . - -2011-06-23 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c (rs_recover) [STANDALONE]: - Prevent memory leak. - -2011-06-23 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c (rs_recover): Prevent memory leak. - (main): Close file. - Reported by: David Volgyes . - -2011-06-23 Vladimir Serbinenko - - * grub-core/loader/i386/xnu.c (grub_cpu_xnu_fill_devprop): Don't attempt - to continue if allocation is failed. - - Reported by: David Volgyes . - -2011-06-23 David Volgyes - - * grub-core/bus/usb/ohci.c (grub_ohci_pci_iter): Avoid NULL-pointer - dereference. - -2011-06-23 Vladimir Serbinenko - - Fix spurious warning. - - * grub-core/partmap/acorn.c (grub_acorn_boot_block): Make a union. - (acorn_partition_map_find): Use .bin member. - -2011-06-23 Vladimir Serbinenko - - * grub-core/kern/emu/getroot.c (grub_guess_root_device): Don't accept - /dev/root as a valid device. - -2011-06-23 Jim Meyering - - Avoid NULL deref in grub_device_open. - - * grub-core/kern/device.c (grub_device_open): Don't dereference - a NULL pointer upon failed grub_env_get. - -2011-06-23 Vladimir Serbinenko - - Support non-512B sectors and agglomerate reads. - - * Makefile.util.def (libgrubmods.a): Add grub-core/commands/testload.c. - * grub-core/disk/efi/efidisk.c (grub_efidisk_data): Remove disk_io. - (disk_io_guid): Removed. - (make_devices): Locate solely by BlockIO. - (grub_efidisk_open): Fill log_sector_size and total_sectors. - (grub_efidisk_read): Use read_blocks. - (grub_efidisk_write): Use write_blocks. - * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_open): Fill - log_sector_size. - (get_safe_sectors): Handle non-512B sectors. - (grub_biosdisk_read): Remove special CDROM handling. Handle non-512B - sectors. - (grub_biosdisk_write): Handle non-512B sectors. - * grub-core/disk/scsi.c (grub_scsi_open): Fill log_sector_size. - (grub_scsi_read): Remove special non-512B block handling (now handled - one level up). - * grub-core/kern/disk.c (grub_disk_open): Fill default log_sector_size - and do sanity checks. - (grub_disk_adjust_range): Handle non-512B sectors. - (transform_sector): New function. - (grub_disk_read_small): Likewise. - (grub_disk_read): Rewritten. - (grub_disk_write): Handle non-512B sectors. - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_open): Fill - log_sector_size. - (open_device): Use log_sector_size. - (grub_util_biosdisk_read): Likewise. - (grub_util_biosdisk_write): Likewise. - * grub-core/partmap/msdos.c (grub_partition_msdos_iterate): Handle - non-512B sectors. - (pc_partition_map_embed): Likewise. - * include/grub/disk.h (grub_disk): New field log_sector_size. - (GRUB_DISK_CACHE_SIZE): Redefined from GRUB_DISK_CACHE_BITS. - (GRUB_DISK_CACHE_BITS): Increased to 6. - * util/grub-fstest.c (fstest): New command testload. - (argp_parser): Likewise. - -2011-06-16 Robert Millan - - Detect `ataraid' devices on GNU/kFreeBSD. Fix for ATA devices using - `ata' driver on kernel of FreeBSD 9. - - * util/deviceiter.c [__FreeBSD_kernel__] (get_ada_disk_name) - (get_ataraid_disk_name): New functions. - [__FreeBSD_kernel__] (grub_util_iterate_devices): Scan for ataraid - (/dev/ar[0-9]+) and ada (/dev/ada[0-9]+) devices using - get_ataraid_disk_name() and get_ada_disk_name(). - -2011-06-13 Colin Watson - - * docs/man/grub-mklayout.h2m (DESCRIPTION): Add a reference to the - input format. - -2011-05-29 Colin Watson - - * docs/grub.texi (Obtaining and Building GRUB): Substitute - `ftp.gnu.org' for `alpha.gnu.org'. - -2011-05-27 Colin Watson - - * grub-core/kern/emu/hostdisk.c (linux_find_partition): Handle - partitions under /dev/disk/by-id/. - -2011-05-27 Colin Watson - - * grub-core/kern/emu/hostdisk.c (linux_find_partition): Give up - after ten consecutive open failures. Scanning all the way up to - 10000 is excessive and can cause serious performance problems in - some configurations. - Fixes Ubuntu bug #787461. - -2011-05-21 Vladimir Serbinenko - - * grub-core/disk/arc/arcdisk.c (reopen): Close old handle before - opening new one. - -2011-05-21 Colin Watson -2011-05-21 Vladimir Serbinenko - - Don't stat devices unless we have to. - - * grub-core/kern/emu/getroot.c (grub_find_device): Recognize - dir == /dev/mapper. - (grub_guess_root_device): Use already known os_dev if possible. - * grub-core/kern/emu/hostdisk.c - (convert_system_partition_to_system_disk): Scan only in /dev/mapper - if device is known to be a dm one. - -2011-05-20 Colin Watson - - * util/grub-mkconfig.in: Export GRUB_CMDLINE_LINUX_XEN_REPLACE and - GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT. - Reported by: Pawel Tecza. - -2011-05-19 Vladimir Serbinenko - - * grub-core/Makefile.core.def (lsacpi): Fix ia64 mismerge. - (lsefisystab): Likewise. - (lssal): Likewise. - (lsefimmap): Likewise. - (hdparm): Enable on qemu-mips. - (setjmp): Add ia64 nodist. - (serial): Simplify tags. - -2011-05-18 Colin Watson - - * Makefile.util.def (grub-ofpathname): Install manual page. - -2011-05-18 Colin Watson - - * grub-core/fs/squash4.c: Add missing GRUB_MOD_LICENSE. - -2011-05-18 Colin Watson - - * .bzrignore: Add grub-core/modinfo.sh and a number of test files. - -2011-05-18 Vladimir Serbinenko - - * grub-core/bus/usb/usbhub.c (poll_nonroot_hub): Downgrade a printf - into dprintf. - -2011-05-18 Vladimir Serbinenko - - Use full 64-bit division. - - * grub-core/kern/misc.c (grub_divmod64_full): Renamed to ... - (grub_divmod64): ... this. - * include/grub/misc.h (grub_divmod64): Removed. All users switch to full - version. - -2011-05-18 Colin Watson - - * util/grub-mkrescue.in: Use portable `.' rather than non-portable - `source'. - -2011-05-18 Colin Watson - - * grub-core/genmod.sh.in: Use 'set -e' rather than '#! /bin/sh -e', - to avoid accidents when debugging with 'sh -x'. - * grub-core/gensyminfo.sh.in: Likewise. - * tests/example_scripted_test.in: Likewise. - * tests/grub_cmd_regexp.in: Likewise. - * tests/grub_script_blanklines.in: Likewise. - * tests/grub_script_dollar.in: Likewise. - * tests/grub_script_expansion.in: Likewise. - * tests/grub_script_final_semicolon.in: Likewise. - * tests/partmap_test.in: Likewise. - * tests/util/grub-shell-tester.in: Likewise. - * tests/util/grub-shell.in: Likewise. - -2011-05-18 Colin Watson - - Move gfxmenu color handling to video, so that gfxterm can use it - too. - - * grub-core/gfxmenu/named_colors.c: Move to ... - * grub-core/video/colors.c: ... here. Rename - grub_gui_get_named_color to grub_video_get_named_color. - * grub-core/gfxmenu/gui_string_util.c (my_isxdigit): Move to ... - * grub-core/video/colors.c (my_isxdigit): ... here. - * grub-core/gfxmenu/gui_string_util.c (parse_hex_color_component): - Move to ... - * grub-core/video/colors.c (parse_hex_color_component): ... here. - * grub-core/gfxmenu/gui_string_util.c (grub_gui_parse_color): Move - to ... - * grub-core/video/colors.c (grub_video_parse_color): ... here. - - * include/grub/gui.h (grub_gui_color_t): Move to ... - * include/grub/video.h (grub_video_rgba_color_t): ... here. - * include/grub/gui.h (grub_gui_color_rgb): Move to ... - * include/grub/video.h (grub_video_rgba_color_rgb): ... here. - * include/grub/gui.h (grub_gui_map_color): Move to ... - * include/grub/video.h (grub_video_map_rgba_color): ... here. - * include/grub/gui_string_util.h (grub_gui_get_named_color): Move - to ... - * include/grub/video.h (grub_video_get_named_color): ... here. - * include/grub/gui_string_util.h (grub_gui_parse_color): Move to ... - * include/grub/video.h (grub_video_parse_color): ... here. - - * grub-core/Makefile.core.def (kernel) [videoinkernel]: Add - video/colors.c. - (gfxmenu): Remove gfxmenu/named_colors.c. - (video) [videomodules]: Add video/colors.c. - - Add a background_color command. - - * grub-core/term/gfxterm.c (grub_gfxterm_background_color_cmd): New - function. - (GRUB_MOD_INIT): Register background_color command. - (GRUB_MOD_FINI): Unregister background_color command. - (redraw_screen_rect): Allow blend/replace of text layer to be - controlled independently from whether there is a background bitmap. - (grub_gfxterm_background_image_cmd): Change blend_text_bg when - changing bitmap. - -2011-05-18 Vladimir Serbinenko - - Patch BPB in ntldr and chainloader --bpb. - - * grub-core/fs/fat.c: Include grub/fat.h. - (grub_fat_bpb): Moved to ... - * include/grub/fat.h (grub_fat_bpb): ... here. New file. - * grub-core/loader/i386/pc/chainloader.c: Include grub/fat.h and - grub/ntfs.h. - * include/grub/i386/pc/chainloader.h (grub_chainloader_flags_t): - Moved from here... - * grub-core/loader/i386/pc/chainloader.c (grub_chainloader_flags_t): ... - here. - * grub-core/loader/i386/pc/chainloader.c (grub_chainloader_patch_bpb): - New function. - (grub_chainloader_cmd): Patch BPB if --bpb is given. - (GRUB_MOD_INIT): Show --bpb. - * grub-core/loader/i386/pc/ntldr.c (grub_cmd_ntldr): Patch BPB. - * grub-core/normal/main.c (features): New variable. - (GRUB_MOD_INIT): Set feature_* variables. - * include/grub/i386/pc/chainloader.h (grub_chainloader_patch_bpb): New - proto. - * include/grub/ntfs.h (grub_ntfs_bpb): New field bios_drive. - -2011-05-18 Vladimir Serbinenko - - * grub-core/Makefile.core.def (ieee1275_fb): Use enable=powerpc_ieee1275 - for cleanness. - -2011-05-18 Vladimir Serbinenko - - FreeDOS direct loading support. - - * docs/grub.texi (Supported OS): Add FreeDOS. - * grub-core/Makefile.core.def (freedos): New module. - * grub-core/lib/i386/relocator.c (grub_relocator16_ebx): New extern - variable. - (grub_relocator16_boot): Handle %ebx. - * grub-core/lib/i386/relocator16.S: Likewise. - * grub-core/loader/i386/pc/freedos.c: New file. - -2011-05-18 Vladimir Serbinenko - - Long Linux command line support. - - * grub-core/loader/i386/linux.c (GRUB_LINUX_CL_END_OFFSET): Removed. - (maximal_cmdline_size): New variable. - (allocate_pages): Use maximal_cmdline_size. - (grub_cmd_linux): Set and use maximal_cmdline_size. - * grub-core/loader/i386/pc/linux.c (GRUB_LINUX_CL_END_OFFSET): Removed. - (allocate_pages): Use maximal_cmdline_size. - (grub_cmd_linux): Set and use maximal_cmdline_size. - * include/grub/i386/linux.h (GRUB_LINUX_SETUP_MOVE_SIZE): Removed. - (linux_kernel_header): Add fields kernel_alignment, relocatable, pad - and cmdline_size. - -2011-05-18 Vladimir Serbinenko -2011-05-18 Colin Watson - - Improve devmapper support - - * grub-core/kern/emu/getroot.c (grub_util_is_dmraid): Removed. - (grub_util_is_lvm): New function. - (grub_util_get_dev_abstraction): Assume dmraid if not lvm rather - than lvm if not dmraid. - Handle mapped md nodes. - * grub-core/kern/emu/hostdisk.c (device_is_mapped): Rename to ... - (grub_util_device_is_mapped): ... this. Make always available. All users - updated. - (grub_util_get_dm_node_linear_info) [HAVE_DEVICE_MAPPER]: New function. - (convert_system_partition_to_system_disk): Handle lvm, mpath and - dmraid nodes. - * include/grub/emu/misc.h (grub_util_device_is_mapped): New proto. - -2011-05-18 Vladimir Serbinenko - - Unify grub-mkrescue (except powerpc) and grrub-mknetdir across platforms - - * grub-core/Makefile.am (platform_DATA): Add modinfo.sh. - * grub-core/modinfo.sh.in: New file. - * grub-core/Makefile.core.def (modinfo.sh): New script. - * util/grub-mknetdir.in: Use modinfo.sh. - * util/grub-mkrescue.in: Likewise. - -2011-05-17 Vladimir Serbinenko - - * grub-core/kern/ia64/dl_helper.c (grub_ia64_dl_get_tramp_got_size): - Fix potential usage of Elf32 instead of Elf64 when compiling on - 32-bit architecture. Add endianness macros while on it. - -2011-05-17 Vladimir Serbinenko - - Use mipsel- rather than mips- in directories involving mipsel ports to - allow both endiannesses coexist. - - * configure.ac: proparate target_cpu=mipsel rather than resetting to - mips. All conditions adjusted. - * tests/util/grub-shell-tester.in: Remove gratuitious target_cpu - variable. - * util/grub-install.in: Adjust conditions to take renaming into account. - * util/grub-mkimage.c (image_targets): Likewise. New target - mips-qemu_mips-elf for bigendian mips. - -2011-05-17 Vladimir Serbinenko - - Avoid unnecessary copying on MIPS. - - * grub-core/boot/decompressor/none.c (grub_decompress_core): Exit - early if src == dest. - * util/grub-mkimage.c (generate_image): Arange for src == dest if - compression is none. - -2011-05-17 Vladimir Serbinenko - - Reduce memory footprint on SGI by putting modules before the kernel - as opposed to after. - - * grub-core/Makefile.core.def (kernel): Increase linking address. - (none_decompress): Likewise. - (xz_decompress): Likewise. - * grub-core/boot/mips/startup_raw.S: Use prewritten uncompression - address. - * grub-core/kern/mips/arc/init.c (grub_machine_init): Handle memory - layout change. - (grub_arch_modules_addr): New function. - * grub-core/kern/mips/init.c (grub_arch_modules_addr): Moved from here... - * grub-core/kern/mips/loongson/init.c (grub_arch_modules_addr): .. here - * grub-core/kern/mips/qemu_mips/init.c (grub_arch_modules_addr): ... and - here. - * grub-core/kern/mips/startup.S (total_size): Rename to ... - (grub_total_modules_size): ... this. Make global. - [GRUB_MACHINE_ARC]: Don't attempt to move modules out of the bss. - * include/grub/offsets.h (GRUB_KERNEL_MIPS_LOONGSON_UNCOMPRESSED_ADDR): - New definition. - (GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_ADDR): Likewise. - (GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_ADDR): Likewise. - (GRUB_KERNEL_MACHINE_UNCOMPRESSED_ADDR): Likewise. - (GRUB_KERNEL_MIPS_ARC_LINK_ADDR): Increased. - * util/grub-mkimage.c (image_target_desc): New flag - PLATFORM_FLAGS_MODULES_BEFORE_KERNEL. - (image_targets): Set PLATFORM_FLAGS_MODULES_BEFORE_KERNEL on mips-arc. - (generate_image): Handle images with modules before kernel. - -2011-05-17 Vladimir Serbinenko - - Prevent potential loss of memory map by overwrite on qemu-mips. - - * grub-core/boot/mips/startup_raw.S [GRUB_MACHINE_MIPS_QEMU_MIPS]: - Save ram size in $s4. - * grub-core/kern/mips/qemu_mips/init.c (RAMSIZE): Removed. - All users changed to grub_arch_memsize. - * grub-core/kern/mips/startup.S (grub_arch_machine): Restrict to - Loongson. - [GRUB_MACHINE_MIPS_QEMU_MIPS]: Save grub_arch_memsize. - * grub-core/loader/mips/linux.c (grub_linux_boot): Pass memory size. - * include/grub/mips/qemu_mips/memory.h (grub_arch_memsize): New - external variable. - -2011-05-17 Colin Watson - - * .bzrignore: Remove grub-dumpbios. - -2011-05-17 Colin Watson - - * util/grub.d/20_linux_xen.in: Honour GRUB_CMDLINE_LINUX_XEN_REPLACE - and GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT, which replace - GRUB_CMDLINE_LINUX and GRUB_CMDLINE_LINUX_DEFAULT (complementing the - existing options which append). - * docs/grub.texi (Simple configuration): Document new options. - Reported by: Ian Jackson. Fixes Debian bug #617538. - -2011-05-17 Colin Watson - - * util/grub-fstest.c (cmd_cat): New function. - (fstest): Handle CMD_CAT. - (options): Add cat. - (argp_parser): Handle cat. - -2011-05-17 Colin Watson - - * Makefile.util.def (grub-bin2h): Don't install. - * docs/man/grub-bin2h.h2m: Remove. - -2011-05-17 Vladimir Serbinenko - - * grub-core/kern/mips/startup.S (grub_arch_cpuclock): Move to the right - place. - -2011-05-17 Vladimir Serbinenko - - Reenable qemu-mips port. - - * configure.ac: Handle --target=qemu-mips and --target=qemu_mips. - Fix small arc bug while on it. - * gentpl.py: Handle qemu_mips. - * grub-core/Makefile.am: Likewise. - * grub-core/Makefile.core.def: Likewise. - * grub-core/disk/ata.c [GRUB_MACHINE_MIPS_QEMU_MIPS]: Remove - inappropriate includes. - (grub_ata_pciinit) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Removed. - (grub_ata_initialize): [GRUB_MACHINE_MIPS_QEMU_MIPS]: Rewritten. - * grub-core/kern/main.c (grub_modules_get_end) - [GRUB_MACHINE_MIPS_QEMU_MIPS]: Enable. - * grub-core/kern/mips/qemu-mips: Moved to .. - * grub-core/kern/mips/qemu_mips: ... this. - * grub-core/kern/mips/qemu_mips/init.c (grub_get_rtc): Removed. - (grub_machine_init): Call terminfo_init and serial_init. - * grub-core/kern/mips/startup.S: Change MIPS_LOONGSON to MACHINE. - * grub-core/loader/mips/linux.c (params) [GRUB_MACHINE_MIPS_QEMU_MIPS]: - New variable. - (grub_linux_boot) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Handle the qemu-mips - parameter passing. - (grub_linux_unload) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Free params. - (grub_cmd_linux) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Handle params. - (grub_cmd_initrd) [GRUB_MACHINE_MIPS_QEMU_MIPS]: Likewise. - * include/grub/mips/qemu_mips/cmos.h: New file. - * include/grub/mips/qemu-mips/kernel.h: Don't include cpu/kernel.h. - * include/grub/mips/qemu-mips/memory.h (grub_machine_mmap_iterate): - Removed. - * include/grub/mips/qemu-mips/serial.h (GRUB_MACHINE_SERIAL_PORTS): - Use correct mips-style address. - * include/grub/mips/qemu-mips/time.h: Include cpu/time.h. - (GRUB_TICKS_PER_SECOND): Removed. - (grub_get_rtc): Likewise. - (grub_cpu_idle): Likewise. - * include/grub/offsets.h (GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ADDR): - New definition. - (GRUB_KERNEL_MIPS_QEMU_MIPS_LINK_ALIGN): Likewise. - (GRUB_KERNEL_MIPS_QEMU_MIPS_COMPRESSED_SIZE): Likewise. - (GRUB_KERNEL_MIPS_QEMU_MIPS_UNCOMPRESSED_SIZE): Likewise. - (GRUB_KERNEL_MIPS_QEMU_MIPS_TOTAL_MODULE_SIZE): Likewise. - (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX): Likewise. - (GRUB_KERNEL_MIPS_QEMU_MIPS_PREFIX_END): Likewise. - (GRUB_KERNEL_MIPS_QEMU_MIPS_MOD_ALIGN): Likewise. - * util/grub-mkimage.c (image_targets): Add mipsel-qemu_mips-elf. - -2011-05-17 Vladimir Serbinenko - - SGI ARCS port. - - * Makefile.util.def (libgrubmods.a): Add dvh.c. - * conf/Makefile.common (CCASFLAGS_PLATFORM): Add -mips3 on all mips - platforms. - * configure.ac: New target mips-arc. - * gentpl.py: Likewise. - * grub-core/Makefile.am: Likewise. - * grub-core/Makefile.core.def: Likewise. - (xz_decompress): Remove -D GRUB_MACHINE_LINK_ADDR. - (none_decompress): Likewise. - (lsdev): New module. - (datetime): Use lib/arc/datetime.c on ARC. - (part_dvh): New module. - * grub-core/commands/arc/lsdev.c: New file. - * grub-core/disk/arc/arcdisk.c: Likewise. - * grub-core/kern/mips/arc/init.c: Likewise. - * grub-core/kern/mips/cache_flush.S: Don't flush non 4-byte - aligned addresses. - * grub-core/kern/mips/dl.c (grub_arch_dl_check_header): Fix bigendian - support. - (grub_arch_dl_relocate_symbols): Likewise. - * grub-core/kern/mips/loongson/init.c (grub_get_rtc): Moved from here... - * grub-core/kern/mips/init.c (grub_get_rtc): ... here. - * grub-core/kern/mips/startup.S (grub_arch_cpuclock): Have on all - platforms. - * grub-core/lib/arc/datetime.c: New file. - * grub-core/loader/mips/linux.c: Always include time.h. Don't include - pci.h on non-loongson. - (envp_off) [!GRUB_MACHINE_MIPS_LOONGSON]: Remove. - (grub_linux_boot): Set unused registers to 0. - (grub_cmd_linux) [!GRUB_MACHINE_MIPS_LOONGSON]: Remove envp. - * grub-core/mmap/mips/loongson/uppermem.c: Moved from here ... - * grub-core/mmap/mips/uppermem.c: ...here. - * grub-core/partmap/dvh.c: New file. - * grub-core/term/arc/console.c: Likewise. - * grub-core/term/terminfo.c (ANSI_C0_STR): New const. - (grub_terminfo_set_current): Add terminal "arc". - (grub_terminfo_readkey): Support ARC sequences. - * include/grub/arc/arc.h: New file. - * include/grub/arc/console.h: Likewise. - * include/grub/disk.h (grub_disk_dev_id): Add - GRUB_DISK_DEVICE_ARCDISK_ID. - * include/grub/mips/arc/kernel.h: New file. - * include/grub/mips/arc/memory.h: Likewise. - * include/grub/mips/arc/time.h: Likewise. - * include/grub/mips/loongson/kernel.h (grub_halt): Moved from here ... - * include/grub/mips/kernel.h (grub_halt): ... here. - * include/grub/mips/loongson.h (GRUB_CPU_REGISTER_WRAP): Moved from - here... - * include/grub/mips/mips.h (GRUB_CPU_REGISTER_WRAP): ... here. - (GRUB_CPU_LOONGSON_COP0_TIMER_COUNT): Moved from here ... - * include/grub/mips/mips.h (GRUB_CPU_LOONGSON_COP0_TIMER_COUNT): .. here - * include/grub/mips/loongson/kernel.h (grub_reboot): Removed redundant - proto. - * include/grub/mips/loongson/memory.h (GRUB_ARCH_LOWMEMVSTART): Moved - from here ... - * include/grub/mips/memory.h (GRUB_ARCH_LOWMEMVSTART): ... here. - (GRUB_ARCH_LOWMEMPSTART): Moved from here ... - * include/grub/mips/memory.h (GRUB_ARCH_LOWMEMPSTART): ... here. - (GRUB_ARCH_LOWMEMMAXSIZE): Moved from here ... - * include/grub/mips/memory.h (GRUB_ARCH_LOWMEMMAXSIZE): ... here. - (GRUB_ARCH_HIGHMEMPSTART): Moved from here ... - * include/grub/mips/memory.h (GRUB_ARCH_HIGHMEMPSTART): ... here. - (grub_phys_addr_t): Moved from here ... - * include/grub/mips/memory.h (grub_phys_addr_t): ... here. - (grub_vtop): Moved from here ... - * include/grub/mips/memory.h (grub_vtop): ... here. - (grub_map_memory): Moved from here ... - * include/grub/mips/memory.h (grub_map_memory): ... here. - (grub_unmap_memory): Moved from here ... - * include/grub/mips/memory.h (grub_unmap_memory): ... here. - (grub_machine_mmap_iterate): Moved from here ... - * include/grub/mips/memory.h (grub_machine_mmap_iterate): ... here. - (grub_mmap_get_lower): Moved from here ... - * include/grub/mips/memory.h (grub_mmap_get_lower): ... here. - (grub_mmap_get_upper): Moved from here ... - * include/grub/mips/memory.h (grub_mmap_get_upper): ... here. - * include/grub/mips/loongson/time.h (grub_arch_cpuclock): Moved from - here ... - * include/grub/mips/time.h (grub_arch_cpuclock): ... here. - * include/grub/mips/loongson/time.h (grub_get_rtc): Moved from - here ... - * include/grub/mips/time.h (grub_get_rtc): ... here. - * include/grub/mips/loongson/time.h (grub_arch_cpuclock): Moved from - here ... - * include/grub/mips/time.h (grub_arch_cpuclock): ... here. - * include/grub/mips/loongson/time.h (grub_cpu_idle): Moved from - here ... - * include/grub/mips/time.h (grub_cpu_idle): ... here. - * include/grub/offsets.h (GRUB_KERNEL_MIPS_ARC_LINK_ADDR): New - definition. - (GRUB_KERNEL_MIPS_ARC_LINK_ALIGN): Likewise. - (GRUB_KERNEL_MIPS_ARC_COMPRESSED_SIZE): Likewise. - (GRUB_KERNEL_MIPS_ARC_UNCOMPRESSED_SIZE): Likewise. - (GRUB_KERNEL_MIPS_ARC_TOTAL_MODULE_SIZE): Likewise. - (GRUB_KERNEL_MIPS_ARC_PREFIX): Likewise. - (GRUB_KERNEL_MIPS_ARC_PREFIX_END): Likewise. - (GRUB_KERNEL_MIPS_ARC_MOD_ALIGN): Likewise. - (GRUB_MACHINE_LINK_ADDR): Likewise. - * include/grub/terminfo.h (GRUB_TERMINFO_READKEY_MAX_LEN): Increased - to 6. - * util/grub-install.in: Run dvhtool on ARC. - * util/grub-mkimage.c (image_targets): Add mips-arc. - (generate_image): Handle ECOFF output for mips-arc. - -2011-05-16 Vladimir Serbinenko - - * grub-core/bus/pci.c (grub_memalign_dma32): Always allocate in 64-byte - blocks. - -2011-05-16 Vladimir Serbinenko - - * grub-core/bus/usb/usbhub.c (attach_root_port): Wait 10ms - after enabling port. - -2011-05-16 Vladimir Serbinenko - - Skip incorrect USB devices. - - * grub-core/bus/usb/usb.c (grub_usb_device_initialize): Fail if - configcnt == 0. - * include/grub/usb.h (grub_usb_err_t): New enum value - GRUB_USB_ERR_BADDEVICE. - -2011-05-16 Vladimir Serbinenko - - Fuloong video init support. - - * include/grub/vga.h (grub_vga_write_arx): inb monochrome address as - well. - (grub_vga_read_arx): New function. - * grub-core/video/sis315pro.c (GRUB_SIS315PRO_MMIO_SPACE): New - definition. - (framebuffer): New members io, mmioptr and mmiobase. - (read_sis_cmd): New function. - (write_sis_cmd): Likewise. - (grub_video_sis315pro_setup): Do the initialisation. Use 640x480 - rather than 640x400. - * grub-core/video/sis315_init.c: New file. - -2011-05-15 Vladimir Serbinenko - - * grub-core/bus/cs5536.c: Don't include grub/machine/kernel.h on - non-loongson. - * grub-core/kern/mips/dl.c (grub_arch_dl_init_linker): Fix argument - to grub_dl_register_symbol. - -2011-05-15 Vladimir Serbinenko - - Fix compilation errors. - - * grub-core/term/ns8250.c (serial_get_divisor): Declare 'port' as - potentially unused. - * grub-core/loader/i386/linux.c (grub_linux_setup_video): - Handle GRUB_VIDEO_DRIVER_SIS315PRO. - * grub-core/bus/cs5536.c (grub_cs5536_init_geode): Restrict DIVIL init - to loongson machines. - -2011-05-15 Vladimir Serbinenko - - Several FS mtime support. - - * grub-core/fs/affs.c (grub_affs_time): New struct. - (grub_affs_file): New field mtime. - (grub_fshelp_node): Changed 'block' and 'parent' to more appropriate - type. Removed 'size'. New field 'di'. All users updated. - (grub_affs_mount): Simplify checsum checking. - (grub_affs_iterate_dir): New helper grub_affs_create_node. - (grub_affs_dir): Handle mtime. - * grub-core/fs/cpio.c (grub_cpio_find_file): Handle mtime. - (grub_cpio_dir): Likewise. - * grub-core/fs/hfs.c (grub_hfs_dirrec): New fields 'ctime' and 'mtime'. - (grub_hfs_filerec): New field mtime. - (grub_hfs_dir): Handle mtime. - (grub_hfs_mtime): New function. - (grub_hfs_fs): Register grub_hfs_mtime. - * grub-core/fs/iso9660.c (grub_iso9660_date2): New struct. - (grub_iso9660_dir): New field mtime. - (grub_fshelp_node): New field dirent. - (iso9660_to_unixtime): New function. - (iso9660_to_unixtime2): Likewise. - (grub_iso9660_read_symlink): Use node->dirent. - (grub_iso9660_iterate_dir): Likewise. - (grub_iso9660_dir): Set mtime. - (grub_iso9660_mtime): New function. - (grub_iso9660_fs): Register grub_iso9660_mtime. - * grub-core/fs/jfs.c (grub_jfs_time): New struct. - (grub_jfs_inode): New fields atime, ctime and mtime. - (grub_jfs_dir): Set mtime. - * grub-core/fs/minix.c (grub_minix_dir): Likewise. - * grub-core/fs/ntfs.c (list_file): Set mtime. - (grub_ntfs_dir): Likewise. - * grub-core/fs/reiserfs.c (grub_fshelp_node): New field 'mtime'. - (grub_reiserfs_iterate_dir): Set mtime. - (grub_reiserfs_dir): Likewise. - * grub-core/fs/sfs.c (grub_sfs_obj): New field mtime. - (grub_fshelp_node): Likewise. - (grub_sfs_iterate_dir): Set mtime. - (grub_sfs_dir): Likewise. - * grub-core/fs/udf.c (grub_udf_dir): Set mtime. - * grub-core/fs/xfs.c (grub_xfs_time): New struct. - (grub_xfs_inode): New fields atime, mtime, ctime. - (grub_xfs_dir): Set mtime. - * include/grub/datetime.h (grub_datetime2unixtime): New function. - * include/grub/hfs.h (grub_hfs_sblock): New fields ctime and mtime. - * include/grub/ntfs.h (grub_fshelp_node): New field mtime. - - Support UDF symlinks. - - * grub-core/fs/udf.c (grub_udf_iterate_dir): Handle symlinks. - (grub_ufs_read_symlink): New function. All users updated. - - Check amiga partmap checksum. - - * grub-core/partmap/amiga.c (grub_amiga_rdsk): Pad to 128 bytes. - (grub_amiga_partition): Likewise. - (amiga_partition_map_checksum): New function. - (amiga_partition_map_iterate): Check checksum. - -2011-05-15 Vladimir Serbinenko - - ROMFS support. - - * Makefile.util.def (libgrubmods.a): Add romfs. - * grub-core/Makefile.core.def (romfs): New module. - * grub-core/fs/romfs.c: New file. - -2011-05-15 Vladimir Serbinenko - - Squashfs v4 support. - - * Makefile.util.def (libgrubmods.a): Add squash4. - * grub-core/Makefile.core.def (squash4): New module. - * grub-core/fs/squash4.c: New file. - * grub-core/io/gzio.c (grub_gzio): New members disk_input_off, - disk_input_start, disk_input. - (get_byte): Handle disk_input. - (grub_zlib_disk_read): New function. - * include/grub/deflate.h (grub_zlib_disk_read): New proto. - -2011-05-15 Vladimir Serbinenko -2011-05-15 Feiran Zheng - - * Makefile.util.def (libgrubmods.a): Add minix3. - * grub-core/Makefile.core.def (minix3): New module. - * grub-core/fs/minix.c (GRUB_MINIX_MAGIC) [MODE_MINIX3]: New value. - (GRUB_MINIX_BSIZE): Removed. - (GRUB_MINIX_INODE_DIR_BLOCKS): New definition. All users updated. - (grub_minix_ino_t): New type. - (grub_minix_le_to_cpu_ino): New macro. - (GRUB_MINIX_ZONE2SECT): New definition. All users updated. - (grub_minix_sblock) [MODE_MINIX3]: Change for minix3. - (grub_minix_data): New field block_size. - (grub_minix_read_file): Handle 64-bit correctly. - * grub-core/fs/minix3.c: New file. - -2011-05-15 Tristan Gingold -2011-05-15 Robert Millan -2011-05-15 Vladimir Serbinenko - - IA64 support. - - * Makefile.util.def (libgrubmods.a): Add grub-core/kern/ia64/dl_helper.c - * configure.ac: Add ia64-efi target. - Probe for __ia64_trampoline, __udivsi3, __umoddi3, __udivdi3, - __divsi3, __modsi3, __umodsi3, __moddi3 and __divdi3 symbols. - * gentpl.py: Add ia64_efi platform. - Rename x86_efi to efi and Add ia64-efi. All users updated. - * grub-core/Makefile.am: Set KERNEL_HEADER_FILES for ia64-efi. - * grub-core/Makefile.core.def (kernel.img): Add compile flags for ia64. - Remove kern/generic/rtc_get_time_ms.c on EFI. - Add kern/ia64/efi/startup.S, kern/ia64/efi/init.c, kern/ia64/dl.c, - kern/ia64/dl_helper.c on ia64-efi. - Add kern/emu/cache.c on emu. - (linux): Use on loader/ia64/efi/linux.c on ia64. - * grub-core/gensymlist.sh (grub_register_exported_symbols): Check - whether symbol is a function. - * grub-core/kern/dl.c [GRUB_MACHINE_EMU]: Include sys/mman.h. - (grub_symbol): New field 'isfunc'. - (grub_dl_resolve_symbol): Return whole symbol rather than just address. - (grub_dl_register_symbol): New argument 'isfunc'. All users updated. - (grub_dl_load_segments): Place all sections into the same region. - [__ia64__]: Create trampolines and got. - [GRUB_MACHINE_EMU]: Call mprotect. - (grub_dl_resolve_symbols): Resolve symbol type as well. - [__ia64__]: Create function descriptors. - * grub-core/kern/efi/efi.c (grub_get_rtc): Renamed to ... - (grub_rtc_get_time_ms): ... this. Expressions simplified. - (grub_get_rtc): New function. - * grub-core/kern/emu/cache.c [__ia64__]: New file. - * grub-core/kern/emu/cache.S: Renamed to ... - * grub-core/kern/emu/cache_s.S: ... this. - [__ia64__]: Add a nop. - * grub-core/kern/emu/full.c (grub_arch_dl_get_tramp_got_size) - [__ia64__]: New function. - * grub-core/kern/emu/lite.c [__ia64__]: Include ../ia64/dl.c. - * grub-core/kern/ia64/dl.c: New file. - * grub-core/kern/ia64/dl_helper.c: Likewise. - * grub-core/kern/ia64/efi/init.c: New file. - * grub-core/kern/ia64/efi/startup.S: Likewise. - * grub-core/lib/efi/halt.c [__ia64__]: Don't try acpi. - * grub-core/lib/ia64/longjmp.S: New file (from glibc). - * grub-core/lib/ia64/setjmp.S: Likewise (from glibc). - * grub-core/lib/setjmp.S [__ia64__]: Include ./ia64/setjmp.S. - * grub-core/loader/ia64/efi/linux.c: New file. - * include/grub/dl.h (GRUB_MOD_NAME): Redefined using C rather than asm. - (GRUB_MOD_DEP): Likewise. - (grub_dl) [__ia64__]: New fields got and tramp. - (grub_dl): New field 'base'. - (grub_dl_register_symbol): New argument isfunc. All users updated. - (GRUB_IA64_DL_TRAMP_ALIGN): New definition. - (GRUB_IA64_DL_TRAMP_SIZE): Likewise. - (GRUB_IA64_DL_GOT_ALIGN): Likewise. - (grub_ia64_dl_get_tramp_got_size): New proto. - (GRUB_ARCH_DL_TRAMP_ALIGN) [__ia64__]: Likewise - (GRUB_ARCH_DL_GOT_ALIGN) [__ia64__]: Likewise - (grub_arch_dl_get_tramp_got_size) [__ia64__]: Likewise - * include/grub/efi/api.h: Skip call wrappers on ia64. - * include/grub/efi/pe32.h (GRUB_PE32_MACHINE_IA64): New definition. - * include/grub/efi/time.h (GRUB_TICKS_PER_SECOND): Change to 1000. - * include/grub/elf.h (ELF_ST_INFO): New definition. - * include/grub/ia64/efi/kernel.h: New file. - * include/grub/ia64/efi/memory.h: Likewise. - * include/grub/ia64/efi/time.h: Likewise. - * include/grub/ia64/kernel.h: Likewise. - * include/grub/ia64/setjmp.h: Likewise (from glibc). - * include/grub/ia64/time.h: New file. - * include/grub/ia64/types.h: Likewise. - * include/grub/libgcc.h (__udivsi3, __umodsi3, __umoddi3, __udivdi3, - __moddi3, __divdi3, __divsi3, __modsi3, __ia64_trampoline): - New protos. - * include/grub/offsets.h (GRUB_KERNEL_IA64_EFI_PREFIX): New definition. - (GRUB_KERNEL_IA64_EFI_PREFIX_END): Likewise. - * include/grub/types.h (PRIxGRUB_ADDR): Likewise. - * util/grub-mkimage.c (image_target_desc): New field pe_target. - All users updated. - (EFI64_HEADER_SIZE): New definition. All users updated. - (image_targets): Add ia64-efi. - * util/grub-mkimagexx.c (relocate_symbols): New arguments jumpers and - jumpers_addr. All users updated. - Create function descriptors. - (count_funcs): New function. - (unaligned_uint32): New struct. - (MASK20): New definition. - (MASK19): Likewise. - (MASKF21): Likewise. - (add_value_to_slot_20b): New function. - (add_value_to_slot_21_real): Likewise. - (add_value_to_slot_21): Likewise. - (ia64_kernel_trampoline): New struct. - (nopm): New variable. - (jump): Likewise. - (make_trampoline): New function. - (relocate_addresses): Handle ia64. - (make_reloc_section): Likewise. - (load_image): Likewise. - -2011-05-15 Vladimir Serbinenko - - * grub-core/fs/btrfs.c (grub_btrfs_read_logical): Silence spurious - warning. Move variables before code while on it. - -2011-05-15 Vladimir Serbinenko - - Fuloong support. - - * configure.ac: Rename yeeloong platform to loongson. All users updated. - * grub-core/Makefile.core.def (fwstart_fuloong): New image. - * grub-core/boot/mips/loongson/fuloong.S: New file. - * grub-core/boot/mips/loongson/fwstart.S: Wait for CS5536 to come up. - Explicitly init CS5536. - [FULOONG]: Don't use serial until CS5536 is available. - Set GPIO based on dumps. - (serial_hw_init) [FULOONG]: Handle CS5536 parts. - [FULOONG]: Handle GPIO and memory controller differences. - Parse machine type in $a2. - * grub-core/boot/mips/startup_raw.S: Determine and save the - architecture. - * grub-core/bus/cs5536.c (gpiodump): Move to fwstart.S. - (grub_cs5536_init_geode): Remove gpio part. Conditionalise DIVIL - init on architecture type. - * grub-core/kern/mips/loongson/init.c (grub_machine_init): Init - SIS315E. Don't init at_keyboard on fuloong. - (grub_halt): Support Fuloong. - * grub-core/kern/mips/startup.S [LOONGSON]: Save $s7. - * grub-core/loader/mips/linux.c (LOONGSON_MACHTYPE): Removed. - (loongson_machtypes): New array. - (grub_cmd_linux) [GRUB_MACHINE_MIPS_LOONGSON]: Pass the right machine - type. - * grub-core/term/ns8250.c (serial_get_divisor): New parameter port and - config. All users updated. Handle CS5536 serial. - * grub-core/term/serial.c (grub_serial_register): Conditionalise - default port on machine type. Register serial as inactive. - * grub-core/video/sis315pro.c: New file. - * include/grub/cs5536.h (GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED): New - definition. - (GRUB_CS5536_MSR_MAILBOX_CONFIG): Likewise. - (GRUB_CS5536_MSR_DIVIL_LEG_IO_UART1_COM1): Likewise. - (GRUB_CS5536_MSR_DIVIL_LEG_IO_UART2_COM3): Likewise. - (GRUB_CS5536_MSR_DIVIL_UART1_CONF): Likewise. - (GRUB_CS5536_MSR_DIVIL_UART2_CONF): Likewise. - * include/grub/mips/loongson.h (GRUB_CPU_LOONGSON_SHUTDOWN_GPIO): Rename - to ... - (GRUB_CPU_YEELOONG_SHUTDOWN_GPIO): ... this. - * include/grub/mips/loongson/kernel.h (GRUB_ARCH_MACHINE_YEELOONG): New - definition. - (GRUB_ARCH_MACHINE_FULOONG): Likewise. - (grub_arch_machine): New extern var. - * include/grub/mips/loongson/serial.h - (GRUB_MACHINE_SERIAL_DIVISOR_115200): Renamed to ... - (GRUB_MACHINE_SERIAL_PORT0_DIVISOR_115200): ... this. - (GRUB_MACHINE_SERIAL_PORT): Renamed to ... - (GRUB_MACHINE_SERIAL_PORT0): ... this. - (GRUB_MACHINE_SERIAL_PORT2_DIVISOR_115200): New definition. - (GRUB_MACHINE_SERIAL_PORT1): Likewise. - (GRUB_MACHINE_SERIAL_PORT2): Likewise. - (GRUB_MACHINE_SERIAL_PORTS): Include ports 1 and 2. - * include/grub/term.h (grub_term_register_input_inactive): New inline - function. - (grub_term_register_output_inactive): Likewise. - * include/grub/video.h (grub_video_driver_id): New value - GRUB_VIDEO_DRIVER_SIS315PRO. - * util/grub-mkimage.c (image_target_desc): Rename name to dirname. - New field "names". All users updated. - New field value IMAGE_FULOONG_FLASH. - (generate_image): USe separate fwstart hashes for yeeloong and fuloong. - -2011-05-14 Jordan Uggla - - * docs/grub.texi (Invoking grub-install): Fix additional outdated claims - and add some clarification. - -2011-05-14 Vladimir Serbinenko - - * util/grub.d/10_linux.in: Autoload gzio since it's needed on some - platforms if kernel is compressed. - -2011-05-14 Vladimir Serbinenko - - * grub-core/kern/mm.c (grub_memalign): Disable auto-unloadding of - unused modules since currently referrence counter isn't reliable and - there isn't much memory to recover there anyway. - -2011-05-14 Vladimir Serbinenko - - * grub-core/kern/dl.c (grub_dl_load_file): Decrease ref counter - rather than resetting it to allow modules to reference themselves - in init. - -2011-05-14 Vladimir Serbinenko - - * grub-core/kern/dl.c (grub_dl_unload): Don't decrease reference - counter on dependencies since grub_dl_unref already handles this. - -2011-05-14 Vladimir Serbinenko - - * grub-core/font/font_cmd.c (loadfont_command): Set grub_errno - on error if not already done. - -2011-05-14 Vladimir Serbinenko - - Fix few potential memory misusage. - - * grub-core/font/font.c (load_font_index): Don't free char_index to - avoid double free. - (grub_font_load): Zero-fill font at alloc for safety. - Close file on error. - (free_font): Free bmp_idx. - -2011-05-14 Vladimir Serbinenko - - * docs/grub.texi (Installation): Fix several outdated claims. - -2011-05-14 Vladimir Serbinenko - - Handle module_license on windows. - - * util/grub-pe2elf.c (MODLICENSE_SECTION): New definition. All following - sections shifted. - (insert_string): Make argument const char * instead of char *. - (write_section_data): Handle long section names. - Handle module_license. - -2011-05-14 Vladimir Serbinenko - - * grub-core/commands/menuentry.c (grub_cmd_menuentry): Correctly - handle class-free menuentries. - (grub_normal_add_menu_entry): Add a check to be sure. - -2011-05-14 Vladimir Serbinenko - - * grub-core/term/at_keyboard.c (set1_e0_mapping): Fix swap between - PgUp and PgDown. - -2011-05-13 Vladimir Serbinenko - - * configure.ac: Bump version to 1.99. - -2011-05-13 Vladimir Serbinenko - - Give ATA device a bit more time on first try in order to allow disks - to spin up. - - * grub-core/disk/ata.c (grub_atapi_identify): Use GRUB_ATA_TOUT_DEV_INIT - if dev->present is 1. Reset dev->present on failure. - (grub_ata_device_initialize): Set dev->present to 1. - * include/grub/ata.h (GRUB_ATA_TOUT_DEV_INIT): New value. - (grub_ata_device): New member 'present'. - -2011-05-13 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Update hash. - -2011-05-13 Vladimir Serbinenko - - Flush caches on DMA memory. - - * grub-core/kern/mips/cache.S (grub_arch_sync_dma_caches): New function. - * grub-core/bus/pci.c (grub_memalign_dma32): Flush caches. - (grub_dma_free): Likewise. - * include/grub/cache.h (grub_arch_sync_dma_caches): New declaration. - -2011-05-13 Vladimir Serbinenko - - * grub-core/boot/mips/yeeloong/fwstart.S: Add explicit set mips3 - to avoid asm treating ld and sd as macros. - -2011-05-13 Vladimir Serbinenko - - * grub-core/boot/mips/startup_raw.S: Flush cache after loading - decompressor. - -2011-05-13 Vladimir Serbinenko - - * grub-core/boot/mips/startup_raw.S: Use jalr rather than bal to call - grub_decompress_core since later would fail if grub_decompress_core - is too far. - -2011-05-13 Vladimir Serbinenko - - * grub-core/kern/mips/dl.c (grub_arch_dl_relocate_symbols): Handle - R_MIPS_JALR since it's used by newer compiler. - -2011-05-10 Vladimir Serbinenko - - * util/grub.d/10_linux.in: Correctly handle the Linux in root. - -2011-05-09 Vladimir Serbinenko - - * grub-core/loader/efi/chainloader.c (grub_chainloader_unload): Set - file_path to 0 for surety. - (grub_chainloader_boot): Set exit_data to NULL. - Unset the loader once done. - (grub_cmd_chainloader): Fix confusing error message if file is empty. - -2011-05-09 Vladimir Serbinenko - - * grub-core/term/at_keyboard.c (fetch_key): Make a printf on - unknown key into a dprintf. - -2011-05-09 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (linux_find_partition): Don't abort - on first non-existant partition. - -2011-05-09 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (open_device): Set data->fd to -1 if - openning fails. - Reported by: Mark Korenberg. - -2011-05-09 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (linux_find_partition): Prevent possible - overflow. - -2011-05-09 Vladimir Serbinenko - - * util/grub-mkimage.c (main): Explicitely flush and sync the output - before closing to ensure that it will be readable by grub-setup. - -2011-05-05 Vladimir Serbinenko - - * grub-core/loader/efi/appleloader.c (MAKE_PIWG_PATH): New macro. - (devpath_1): Use MAKE_PIWG_PATH. - (devpath_2): Likewise. - (devpath_3): Likewise. - (devpath_4): Likewise. - (devpath_5): Likewise. - (devpath_6): Likewise. - - The appleldr.mod was checked that to be binary identical to previous - version. - -2011-05-05 Zach - - Support 2010 Macbooks. - - * grub-core/loader/efi/appleloader.c (devpath_6): New variable. - (devs): Add devpath_6. - -2011-05-05 Vladimir Serbinenko - - * util/grub-mkpasswd-pbkdf2.c (main): Use /dev/urandom and not - /dev/random. /dev/urandom is good enough for our purposes (salting). - -2011-05-05 Vladimir Serbinenko - - * util/grub-mkrescue.in (process_input_dir): Include efiemu??.o. - -2011-05-05 Vladimir Serbinenko - - * grub-core/lib/legacy_parse.c (grub_legacy_parse): Correctly handle - hexadecimal. - -2011-05-05 Vladimir Serbinenko - - * grub-core/efiemu/main.c (grub_efiemu_load_file): Return grub_errno - and not 0 on failure. - -2011-05-03 Colin Watson - - * grub-core/fs/i386/pc/pxe.c (grub_pxefs_dir): Return - GRUB_ERR_BAD_FS rather than GRUB_ERR_IO if the disk is not a pxe - disk; otherwise grub_fs_probe will not fall back to the next - filesystem. - (grub_pxefs_open): Likewise, for consistency. - Reported and tested by: Ezekiel Grave. - -2011-05-03 Colin Watson - - * tests/partmap_test.in: Don't hardcode path to parted. - Reported by: Peter Hjalmarsson. Fixes Savannah bug #33150. - -2011-05-01 Colin Watson - - * docs/grub.texi (GRUB only offers a rescue shell): Suggest the use - of `ls' to find out which devices are available. - -2011-04-25 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (grub_linux_boot): Supply target rather - than source address for efi mmap buffer. - -2011-04-25 Vladimir Serbinenko - - * grub-core/partmap/amiga.c (amiga_partition_map_iterate): Fix a - wrong action on non-detecting the magic. - -2011-04-25 Vladimir Serbinenko - - * grub-core/gnulib/regex.c: Remove GRUB_MOD_LICENSE since it's - already supplied by another part of the module (fixes compilation on - FreeBSD). - -2011-04-25 Vladimir Serbinenko - - * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Make mdraid UUID - match the one used by mdadm. - -2011-04-21 Colin Watson - - * po/README: Add instructions for creating po/LINGUAS. - -2011-04-21 Colin Watson - - Add "SEE ALSO" sections to most man pages. Fixes Debian bug - #551428. - - * docs/man/grub-editenv.h2m (SEE ALSO): New section. - * docs/man/grub-emu.h2m (SEE ALSO): Likewise. - * docs/man/grub-fstest.h2m (SEE ALSO): Likewise. - * docs/man/grub-install.h2m (SEE ALSO): Likewise. - * docs/man/grub-macho2img.h2m (SEE ALSO): Likewise. - * docs/man/grub-menulst2cfg.h2m (SEE ALSO): Likewise. - * docs/man/grub-mkconfig.h2m (SEE ALSO): Likewise. - * docs/man/grub-mkdevicemap.h2m (SEE ALSO): Likewise. - * docs/man/grub-mkfont.h2m (SEE ALSO): Likewise. - * docs/man/grub-mkimage.h2m (SEE ALSO): Likewise. - * docs/man/grub-mklayout.h2m (SEE ALSO): Likewise. - * docs/man/grub-mknetdir.h2m (SEE ALSO): Likewise. - * docs/man/grub-mkpasswd-pbkdf2.h2m (SEE ALSO): Likewise. - * docs/man/grub-mkrelpath.h2m (SEE ALSO): Likewise. - * docs/man/grub-mkrescue.h2m (SEE ALSO): Likewise. - * docs/man/grub-ofpathname.h2m (SEE ALSO): Likewise. - * docs/man/grub-pe2elf.h2m (SEE ALSO): Likewise. - * docs/man/grub-probe.h2m (SEE ALSO): Likewise. - * docs/man/grub-reboot.h2m (SEE ALSO): Likewise. - * docs/man/grub-script-check.h2m (SEE ALSO): Likewise. - * docs/man/grub-set-default.h2m (SEE ALSO): Likewise. - * docs/man/grub-setup.h2m (SEE ALSO): Likewise. - -2011-04-21 Colin Watson - - * grub-core/kern/emu/getroot.c - (grub_find_root_device_from_mountinfo): Remove non-virtual-device - test that was incorrectly reintroduced in r3214. - Reported by: Ian Dall. Fixes Savannah bug #33133. - -2011-04-21 Colin Watson - - Fix stack pointer handling in 16-bit relocator. - - * grub-core/lib/i386/relocator16.S (grub_relocator16_start): Move - grub_relocator16_sp to %esp rather than %ss, and zero-extend it. - Fixes Ubuntu bug #683904. - -2011-04-20 Vladimir Serbinenko - - * configure.ac: Bump version to 1.99~rc2. - -2011-04-20 Vladimir Serbinenko - - * include/grub/dl.h [ASM_FILE]: Adapt for assembly. - * grub-core/lib/i386/setjmp.S: Add missing GRUB_MOD_LICENSE. - * grub-core/lib/x86_64/setjmp.S: Likewise. - * grub-core/lib/mips/setjmp.S: Likewise. - * grub-core/lib/powerpc/setjmp.S: Likewise. - * grub-core/lib/sparc64/setjmp.S: Likewise. - -2011-04-20 Vladimir Serbinenko - - * grub-core/lib/efi/datetime.c: Add missing GRUB_MOD_LICENSE. - * grub-core/lib/efi/datetime.c: Likewise. - -2011-04-19 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_flush): - New function. - (grub_util_biosdisk_close): Use grub_util_biosdisk_flush. - * include/grub/emu/hostdisk.h (grub_util_biosdisk_flush): New proto. - * util/grub-setup.c (setup): Use grub_util_biosdisk_flush. - -2011-04-19 Vladimir Serbinenko - - * grub-core/term/gfxterm.c (grub_gfxterm_fullscreen): Preserve previous - bitmap. - (grub_gfxterm_term_init): Likewise. - -2011-04-19 Vladimir Serbinenko - - Take into account the decorations the computing menu entry width. - - * grub-core/gfxmenu/widget-box.c (get_border_width): New function. - (grub_gfxmenu_create_box): Register get_border_width. - * grub-core/gfxmenu/gui_list.c (draw_menu): Use get_border_width - if available. - * include/grub/gfxwidgets.h (grub_gfxmenu_box): New member - get_border_width. - -2011-04-18 Endres Puschner - - * grub-core/gfxmenu/icon_manager.c (grub_gfxmenu_icon_manager_get_icon): - Don't skip first class. - -2011-04-18 Vladimir Serbinenko - - * grub-core/fs/btrfs.c (grub_btrfs_read_logical): Support huge - chunks. - * include/grub/err.h (grub_err_t): New enum value GRUB_ERR_BUG. - -2011-04-18 Vladimir Serbinenko - - Complete 64-bit division support. - - * grub-core/kern/misc.c (grub_divmod64): Rename to ... - (grub_divmod64_full): ... this. Support 64-bit divisor and reminder. - * include/grub/misc.h (grub_divmod64): Rename to ... - (grub_divmod64_full): ... this. - (grub_divmod64): New inline function. - -2011-04-18 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Add forgotten comma. - -2011-04-18 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Update fwstart.img hash after - performing the necessary test. - -2011-04-17 Vladimir Serbinenko - - * Makefile.am (multiboot.elf): Add -Wl,--build-id=none. - (kfreebsd.elf): Likewise. - (pc-chainloader.elf): Likewise. - (ntldr.elf): Likewise. - -2011-04-17 Vladimir Serbinenko - - Identify RAID by its UUID rather than (guessed) name. - - * grub-core/disk/raid.c (ascii2hex): New function. - (grub_raid_open): Accept mduuid/%s specification. - * grub-core/kern/emu/getroot.c (get_mdadm_name): Revamped into ... - (get_mdadm_uuid): ... this. - (grub_util_get_grub_dev): Use mduuid/%s if UUID is available. - -2011-04-16 Vladimir Serbinenko - - * grub-core/gfxmenu/gui_image.c (rescale_image): Don't attempt to scale - to negative size. - -2011-04-13 Colin Watson - - * util/grub.d/10_linux.in: Add rootflags=subvol= if / is on a - btrfs subvolume. - * util/grub.d/20_linux_xen.in: Likewise. - -2011-04-13 Colin Watson - - Rewrite /proc/self/mountinfo handling to cope with bind-mounts and - move-mounts appearing out of order. Fixes Ubuntu bug #738345. - - * grub-core/kern/emu/getroot.c (find_root_device_from_mountinfo): - Build a list of relevant visible mounts using the mnt_id and - parent_mnt_id fields, and then scan that list at the end. - -2011-04-12 Colin Watson - - * docs/grub.texi (normal): New section. - (normal_exit): New section. - (Embedded configuration): Add reference to normal. - (GRUB only offers a rescue shell): Likewise. - * docs/grub-dev.texi (Error Handling): Fix typo. - -2011-04-12 Colin Watson - - * NEWS: Drop obsolete entry about probe-only btrfs support. - -2011-04-12 Colin Watson - - * util/import_gcry.py: Fix typo. - -2011-04-11 Vladimir Serbinenko - - * NEWS: Add btrfs support. - -2011-04-11 Vladimir Serbinenko -2011-04-11 Colin Watson - - BtrFS support. Written by me (Vladimir) with important bugfixes and - even more important testing by Colin. - - * Makefile.util.def (libgrubmods.a): Add crc.c and gzio.c - * grub-core/Makefile.core.def (btrfs): Add crc.c. - * grub-core/fs/btrfs.c: Stub replaced with real implementation. - * grub-core/io/gzio.c (grub_gzio): New fields mem_input_size, - mem_input_off and mem_input. All users updated to accept in-RAM input. - (gzio_seek): New function. - (test_zlib_header): Likewise. - (grub_gzio_read): Likewise. - (grub_zlib_decompress): Likewise. - * grub-core/kern/emu/getroot.c (grub_find_root_device_from_mountinfo): - Accept partial and non-virtual mounts. - (grub_guess_root_device): Do rescanning after device_from_mountinfo to - avoid receiving /dev/dm-X as device. - * grub-core/kern/emu/misc.c (grub_make_system_path_relative_to_its_root): - Handle bind and partial mounts. - * grub-core/lib/crc.c: New file. - * include/grub/deflate.h: Likewise. - * include/grub/emu/misc.h (grub_find_root_device_from_mountinfo): New - proto. - * include/grub/lib/crc.h: New file. - -2011-04-11 Vladimir Serbinenko - - Implement automatic module license checking according to new GNU - guidelines. - - * grub-core/kern/dl.c (grub_dl_check_license): New function. - (grub_dl_load_core): Use grub_dl_check_license. - * include/grub/dl.h (GRUB_MOD_SECTION): New macro. - (GRUB_MOD_LICENSE): Likewise. - (GRUB_MOD_DUAL_LICENSE): Likewise. - All modules updated. - -2011-04-11 Colin Watson - - * grub-core/fs/btrfs.c (grub_btrfs_fs) [GRUB_UTIL]: Set - reserved_first_sector to 1. btrfs reserves plenty of space for boot - loaders. - Reported by: Gene Cumm. Fixes Ubuntu bug #757446. - -2011-04-11 Vladimir Serbinenko - - * util/grub-fstest.c (cmd_cmp): Check that sizes match. - -2011-04-11 Vladimir Serbinenko - - * util/grub-fstest.c (read_file): Report GRUB error if file opening - failed. - -2011-04-11 Vladimir Serbinenko - - * grub-core/kern/file.c (grub_file_open): Don't take into account the - parenthesis in the middle of the filename. - -2011-04-10 Vladimir Serbinenko - - * grub-core/loader/mips/linux.c (grub_cmd_initrd): Use correct limits - rather than trying to put initrd way too high. - Reported by: Ryan Lortie - -2011-04-10 Vladimir Serbinenko - - * grub-core/boot/mips/yeeloong/fwstart.S (no_cs5536): Put back - improperly removed string. - -2011-04-10 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_data): New member - is_disk. - (grub_util_biosdisk_open): Don't apply ioctl on non-disk devices. - (open_device) Likewise. - (grub_util_biosdisk_close): Likewise. - Reported by: Mark Korenberg. - -2011-04-10 Alexander Kurtz - - * util/grub-mkconfig_lib.in: Add missing quotes. - -2011-04-10 Colin Watson - - * grub-core/gnulib/argp-parse.c (__argp_input): Don't crash if pstate - is NULL. - -2011-04-10 Vladimir Serbinenko - - Dynamically count the number of lines for the lower banner. - - * grub-core/normal/menu_entry.c (per_term_screen): New member - num_entries. - (print_down): Use num_entries. - (update_screen): Likewise. - (grub_menu_entry_run): Set num_entries. - * grub-core/normal/menu_text.c (menu_viewer_data): New member - num_entries. - (grub_print_message_indented): Move real part to ... - (grub_print_message_indented_real): ... here. Additional argument - dry_run. - (draw_border): Additional argument num_entries. - (print_message): Additional argument dry_run. - (print_entries): Receive menu viewer data. - (grub_menu_init_page): New argment num_entries. - (menu_text_set_chosen_entry): Use num_entries. - (grub_menu_try_text): Likewise. - * grub-core/normal/term.c (print_ucs4_terminal): New argument dry_run. - All users updated. - (grub_ucs4_count_lines): New function. - * include/grub/term.h (grub_term_cursor_x): Moved from here .. - * grub-core/normal/menu_text.c (grub_term_cursor_x): ... to here. - * include/grub/term.h (GRUB_TERM_MESSAGE_HEIGHT): Removed. - (grub_term_border_height): Likewise. - (grub_term_num_entries): Likewise. - -2011-04-10 Vladimir Serbinenko - - * grub-core/boot/mips/yeeloong/fwstart.S: Fix address to error message. - Remove now unused string. - -2011-04-09 Colin Watson - - * docs/grub-dev.texi (Finding your way around): Update for 1.99 - build system. - (Getting started): GRUB is developed in Bazaar now, not Subversion. - - (Comment): Fix typo. - (Getting started): General copy-editing. - (Typical Development Experience): Likewise. - (Error Handling): Likewise. - (Video API): Likewise. - -2011-04-09 Colin Watson - - * docs/grub-dev.texi: Replace MoinMoin syntax with Texinfo syntax - throughout. - -2011-04-08 Vladimir Serbinenko - - * util/grub-mkimage.c (main): Handle special naming of yeeloong - directory. - -2011-04-08 Colin Watson - - * docs/grub-dev.texi: Fix spelling of "developer" throughout. - * grub-core/fs/i386/pc/pxe.c (parse_dhcp_vendor): Fix spelling of - "development". - -2011-04-08 Vladimir Serbinenko - - * grub-core/normal/menu_entry.c (run): Use grub_memcpy rather than - grub_strcpy since the lines aren't necessarily 0-terminated. - -2011-04-08 Vladimir Serbinenko - - * grub-core/lib/legacy_parse.c (legacy_commands): Find doesn't set - root on legacy. - -2011-04-08 Vladimir Serbinenko - - * grub-core/commands/probe.c (options): Argument to set isn't optional. - (GRUB_MOD_INIT): DEVICE isn't optional. - -2011-04-08 Vladimir Serbinenko - - * grub-core/normal/term.c (print_ucs4_terminal): Don't try to put the - word on new line if it's too long anyway. Fixes a hang. - -2011-04-08 Vladimir Serbinenko - - * include/grub/util/raid.h (grub_util_raid_getmembers): Make argument - const. - * util/grub-setup.c (main): Reuse md device name if available. - * util/raid.c (grub_util_raid_getmembers): Receive device name and - not GRUB name as argument. - Based on patch by: Florian Wagner . - -2011-04-08 Vladimir Serbinenko - - * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_make_mbi): - Place mbi on low memory for better compatibility. - -2011-04-08 Vladimir Serbinenko - - * include/grub/efiemu/efiemu.h: Use grub_memory_hook_t type. - -2011-04-08 Vladimir Serbinenko -2011-04-08 Colin Watson - - * autogen.sh: Ensure that collate and ctype locale is C. - * conf/Makefile.common: Likewise. - -2011-04-08 Vladimir Serbinenko - - * grub-core/normal/menu.c: Add missing include. - -2011-04-08 Vladimir Serbinenko - - * grub-core/disk/raid.c [GRUB_UTIL]: Add missing include. - -2011-04-08 Martin Zuther - - * util/grub-mkconfig.in: Ignore emacsen backup. - -2011-04-08 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (open_device): Sync on close and not - on open. - (grub_util_biosdisk_close): Likewise. - -2011-04-08 Vladimir Serbinenko - - * grub-core/kern/emu/getroot.c (grub_util_get_grub_dev): Add missing - const attribute and use grub_isdigit. - -2011-04-06 Andrey - - * grub-core/video/fb/video_fb.c (grub_video_fb_setup): Silence older - gcc warning. - -2011-04-06 Vladimir Serbinenko - - * grub-core/lib/relocator.c (grub_relocator_alloc_chunk_align): Add few - useful grub_dprintf's. - -2011-04-06 Vladimir Serbinenko - - * include/grub/fs.h (grub_dirhook_info): Use unsigned for 1-bit fields. - -2011-04-06 Vladimir Serbinenko - - * util/grub.d/00_header.in: Don't use LANG unless unifont is available. - -2011-04-06 Vladimir Serbinenko - - Output errors if theme loading failed. - - * grub-core/gfxmenu/gfxmenu.c (grub_gfxmenu_try): Move the call to - grub_gfxterm_fullscreen on error paths to ... - * grub-core/normal/menu.c (menu_init): ...here. Wait after showing - theme loading error. - -2011-04-06 Vladimir Serbinenko - - * include/grub/offsets.h (GRUB_KERNEL_I386_PC_RAW_SIZE): Let a bit more - space for older compilers. - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): Likewise. - -2011-04-06 Vladimir Serbinenko - - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Detect spares - and report them as not RAID members since they are useless for GRUB. - * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Likewise. - -2011-04-02 Vladimir Serbinenko - - Increase LVM implementation robustness in order not to crash on - configurations like pvmove. Previously code assumed that in some places - only lvs or only pvs are used whereas it seems that they are used - interchangeably. - - * grub-core/disk/lvm.c (read_node): New function. - (read_lv): Use read_node. - (grub_lvm_scan_device): Use only first mirror on pvmove'd lvs. - Match volumes only at the end when all lvs are found. Take both - pvs (first) and lvs (second) into account. - * include/grub/lvm.h (grub_lvm_segment): Merge fields stripe_* and - mirror_* into node_*. All users updated. - (grub_lvm_stripe): Merge this ... - (grub_lvm_mirror): ... and this ... - (grub_lvm_node): ... into this. All users updated. - -2011-04-02 Vladimir Serbinenko - - * grub-core/disk/lvm.c (grub_lvm_scan_device): Print errors on the end - of function to allow further scanning for LVMs. - -2011-04-02 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_read): Don't close - on failed seek as it breaks open fd reusage. - -2011-04-02 Vladimir Serbinenko - - * util/grub-install.in: Add a recommendation to use --recheck before - reporting bugs. - -2011-04-02 Vladimir Serbinenko - - * docs/grub.texi (Vendor power-on buttons): Explain how the numbers - are obtained. - -2011-04-02 Vladimir Serbinenko - - GRUB developper manual based on existing Internals section and - contributions by the various authors with active copyright assignment. - - * docs/Makefile.am (info_TEXINFOS): Add grub-dev.texi. - * docs/font_char_metrics.png: New file. - * docs/font_char_metrics.txt: Likewise. - * docs/grub-dev.texi: Likewise. - * docs/grub.texi (Internals): Move from here ... - * docs/grub-dev.texi: ... here. - -2011-04-01 Colin Watson - - Store the loopback device as data on loopback grub_disk structures, - rather than the file it points to. This fixes use of freed memory - if an existing loopback device is replaced. - - * grub-core/disk/loopback.c (grub_loopback_open): Store dev in - disk->data, not dev->file. - (grub_loopback_read): Adjust file assignment to match. - Fixes Ubuntu bug #742967. - -2011-04-01 Colin Watson - - * grub-core/disk/loopback.c (grub_cmd_loopback): Fix a memory leak - when replacing an existing device. - -2011-04-01 Vladimir Serbinenko - - Fix incorrect types in jfs.c. This enables >2TiB disks and fixes some - memory corruptions. - - * grub-core/fs/jfs.c (struct grub_jfs_diropen): Interpret bytes as - unsigned. - (grub_jfs_lookup_symlink): Make ino a grub_uint32_t rather than int. - (grub_jfs_blkno): Use 64-bit quantities for block sectors. - (grub_jfs_read_inode): Likewise. - (grub_jfs_opendir): Likewise. Remove now useless casts. - (grub_jfs_getent): Likewise. - Make ino a grub_uint32_t rather than int. - (grub_jfs_mount): Ensure that blksize and log2_blksize are consistent. - (grub_jfs_read_file): Use 64-bit quantities when necessary. Replace - division and module with bit operations. - (grub_jfs_find_file): Make ino a grub_uint32_t. - (grub_jfs_lookup_symlink): Likewise. Use 64-bit quantities - -2011-04-01 Colin Watson - - * grub-core/normal/menu_entry.c (run): Quieten uninitialised - warning. (This was in fact always initialised before use, but GCC - wasn't smart enough to prove that.) - * grub-core/script/lexer.c (grub_script_lexer_yywrap): Likewise. - -2011-03-31 Vladimir Serbinenko - - * grub-core/kern/x86_64/efi/callwrap.S (efi_wrap_0): Preserve 16-byte - stack alignment. - (efi_wrap_1): Likewise. - (efi_wrap_2): Likewise. - (efi_wrap_3): Likewise. - (efi_wrap_4): Likewise. - (efi_wrap_5): Likewise. - (efi_wrap_6): Likewise. - (efi_wrap_10): Likewise. - Based on information by: Red Hat/Peter Jones. - -2011-03-31 Colin Watson - - * grub-core/mmap/efi/mmap.c (grub_mmap_unregister): Remove - set-but-not-used variable. - -2011-03-31 Colin Watson - - * docs/grub.texi (Simple configuration): Be more explicit about - GRUB_DEFAULT, and add an example. - Reported by: Leslie Rhorer. - -2011-03-30 Colin Watson - - * docs/grub.texi (Commands): Link to "GRUB only offers a rescue - shell". - -2011-03-30 Alexey Shvetsov - - * util/grub.d/10_linux.in: Add gentoo-specific config filename. - * util/grub.d/20_linux_xen.in: Likewise. - -2011-03-30 Vladimir Serbinenko - - * util/grub.d/10_linux.in: Try alternative config filenames where - we parse config file. - * util/grub.d/20_linux_xen.in: Likewise. - -2011-03-30 Alexey Shvetsov - - * util/grub.d/10_linux.in: Add gentoo-specific Linux and initrd names. - * util/grub.d/20_linux_xen.in: Likewise. - -2011-03-30 Vladimir Serbinenko - - * grub-core/disk/raid.c (insert_array): Add few potentially - useful grub_util_info. - (grub_raid_register): Likewise. - -2011-03-30 Vladimir Serbinenko - - * grub-core/kern/emu/getroot.c (grub_util_get_grub_dev) [__linux__]: - Preserve partition number in mdadm code path. - -2011-03-30 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev): Add - few potentially useful grub_util_info. - -2011-03-30 Vladimir Serbinenko - - * grub-core/disk/lvm.c (grub_lvm_scan_device): Remove spurious \n. - -2011-03-30 Colin Watson - - * docs/grub.texi (default): Use @example rather than nested - itemized lists to avoid breaking gendocs. - -2011-03-30 Colin Watson - - * docs/grub.texi (Future): Update. - -2011-03-30 Colin Watson - - * docs/grub.texi (Environment): New chapter. - (Changes from GRUB Legacy): Link to "Environment block" section for - details of limitations. - (Simple configuration): Likewise. Link to documentation of gfxmode - and gfxpayload variables from GRUB_GFXMODE and GRUB_GFXPAYLOAD - respectively. - (Shell-like scripting): Note that normal variables are stored in the - environment. - (gettext): Link to documentation of lang and locale_dir. - (list_env): New section. - (load_env): New section. - (save_env): New section. - - (Reporting bugs): Fix typo. - -2011-03-30 Vladimir Serbinenko - - * docs/grub.texi: Correctly use "terminal_input" and not "terminal" in - the example. - -2011-03-30 Vladimir Serbinenko - - * grub-core/term/at_keyboard.c (set_scancodes) - [!GRUB_MACHINE_MIPS_YEELOONG && !GRUB_MACHINE_QEMU]: Use scancode set 1. - -2011-03-30 Colin Watson - - * docs/grub.texi (Menu-specific commands): Remove some semantics - that were true in GRUB Legacy but not in GRUB 2. - (submenu): New section. - (false): New section. - (read): New section. - (true): New section. - -2011-03-30 Colin Watson - - * docs/grub.texi (Changes from GRUB Legacy): Minor proofreading. - -2011-03-30 Colin Watson - - * docs/grub.texi (Simple configuration): Explain some of the - current limitations of grub-mkconfig. - Reported by: Leslie Rhorer. - -2011-03-29 Vladimir Serbinenko - - Old macs search for boot.efi rather than for bootia32.efi. - - * util/grub-install.in: Copy bootia32.efi to boot.efi. - * util/grub-mkrescue.in: Likewise. - Suggested by: Peter Jones. - -2011-03-29 Vladimir Serbinenko - - * util/grub.d/20_linux_xen.in: Accept old-style xen kernels. - -2011-03-29 Vladimir Serbinenko - - * include/grub/lvm.h (grub_lvm_lv): New field 'visible'. - (grub_lvm_segment): New fields 'type', 'mirror_count' and 'mirrors'. - (grub_lvm_mirror): New struct. - * grub-core/disk/lvm.c (grub_lvm_checkvalue): Commented out. - (grub_lvm_iterate): Iterate only visible volumes. - (grub_lvm_read): Factor out to .. - (read_lv): ... this. Support mirrors. - (grub_lvm_read): New wrapper function. - (grub_lvm_scan_device): Parse mirrors. Skip everything that isn't - stripped or mirrored. - -2011-03-29 Vladimir Serbinenko - - * util/grub.d/10_linux.in: Skip vmlinux-* on x86 platforms. - -2011-03-29 Colin Watson - - * docs/grub.texi (loopback): New section. - -2011-03-29 Colin Watson - - * grub-core/disk/loopback.c (GRUB_MOD_INIT): Stop documenting - removed -p option. - -2011-03-29 Colin Watson - - * docs/grub.texi (BIOS installation): New section, partly based on - previous text in other sections. - (Installing GRUB using grub-install): Replace BIOS discussion with a - cross-reference. - (Images): Likewise. - -2011-03-29 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (find_partition_start) - [HAVE_DIOCGDINFO]: Add safety checks. - -2011-03-29 Vladimir Serbinenko - - * util/grub.d/10_kfreebsd.in: Allow ufs.ko to be missing as it's - per default compiled in kernel and prior to 8.0 isn't shipped at all. - -2011-03-29 Colin Watson - - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): If - real_sb->size is zero (e.g. RAID-0), get the disk size from - real_sb->data_size instead. - Fixes Ubuntu bug #743136. - -2011-03-29 Vladimir Serbinenko - - * grub-core/normal/misc.c (grub_normal_print_device_info): Use correct - printf clauses for printing size and start. - -2011-03-29 Vladimir Serbinenko - - * grub-core/fs/ext2.c (grub_ext2_read_inode): Fix an overflow. - Reported and tested by: Timothy Nikkel. - -2011-03-29 Vladimir Serbinenko - - * grub-core/term/gfxterm.c (dirty_region_add): Move core part to ... - (dirty_region_add_real): ... this. - (dirty_region_add): Don't discard margin refresh when performing - scheduled repaint. - -2011-03-29 Vladimir Serbinenko - - * grub-core/lib/relocator.c (allocate_regstart) - [!DEBUG_RELOCATOR_NOMEM_DPRINTF]: Avoid grub_dprintf since not all - terminals are capabple of malloc-free operation. - (allocate_inreg) [!DEBUG_RELOCATOR_NOMEM_DPRINTF]: Likewise. - (malloc_in_range) [!DEBUG_RELOCATOR_NOMEM_DPRINTF]: Likewise. - -2011-03-29 Mario Limonciello - - * util/grub-setup.c: Copy the partition table zone if floppy support - is disabled, even if no partition table is found. - - Otherwise, the BIOS on Dell Latitude E series laptops will freeze - during POST if an invalid partition table is contained in the PBR - of the active partition when GRUB is installed to a partition. - -2011-03-28 Colin Watson - - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Remove stale - comment. - -2011-03-28 Colin Watson - - * grub-core/disk/raid.c (grub_raid_register): Adjust debug message - to be specific about what kind of RAID device we're scanning for. - -2011-03-26 Seth Goldberg - - * grub-core/kern/emu/getroot.c (find_root_device_from_libzfs): Don't - return freed string. - -2011-03-26 Vladimir Serbinenko - - * grub-core/fs/iso9660.c (grub_iso9660_label): Rtrim the label. - -2011-03-26 Vladimir Serbinenko - - Use libgeom on FreeBSD to detect partitions. - - * Makefile.util.def (grub-mkimage): Add LIBGEOM to ldadd. - (grub-mkrelpath): Likewise. - (grub-script-check): Likewise. - (grub-editenv): Likewise. - (grub-mkpasswd-pbkdf2): Likewise. - (grub-fstest): Likewise. - (grub-mkfont): Likewise. - (grub-mkdevicemap): Likewise. - (grub-probe): Likewise. - (grub-setup): Likewise. - (grub-ofpathname): Likewise. - (grub-mklayout): Likewise. - (example_unit_test): Likewise. - (grub-menulst2cfg): Likewise. - * grub-core/Makefile.core.def (grub-emu): Likewise. - (grub-emu-lite): Likewise. - * configure.ac: Check for -lgeom on FreeBSD and set LIBGEOM. - * grub-core/kern/emu/hostdisk.c [FreeBSD]: Include libgeom.h. Don't - define HAVE_DIOCGDINFO. - (follow_geom_up) [FreeBSD]: New function. - (find_partition_start) [FreeBSD]: Rewritten using follow_geom_up. - (convert_system_partition_to_system_disk) [FreeBSD]: Likewise. - (grub_util_biosdisk_get_grub_dev) [FreeBSD]: Use FreeBSD path - unconditionally of HAVE_DIOCGDINFO. - -2011-03-26 Vladimir Serbinenko - - Fix FreeBSD compilation problem. - - * grub-core/kern/emu/hostdisk.c (MAJOR) [FreeBSD]: New definition. - (FLOPPY_MAJOR) [FreeBSD]: Likewise. - -2011-03-24 Colin Watson - - * grub-core/video/fb/video_fb.c (grub_video_fb_get_info_and_fini): - Switch back to page zero before loading a kernel, since some kernel - drivers expect that. - Thanks to: Felix Kuehling. - -2011-03-24 Vladimir Serbinenko - - * grub-core/lib/relocator.c (grub_relocator_alloc_chunk_addr) - [DEBUG_RELOCATOR]: Reuse grub_mm_check. - (grub_relocator_alloc_chunk_align) [DEBUG_RELOCATOR]: Likewise. - -2011-03-24 Vladimir Serbinenko - - * include/grub/mm.h (GRUB_MM_CHECK): Rename to ... - (grub_mm_check): ... this. MAke a function-like macro and use GRUB_FILE. - -2011-03-24 Vladimir Serbinenko - - * grub-core/lib/relocator.c (allocate_inreg): Avoid dprintf unless - DEBUG_RELOCATOR is defined since gfxterm can't cope with output when - malloc is disabled. - -2011-03-24 Vladimir Serbinenko - - * grub-core/loader/i386/bsdXX.c (grub_freebsd_load_elfmodule): Account - for modules headers when counting the needed allocation size. - -2011-03-23 Vladimir Serbinenko - - * grub-core/term/gfxterm.c (calculate_normal_character_width): Return 8 - if no ASCII character is found to prevent crash. - -2011-03-23 Alexander Kurtz - - * grub-core/video/bitmap.c (match_extension): Ignore case. - -2011-03-23 Vladimir Serbinenko - - * grub-core/normal/menu_entry.c (init_line): Fix off-by-one error. - -2011-03-23 Vladimir Serbinenko - - * grub-core/script/parser.y: Declare "time" as valid argument. - -2011-03-23 Peter Jones - - Fix incorrect assert failure reporting. - - * grub-core/tests/example_functional_test.c (example_test): Add - a failure comment. - * grub-core/tests/lib/test.c (add_failure): Renamed to ... - (failure_start): ...this. Check that malloc succeeded. - Don't call xvasprintf. Return failure struct. - (failure_append_vtext): New function. - (failure_append_text): Likewise. - (add_failure): Likewise. - (grub_test_assert_helper): Likewise. - * include/grub/test.h (grub_test_assert_helper): New declaration. - (grub_test_assert): Macro rewritten. - -2011-03-23 Vladimir Serbinenko - - * grub-core/normal/main.c (GRUB_MOD_INIT): Export pager variable. - -2011-03-23 Vladimir Serbinenko - - * grub-core/lib/i386/pc/biosnum.c: Add missing include. - -2011-03-23 Vladimir Serbinenko - - * grub-core/disk/usbms.c (grub_usbms_reset): Transform USB-style error - into GRUB-style one. - -2011-03-23 Vladimir Serbinenko - - * grub-core/bus/usb/usbtrans.c (grub_usb_control_msg): Return usb-style - error and not grub_errno. - * grub-core/bus/usb/usbhub.c (grub_usb_add_hub): Likewise. - -2011-03-23 Vladimir Serbinenko - - * grub-core/bus/usb/uhci.c (grub_uhci_detect_dev): Return - GRUB_USB_SPEED_NONE in case of failure and not the error code. - -2011-03-23 Vladimir Serbinenko - - * grub-core/efiemu/i386/pc/cfgtables.c - (grub_machine_efiemu_init_tables): Make declaration a prototype. - * grub-core/loader/xnu.c (grub_xnu_lock): Likewise. - (grub_xnu_unlock): Likewise. - * grub-core/normal/cmdline.c (grub_cmdline_get/cl_set_pos_all): Likewise. - -2011-03-23 Vladimir Serbinenko - - * grub-core/bus/usb/usb.c (attach_hooks): Make static. - * grub-core/bus/usb/usbhub.c (hubs): Likewise. - * grub-core/commands/hashsum.c (aliases): Likewise. - * grub-core/commands/setpci.c (pci_registers): Likewise. - * grub-core/disk/usbms.c (attach_hook): Likewise. - * grub-core/fs/zfs/zfs.c (decomp_table): Likewise. - (zio_checksum_table): Likewise. - * grub-core/gettext/gettext.c (grub_gettext_msg_list): Likewise. - * grub-core/gfxmenu/gfxmenu.c (cached_view): Likewise. - * grub-core/lib/legacy_parse.c (legacy_commands): Likewise. - * grub-core/lib/relocator.c (leftovers): Likewise. - (extra_blocks): Likewise. - * grub-core/loader/i386/bsd.c (relocator): Likewise. - * grub-core/loader/i386/multiboot_mbi.c (modules): Likewise. - (modules_last): Likewise. - * grub-core/loader/i386/xnu.c (table_aliases): Likewise. - (devices): Likewise. - * grub-core/loader/multiboot_mbi2.c (modules): Likewise. - (modules_last): Likewise. - * grub-core/normal/auth.c (users): Likewise. - * grub-core/normal/context.c (initial_menu): Likewise. - (current_menu): Likewise. - * grub-core/normal/crypto.c (crypto_specs): Likewise. - * grub-core/term/serial.c (grub_serial_ports): Likewise. - (grub_serial_terminfo_input_template): Likewise. - (grub_serial_terminfo_output_template): Likewise. - (grub_serial_terminfo_input): Likewise. - (grub_serial_terminfo_output): Likewise. - (registered): Likewise. - * grub-core/term/usb_keyboard.c (attach_hook): Likewise. - -2011-03-23 Vladimir Serbinenko - - * grub-core/video/bochs.c (grub_video_bochs_setup): Use - grub_video_mode_type_t. - * grub-core/video/cirrus.c (grub_video_cirrus_setup): Likewise. - * grub-core/video/i386/pc/vbe.c (grub_video_vbe_setup): Likewise. - * grub-core/video/i386/pc/vga.c (grub_video_vga_setup): Likewise. - -2011-03-23 Vladimir Serbinenko - - * util/grub-install.in: Correct the x86-64 name as x86_64. - -2011-03-11 Colin Watson - - * grub-core/boot/i386/pc/lnxboot.S (real_code_2): Ensure that the - initial chunk read from the kernel always includes GRUB's multiboot - header, which is now outside the first sector. - -2011-03-09 Colin Watson - - * grub-core/loader/i386/linux.c (find_efi_mmap_size): Page-align - cached mmap_size, so that this works correctly when called multiple - times. - Reported by: Daniel Kahn Gillmor. Should fix Debian bug #616638. - -2011-03-09 Colin Watson - - * docs/grub.texi (Simple configuration): Tidy up formatting. - -2011-03-07 Szymon Janc - - * grub-core/fs/zfs/zfs.c (zap_leaf_lookup): - Set-but-not-used variable removed. - -2011-02-12 Vladimir Serbinenko - - Workaround yet another IEEE1275 bug. - - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New enum value - GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS. - * grub-core/kern/ieee1275/mmap.c (grub_machine_mmap_iterate): Ignore - adress_cells and size:cells if GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS - is set. - * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set - GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS on powermacs. - -2011-02-12 Vladimir Serbinenko - - * grub-core/partmap/msdos.c (pc_partition_map_embed): Fix off by one - error. - -2011-02-11 Colin Watson - - * util/grub.d/20_linux_xen.in: Bail out early if linux_list is - empty, since in that case we can only generate either nothing or a - syntactically invalid configuration file. - Reported by: Michal Suchanek. Fixes Debian bug #612898. - -2011-02-09 Colin Watson - - * docs/grub.texi (Kernel): Add reference to grub-mkrescue. - (Making a GRUB bootable CD-ROM): Likewise. - (Invoking grub-mkrescue): New section. - Reported by: Yann Dirson. Fixes Debian bug #612585. - -2011-02-09 Colin Watson - - * util/grub-install.in: Remove unnecessary brackets from tr - arguments. - * util/grub.d/10_hurd.in: Likewise. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - Reported by: Jamie Heilman. Fixes Debian bug #612564. - -2011-02-08 Colin Watson - - * include/grub/file.h (not_easly_seekable): Rename to ... - (not_easily_seekable): ... this. Update all users. - -2011-01-28 Colin Watson - - * docs/grub.texi (Making a GRUB bootable CD-ROM): Update to describe - grub-mkrescue. - -2011-01-24 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Refuse to create the images - bigger than the actual flash (512K) in Loongson machines. 512K is also - the biggest chip supported by them. - -2011-01-22 Vladimir Serbinenko - - * grub-core/kern/emu/getroot.c: Include config-util.h explicitly. - -2011-01-22 Anthony DeRobertis - - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Check - super_offset field. - -2011-01-22 Vladimir Serbinenko - - * util/grub-install.in: Ignore install device on platforms - where it doesn't make sense. Always use UUIDs except on pc, efi and - sparc64. - Reported by: Daniel Kahn Gillmor. - -2011-01-22 Vladimir Serbinenko - - * grub-core/bus/bonito.c (write_bases): Fix direction of the shift. - -2011-01-22 Vladimir Serbinenko - - * grub-core/partmap/bsdlabel.c: Include grub/emu/misc.h and not grub/util/misc.h. - (iterate_real): Don't rely on partition being non-NULL. - -2011-01-22 Vladimir Serbinenko - - * grub-core/script/argv.c (round_up_exp): unsigned is 32-bit on all - supported platforms. Put a compile time assert for this rather than - generate a warning with 32-bit shift. - -2011-01-22 Vladimir Serbinenko - - * grub-core/disk/scsi.c (grub_scsi_read): Fix binary and check and make - logical expression more readable. - -2011-01-22 Vladimir Serbinenko - - * grub-core/disk/raid.c (insert_array): Ensure uniqueness of p->number - even if some elements have a name. - Reported by: Alexander GQ Gerasiov. - -2011-01-22 Colin Watson - - * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Consider a - path unreadable if `grub-probe -t abstraction' fails, for example if - memberlist fails on an LVM volume group. - Reported by: Darius Jahandarie. - -2011-01-22 Colin Watson - - * docs/grub.texi (Simple configuration): Document - GRUB_PRELOAD_MODULES. - -2011-01-17 Colin Watson - - * .bzrignore: Remove nonexistent grub-pbkdf2. - -2011-01-16 Vladimir Serbinenko - - * configure.ac: Bump version to 1.99~rc1. - -2011-01-15 Vladimir Serbinenko - - * util/grub-mkimage.c (generate_image): Check fwstart.img checksum - for safety. - -2011-01-14 Vladimir Serbinenko - - * grub-core/kern/mips/yeeloong/init.c (grub_machine_init): Init boot - module. - -2011-01-14 Vladimir Serbinenko - - * grub-core/Makefile.core.def (fwstart): Add lost LDFLAGS. - -2011-01-13 Vladimir Serbinenko - - * grub-core/fs/zfs/zfsinfo.c (grub_cmd_zfs_bootfs): Quote bootpath and - diskdevid. - -2011-01-13 Vladimir Serbinenko - - Fix compilation on cygwin. - - * conf/Makefile.common (STRIPFLAGS_KERNEL): Add -F elf32-i386 and - -R .drectve on cygwin. - * conf/i386-pc-cygwin-img-ld.sc: Merge rdata and pdata into data. - * configure.ac: Use $(top_builddir) in TARGET_OBJ2ELF. - (COND_CYGWIN): New condition. - * grub-core/Makefile.am (%.mod): Set TARGET_OBJ2ELF. - * grub-core/genmod.sh.in: Use ${TARGET_OBJ2ELF} and - not @TARGET_OBJ2ELF@. - * util/grub-pe2elf.c (write_symbol_table): Use pe_symtab->type and not - type to determine whether aux is to be used. - -2011-01-12 Vladimir Serbinenko - - * util/ieee1275/ofpath.c (grub_util_devname_to_ofpath): Use the - realpath'ed device string. - Handle floppy (somewhat). - Issue error in unknown case rather than garbage. - Reported by: Axel Beckert. - -2011-01-12 Vladimir Serbinenko - - * util/grub.d/00_header.in (load_video): Handle the case when no video - drivers available. - Thanks to: Axel Beckert. - -2011-01-12 Vladimir Serbinenko - - * util/grub-mkfont.c (write_font_pf2): Use appropriate type for data - variable. Fixes problem on big endian platforms. - -2011-01-12 Vladimir Serbinenko - - * grub-core/Makefile.core.def (ieee1275_fb): Disable on sparc. - It doesn't work well there. - -2011-01-12 Vladimir Serbinenko - - * grub-core/normal/context.c (grub_env_context_close): Silence spurious - warning. - * grub-core/normal/menu.c (grub_menu_execute_entry): Likewise. - * grub-core/partmap/msdos.c (pc_partition_map_embed): Use unsigned - counter. - -2011-01-12 Vladimir Serbinenko - - Use alias->path rather than buggy "canon". - - * grub-core/disk/ieee1275/ofdisk.c (ofdisk_hash_add_real): New function. - (ofdisk_hash_add): New argument curcan. All users updated. - -2011-01-11 Colin Watson - - * configure.ac: Fall back to `true' if `makeinfo' does not exist. - -2011-01-11 Vladimir Serbinenko - - * grub-core/loader/powerpc/ieee1275/linux.c (grub_linux_load32): Apply - loadmask before doing any calculations. Use correct type for offset. - (grub_linux_load64): Likewise. - -2011-01-11 Colin Watson - - * util/grub-mklayout.c (console_grub_equivalences_shift): Terminate - with NULL. - (console_grub_equivalences_unshift): Likewise. - Reported by: Daniel Dehennin. - -2011-01-11 Vladimir Serbinenko - - * grub-core/fs/i386/pc/pxe.c (set_mac_env): Export variable. - (set_env_limn_ro): Likewise. - (GRUB_MOD_INIT): Likewise. - * grub-core/hook/datehook.c (GRUB_MOD_INIT): Likewise. Change to - ARRAY_SIZE while on it. - (GRUB_MOD_FINI): Change to ARRAY_SIZE. - * grub-core/normal/context.c (grub_env_export): Move from here ... - * grub-core/kern/env.c (grub_env_export): ... here. - * grub-core/normal/context.c (grub_cmd_export): Skip exporting root and - prefix. - * grub-core/kern/main.c (grub_main): Export root and prefix. - * include/grub/env.h (grub_env_export): Export. - Reported by: Seth Goldberg. - -2011-01-11 Vladimir Serbinenko - - * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_make_mbi): - Take into account space used by ELF sections and multiboot palette. - Reported by: GrĂ©goire Sutre. - -2011-01-11 Vladimir Serbinenko - - * BUGS: New file. - -2011-01-10 Vladimir Serbinenko - - Pass more appropriate video id to Linux. - - * grub-core/loader/i386/linux.c (grub_linux_setup_video): Use - grub_video_get_driver_id and variable gfxpayloadforcelfb to - fill have_vga. - (grub_linux_boot): Rely on grub_linux_setup_video to fill have_vga and - shift params->lfb_size. - * include/grub/i386/linux.h: Make an enume out of have_vga values. - -2011-01-10 Vladimir Serbinenko - - * util/grub-menulst2cfg.c: Add missing include of misc.h. - -2011-01-10 Vladimir Serbinenko - - * grub-core/fs/zfs/zfsinfo.c (grub_cmd_zfs_bootfs): Use comma as - separator and pass bootpath/devid even if only one of them is available. - Reported by: Seth Goldberg. - -2011-01-10 Vladimir Serbinenko - - Don't use post-4G memory on EFI even if 64-bit since some non-compliant - implementations bug on them. - - * grub-core/kern/efi/mm.c (grub_efi_allocate_pages): Skip post-4G - memory. - (filter_memory_map): Likewise. - -2011-01-10 Vladimir Serbinenko - - * util/grub-kbdcomp.in: Add missing prefix and exec_prefix variables. - Reported by: nebuchadnezzar. - -2011-01-10 Vladimir Serbinenko - - * util/grub-kbdcomp.in: Add missing transform and bindir variables. - Reported by: nebuchadnezzar. - -2011-01-10 Vladimir Serbinenko - - Submenu default support. - - * grub-core/normal/menu.c (grub_menu_execute_entry): New parameter - auto_boot. All users updated. - Declared static. - Handle chosen and default with submenus. - (grub_menu_execute_with_fallback): Declared static. - Don't notify failure if autobooted. Upper level does it. - (menuentry_eq): New function. - (get_entry_number): Use menuentry_eq. - (show_menu): New parameter "autobooted". All users updated. - (grub_show_menu): Likewise. - * include/grub/normal.h (grub_show_menu): Likewise. - * include/grub/menu.h (grub_menu_execute_entry): Removed. - (grub_menu_execute_with_fallback): Likewise. - -2011-01-10 Vladimir Serbinenko - - * util/grub-mklayout.c (usage): Update help text. - -2011-01-10 Vladimir Serbinenko - - * grub-core/commands/legacycfg.c (legacy_file): Trim the line. - -2011-01-10 Vladimir Serbinenko - - * util/grub-menulst2cfg.c (main): Trim the line. - -2011-01-10 Vladimir Serbinenko - - * grub-core/kern/i386/pc/init.c (grub_get_conv_memsize): Removed. - (grub_machine_init): Don't check amount of low memory as reportedly - INT 12h can be broken and if low memory is too low we wouldn't have - gotten into grub_machine_init anyway. - -2011-01-10 Vladimir Serbinenko - - * grub-core/kern/i386/pc/mmap.c (grub_get_conv_memsize): New function. - (grub_machine_mmap_iterate): Take low memory into account - -2011-01-10 Vladimir Serbinenko - - * grub-core/fs/btrfs.c (grub_btrfs_mount): Transform out of range into - badfs. - Reported by: TiCPU. - -2011-01-10 Vladimir Serbinenko - - * grub-core/disk/raid.c (insert_array): Display RAID name in duplicate - members errors. - -2011-01-09 GrĂ©goire Sutre - - * util/grub.d/10_netbsd.in (netbsd_load_fs_module): New function. - (netbsd_entry): Use netbsd_load_fs_module() to load filesystem module. - -2011-01-09 GrĂ©goire Sutre - - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Handle - openbsd and netbsd types being in part_bsd module. - -2011-01-08 Vladimir Serbinenko - - * config.h.in (_LARGEFILE_SOURCE): Add missing define. - (_FILE_OFFSET_BITS): Likewise. - Reported by: Seth Goldberg. - -2011-01-08 GrĂ©goire Sutre - - * configure.ac: Check for libdevmapper header. - -2011-01-08 Vladimir Serbinenko - - * grub-core/fs/zfs/zfs.c (dmu_read): Use void * for some pointers to - avoid aliasing. - (fzap_lookup): Likewise. - (dnode_get): Likewise. - (make_mdn): Likewise. - (zfs_mount): Likewise. - (fzap_iterate): Use temporary pointer to avoid aliasing. - (grub_zfs_read): Likewise. - * grub-core/loader/i386/xnu.c (grub_xnu_boot): Likewise. - * grub-core/loader/xnu.c (grub_cmd_xnu_kernel): Use void * for some - pointers to avoid aliasing. - (grub_cmd_xnu_kernel64): Likewise. - (grub_xnu_load_driver): Likewise. - -2011-01-08 Vladimir Serbinenko - - * grub-core/commands/terminal.c (grub_cmd_terminal_input): Silence - aliasing warning. - (grub_cmd_terminal_output): Likewise. - Reported and tested by: GrĂ©goire Sutre. - -2011-01-08 Vladimir Serbinenko - - * grub-core/term/at_keyboard.c (grub_keyboard_getkey): Silence spurious - warning. - Reported and tested by: GrĂ©goire Sutre. - -2011-01-08 Vladimir Serbinenko - - * configure.ac: Do CPU substitution even if it's specified explicitly. - Reported and tested by: Alain Greppin. - -2011-01-08 Vladimir Serbinenko - - * grub-core/Makefile.am (rs_decoder.S): Force compilation with -Os. - Reported and tested by: Alain Greppin. - -2011-01-08 Vladimir Serbinenko - - Satisfy some bison versions need for inttypes.h. - - * grub-core/lib/posix_wrap/inttypes.h: New file. - * grub-core/lib/posix_wrap/sys/types.h (int8_t): New type. - (int16_t): Likewise. - (int32_t): Likewise. - (int64_t): Likewise. - Reported and tested by: Alain Greppin. - -2011-01-08 Vladimir Serbinenko - - * grub-core/loader/i386/bsdXX.c (grub_netbsd_load_elf_meta): - Silence spurious warning. - Reported and tested by: Alain Greppin. - -2011-01-07 Szymon Janc - - * docs/grub.texi (Support automatic decompression): Update with xz - decompression support. - -2011-01-07 Szymon Janc - - Improve loaders' kernel command line handling. - - * grub-core/lib/cmdline.c: New file. - * include/grub/lib/cmdline.h: Likewise. - * grub-core/loader/i386/linux.c (grub_cmd_linux): Use - grub_create_loader_cmdline to create kernel command line. - * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Likewise. - * grub-core/loader/powerpc/ieee1275/linux.c (grub_cmd_linux): Likewise. - * grub-core/loader/sparc64/ieee1275/linux.c (grub_cmd_linux): Likewise. - * grub-core/Makefile.core.def (linux16): Add lib/cmdline.c on i386_pc. - (linux): Add lib/cmdline.c on common. - -2011-01-07 Vladimir Serbinenko - - * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Take into account that - inopos might be unaligned. - -2011-01-07 Vladimir Serbinenko - - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Add missing - endian transformations. - * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Likewise. - Based on report by: Doug Nazar. - -2011-01-07 Doug Nazar - - * grub-core/disk/raid5_recover.c (grub_raid5_recover): Add missing - array->members[i].start_sector. - * grub-core/disk/raid6_recover.c (grub_raid6_recover): Likewise. - -2011-01-07 Vladimir Serbinenko - - * util/grub-setup.c (setup): Handle NetBSD and OpenBSD disklabels. - Reported and tested by: GrĂ©goire Sutre. - -2011-01-06 Colin Watson - - * tests/util/grub-shell.in: Set serial terminfo type to `dumb', to - avoid causing test failures by clearing the screen. - -2011-01-06 Colin Watson - - * grub-core/kern/emu/getroot.c (find_root_device_from_mountinfo): - Fix prefix check to handle the case where dir ends with a slash - (most significantly, "/" itself). - Reported by: Michael Vogt. - -2011-01-05 Vladimir Serbinenko - - Run terminfo_cls on initing terminfo output to clear the screen and - move the cursor to (0,0). - - * grub-core/term/ieee1275/ofconsole.c (grub_ofconsole_init_output): - Call grub_terminfo_output_init. - * grub-core/term/serial.c (grub_serial_term_output): Set .init. - * grub-core/term/terminfo.c (grub_terminfo_output_init): New function. - * include/grub/terminfo.h (grub_terminfo_output_init): New declaration. - -2011-01-05 Vladimir Serbinenko - - * util/grub-install.in: Determine ofpathname, nvsetenv and efibootmgr - only when needed. - -2011-01-05 Vladimir Serbinenko - - * grub-core/term/terminfo.c (grub_terminfo_readkey): Handle keys with - CTRL. - -2011-01-05 Vladimir Serbinenko - - The E820 type 5 is BADRAM, not EXEC_CODE. - - * grub-core/loader/i386/bsd.c (GRUB_E820_EXEC_CODE): Removed. - (GRUB_E820_BADRAM): New define. - * grub-core/loader/i386/linux.c (grub_linux_boot): Translate code - into reserved. Propagate BADRAM. - * grub-core/loader/i386/bsd.c (GRUB_E820_EXEC_CODE): Removed. - (GRUB_E820_BADRAM): New define. - -2011-01-04 Vladimir Serbinenko - - * grub-core/lib/efi/relocator.c (grub_relocator_firmware_fill_events): - Ignore the memory post-4G. - (grub_relocator_firmware_alloc_region): Additional debug statement. - -2011-01-04 Vladimir Serbinenko - - * grub-core/kern/emu/getroot.c (grub_util_get_grub_dev): Check md/%s - names. - Reported by: David Pravec. - -2011-01-04 Vladimir Serbinenko - - * grub-core/disk/i386/pc/biosdisk.c (GRUB_MOD_INIT): Workaround buggy - BIOSes. - -2011-01-04 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c (grub_reed_solomon_add_redundancy): - Prevent overflow. - (grub_reed_solomon_recover): Likewise. - -2011-01-04 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c (main) [TEST]: Reactivate normal test. - -2011-01-04 Vladimir Serbinenko - - * grub-core/lib/reed_solomon.c (scratch) [! STANDALONE]: Remove leftover - variable. - -2011-01-04 Colin Watson - - * grub-core/commands/legacycfg.c (GRUB_MOD_INIT): Fix typo in - descriptions of extract_legacy_entries_source and - extract_legacy_entries_configfile. - Reported by: Seung Soo, Ha. - -2011-01-03 Colin Watson - - * grub-core/bus/pci.c (grub_pci_iterate): Skip remaining functions - on devices that do not implement function 0. - -2011-01-03 Dave Vasilevsky - - * grub-core/fs/hfsplus.c: Make parent unsigned. - (grub_hfsplus_cmp_catkey): Don't compare using subtraction, it - overflows. - (grub_hfsplus_cmp_extkey): Likewise - -2011-01-03 Vladimir Serbinenko - - * util/grub-install.in: Correctly use bootloader_id and not - GRUB_DISTRIBUTOR on efibootmgr line. - -2011-01-03 Vladimir Serbinenko - - * util/grub-mkfont.c (main): Report errors in FT_New_Face. - -2010-12-31 Ian Campbell - - * util/grub.d/20_linux_xen.in (linux_entry): Correctly capitalize - Xen and reorder menu item wording to make it clearer that this entry - will launch Xen. Print separate messages when loading Xen and - Linux. - -2010-12-31 Vladimir Serbinenko - - * grub-core/partmap/amiga.c (GRUB_AMIGA_PART_MAGIC): New define. - (amiga_partition_map_iterate): Check "PART" magic to avoid a very long - loop in case of incorrect amiga partmap. - -2010-12-31 Vladimir Serbinenko - - * grub-core/partmap/amiga.c (GRUB_AMIGA_RDSK_MAGIC): New define. - (amiga_partition_map_iterate): Use grub_memcmp instead of grub_strcmp. - Reported by:EHeM. - -2010-12-31 Vladimir Serbinenko - - * grub-core/loader/i386/bsdXX.c (grub_openbsd_find_ramdisk): Silence - spurious warning. - Reported by: crocket - -2010-12-27 Vladimir Serbinenko - - * grub-core/loader/xnu.c (grub_cmd_xnu_kernel) [! GRUB_MACHINE_EFI]: - Preload EFIemu. - (grub_cmd_xnu_kernel64) [! GRUB_MACHINE_EFI]: Likewise. - -2010-12-27 Vladimir Serbinenko - - * grub-core/loader/xnu.c (grub_cmd_xnu_kext): Abort if no kernel - is loaded - (grub_cmd_xnu_kextdir): Likewise. - (grub_cmd_xnu_splash): Likewise. - -2010-12-27 Vladimir Serbinenko - - Avoid using Reed-Solomon with 0 redundancy. - - * grub-core/kern/i386/pc/startup.S: Remove 0-data check. - * grub-core/lib/reed_solomon.c (decode_block): Do not proceed on 0 data - or 0 redundancy. - (grub_reed_solomon_add_redundancy): Do not proceed with 0 redundancy. - (grub_reed_solomon_recover): Likewise. - -2010-12-27 Vladimir Serbinenko - - Don't use disk subsystem in freebsd_boot. - - * grub-core/loader/i386/bsd.c (freebsd_bootdev): New variable. - (freebsd_biosdev): Likewise. - (grub_freebsd_boot): Use freebsd_bootdev and freebsd_biosdev. - (grub_cmd_freebsd): Set freebsd_bootdev and freebsd_biosdev. - -2010-12-26 Vladimir Serbinenko - - Handling of files of unknown size is currently limited. They can't be - used e.g. for initrd or modules. Moreover gzip handling of not - easily seekable files is buggy. Disable unknown file size for now. May - be inefficient but works. - - * grub-core/io/gzio.c (test_header): Always retrieve the file size. - * grub-core/io/xzio.c (grub_xzio_open): Likewise. - -2010-12-25 Mirko Parthey - - * grub-core/boot/i386/pc/boot.S: Fix %es:%bx pointing to nowhere on - floppy probe. - -2010-12-25 Jeroen Dekkers - - * grub-core/disk/raid.c (insert_array): Don't add spurious members. - -2010-12-25 Shea Levy - - * grub-core/genmod.sh.in: Use @OBJCOPY@ rather than objcopy. - -2010-12-25 Vladimir Serbinenko - - * util/grub.d/30_os-prober.in: Don't emit drivemap directive for - Windows Server 2008. - Reported by: Devin Giddings. - -2010-12-25 Vladimir Serbinenko - - * grub-core/commands/acpihalt.c (grub_acpi_halt): Sleep for 1.5 before - writing an error message because of async power management. - * grub-core/kern/mips/yeeloong/init.c (grub_halt): Likewise. - (grub_reboot): Likewise. - -2010-12-23 Jordan Uggla - - * tests/util/grub-shell.in: Suppress "ACPI shutdown failed" error to - keep unit tests from failing when they shouldn't. - -2010-12-21 Colin Watson - - * include/grub/offsets.h (GRUB_KERNEL_I386_PC_RAW_SIZE): The - previous patch increased the size of the RS code by 20 bytes (at - least with gcc-4.4), so increase this by 20 bytes to match. - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): Likewise. - -2010-12-21 Colin Watson - - * grub-core/lib/reed_solomon.c (gauss_solve): Fix size of standalone - scratch area. Make sure to initialise chosen in standalone mode as - well as non-standalone. - Reported by: Robert Hooker and Andy Whitcroft. - Tested by: Andy Whitcroft. - -2010-12-21 Colin Watson - - * grub-core/commands/echo.c (grub_cmd_echo): Make UTF-8-clean by - constructing a new unescaped string and passing it to grub_xputs in - one go, rather than passing characters to grub_printf one at a time. - -2010-12-21 Colin Watson - - * grub-core/fs/udf.c (read_string): Pacify GCC warning by - initialising utf16. - -2010-12-21 Colin Watson - - * util/grub-mkconfig_lib.in (gettext_quoted): Add clarifying - comment. Add an extra layer of quotation, requiring the output of - this function to be used in a printf format string. - (gettext_printf): New function. - * util/grub.d/10_hurd.in: Use gettext_printf where appropriate. - Extract translatable strings from here-documents and use a temporary - variable instead, so that xgettext can find them. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - - * po/grub.d.sed: New file. - * po/Makefile.in.in ($(DOMAIN).pot-update): Extract gettext_printf - arguments. Set c-format flags on all strings extracted from - util/grub.d/ (xgettext refuses to include these itself for strings - it extracted from a shell file, but these really are c-format). - -2010-12-20 Vladimir Serbinenko - - * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_add_module): - Avoid next pointing to nowhere. - -2010-12-19 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_mount): Read data->bblock.rootblock - rather than assuming than rootblock is exactly in the middle. - (grub_affs_label): Likewise. - -2010-12-19 Vladimir Serbinenko - - * grub-core/fs/affs.c (grub_affs_fs) [GRUB_UTIL]: Explicitly set - reserved_first_sector to 0. - * grub-core/fs/cpio.c (grub_cpio_fs) [GRUB_UTIL]: Likewise. - * grub-core/fs/sfs.c (grub_sfs_fs) [GRUB_UTIL]: Likewise. - * grub-core/fs/xfs.c (grub_xfs_fs) [GRUB_UTIL]: Likewise. - -2010-12-19 Vladimir Serbinenko - - Fix handling of UTF-16 UDF labels. - - * grub-core/fs/udf.c (grub_udf_iterate_dir): Move string-parsing part - (read_string): .. here. - (grub_udf_label): Use read_string. - -2010-12-19 BVK Chaitanya - - * grub-core/normal/menu_entry.c (run): Execute commands from menu - editor under argument scope. - Reported by: Jordan Uggla - -2010-12-18 Vladimir Serbinenko - - * util/grub-mkfont.c (main): Handle errors from FT_Set_Pixel_Sizes. - -2010-12-18 Colin Watson - - * grub-core/normal/term.c (print_more): Make \r or \n scroll one - line, and other keys scroll an entire page (previous handling was - for \r and \n to scroll a page and other keys to scroll two lines). - -2010-12-18 Vladimir Serbinenko - - * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_make_mbi): - Set ptrdest to correct get_physical_target_address rather than - incorrect get_virtual_current_address. - -2010-12-18 kashyap garimella - - * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_load): Use - correct cat to grub_uint8_t * rather than grub_uint32_t *. - -2010-12-10 Colin Watson - - * .bzrignore: Ignore grub-core/rs_decoder.S. - -2010-12-10 Colin Watson - - * grub-core/gettext/gettext.c (grub_gettext_init_ext): Factor out - .mo/.mo.gz opening sequence to ... - (grub_mofile_open_lang): ... here. - (grub_gettext_init_ext): If opening ll_CC fails, try ll. - * util/grub.d/00_header.in (grub_lang): Include country part of - locale. - Reported by: Mario Limonciello. - -2010-12-09 Robert Millan - - * NEWS: Document addition of ZFS support. - -2010-12-04 Colin Watson - - * grub-core/kern/i386/pc/startup.S (grub_console_getkey): Use `>> 1' - rather than `/ 2', as the latter requires -Wa,--divide which would - require bumping our minimum binutils version. - -2010-12-03 BVK Chaitanya - - * util/grub-script-check.c (main): Print script line number on - error. - -2010-12-01 Robert Millan - - * grub-core/fs/zfs/zfs.c: New file. - * grub-core/fs/zfs/zfs_fletcher.c: Likewise. - * grub-core/fs/zfs/zfs_lzjb.c: Likewise. - * grub-core/fs/zfs/zfs_sha256.c: Likewise. - * grub-core/fs/zfs/zfsinfo.c: Likewise. - - * include/grub/zfs/dmu.h: Likewise. - * include/grub/zfs/dmu_objset.h: Likewise. - * include/grub/zfs/dnode.h: Likewise. - * include/grub/zfs/dsl_dataset.h: Likewise. - * include/grub/zfs/dsl_dir.h: Likewise. - * include/grub/zfs/sa_impl.h: Likewise. - * include/grub/zfs/spa.h: Likewise. - * include/grub/zfs/uberblock_impl.h: Likewise. - * include/grub/zfs/vdev_impl.h: Likewise. - * include/grub/zfs/zap_impl.h: Likewise. - * include/grub/zfs/zap_leaf.h: Likewise. - * include/grub/zfs/zfs.h: Likewise. - * include/grub/zfs/zfs_acl.h: Likewise. - * include/grub/zfs/zfs_znode.h: Likewise. - * include/grub/zfs/zil.h: Likewise. - * include/grub/zfs/zio.h: Likewise. - * include/grub/zfs/zio_checksum.h: Likewise. - - * Makefile.util.def: Build ZFS into libgrubmods. - * grub-core/Makefile.core.def: Build zfs.mod. - -2010-11-30 Szymon Janc - - * grub-core/commands/regexp.c (grub_cmd_regexp): Remove unused - variable. - * grub-core/commands/wildcard.c (match_files): Likewise. - -2010-11-30 Robert Millan - - * grub-core/loader/i386/bsd.c - (grub_cmd_freebsd_loadenv, grub_cmd_freebsd_module_elf): Check - whether kernel is loaded using grub_loader_is_loaded(), rather - than `kernel_type', which may still be `KERNEL_TYPE_NONE' under - certain error conditions. - -2010-11-30 Robert Millan - - * grub-core/commands/echo.c: Include `'. - (grub_cmd_echo): Call grub_refresh() after printing a message. - -2010-11-26 Vladimir Serbinenko - - Avoid using tricks for initialising endian variables. - - * grub-core/partmap/gpt.c (grub_gpt_partition_type_bios_boot): - Make const. - (GRUB_MOD_INIT): Don't byte-swap. - * include/grub/gpt_partition.h (GRUB_GPT_PARTITION_TYPE_BIOS_BOOT): - Use grub_cpu_to_le16_compile_time and grub_cpu_to_le32_compile_time. - * include/grub/types.h (grub_swap_bytes16_compile_time): New macro. - (grub_swap_bytes32_compile_time): Likewise. - (grub_cpu_to_le32_compile_time): Likewise. - (grub_cpu_to_le16_compile_time): Likewise. - -2010-11-26 Vladimir Serbinenko - - * util/grub-setup.c (setup): Stop recommending --force. People who - understand the dangers of blocklists are able to find this option - anyway and the ones who don't shouldn't use it anyway. - -2010-11-26 Robert Millan - - * grub-core/term/i386/pc/vga_text.c (VGA_TEXT_SCREEN): Beautify. - Update all users. - -2010-11-26 Colin Watson - - Fix LVM-on-RAID probing. - - * util/grub-probe.c (probe): Remember which disk was detected as - RAID (perhaps an LVM physical volume). Use that disk's raidname - rather than that of the top-level disk. - -2010-11-25 BVK Chaitanya - - Fix cmdline argument quotes for setparams command of menuentry - definitions. - - * grub-core/commands/menuentry.c (setparams_prefix): Use single - quotes for arguments. - * grub-core/lib/legacy_parse.c (grub_legacy_escape): Use - grub_strchrsub function instead. - - * include/grub/misc.h (grub_strchrsub): New function. - -2010-11-24 Colin Watson - - * util/deviceiter.c (grub_util_iterate_devices): Save a bit of - effort by skipping "." and ".." entries up-front. - Suggested by: Michael Lazarev. - -2010-11-24 Colin Watson - - * grub-core/Makefile.core.def (xz_decompress): Move -lgcc from - ldflags to ldadd, to fix link line ordering. - (none_decompress): Likewise. - -2010-11-24 Colin Watson - - * grub-core/Makefile.core.def (kernel): Add kern/emu/cache.S for emu - platforms. - (grub-emu-lite): Remove kern/emu/cache.S. - -2010-11-23 Colin Watson - - * util/deviceiter.c (compare_devices): If the by-id link for a - device couldn't be resolved, fall back to sorting by the by-id link - rather than segfaulting. - Reported and tested by: Daniel Mierswa. - -2010-11-23 Colin Watson - - * Makefile.util.def (grub-menulst2cfg): List libraries in ldadd, not - ldflags, to fix link line ordering. - -2010-11-23 Colin Watson - - * grub-core/Makefile.am (gentrigtables): Put -lm after $<; some - linkers are picky about this. - -2010-11-23 Colin Watson - - * grub-core/Makefile.am (command.lst): Adjust sed expression - ordering so that extended and priority commands aren't treated as - ordinary commands. - -2010-11-23 Colin Watson - - * include/grub/gpt_partition.h (GRUB_GPT_PARTITION_TYPE_BIOS_BOOT): - Remove byte-swapping function calls, which are not valid in - structure initialisers. - * grub-core/partmap/gpt.c (grub_gpt_partition_type_bios_boot): Make - non-const. - (GRUB_MOD_INIT): Byte-swap data1, data2, and data3 fields of - grub_gpt_partition_type_bios_boot. - -2010-11-22 Colin Watson - - Fix test program build on GNU/kFreeBSD. - - * Makefile.util.def (example_unit_test): Add `$(LIBZFS) - $(LIBNVPAIR)' library dependencies. - -2010-11-22 Colin Watson - - * util/grub-install.in: Fix parsing of --grub-mkrelpath= option. - -2010-11-22 Colin Watson - - * util/grub-install.in: Remove excessive quoting that broke - installations to RAID devices. - -2010-11-19 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (grub_cmd_linux): Pass correctly the - bootloader version instead of 0. - -2010-11-19 Vladimir Serbinenko - - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Fix spurious - warning. - -2010-11-19 Vladimir Serbinenko - - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Don't try to - retrieve the metadat sector if size isn't known. - * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Likewise. - -2010-11-18 Robert Millan - - * grub-core/fs/btrfs.c (grub_btrfs_mount): Replace grub_strncmp() - with grub_memcmp(). - -2010-11-18 Vladimir Serbinenko - - * grub-core/normal/menu_entry.c (print_up): Fix displacement of up - arrow. - Reported by: Jordan Uggla. - -2010-11-16 Vladimir Serbinenko - - Make better UTF compliant. - - * grub-core/normal/charset.c (grub_utf8_to_utf16): Handle 6- and 7-byte - sequences as incorrect. - (grub_is_valid_utf8): Likewise. - (grub_utf8_to_ucs4): Likewise. - (grub_ucs4_to_utf8): Handle codepoints outside of BMP. - (grub_ucs4_to_utf8_alloc): Likewise. - * include/grub/charset.h (grub_utf16_to_utf8): Likewise. - -2010-11-16 Vladimir Serbinenko - - Make legacy_source behave like source. - - * grub-core/commands/legacycfg.c (legacy_file): Don't call - grub_show_menu. - (grub_cmd_legacy_source): Call grub_show_menu if needed. - -2010-11-16 Colin Watson - - * conf/Makefile.common (CFLAGS_GNULIB): Add -Wno-unused-parameter. - (-Wunused implies -Wunused-parameter, but not vice versa). - -2010-11-16 Colin Watson - - * configure.ac: Make error messages less confusing by testing for - -Wtrampolines rather than -Wno-trampolines (since -Wno-* is always - accepted, but produces a diagnostic if something else is wrong). - -2010-11-15 Vladimir Serbinenko - - * grub-core/term/at_keyboard.c (grub_keyboard_controller_read) - [GRUB_MACHINE_MIPS_YEELOONG || GRUB_MACHINE_QEMU]: ifdef-ed out - (now unused). - (grub_keyboard_controller_init) - [GRUB_MACHINE_MIPS_YEELOONG || GRUB_MACHINE_QEMU]: Don't attempt to - read the initial state since controller isn't inited yet. - -2010-11-15 Vladimir Serbinenko - - * grub-core/lib/relocator.c (malloc_in_range): Take into account that - allocate_regbeg may need to create new chunk header. - -2010-11-14 Vladimir Serbinenko - - Fix quoting in legacy parser. - - * grub-core/lib/legacy_parse.c (grub_legacy_escape): Correctly handle - single quotes. - (grub_legacy_parse): Likewise. - Reported by: Jordan Uggla. - Tested by: Jordan Uggla. - -2010-11-14 Vladimir Serbinenko - - Don't add -lgcc on i386 and x86_64. - - * configure.ac (LIBS): Don't add -lgcc on i386 and x86_64. - * conf/Makefile.common (LDADD_KERNEL): Likewise. - * grub-core/Makefile.core.def (kernel): Use LDADD_KERNEL. - -2010-11-14 Vladimir Serbinenko - - * configure.ac: Add -Wno-trampolines when supported. - -2010-11-14 Modestas Vainius - - * grub-core/kern/emu/getroot.c (grub_util_is_dmraid): Recognise ddf1_ - fakeraid. - -2010-11-14 Giuseppe Caizzone - - Add generic logical block size support for UDF. - - * grub-core/fs/udf.c (GRUB_UDF_LOG2_BLKSIZE): Removed. - (GRUB_UDF_BLKSZ): Removed. - (struct grub_udf_data): New field "lbshift" to hold the logical block - size of the file system in log2 format. All users updated. - (sblocklist): Change type to unsigned. - (grub_udf_mount): Change type of "sblklist" to unsigned. - Move AVDP search before VRS recognition, because the latter requires - knowledge of the logical block size, which is detected during the - former. - Detect and validate logical block size during AVDP search, adding - support for block sizes 512, 1024 and 4096. - Make VRS recognition independent of block size. - -2010-11-14 Giuseppe Caizzone - - Properly handle deleted files on UDF. - - * grub-core/fs/udf.c (grub_udf_iterate_dir): Skip directory entries - whose "characteristics" field has the bit GRUB_UDF_FID_CHAR_DELETED - set. - -2010-11-14 Giuseppe Caizzone - - Support reading files larger than 2 GiB. - - * grub-core/fs/udf.c (grub_udf_iterate_dir): Change type of variable - "offset" to grub_off_t. - (grub_udf_read_file): Likewise for parameter "pos". - -2010-11-14 Vladimir Serbinenko - - * docs/grub.texi (Changes from GRUB Legacy): Note when save_env is - unavailable. - (Simple configuration): Refer to Changes from GRUB Legacy about - save_env availability. - -2010-11-14 Vladimir Serbinenko - - * util/grub-install.in: Ignore empty partition table detection - instead of trying to include part_ module. - -2010-11-14 Vladimir Serbinenko - - * grub-core/disk/lvm.c (GRUB_MOD_FINI): Reset the vg_list. Fixes - LVM on RAID support. - -2010-11-14 Vladimir Serbinenko - - Properly define WORDS_BIGENDIAN in wrapped environments. - - * grub-core/lib/libgcrypt_wrap/cipher_wrap.h (WORDS_BIGENDIAN): New - definition. - * grub-core/lib/posix_wrap/sys/types.h (WORDS_BIGENDIAN): Likewise. - - Reported by: Manoel Rebelo Abranches. - Tested by: Manoel Rebelo Abranches. - -2010-11-13 Vladimir Serbinenko - - * util/grub-mkconfig.in: Fix quoting. - -2010-11-13 Vladimir Serbinenko - - Support big ext2 files. - - * grub-core/fs/ext2.c (grub_ext2_inode): Rename dir_acl to size_high. - (grub_ext2_read_block): Support triple indirect blocks. - (grub_ext2_read_file): Use 64-bit types and read size_high. - (grub_ext2_open): Read size_high. - Reported by: Ximin Luo. - Tested by: Manoel Rebelo Abranches. - -2010-11-13 Vladimir Serbinenko - - * util/grub-install.in: Handle filenames containing spaces. - Reported by: Jordan Uggla. - Tested by: Jordan Uggla. - -2010-11-13 Vladimir Serbinenko - - * util/grub-mkconfig.in (grub_script_check): New variable. - Use grub_script_check instead of grub-script-check. - Reported by: Barry Jackson. - -2010-11-13 Vladimir Serbinenko - - * docs/grub.texi (menu): Correct the order. - Reported by: D. Hugh Redelmeier. - -2010-11-12 Vladimir Serbinenko - - * grub-core/kern/i386/pc/startup.S (multiboot_trampoline): Add missing - jump. - -2010-11-08 Manoel Rebelo Abranches - - * include/grub/elfload.h (grub_elf32_size): New parameter. - All users updated. - Return maximum segments alignment. - (grub_elf64_size): Likewise. - * kern/elf.c (grub_elf32_size): New parameter. All users updated. - Return maximum segments alignment. - (grub_elf64_size): Likewise. - * grub-core/loader/powerpc/ieee1275/linux.c: - (grub_linux_claimmap_iterate): New function. Uses the - "available" property in the "memory" node for memory allocation - for kernel in the PowerPC loader. - (grub_linux_load32): Correctly find linux entry point offset. - (grub_linux_load64): Likewise. - -2010-11-07 Robert Millan - - On mips-yeeloong, build with -march=loongson2f when this flag is - available (GCC >= 4.4). - * conf/Makefile.common [COND_mips_yeeloong] (CFLAGS_PLATFORM): Remove - `-march=mips3'. - * configure.ac: For mips-yeeloong, add -march=loongson2f if available, - or otherwise add -march=mips3. - -2010-11-07 BVK Chaitanya - - Suppress shell expansion on echo '*' and echo "*" like cases. - Reported by: Jordan Uggla. - - * grub-core/script/execute.c (grub_script_arglist_to_argv): Escape - string arguments before shell expansion. - * tests/grub_cmd_echo.in: New testcases. - -2010-11-07 Robert Millan - - * conf/mips-qemu-mips.rmk: Remove stale file from previous - transition. - -2010-11-07 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c - (convert_system_partition_to_system_disk): Handle devices like "sdaa1". - -2010-11-06 Vladimir Serbinenko - - * include/grub/emu/misc.h: Don't include grub/util/libzfs.h. - * include/grub/emu/misc.h (grub_get_libzfs_handle): Move from here ... - * include/grub/util/libzfs.h (grub_get_libzfs_handle): ... here. - -2010-11-06 Vladimir Serbinenko - - * grub-core/fs/ntfs.c (grub_ntfs_uuid): Make uppercase. - -2010-11-06 Vladimir Serbinenko - - * util/grub-install.in: Replace useless recomendation to pass - --modules with a recomendation to report a bug. - -2010-11-06 Vladimir Serbinenko - - Properly register serial terminfo. - Reported by: Jordan Uggla - - * grub-core/term/serial.c (grub_serial_terminfo_input_template): New - const. - (grub_serial_terminfo_output_template): Likewise. - (grub_cmd_serial): Register "serial" with terminfo. - (GRUB_MOD_INIT(serial)): Fill grub_serial_terminfo_input and - grub_serial_terminfo_output. - -2010-11-05 Robert Millan - - * util/grub-mkconfig.in: Remove gfxterm.mod probe (no longer - needed). - -2010-11-05 Robert Millan - - On Yeeloong, pass machine type information to Linux. - - * grub-core/loader/mips/linux.c [GRUB_MACHINE_MIPS_YEELOONG] - (LOONGSON_MACHTYPE): New macro, set to - "machtype=lemote-yeeloong-2f-8.9inches". - [LOONGSON_MACHTYPE] (grub_cmd_linux): Pass LOONGSON_MACHTYPE as - additional argument to Linux. - -2010-11-04 Robert Millan - - * util/deviceiter.c (grub_util_iterate_devices): Increase SCSI - limit to 48 (to cope with Sun Fire X4500), and IDE limit to 96 - (its SATA disks are detected as slaveless IDE master drives on - kFreeBSD). - Reported by Carsten Aulbert. - -2010-11-02 Colin Watson - - * util/bin2h.c (main): Fix spelling error in generated output. - -2010-11-01 GrĂ©goire Sutre - - * grub-core/partmap/bsdlabel.c (iterate_real): Fix an integer overflow. - -2010-11-01 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (grub_cmd_linux): Autoload vbe.mod if - vga= option is supplied. - -2010-11-01 Vladimir Serbinenko - - * util/grub.d/10_hurd.in: Don't call savedefault on recovery entries. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - -2010-11-01 Vladimir Serbinenko - - * grub-core/lib/arg.c (grub_arg_parse): Avoid interpreting direct - argument as an argument to no-argument option. - -2010-11-01 Vladimir Serbinenko - - * util/grub.d/10_linux.in: Add missing load_video with explicit - GRUB_GFXPAYLOAD_LINUX. - -2010-11-01 Vladimir Serbinenko - - * Makefile.am (libgrub.pp): Propagate the libgrub.a split. - -2010-11-01 Vladimir Serbinenko - - * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Do not put - elements with invlid index. - * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Likewise. - * grub-core/disk/raid.c (insert_array): Automatically reallocate - members. - * include/grub/raid.h (grub_raid_member): New struct. - (grub_raid_array): Transform devices and start_sector into usage of - grub_raid_member. All users updated - (allocated_devs): New member. - -2010-11-01 Vladimir Serbinenko - - * docs/man/grub-set-default.h2m: Clarify that only saved default entry - is modified - -2010-10-29 BVK Chaitanya - - NetBSD build fix for getline function conflict from gnulib. - - * Makefile.util.def (libgrubkern.a): New library for grub kernel - components that depend on gnulib headers. - (libgrubmods.a): Renamed from earlier libgrub.a. - * conf/Makefile.common: Remove gnulib from *_LIBRARY flags. - -2010-10-26 Vladimir Serbinenko - - * util/grub-setup.c (setup): Refuse to do a cross-disk embeddingless - install rather than creating a broken install. - -2010-10-26 Vladimir Serbinenko - - * util/grub-setup.c (argp): Remove misleading example of installing to - a partition. - -2010-10-26 Vladimir Serbinenko - - * util/grub-setup.c (setup): Clarify the error message. - -2010-10-26 Vladimir Serbinenko - - * include/grub/types.h (grub_target_off_t): Removed no longer used type. - -2010-10-23 Vladimir Serbinenko - - * grub-core/kern/emu/misc.c - (grub_make_system_path_relative_to_its_root) - [HAVE_LIBZFS && HAVE_LIBNVPAIR]: Fix mountpoint return on ZFS. - -2010-10-23 Vladimir Serbinenko - - * grub-core/kern/emu/misc.c - (grub_make_system_path_relative_to_its_root): Revert r2882. - -2010-10-22 Vladimir Serbinenko - - * grub-core/lib/relocator.c (grub_relocator_subchunk): Remove now - useless field head. All users updated. - (free_subchunk): Correct handling of IN_REGION subchunk. - -2010-10-22 Colin Watson - - * docs/grub.texi (Installing GRUB using grub-install): Proofread. - (Supported kernels): Likewise. - -2010-10-18 GrĂ©goire Sutre - - Make mktemp invocations portable. - - * grub-core/genmod.sh.in: Use mktemp with an explicit template, and - exit if mktemp fails. - * tests/grub_script_blockarg.in: Likewise. - * tests/partmap_test.in: Likewise. - * tests/util/grub-shell-tester.in: Likewise. - * tests/util/grub-shell.in: Likewise. - * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. - * Makefile.am: Likewise, and chain shell commands with `&&' - instead of ';'. - * util/grub-mkrescue.in: Use the same explicit template as above, and - exit if mktemp fails. - -2010-10-18 BVK Chaitanya - - * util/grub.d/10_linux.in: Fix built-in initramfs image mode for - Linux kernel, reported by Dennis Schridde. - -2010-10-17 Szymon Janc - - * grub-core/normal/auth.c (grub_auth_check_authentication): - Set-but-not-used variable removed. - -2010-10-17 Vladimir Serbinenko - - * docs/grub.texi (GNU/Linux): Document APM unavailability with - 32-bit linux protocol. - -2010-10-17 Vladimir Serbinenko - - * grub-core/kern/i386/pc/startup.S (grub_console_setcursor): Check - cursor shape for sanity. - -2010-10-17 Vladimir Serbinenko - - * docs/grub.texi (Installation): Document buggy BIOS install. - -2010-10-17 Vladimir Serbinenko - - * docs/grub.texi (Installation): Indent. - -2010-10-17 Vladimir Serbinenko - - * util/grub-setup.c (setup): New parameter allow_floppy. - (arguments): New member allow_floppy. - (argp_parser): Handle --allow-floppy. - (main): Pass allow_floppy. - * util/grub-install.in: New option --allow-floppy passed though to - grub-setup. - -2010-10-17 Vladimir Serbinenko - - * util/grub-install.in: Handle partitionless disks. - -2010-10-17 Vladimir Serbinenko - - * util/grub-setup.c (setup): Don't clean blocklists before readability - verfification. - -2010-10-16 Vladimir Serbinenko - - * docs/grub.texi (Installation): Document embedding zone. Remove - obsolete grub-install example. - -2010-10-16 Szymon Janc - - * grub-core/commands/legacycfg.c (grub_cmd_legacy_kernel): - Set-but-not-used variable ifdef'ed. - * grub-core/lib/legacy_parse.c (grub_legacy_parse): Likewise. - * grub-core/bus/usb/ohci.c (grub_ohci_pci_iter): Set-but-not-used - variable removed. - * grub-core/disk/lvm.c (grub_lvm_scan_device): Likewise. - * grub-core/fs/jfs.c (grub_jfs_find_file): Likewise. - * grub-core/fs/minix.c (grub_minix_dir): Likewise. - * grub-core/fs/sfs.c (grub_sfs_read_extent): Likewise. - * grub-core/fs/ufs.c (grub_ufs_dir): Likewise. - * grub-core/gfxmenu/gui_list.c (grub_gui_list_new): Likewise. - * grub-core/gfxmenu/view.c (redraw_menu_visit): Likewise. - * grub-core/gfxmenu/widget-box.c (draw): Likewise. - * grub-core/lib/relocator.c (malloc_in_range): Likewise. - * grub-core/loader/i386/bsdXX.c (grub_netbsd_load_elf_meta): Likewise. - * grub-core/loader/i386/bsd_pagetable.c (fill_bsd64_pagetable): - Likewise. - -2010-10-16 Vladimir Serbinenko - - * grub-core/commands/acpihalt.c (skip_ext_op): Skip index field op. - * include/grub/acpi.h (GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP): New - enum value. - -2010-10-16 Vladimir Serbinenko - - * grub-core/commands/acpihalt.c (get_sleep_type): Accept \_S5_ as - synonym to _S5_. Needed for some DSDTs. - -2010-10-16 Vladimir Serbinenko - - Userspace ACPI parser debugging. - - * grub-core/commands/acpihalt.c [GRUB_DSDT_TEST]: Include userspace - headers and add relevant defines. Don't include standard headers. - (main) [GRUB_DSDT_TEST]: New function. - * include/grub/acpi.h [GRUB_DSDT_TEST]: Don't include standard headers. - Don't declare functions. - -2010-10-16 Vladimir Serbinenko - - Remove dead grub_efi_mm_fini. - - * grub-core/kern/efi/mm.c (allocated_page): Removed. - (ALLOCATED_PAGES_SIZE): Likewise. - (MAX_ALLOCATED_PAGES): Likewise. - (allocated_pages): Likewise. - (grub_efi_allocate_pages): Don't record allocated pages. - (grub_efi_free_pages): Likewise. - (grub_efi_mm_init): Likewise. - (grub_efi_mm_fini): Removed. - -2010-10-16 Vladimir Serbinenko - - * grub-core/kern/efi/mm.c (BYTES_TO_PAGES): Round up instead of down. - (grub_efi_mm_init): Take into account the memory map size increase. - -2010-10-16 Vladimir Serbinenko - - * grub-core/term/ns8250.c (do_real_config): Set port->broken to 0. - (serial_hw_put): Wait based on real time rather than port reads. Don't - roken ports. - * include/grub/serial.h (grub_serial_port): New field broken. - -2010-10-16 Robert Millan - - * grub-core/kern/emu/misc.c - (grub_make_system_path_relative_to_its_root): Fix premature return - when processing non-root ZFS filesystems. - Reported by Sergio Talens-Oliag. - -2010-10-15 Robert Millan - - * util/grub.d/10_linux.in (list): Expand "vmlinu[zx]" instances to - guarantee compressed ones are processed first. - -2010-10-14 Vladimir Serbinenko - - * grub-core/efiemu/main.c (grub_efiemu_prepare): Handle errors from - grub_efiemu_autocore. - -2010-10-14 Vladimir Serbinenko - - * grub-core/kern/i386/pc/startup.S (bypass_table): Use 0x1b explicitly - rather than 0x1b. - (grub_console_getkey): Use correct jae opcode rather than ja. - -2010-10-12 Robert Millan - - * util/grub-mkconfig.in: Merge `GRUB_DISABLE_LINUX_RECOVERY' and - `GRUB_DISABLE_NETBSD_RECOVERY' into a single `GRUB_DISABLE_RECOVERY' - variable. All references updated. - - * util/grub.d/10_kfreebsd.in: Support recovery boot entries. - -2010-10-08 Vladimir Serbinenko - - Correctly distinguish mdraid flavours. - - * grub-core/disk/raid.c (grub_raid_getname) [GRUB_UTIL]: New function. - (insert_array): New argument raid. - * include/grub/disk.h (grub_disk_dev) [GRUB_UTIL]: New member raidname. - * include/grub/raid.h (grub_raid_array) [GRUB_UTIL]: New member driver. - * util/grub-probe.c (probe): PRint raidname instead of plainly "mdraid". - -2010-10-09 Vladimir Serbinenko - - * grub-core/kern/i386/pc/startup.S (grub_console_getkey): Fix incorrect - handling of special keys. - -2010-10-02 AleÅ¡ Nesrsta - - * include/grub/scsi.h (grub_make_scsi_id): Fix incorrect usgae of - GRUB_SCSI_ID_BUS_SHIFT instead of GRUB_SCSI_ID_LUN_SHIFT. - -2010-10-02 AleÅ¡ Nesrsta - - * grub-core/bus/usb/ohci.c (GRUB_OHCI_TDS): Increase. - * grub-core/bus/usb/uhci.c (N_TD): New definition. All previous implicit - users updated. - * grub-core/bus/usb/usbtrans.c (grub_usb_bulk_setup_readwrite): - Use right endpoint when querying descriptor. - -2010-10-01 Vladimir Serbinenko - - Clear out 0x80 color bit on EFI. - Tested by: decoder - Reported by: decoder and meta tech. - - * grub-core/term/efi/console.c (grub_console_standard_color): Removed. - (grub_console_setcolorstate): Clear out 0x80 bit. - Use GRUB_TERM_DEFAULT_STANDARD_COLOR. - (grub_console_output): Use GRUB_TERM_DEFAULT_NORMAL_COLOR. - Use GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR. - -2010-10-01 Vladimir Serbinenko - - * grub-core/loader/i386/linux.c (DEFAULT_VIDEO_MODE) [GRUB_MACHINE_EFI]: - Set to "auto". - -2010-09-30 Vladimir Serbinenko - - * grub-core/gettext/gettext.c (grub_gettext_init_ext): Avoid using - mo_file after freeing. - -2010-09-30 Vladimir Serbinenko - - * grub-core/normal/term.c (read_terminal_list): Free in a right order. - -2010-09-30 Vladimir Serbinenko - - * grub-core/script/execute.c (grub_script_execute_sourcecode): Set - flags. - -2010-09-30 Vladimir Serbinenko - - * util/grub-setup.c (main) [GRUB_MACHINE_IEEE1275]: Propagate argp - usage. - -2010-09-30 Vladimir Serbinenko - - Put terminfo into core on ieee1275 and yeeloong (needed for console). - - * gentpl.py: New groups terminfoinkernel and terminfomodule. - * grub-core/Makefile.am (KERNEL_HEADER_FILES): Include extcmd.h, arg.h - and terminfo.h when needed. - * grub-core/Makefile.core.def (kernel): Include term/terminfo.c, - term/tparm.c, commands/extcmd.c, lib/arg.c on terminfokernel. - (terminfo): Enable only on terminfokernel. - (extcmd): Likewise. - * include/grub/extcmd.h: Add missing EXPORT_FUNC. - * include/grub/lib/arg.h: Likewise. - * grub-core/term/ieee1275/ofconsole.c (grub_ofconsole_dimensions): Fix - incorrect usage of ->. - -2010-09-29 Vladimir Serbinenko - - * grub-core/loader/multiboot_mbi2.c (grub_multiboot_make_mbi] - [GRUB_MACHINE_EFI && __i386__]: Fix typo. - -2010-09-29 Vladimir Serbinenko - - Fix coreboot compilation. - - * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_get_mbi_size): - Take VBE info into account even if only text is supported. - (fill_vbe_info): Take into account the case when only VGA text - is supported. - * include/grub/multiboot.h (GRUB_MACHINE_HAS_VBE): Set to zero - on coreboot, multiboot and qemu. - -2010-09-29 Vladimir Serbinenko - - * grub-core/lib/relocator.c (malloc_in_range): Trim too verbose - debug messages. - (grub_relocator_prepare_relocs): Set movers_chunk.srcv. - -2010-09-29 Vladimir Serbinenko - - * grub-core/loader/i386/bsd.c (grub_cmd_netbsd): Provide default serial - parameters. - -2010-09-29 Vladimir Serbinenko - - * grub-core/lib/arg.c (grub_arg_parse): Fix treating of all commands as - if they were BSD-style. - -2010-09-29 Vladimir Serbinenko - - * grub-core/boot/i386/pc/lnxboot.S: Replace - GRUB_KERNEL_I386_PC_MULTIBOOT_SIGNATURE with - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART. - -2010-09-29 Vladimir Serbinenko - - Write embedding zone using Reed-Solomon. - - * Makefile.util.def (grub-setup): Add grub-core/lib/reed_solomon.c. - * grub-core/Makefile.am (rs_decoder.S): New target. - (kern/i386/pc/startup.S): Depend on rs_decoder.S. - * grub-core/kern/i386/pc/startup.S (reed_solomon_redundancy): New field. - (multiboot): Move to RS part. - (post_reed_solomon): New label. - (grub_boot_drive): Move to non-RS part since it's modified in memory - on boot. - Include rs_decoder.S. - * grub-core/lib/reed_solomon.c: New file. - * include/grub/offsets.h (GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY): - New definition. - (GRUB_KERNEL_I386_PC_MULTIBOOT_SIGNATURE): Removed. - (GRUB_KERNEL_I386_PC_RAW_SIZE): Updated. - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): New definition. - * include/grub/partition.h (grub_partition_map): Change prototype of - embed to allow returning additional sectors. - * include/grub/reed_solomon.h: New file. - * util/grub-setup.c (setup): Handle Reed-Solomon. - -2010-09-28 Colin Watson - - * grub-core/loader/multiboot_mbi2.c (grub_multiboot_make_mbi): Fix - i386 and x86-64 definedness tests. - -2010-09-27 Yves Blusseau - - Fix generation of kernel_syms.lst - - * grub-core/Makefile.am (kernel_syms.lst): Fix value and position of - ASM_PREFIX - -2010-09-26 Robert Millan - - Support degraded ZFS arrays in "grub-probe -t device" resolution. - - * grub-core/kern/emu/getroot.c (find_root_device_from_libzfs): When - the pool is an array of devices, iterate through it and return the - first device that passes a stat() test (instead of blindly returning - the first one). - -2010-09-26 Robert Millan - - Build fixes for GNU/kFreeBSD. - - * Makefile.util.def: Add `$(LIBZFS) $(LIBNVPAIR)' library dependencies - to programs that require ZFS conversion. - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): Support - kernels that don't have FLOPPY_MAJOR. - -2010-09-25 BVK Chaitanya - - * grub-core/kern/emu/full.c (grub_emu_post_init): Fix typo. - -2010-09-25 BVK Chaitanya - - Fix grub-emu build. - - * grub-core/kern/emu/main.c: Remove #include . - * grub-core/kern/emu/full.c: Split grub_mdraid_{init,fini} into - mdraid09 and mdraid1x. - -2010-09-24 Colin Watson - - Re-enable grub-extras. - - * autogen.sh: Create symlinks to ${GRUB_CONTRIB} if necessary to - avoid confusing Automake. Run autogen only twice, once for the top - level and once for grub-core. Add Makefile.util.def and - Makefile.core.def from extra modules to the appropriate autogen - invocations. If Makefile.common exists in an extra module, include - it in both Makefile.util.am and grub-core/Makefile.core.am; - similarly, include any Makefile.util.common file in Makefile.util.am - and any Makefile.core.common file in grub-core/Makefile.core.am. - * conf/Makefile.common ($(top_srcdir)/grub-core/Makefile.core.am): - Depend on $(top_srcdir)/grub-core/Makefile.gcry.def. - ($(top_srcdir)/grub-core/Makefile.gcry.def): Remove. - * grub-core/Makefile.am: Remove inclusion of Makefile.gcry.am. - - * gentpl.py (gvar_add): Turn GVARS into a set. - (global_variable_initializers): Sort global variables on output. - (vars_init): New function. - (first_time): Likewise. - (library): Ensure that non-global variable initialisations are - emitted before the first time we emit code for a library block. - Append to variables rather than setting them. Only emit - noinst_LIBRARIES, BUILT_SOURCES, and CLEANFILES the first time for - each conditional path. - (program): installdir() emits an Autogen macro, so must be passed to - var_add rather than gvar_add. - (data): Likewise. - (script): Likewise. - (rules): New function, centralising handling for different target - types. Set up Guile association lists for first_time and vars_init, - and send most output to a diversion so that variable initialisations - can be emitted first. - (module_rules): Use new rules function. - (kernel_rules): Likewise. - (image_rules): Likewise. - (library_rules): Likewise. - (program_rules): Likewise. - (script_rules): Likewise. - (data_rules): Likewise. - - * configure.ac: Add AC_PROG_LN_S, for the benefit of ntldr-img. - - * .bzrignore: Add contrib and grub-core/contrib. Remove - grub-core/Makefile.gcry.am. - -2010-09-24 Yves Blusseau - - * grub-core/lib/LzFind.c: Add missing include. - * grub-core/lib/LzmaEnc.c: Likewise. - * grub-core/script/lexer.c: Likewise. - * grub-core/script/yylex.l: Likewise. - * util/grub-macho2img.c: Likewise. - * util/grub-menulst2cfg.c: Likewise. - * util/grub-mklayout.c: Likewise. - * util/grub-mkpasswd-pbkdf2.c - * util/grub-mkrelpath.c: Likewise. - * util/resolve.c: Likewise. - -2010-09-24 BVK Chaitanya - - * Makefile.util.def (example_unit_test): Add - grub-core/gnulib/libgnu.a. - -2010-09-23 GrĂ©goire Sutre - - * grub-core/commands/acpihalt.c (get_sleep_type): Initialize prev. - -2010-09-23 Vladimir Serbinenko - - Support xz compression on yeeloong. - - * Makefile.util.def (grub-mkimage): Add $(LIBLZMA). - * configure.ac: Check for LZMA. - * grub-core/Makefile.core.def (xz_decompress): New target. - (none_decompress): Likewise. - * grub-core/boot/decompressor/minilib.c: New file. - * grub-core/boot/decompressor/none.c: Likewise. - * grub-core/boot/decompressor/xz.c: Likewise. - * grub-core/kern/mips/cache.S: Change to noreorder nomacro. - * grub-core/kern/mips/cache_flush.S: Likewise. - * grub-core/kern/i386/pc/lzma_decode.S: Remove dead code. - * grub-core/kern/mips/startup.S: Move first stage to ... - * grub-core/boot/mips/startup_raw.S: ...here. Change to noreorder - nomacro. - * grub-core/kern/mips/startup.S: Change to noreorder nomacro. - * grub-core/lib/mips/relocator_asm.S: Change to noreorder nomacro. - * grub-core/lib/xzembed/xz_dec_bcj.c [GRUB_EMBED_DECOMPRESSOR]: - Allocate statically. - * grub-core/lib/xzembed/xz_dec_lzma2.c [GRUB_EMBED_DECOMPRESSOR]: - Allocate statically or use scratch. Don't check CRC32. - * grub-core/lib/xzembed/xz_dec_stream.c [GRUB_EMBED_DECOMPRESSOR]: - Allocate statically. Don't check CRC32. - * include/grub/decompressor.h: New file. - * include/grub/offsets.h (GRUB_KERNEL_MIPS_YEELOONG_RAW_SIZE): - Removed. - (GRUB_KERNEL_MIPS_YEELOONG_UNCOMPRESSED_SIZE): New field. - (GRUB_KERNEL_MIPS_YEELOONG_TOTAL_MODULE_SIZE): Adjusted. - (GRUB_KERNEL_MIPS_YEELOONG_PREFIX): Likewise. - (GRUB_KERNEL_MIPS_YEELOONG_PREFIX_END): Likewise. - (GRUB_KERNEL_MACHINE_UNCOMPRESSED_SIZE): New define. - * util/grub-mkimage.c (grub_compression_t): New type. - (PLATFORM_FLAGS_DECOMPRESSORS): New flag. - (image_target_desc): New field default_compression. - (image_targets): Adjust yeeloong targets. - (compress_kernel_xz) [HAVE_LIBLZMA]: New function. - (compress_kernel): New parameter comp. - (generate_image): Likewise. Handle new compression case. - (options): New option --compression - (help): Likewise. - (main): Handle new option. - -2010-09-22 GrĂ©goire Sutre - - * grub-core/kern/emu/hostdisk.c [__NetBSD__]: Define FLOPPY_MAJOR. - -2010-09-22 Colin Watson - - * grub-core/loader/multiboot_mbi2.c (grub_multiboot_make_mbi): Fix - typo in __i386__ conditional. - -2010-09-22 Vladimir Serbinenko - - * grub-core/loader/multiboot_mbi2.c (GRUB_MACHINE_EFI): Add missing - include. - -2010-09-22 Vladimir Serbinenko - - Implement EFI and ACPI multiboot2 extensions. - - * grub-core/loader/multiboot_mbi2.c (grub_multiboot_load): Declare - new tags as supported. - (acpiv2_size): New function. - (grub_multiboot_get_mbi_size): Take new tags into account. - (grub_multiboot_make_mbi): Add new tags. - * include/grub/multiboot.h (GRUB_MACHINE_HAS_ACPI): New definition. - -2010-09-21 AleÅ¡ Nesrsta - - * grub-core/bus/usb/serial/common.c (grub_usbserial_attach): - Added missing configuration of USB device. - -2010-09-21 Colin Watson - - * grub-core/normal/menu_entry.c (run): Make sure we always return - a value. - -2010-09-21 Colin Watson - - * grub-core/commands/efi/lsefimmap.c (grub_cmd_lsefimmap): - NumberOfPages is UINT64 according to the UEFI specification, not - UINTN. Fix printf format. - -2010-09-21 Colin Watson - - * grub-core/bus/usb/usbhub.c (poll_nonroot_hub): Change type of - `err' to grub_usb_err_t. - Reported and tested by: KESHAV P.R. - -2010-09-21 Colin Watson - - * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Make - tpart non-const, so that we can assign to it. (Since this is a - typedef, the constness refers to the pointer rather than what it - points to.) - -2010-09-21 Colin Watson - - * conf/Makefile.common (CPPFLAGS_GNULIB): Add - $(top_srcdir)/grub-core/gnulib as well as - $(top_builddir)/grub-core/gnulib. - Reported by: KESHAV P.R. - -2010-09-21 Colin Watson - - * util/grub-install.in: Fix the bootloader ID option to be - consistently --bootloader-id, not --bootloader_id. - Reported by: KESHAV P.R. - -2010-09-21 Colin Watson - - * grub-core/commands/hashsum.c (GRUB_MOD_INIT): Make "Compute or - check hash checksum." consistently translatable. - -2010-09-21 Yves Blusseau - - * conf/Makefile.common (CPPFLAGS_GNULIB): Replace $(top_srcdir) with - $(top_builddir). - -2010-09-21 Colin Watson - - * grub-core/commands/hashsum.c (aliases): Add sha1sum alias. - (GRUB_MOD_INIT): Register sha1sum command. - (GRUB_MOD_FINI): Unregister sha1sum command. - -2010-09-21 Yves Blusseau - - Keep boot and grub directory names in sync with utils scripts - - * configure.ac: Define GRUB_BOOT_DIR_NAME and GRUB_DIR_NAME macros. - * config.h.in: Add previous macros. - * include/grub/emu/misc.h (DEFAULT_DIRECTORY): Use previous macros. - * util/grub-install.in: Use $bootdir and $grubdir variables. - -2010-09-21 Colin Watson - - * grub-core/kern/emu/hostdisk.c (find_system_device): Only try to - convert partition names to disk names if the new `convert' parameter - is set. - (grub_util_biosdisk_get_grub_dev): If opening the disk device - returns GRUB_ERR_UNKNOWN_DEVICE, treat the partition device as a - disk in its own right. This can happen with Xen disk images. - -2010-09-21 Yves Blusseau - - * util/grub-editenv.c: Update strings to avoid warnings when generating - grub.pot file. - * util/grub-setup.c: Likewise. - -2010-09-21 Vladimir Serbinenko - - * configure.ac: Change version to 1.99~beta0. - -2010-09-21 Vladimir Serbinenko - - * grub-core/loader/i386/multiboot_mbi.c (grub_fill_multiboot_mmap): - Add BADRAM. - * grub-core/loader/multiboot_mbi2.c (grub_fill_multiboot_mmap): - Likewise. - * include/multiboot.h: Resynced with specification. - * include/multiboot2.h: Likewise. - -2010-09-21 Colin Watson - - Fix po directory handling. - - * configure.ac: Create po/Makefile.in rather than po/Makefile. - * grub-core/gnulib/Makefile.am: Import gettext module. - * m4/gnulib-cache.m4: Likewise. - * m4/gnulib-comp.m4: Likewise. - * m4/gettext.m4: New file, from gnulib. - * m4/glibc2.m4: Likewise. - * m4/iconv.m4: Likewise. - * m4/intdiv0.m4: Likewise. - * m4/intl.m4: Likewise. - * m4/intldir.m4: Likewise. - * m4/intlmacosx.m4: Likewise. - * m4/intmax.m4: Likewise. - * m4/inttypes-pri.m4: Likewise. - * m4/lcmessage.m4: Likewise. - * m4/lib-ld.m4: Likewise. - * m4/lib-link.m4: Likewise. - * m4/lib-prefix.m4: Likewise. - * m4/lock.m4: Likewise. - * m4/nls.m4: Likewise. - * m4/po.m4: Likewise. - * m4/printf-posix.m4: Likewise. - * m4/progtest.m4: Likewise. - * m4/threadlib.m4: Likewise. - * m4/uintmax_t.m4: Likewise. - * m4/visibility.m4: Likewise. - * po/Makefile.am: Remove. - * po/Makefile.in.in: New file, from gettext. - ($(DOMAIN).pot-update): Support POTFILES-shell. - * po/Makevars: New file. - * po/POTFILES-shell: Rename to ... - * po/POTFILES-shell.in: ... this. Update. - * po/POTFILES: Rename to ... - * po/POTFILES.in: ... this. Update. - * po/Rules-quot: New file, from gettext. - * po/boldquot.sed: Likewise. - * po/en@boldquot.header: Likewise. - * po/en@quot.header: Likewise. - * po/insert-header.sin: Likewise. - * po/quot.sed: Likewise. - * po/remove-potcdate.sin: Likewise. - -2010-09-20 Vladimir Serbinenko - - * util/grub.d/10_kfreebsd.in (kfreebsd_entry): Use UUID when possible. - -2010-09-20 Vladimir Serbinenko - - * util/grub.d/20_linux_xen.in: Use submenus. - -2010-09-20 Vladimir Serbinenko - - Support submenus. - - * grub-core/commands/menuentry.c (grub_normal_add_menu_entry): New - parameter submenu. All users updated. - * grub-core/normal/main.c (free_menu): Rename to ... - (grub_normal_free_menu): ... this. Made global. - * grub-core/normal/menu.c (grub_menu_execute_entry): Open new context - if requested. - * grub-core/normal/menu_entry.c (screen): New field submenu. - (make_screen): Set submenu. - (run): Open new context if requested. - * include/grub/menu.h (grub_menu_entry): New field submenu. - * include/grub/normal.h (grub_normal_free_menu): New proto. - -2010-09-20 Vladimir Serbinenko - - Menu entries extractor. - - * grub-core/commands/configfile.c (grub_cmd_source): Implement extractor - variants. - (GRUB_MOD_INIT): Register new variants. - (GRUB_MOD_FINI): Unregister new variants. - * grub-core/commands/legacycfg.c (grub_cmd_legacy_configfile): Merge - into grub_cmd_legacy_source. - (grub_cmd_legacy_source): Implement extractor variants. - (GRUB_MOD_INIT): Register new variants. - (GRUB_MOD_FINI): Unregister new variants. - * grub-core/commands/menuentry.c (grub_menu_init): Declare menuentry - as an extractor. - * grub-core/commands/search_wrap.c (GRUB_MOD_INIT): Declare - search as an extractor. - * grub-core/commands/test.c (GRUB_MOD_INIT): Declare - test as an extractor. - * grub-core/kern/corecmd.c (grub_register_core_commands): Declare set - as an extractor. - * grub-core/normal/context.c (grub_env_context_open): Reorganised. - (grub_env_new_context): New function. - (grub_env_context_open): Likewise. - (grub_env_extractor_open): Likewise. - (grub_env_extractor_close): Likewise. - * grub-core/script/execute.c (grub_script_execute_cmdline): Handle - grub_extractor_level. - * include/grub/command.h (GRUB_COMMAND_FLAG_EXTRACTOR): New flag. - * include/grub/env.h (grub_env_extractor_open): New proto. - (grub_env_extractor_close): Likewise. - * include/grub/normal.h (grub_extractor_level): New external variable. - -2010-09-20 Vladimir Serbinenko - - Make cutmem accept a region specification. - Suggested by: Samuel Thibault - - * grub-core/mmap/mmap.c (parsemem): New function. - (grub_cmd_cutmem): Handle new arguments. - -2010-09-20 Vladimir Serbinenko - - New command cutmem. - - * grub-core/mmap/mmap.c (grub_cmd_cutmem): New function. - (GRUB_MOD_INIT): Register new command. - (GRUB_MOD_FINI): Unregister new command. - -2010-09-20 Vladimir Serbinenko - - Support some annoying BSD and Minix subpartitions. - - * Makefile.util.def (libgrub.a): Add grub-core/partmap/bsdlabel.c. - * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): - Properly handle concatenation. - * grub-core/kern/device.c (grub_device_iterate): Likewise. - * grub-core/normal/completion.c (iterate_partition): Likewise. - * grub-core/kern/disk.c (grub_disk_open): Make disk->name not - contain partition. All users updated. - * grub-core/partmap/bsdlabel.c (grub_netbsdlabel_partition_map): New - struct. - (grub_openbsdlabel_partition_map): Likewise. - (bsdlabel_partition_map_iterate): Rename to .. - (iterate_real): ... this. New arguments sector, freebsd and pmap. - (bsdlabel_partition_map_iterate): New function. - (netopenbsdlabel_partition_map_iterate): Likewise. - (netbsdlabel_partition_map_iterate): Likewise. - (openbsdlabel_partition_map_iterate): Likewise. - (GRUB_MOD_INIT): Register new partmaps. - (GRUB_MOD_FINI): Unregister new partmaps. - * grub-core/partmap/msdos.c (pc_partition_map_iterate): Rename to ... - (grub_partition_msdos_iterate): ... this. All users updated. - Don't support embedding other than in a minix partition. - * include/grub/msdos_partition.h (grub_partition_msdos_iterate): New - proto. - * include/grub/partition.h (grub_partition): New field msdostype. - * util/grub-install.in: Handle openbsd and netbsd types being in - part_bsd module. - -2010-09-20 Vladimir Serbinenko - - Split mdraid.mod into mdraid09.mod and mdraid1x.mod. - - * Makefile.util.def (libgrub.a): Add grub-core/disk/mdraid1x_linux.c. - * grub-core/Makefile.core.def (mdraid): Renamed to ... - (mdraid09): ... this. - (mdraid1x): New module. - * grub-core/disk/mdraid_linux.c: Move 1.x parts ... - * grub-core/disk/mdraid1x_linux.c: ...here. All users updated. - -2010-09-20 Vladimir Serbinenko - - * grub-core/kern/emu/misc.c (asprintf): Use vsnprintf instead of - vsprintf. - -2010-09-20 Colin Watson - - * grub-core/commands/efi/lsefimmap.c: Correct header. - * NEWS: Update. - -2010-09-20 Colin Watson - - * util/grub-editenv.c (argp_parser): Don't pass translated strings - as printf format strings; the translations might contain '%' which - could cause a crash. - (main): Likewise. - * util/grub-fstest.c (argp_parser): Likewise. - * util/grub-setup.c (argp_parser): Likewise. - (main): Likewise. - -2010-09-20 Vladimir Serbinenko - - Use argp in grub-fstest. - - * util/grub-fstest.c: Don't include getopt.h. - Include argp.h. - (root): New variable. - (args_count): Likewise. - (nparm): Likewise. - (num_disks): Likewise. - (images): Likewise. - (cmd): Likewise. - (debug_str): Likewise. - (args): Likewise. - (options): Transformed to argp. - (usage): Removed. - (main): Split argument parsing into ... - (argp_parser): ... this. Changed to argp format. - (argp): New variable. - (main): Use argp_parse. - -2010-09-20 Tristan Gingold -2010-09-20 Robert Millan -2010-09-20 Vladimir Serbinenko - - * grub-core/commands/efi/lsefimmap.c: New file. - * grub-core/Makefile.core.def (lsefimmap): New module. - * include/grub/efi/api.h (PRIxGRUB_EFI_UINTN_T): New definition. - -2010-09-20 Vladimir Serbinenko - - Pause the execution (10s max) if any errors are displayed so the user - has a chance to see them. - - * grub-core/kern/err.c (grub_err_printed_errors): New variable. - (grub_print_error): Increment grub_err_printed_errors. - * grub-core/normal/menu.c (grub_menu_execute_entry): Pause the - execution if any errors were displayed. - (show_menu): Remove old code for pause. - * grub-core/normal/menu_entry.c (run): Likewise. - * grub-core/normal/term.c (grub_normal_char_counter): Removed. All - users updated. - (grub_normal_get_char_counter): Likewise. - * include/grub/err.h (grub_err_printed_errors): New external variable. - * include/grub/normal.h (grub_normal_get_char_counter): Removed. - -2010-09-20 Vladimir Serbinenko - - Support multiboot VBE info. - - * grub-core/loader/i386/multiboot_mbi.c (grub_multiboot_get_mbi_size): - Take VBE info into account. - (fill_vbe_info) [GRUB_MACHINE_HAS_VBE]: New function. - (retrieve_video_parameters) [GRUB_MACHINE_HAS_VBE]: - Call fill_vbe_info when appropriate. - (grub_multiboot_make_mbi): Account for the size occupied by VBE info. - * grub-core/loader/multiboot_mbi2.c (grub_multiboot_load): Declare tags - as supported. - (grub_multiboot_get_mbi_size): Take new tags into account. - (fill_vbe_tag) [GRUB_MACHINE_HAS_VBE]: New function. - (retrieve_video_parameters) [GRUB_MACHINE_HAS_VBE]: - Call fill_vbe_tag when appropriate. - (grub_multiboot_make_mbi): Properly align tags. - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_pm_interface): New - function. - * include/grub/i386/pc/vbe.h (grub_vbe_bios_get_pm_interface): New - proto. - * include/grub/multiboot.h (GRUB_MACHINE_HAS_VBE): New definition. - -2010-09-20 Vladimir Serbinenko - - Suport manual terminal geometry specification. - - * grub-core/term/ieee1275/ofconsole.c (grub_ofconsole_dimensions): - Save state in grub_ofconsole_terminfo_output. - (grub_ofconsole_term): Use grub_terminfo_getwh. - (grub_ofconsole_getwh): Removed. - * grub-core/term/serial.c (grub_serial_getwh): Removed. - (grub_serial_term): Use grub_terminfo_getwh. - * grub-core/term/terminfo.c (grub_terminfo_getwh): New function. - (options): New struct. - (OPTION_*): New enum. - (grub_cmd_terminfo): Transform into extcmd and handle new parameters. - * include/grub/terminfo.h (grub_terminfo_output_state): New fields - width and height. - (grub_terminfo_getwh): New proto. - * grub-core/lib/legacy_parse.c (grub_legacy_parse): Handle --lines. - -2010-09-20 Vladimir Serbinenko - - Handle legacy "terminal" command. - - * grub-core/lib/legacy_parse.c (legacy_command): New flags FLAG_TITLE - and FLAG_TERMINAL. - (legacy_commands): Add terminal and title. - (grub_legacy_parse): Handle terminal. Simplify title handling. - -2010-09-20 Vladimir Serbinenko - - * grub-core/lib/arg.c (grub_arg_show_help): Correctly handle - parameters overflow. - -2010-09-20 Colin Watson - - * .bzrignore: Add grub-core/gnulib/sys, widthspec.bin, and - widthspec.h. - - * docs/grub.texi (Shell-like scripting): Document `!'. - (Network): Simplify using new i386-pc-pxe format. Mention - grub-mknetdir. - - * NEWS: Update. - -2010-09-20 Colin Watson - - * Makefile.am (SUBDIRS): Restore "."; it's important to force - ordering, so that e.g. ascii.h is built before grub-core/font/font.c - when needed. - -2010-09-20 Colin Watson - - * grub-core/commands/efi/lsefisystab.c: Correct header. - * grub-core/commands/efi/lssal.c: Likewise. - * grub-core/commands/testload.c: Likewise. - -2010-09-20 Colin Watson - - * util/grub-mkrescue.in: Add explicit root argument to --set to - prevent the UUID being interpreted as an argument to --set (matches - previous change to prepare_grub_to_access_device). - -2010-09-20 Colin Watson - - * kern/emu/hostdisk.c: Include and - on FreeBSD. Define HAVE_DIOCGDINFO on NetBSD and FreeBSD to reduce - the verbosity of later #ifs. - (find_partition_start): Define this function on FreeBSD too. - (device_is_wholedisk) [__FreeBSD__ || __FreeBSD_kernel__]: New - function. - (grub_util_biosdisk_get_grub_dev): Use partition-start-sector logic - on FreeBSD. - -2010-09-20 Yves Blusseau - - * util/grub-editenv.c: Use argp instead of getopt. - -2010-09-20 Yves Blusseau - - * util/grub-setup.c: Use argp instead of getopt. - -2010-09-20 Yves Blusseau - - Use gnulib-tool to create gnulib source files. - - * Add gnulib files generated by gnulib-tool in build-aux, m4 and - grub-core/gnulib directories - * .bzignore: Add **/.deps and autogenerated gnulib files - * configure.ac: Assign auxiliary directory to build-aux, add invocation - of gnulib macros, add grub-core/gnulib/Makefile - * Makefile.am: Add gnulib directory in SUBDIRS (removing unnecessary .), - include m4 directory to aclocal. - * Makefile.util.def: Remove direct compilation of gnulib source files - and use the new grub-core/gnulib/libgnu.a. - * build-aux/config.rpath: move config.rpath from top directory to - build-aux - * conf/Makefile.common: Remove the macro _GL_UNUSED already defined - in gnulib headers - * conf/Makefile.extra-dist: Add m4/gnulib-cache.m4 - * grub-core/Makefile.core.def: Remove unnecessary extra_dist - * grub-core/lib/posix_wrap/localcharset.h (locale_charset): Update - header. - * grub-core/lib/posix_wrap/langinfo.h (nl_langinfo): Return static - string. - -2010-09-20 Yves Blusseau - - * .bzrignore: Add grub-kbdcomp, grub-menulst2cfg, *.marker, - grub-core/genmod.sh and grub-core/gensyminfo.sh - -2010-09-20 BVK Chaitanya - - Add a test for echo command options. - - * tests/grub_cmd_echo.in: New test. - * Makefile.util.def: Rules for new test. - -2010-09-20 Szymon Janc - - Remove crc.mod and move crc command to hashsum.mod. - Remove lib/crc.c - users updated to use gcrypt implementation. - - * grub-core/commands/crc.c: Removed. - * grub-core/Makefile.core.def (crc): Module removed. - * grub-core/commands/hashsum.c (aliases[]): Add crc alias. - * grub-core/commands/hashsum.c (GRUB_MOD_INIT): Register crc command. - * grub-core/commands/hashsum.c (GRUB_MOD_FINI): Unregister crc command. - * grub-core/lib/crc.c: Removed. - * include/grub/lib/crc.h: Removed. - * Makefile.util.def (crc): Remove lib/crc.c - * grub-core/Makefile.core.def (libgrub.a): Remove grub-core/lib/crc.c. - * util/grub-fstest.c (cmd_crd): Use libgcrypt crc implementation. - * Makefile.util.def (libgrub.a): Add grub-core/lib/libgcrypt-grub/cipher/crc.c. - * Makefile.util.def (grub-fstest): Add CFLAGS_GCRY to cflags. - * Makefile.util.def (grub-fstest): Add CPPFLAGS_GCRY to cppflags. - * grub-core/efiemu/prepare.c (grub_efiemu_crc): Use libgcrypt crc implementation. - -2010-09-20 Vladimir Serbinenko - - * grub-core/boot/i386/pc/boot.S: Ignore %dl if it's not in a sane range. - -2010-09-19 Vladimir Serbinenko - - Split config.h for util and core. - - * acinclude.m4 (HAVE_ASM_USCORE): Transformed into a variable. - (ADDR32): Likewise. - (DATA32): Likewise. - (BSS_START_SYMBOL): Likewise. - (END_SYMBOL): Likewise. - (NEED_ENABLE_EXECUTE_STACK): Likewise. All users updated. - (grub_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK): Removed. - * config.h.in: New file. - * configure.ac: Use config-util.h as config define file. - Rename MACHINE into GRUB_MACHINE. All users updated. - (NEED_REGISTER_FRAME_INFO): Transformed into a variable. All users - updated. - (NESTED_FUNC_ATTR): Likewise. - Substitue new variables. - (COND_HAVE_ASM_USCORE): New conditional. - * grub-core/Makefile.am (ASM_PREFIX): New variable. - (kernel_syms.lst): Use ASM_PREFIX. - * grub-core/kern/emu/console.c: Include config-util.h. - * grub-core/kern/emu/misc.c: Likewise. - * grub-core/kern/emu/mm.c: Likewise. - * include/grub/emu/misc.h: Likewise. - * include/grub/libgcc.h: Likewise. - -2010-09-19 Vladimir Serbinenko - - * grub-core/term/efi/console.c (efi_codes): Fix GRUB_TERM_KEY_* - constants usage. - * grub-core/kern/emu/console.c (grub_ncurses_getkey): - Fix GRUB_TERM_KEY_* constants usage. - * grub-core/kern/emu/misc.c (asprintf): Fix vasprintf usage. - -2010-09-19 Vladimir Serbinenko - - * grub-core/bus/usb/ohci.c (grub_ohci_cancel_transfer): Use %p to - print pointer. - * grub-core/bus/usb/uhci.c: Remove empty define. - (grub_uhci_check_transfer): Add missing cast. - * grub-core/bus/usb/usbhub.c (poll_nonroot_hub): Use %p to - print pointer. - * grub-core/term/usb_keyboard.c (grub_usb_keyboard_getkey): Use - PRIuGRUB_SIZE. - * include/grub/types.h (PRIuGRUB_SIZE): New definition. - -2010-09-19 Vladimir Serbinenko - - * grub-core/Makefile.core.def (legacycfg): Add - lib/i386/pc/vesa_modes_table.c on emu. - -2010-09-19 BVK Chaitanya - - Reduce number of temporary files generated by build system. - - * grub-core/gencmdlist.sh: Removed. - * grub-core/genfslist.sh: Removed. - * grub-core/genhandlerlist.sh: Removed. - * grub-core/genmodsrc.sh: Removed. - * grub-core/genpartmaplist.sh: Removed. - * grub-core/genparttoollist.sh: Removed. - * grub-core/gentermiinallist.sh: Removed. - * grub-core/genvideolist.sh: Removed. - - * grub-core/genmod.sh.in: New file. - * grub-core/gensyminfo.sh.in: New file. - - * conf/Makefile.common (CPPFLAGS_*_LIST): New marker flags. - * conf/Makefile.extra-dist: Update with new files. - * gentpl.py: Remove rules related to unnecessary temporary files. - * grub-core/Makefile.am (syminfo.lst): New replacement for def-* - and und-* files. - * grub-core/Makefile.core.def: New rules for gensyminfo.sh and - genmod.sh scripts. - * grub-core/bus/usb/uhci.c: Remove empty #define. - * grub-core/genmoddep.awk: Updated with new syminfo format. - * util/bash-completion.d/Makefile.am: Add config.log to - CLEANFILES. - -2010-09-19 Yves Blusseau - - * Makefile.util.def: Add forgotten $(LIBINTL) library. - -2010-09-19 BVK Chaitanya - - * util/grub-mkconfig.in: Check the config script for syntax errors - before saving. - -2010-09-19 Colin Watson -2010-09-19 Vladimir Serbinenko - - * Makefile.util.def (grub-install): Use util/grub-install.in on all - platforms. - * util/grub-install.in: Add EFI and IEEE1275 support. - * util/i386/efi/grub-install.in: Removed. - * util/ieee1275/grub-install.in: Likewise. - -2010-09-19 Vladimir Serbinenko - - * grub-core/commands/i386/cmostest.c (+parse_args): New function. - (grub_cmd_cmosclean): Likewise. - (GRUB_MOD_INIT): Register command cmosclean. - * util/grub-mkconfig.in: Export GRUB_BUTTON_CMOS_CLEAN. - * util/grub.d/00_header.in: Handle GRUB_BUTTON_CMOS_CLEAN. - -2010-09-18 Carles Pina i Estany -2010-09-18 AleÅ¡ Nesrsta -2010-09-18 Vladimir Serbinenko - - Add keyboard layouts support. - - * Makefile.util.def (grub-mklayout): New file. - (grub-kbdcomp): New script. - * grub-core/Makefile.am (KERNEL_HEADER_FILES) [COND_mips_yeeloong]: - Add keyboard_layouts.h. - * grub-core/Makefile.core.def (kernel): Add commands/keylayouts.c and - commands/boot.c on yeeloong. - (keylayouts): New module. - * grub-core/bus/usb/ohci.c - * grub-core/bus/usb/uhci.c - * grub-core/bus/usb/usbhub.c (rescan): New variable. - (grub_usb_add_hub): Poll interrupt pipe for device handling. - (attach_root_port): Likewise. - (poll_nonroot_hub): Likewise. - (grub_usb_poll_devices): Likewise. - (detach_device): Close transfer. - * grub-core/bus/usb/usbtrans.c (grub_usb_execute_and_wait_transfer): New - function. - (grub_usb_bulk_setup_readwrite): Likewise. - (grub_usb_bulk_finish_readwrite): Likewise. - * grub-core/commands/keylayouts.c: New file. - * grub-core/commands/keystatus.c (grub_getkeystatus): New function. - * grub-core/commands/menuentry.c (hotkey_aliases): All several new - aliases. - * grub-core/term/at_keyboard.c: Restructured to use keylayouts and - support scancode 2. - * grub-core/term/usb_keyboard.c: Restructured to use keylayouts. - * include/grub/keyboard_layouts.h: New file. - * util/grub-mklayout.c: New file. - * util/grub-kbdcomp.in: Likewise. - -2010-09-18 Vladimir Serbinenko - - Unify memory types. - - * grub-core/Makefile.am (KERNEL_HEADER_FILES): Include memory.h. - * grub-core/commands/lsmmap.c (grub_cmd_lsmmap): Output user-readable - types. - * grub-core/kern/i386/multiboot_mmap.c (grub_lower_mem): Removed. - (grub_upper_mem): Likewise. - * grub-core/kern/ieee1275/init.c (grub_upper_mem): Likewise. - * include/grub/memory.h (grub_memory_type_t): New enum. - All users updated. - -2010-09-18 Vladimir Serbinenko - - * grub-core/Makefile.core.def (lsapm): New module. - * grub-core/commands/i386/pc/lsapm.c: New file. - * grub-core/loader/i386/multiboot_mbi.c (make_mbi) [GRUB_MACHINE_PCBIOS]: Pass APM info. - * grub-core/loader/multiboot_mbi2.c (make_mbi) [GRUB_MACHINE_PCBIOS]: - Likewise. - * include/grub/i386/pc/apm.h: New file. - * include/multiboot.h (multiboot_apm_info): New struct. - -2010-09-18 Vladimir Serbinenko - - GRUB-legacy configuration file support. - - * Makefile.util.def (grub-menulst2cfg): New util. - * docs/man/grub-menulst2cfg.h2m: New file. - * grub-core/Makefile.core.def (legacycfg): New module. - * grub-core/commands/legacycfg.c: New file. - * grub-core/commands/menuentry.c (append_menu_entry): Rename to ... - (grub_normal_add_menu_entry): ... this. - * grub-core/commands/password.c (grub_cmd_password): Split main part to ... - (grub_normal_set_password): ...this. - * grub-core/commands/videoinfo.c (grub_cmd_videoinfo): Support MODE. - * grub-core/loader/i386/linux.c (linux_vesafb_res): Move to .., - * grub-core/lib/i386/pc/vesa_modes_table.c: ... here. - * grub-core/lib/legacy_parse.c: New file. - * grub-core/normal/auth.c (grub_cmd_authenticate): New command. - * include/grub/i386/pc/vesa_modes_table.h: New file. - * include/grub/legacy_parse.h: Likewise. - * include/grub/normal.h (grub_normal_add_menu_entry): New proto. - * util/grub-menulst2cfg.c: New file. - -2010-09-17 Colin Watson - - * grub-core/kern/emu/hostdisk.c - (convert_system_partition_to_system_disk): Initialise node. - -2010-09-17 Colin Watson - - * grub-core/kern/emu/hostdisk.c - (convert_system_partition_to_system_disk): Fix devmapper memory pool - leak. - Reported and based on patch by: Modestas Vainius. - -2010-09-17 Colin Watson - - Fix DM-RAID probing with recent versions of device-mapper udev - rules. - - * grub-core/kern/emu/hostdisk.c (read_device_map): Don't - canonicalise device paths under /dev/mapper/. - (convert_system_partition_to_system_disk): Compare the - uncanonicalised path to /dev/mapper/ rather than the canonicalised - path, since device nodes under /dev/mapper/ are often symlinks. - -2010-09-17 Yves Blusseau - - * .bzrignore: *.d removed (old rule), add *.image and symlist.h. - -2010-09-16 Yves Blusseau - - * configure.ac: Avoid some annoying error messages if freetype-config - program is not found. - -2010-09-16 Colin Watson - - Support RAID on virtio devices, and others. - - * grub-core/kern/emu/getroot.c [__MINGW32__] (find_root_device): - Rename to ... - [__MINGW32__] (grub_find_device): ... this. - [! __MINGW32__ && ! __CYGWIN__] (find_root_device): Rename to ... - [! __MINGW32__ && ! __CYGWIN__] (grub_find_device): ... this. Use a - reasonable default if dir is NULL. - [! __MINGW32__ && __CYGWIN__] (find_cygwin_root_device): Rename to - ... - [! __MINGW32__ && __CYGWIN__] (grub_find_device): ... this. - (grub_guess_root_device): Update callers. - * include/grub/emu/getroot.h (grub_find_device): Add prototype. - - * util/raid.c (grub_util_getdiskname): Remove. - (grub_util_raid_getmembers): Use grub_find_device rather than - grub_util_getdiskname. - -2010-09-16 Colin Watson - - * docs/grub.texi (serial): Remove obsolete comment about GRUB - needing to be compiled with serial support. - (ls): Indicate that multiple files are accepted. - * grub-core/commands/ls.c (GRUB_MOD_INIT): Update help text to - indicate that multiple files are accepted. - -2010-09-16 Colin Watson - - * .bzrignore: Add *.1, *.8, grub-shell, grub-shell-tester, - libgrub_a_init.c, and util/bash-completion.d/grub. - -2010-09-15 Vladimir Serbinenko - - * util/grub-setup.c (setup): Fix incorrect container semantics. - -2010-09-15 Vladimir Serbinenko - - * grub-core/commands/parttool.c (grub_cmd_parttool): Fix a variable - misusage. - Reported by: J. Nick Terry - -2010-09-15 Vladimir Serbinenko - - Move embedding routines to partmap sources files. - - * grub-core/partmap/gpt.c (grub_gpt_partition_type_bios_boot) - [GRUB_UTIL]: New variable. - (gpt_partition_map_iterate): Set part.parent. - (gpt_partition_map_embed) [GRUB_UTIL]: New function. - (grub_gpt_partition_map) [GRUB_UTIL]: Set .embed. - * grub-core/partmap/msdos.c (pc_partition_map_embed) [GRUB_UTIL]: - New function. - (grub_msdos_partition_map) [GRUB_UTIL]: Set .embed. - * include/grub/partition.h (grub_embed_type_t) [GRUB_UTIL]: New type. - (grub_partition_map) [GRUB_UTIL]: New field embed. - * util/grub-setup.c (grub_gpt_partition_type_bios_boot): Removed. - (setup): Use ->embed. - -2010-09-15 Vladimir Serbinenko - - * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): New - function. - * include/grub/emu/hostdisk.h (grub_util_biosdisk_is_floppy): New proto. - * util/grub-setup.c (setup): Use grub_util_biosdisk_is_floppy. - -2010-09-15 Yves Blusseau - - Add function to get completions from usage. - - * util/bash-completion.d/grub-completion.bash.in: Add function to get - completions from usage. Use LC_ALL=C to get options properly. - -2010-09-15 Vladimir Serbinenko - - * grub-core/gnulib/basename-lgpl.c: Imported. - * grub-core/gnulib/basename.c: Likewise. - * grub-core/gnulib/dirname-lgpl.c: Likewise. - * grub-core/gnulib/dirname.c: Likewise. - * grub-core/gnulib/dirname.h: Likewise. - * grub-core/gnulib/stripslash.c: Likewise. - -2010-09-15 Vladimir Serbinenko - - * grub-core/gnulib/error.c: Resynced. - * grub-core/gnulib/getopt.c: Likewise. - * grub-core/gnulib/getopt_int.h: Likewise. - * grub-core/gnulib/regex.h: Likewise. - * grub-core/gnulib/regex_internal.c: Likewise. - * grub-core/gnulib/regex_internal.h: Likewise. - -2010-09-15 Szymon Janc - - * grub-core/lib/xzembed/xz_dec_stream.c (dec_main): Fix index and block - CRC calculations and validity checks. - * grub-core/lib/xzembed/xz_dec_stream.c (dec_index): Fix index CRC - calculations. - -2010-09-15 Szymon Janc - - * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_end): Fix memory leak. - -2010-09-14 Vladimir Serbinenko - - Fix incorrect echo options handling. - Reported by: Yves Blusseau. - - * include/grub/command.h (grub_command_flags_t): New flags - GRUB_COMMAND_ACCEPT_DASH and GRUB_COMMAND_OPTIONS_AT_START. - * grub-core/lib/arg.c (grub_arg_parse): Handle new flags. - * grub-core/commands/echo.c (GRUB_MOD_INIT): Use new flags. - -2010-09-14 Vladimir Serbinenko - - * include/grub/command.h (GRUB_COMMAND_FLAG_CMDLINE): Removed. All - users updated. - (GRUB_COMMAND_FLAG_MENU): Likewise. - (GRUB_COMMAND_FLAG_BOTH): Likewise. - (GRUB_COMMAND_FLAG_TITLE): Removed. - (GRUB_COMMAND_FLAG_NO_ECHO): Likewise. - (GRUB_COMMAND_FLAG_EXTCMD): Moved into enum. - (GRUB_COMMAND_FLAG_DYNCMD): Likewise. - (GRUB_COMMAND_FLAG_BLOCKS): Likewise. - (grub_command_flags_t): New enum. All users updated. - -2010-09-14 Seth Goldberg - - Fix solaris compilation. - - * grub-core/Makefile.core.def (kernel): Include gnulib/error.c on emu. - (grub-emu): Add LIBZFS and LIBNVPAIR to ldadd. - (grub-emu-list): Likewise. - -2010-09-14 Vladimir Serbinenko - - Remove deprecated root command. - - * grub-core/commands/minicmd.c (grub_mini_cmd_root): Removed. All users - updated. - -2010-09-14 Vladimir Serbinenko - - * util/i386/pc/grub-setup.c: Merge this ... - * util/sparc64/ieee1275/grub-setup.c: ... and this ... - * util/grub-setup.c: ... into this. - * include/grub/sparc64/ieee1275/boot.h (grub_boot_blocklist) [ASM_FILE]: - New struct. - -2010-09-14 Vladimir Serbinenko - - * grub-core/fs/ext2.c (grub_ext2_open): Use return error value when - possible. - -2010-09-14 Vladimir Serbinenko - - * grub-core/partmap/sun.c (sun_partition_map_iterate): Don't needlesly - allocate p. - -2010-09-14 Vladimir Serbinenko - - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Add - explicit root argument to set to prevent UUID to be interpreted as - argument to set. - -2010-09-14 Vladimir Serbinenko - - * grub-core/kern/sparc64/ieee1275/crt0.S: Align stack. - -2010-09-14 Vladimir Serbinenko - - Don't export grub_gate_a20. - - * grub-core/kern/i386/pc/init.c: Remove leftovers. - * grub-core/kern/i386/pc/startup.S (FUNCTION(grub_gate_a20)): Rename - to ... - (grub_gate_a20): ... this. All users updated. - * include/grub/i386/pc/init.h: Removed. All users updated. - -2010-09-14 Vladimir Serbinenko - - Create euro.pf2 which supports most European languages. - - * Makefile.am (grubdata_DATA): Add euro.pf2. - (euro.pf2): New target. - (CLEANFILES): Add euro.pf2. - -2010-09-14 Vladimir Serbinenko - - * configure.ac: Disable emu-usb by default to prevent inadvertent - device takeover. - -2010-09-13 Vladimir Serbinenko - - Disable usbserial on grub-emu since our libusb code isn't good enough - yet. - - * grub-core/Makefile.core.def (usbserial_common): Disable on emu. - (usbserial_pl2303): Likewise. - (usbserial_ftdi): Likewise. - -2010-09-13 Vladimir Serbinenko - - * include/grub/disk.h (grub_disk): Remove has_partitions. - All users updated. - * disk/loopback.c (grub_loopback): Remove has_partitions. - All users updated. - (options): Remove partitions. All users updated. - * util/grub-fstest.c (fstest): Don't pass "-p" to loopback. - * util/i386/pc/grub-setup.c (setup): copy partition table only when - actual partition table is found. - -2010-09-13 Vladimir Serbinenko - - Remove readability checks (too many false negatives). - - * util/grub-install.in: Remove readability checks. - * util/grub-mkconfig.in: Likewise. - * util/grub.d/10_hurd.in: Likewise. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Revert to old - way. - -2010-09-13 Vladimir Serbinenko - - Enable acpi shutdown on all ACPI platforms. - - * grub-core/Makefile.core.def (halt): Inlude commands/acpihalt.c - on coreboo, multiboot and EFI. - * grub-core/commands/acpihalt.c (get_sleep_type): Add missing casts. - (grub_acpi_halt): Likewise. - * grub-core/commands/i386/pc/halt.c (grub_halt): Call grub_acpi_halt. - (grub_cmd_halt): Don't call grub_acpi_halt directly. - * grub-core/lib/efi/halt.c (grub_halt): Call grub_acpi_halt. - * grub-core/lib/i386/halt.c (grub_halt) - [GRUB_MACHINE_COREBOOT || GRUB_MACHINE_MULTIBOOT]: Likewise. - -2010-09-13 Vladimir Serbinenko - - * grub-core/commands/iorw.c (grub_cmd_read): Declare buf in smallest - context. - -2010-09-13 Vladimir Serbinenko - - * grub-core/video/efi_gop.c: Fix over-80-chars line. - * grub-core/video/efi_uga.c: Likewise. - -2010-09-13 Vladimir Serbinenko - - Filter devaliases and never open same device twice. - - * grub-core/disk/ieee1275/ofdisk.c (last_devpath): New variable. - (last_ihandle): Likewise. - (ofdisk_hash_ent): New member shortest. - (ofdisk_hash_add): Add canonical path too. - (scan): New function. - (grub_ofdisk_iterate): Iterate over hashed entries. - (compute_dev_path): Don't add :0. - (grub_ofdisk_open): Don't really open the disk. - (grub_ofdisk_close): Avoid closing unrelated disk. - (grub_ofdisk_read): Implement reopen logic. - * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_canonicalise_devname): - New function. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_canonicalise_devname): - New proto. - -2010-09-13 Vladimir Serbinenko - - Fix sparc64. - - * configure.ac (GRUB_KERNEL_MACHINE_LINK_ADDR): Removed. - * grub-core/Makefile.core.def (kernel): Make ldflags just use the - right address. Add sparc64_ieee1275_ldflags. - * grub-core/loader/sparc64/ieee1275/linux.c: Remove leftover include. - * util/grub-mkimagexx.c (locate_sections): Correct grub_host_to_target32 - to grub_host_to_target_addr - (load_image): Likewise. - -2010-09-13 Vladimir Serbinenko - - * grub-core/normal/completion.c (complete_file): Handle device - containing slash. - Fix based on patch by Doug Nazar. - -2010-09-13 Vladimir Serbinenko - - grub-mknetdir script. - - * Makefile.util.def (grub-mknetdir): New module. - * tests/util/grub-shell.in: Support boot=net - * util/grub-mknetdir.in: New file. - -2010-09-13 Vladimir Serbinenko - - videoinfo on non-vbe. - - * grub-core/Makefile.core.def (vbeinfo): Removed. - (vbetest): Removed. - (videoinfo): New module. - * grub-core/commands/i386/pc/vbeinfo.c: Removed. - * grub-core/commands/i386/pc/vbetest.c: Removed. - * grub-core/commands/videoinfo.c: New file. - * grub-core/commands/videotest.c (grub_cmd_videotest): Support mode - specification. - (grub_cmd_videotest) [GRUB_MACHINE_PCBIOS]: Load vbe.mod when invoked - as vbetest. - (GRUB_MOD_INIT) [GRUB_MACHINE_PCBIOS]: New command vbetest. - (GRUB_MOD_FINI) [GRUB_MACHINE_PCBIOS]: Unregister vbetest. - * grub-core/video/efi_gop.c (grub_video_gop_fill_mode_info): Fill - mode_number. New parameter mode. All users updated. - (grub_video_gop_iterate): New function. - (grub_video_efi_gop): New member iterate. - * grub-core/video/i386/pc/vbe.c (framebuffer): Removed leftover fields. - (grub_vbe_set_video_mode): Remove setting useless fields. - (vbe2videoinfo): New function. - (grub_video_vbe_iterate): Likewise. - (grub_video_vbe_setup): Use vbe2videoinfo. - (grub_video_vbe_print_adapter_specific_info): New function. - (grub_video_vbe_adapter): New fields iterate and - print_adapter_specific_info. - * include/grub/video.h (GRUB_VIDEO_MODE_*): Transform into enum. - All users updated. - (grub_video_mode_info): New field mode_number. - (grub_video_adapter): New fields iterate and - print_adapter_specific_info. - -2010-09-13 Tristan Gingold -2010-09-13 Robert Millan -2010-09-13 Vladimir Serbinenko - - * grub-core/commands/efi/lsefisystab.c: New file. - * grub-core/commands/efi/lssal.c: Likewise. - * grub-core/Makefile.core.def (lsacpi): New module. - (lsefisystab): Likewise. - * include/grub/efi/api.h (GRUB_EFI_SAL_TABLE_GUID): New definition. - (GRUB_EFI_HCDP_TABLE_GUID): Likewise. - (grub_efi_sal_system_table): New struct. - (grub_efi_sal_system_table_entrypoint_descriptor): Likewise. - (grub_efi_sal_system_table_memory_descriptor): Likewise. - (grub_efi_sal_system_table_platform_features): Likewise. - (grub_efi_sal_system_table_translation_register_descriptor): Likewise. - (grub_efi_sal_system_table_purge_translation_coherence): Likewise. - (grub_efi_sal_system_table_ap_wakeup): Likewise. - * include/grub/types.h (PRIuGRUB_UINT64_T): New definition. - -2010-09-13 Vladimir Serbinenko - - Support explicit user claim that a device is BIOS-visible. - - * grub-core/kern/emu/getroot.c (grub_util_get_dev_abstraction): - Return GRUB_DEV_ABSTRACTION_NONE if device is in device.map. - * grub-core/kern/emu/hostdisk.c - (convert_system_partition_to_system_disk): Support mdX. - (find_system_device): New parameter add. All users updated. - (grub_util_biosdisk_is_present): New function. - * include/grub/emu/hostdisk.h (grub_util_biosdisk_is_present): New - proto. - -2010-09-13 Vladimir Serbinenko - - Search hints support. - - * commands/search.c (FUNC_NAME): New arguments hints and nhints. - All users updated. - -2010-09-13 Yves Blusseau - - Bash completion script for util commands - - * Makefile.am: Add util/bash-completion.d directory - * configure.ac: Likewise. - * util/bash-completion.d/Makefile.am: New file. - * util/bash-completion.d/grub-completion.bash.in: Likewise. - -2010-09-12 Vladimir Serbinenko - - * grub-core/normal/term.c (put_glyphs_terminal): Correct sign. - (print_backlog): set backlog_ucs4 and backlog_glyphs. - Reported by: Yves Blusseau. - -2010-09-12 Vladimir Serbinenko - - * grub-core/normal/misc.c (grub_normal_print_device_info): Show - partition size and offset. - -2010-09-12 Vladimir Serbinenko - - * grub-core/commands/wildcard.c (make_regex): Escape brackets. - -2010-09-12 Vladimir Serbinenko - - * grub-core/commands/ls.c (grub_cmd_ls): Accept multiple files. - -2010-09-12 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_vprintf): Use va_copy when necessary. - (grub_xvasprintf): Likewise. - -2010-09-12 Vladimir Serbinenko - - * grub-core/kern/emu/main.c (main): Call hostfs_init only after init_all. - -2010-09-12 Vladimir Serbinenko - - * grub-core/commands/menuentry.c (append_menu_entry): Don't rely on - args ending with NULL. - -2010-09-12 Vladimir Serbinenko - - * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_reset): Preserve context - pointer. - -2010-09-11 Szymon Janc - - * grub-core/commands/lsacpi.c (grub_cmd_lsacpi): Fix prototype. - -2010-09-11 Vladimir Serbinenko - - Shutdown using ACPI. - - * grub-core/Makefile.core.def (halt): Add commands/acpihalt.c on i386-pc. - * grub-core/commands/acpihalt.c: New file. - * grub-core/commands/i386/pc/halt.c (grub_cmd_halt): Call grub_acpi_halt. - * include/grub/acpi.h (grub_acpi_fadt): New member pm1a. - (grub_acpi_halt): New proto. - (GRUB_ACPI_SLP_EN): New const. - (GRUB_ACPI_SLP_TYP_OFFSET): Likewise. - (GRUB_ACPI_OPCODE_*): New enum. - (GRUB_ACPI_EXTOPCODE_*): Likewise. - -2010-09-11 Tristan Gingold -2010-09-11 Robert Millan -2010-09-11 Vladimir Serbinenko - - * commands/lsacpi.c: New file. - * grub-core/Makefile.core.def (lsacpi): New module. - * include/grub/acpi.h (GRUB_ACPI_FADT_SIGNATURE): New definition. - (GRUB_ACPI_MADT_SIGNATURE): Likewise. - (grub_acpi_madt_entry_header): New struct. - (grub_acpi_madt): Likewise. - (grub_acpi_madt_entry_interrupt_override): Likewise. - (grub_acpi_madt_entry_sapic): Likewise. - (grub_acpi_madt_entry_lsapic): Likewise. - (grub_acpi_madt_entry_platform_int_source): Likewise. - * include/grub/types.h (PRIxGRUB_UINT32_T): New definition. - (PRIuGRUB_UINT32_T): Likewise. - (PRIxGRUB_UINT64_T): Likewise. - -2010-09-11 Vladimir Serbinenko - - Implement loading palette on ieee1275_fb. - - * grub-core/video/ieee1275.c (stdout_ihandle): New variable. - (have_setcolors): Likewise. - (grub_video_ieee1275_init): Fill stdout_ihandle and have_setcolors. - (grub_video_ieee1275_setup): Use grub_video_ieee1275_set_palette. - (grub_video_ieee1275_set_palette): Implement. - -2010-09-11 Vladimir Serbinenko -2010-09-11 Colin Watson - - * util/grub-install.in (grub_partition): New variable. - Set prefix_drive on EFI and PC to (,$grub_partition) as last resort. - * util/i386/pc/grub-setup.c (setup): Don't touch prefix. - Fixes a bug reported by Yves Blusseau. - -2010-09-11 Vladimir Serbinenko - - Fix emu on mipsel. - - * conf/Makefile.common (CFLAGS_PLATFORM): Add -mflush-func - =grub_cpu_flush_cache on all mips and not only yeeloong. - * configure.ac (COND_mips): New conditional. - * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add libgcc on all - platforms. - * grub-core/kern/emu/cache.S (__mips__): Use _flush_cache. - * grub-core/kern/emu/full.c (grub_arch_dl_init_linker) - [GRUB_LINKER_HAVE_INIT]: New function. - (grub_emu_post_init): Likewise. - * grub-core/kern/emu/lite.c (grub_emu_post_init): Likewise. - * grub-core/kern/emu/main.c: Use grub_emu_post_init. - * include/grub/cache.h (_mips): Include mips/cache.h. - * include/grub/disk.h [GRUB_UTIL || GRUB_MACHINE_EMU]: Add missing - LVM and RAID prototypes. - * include/grub/emu/misc.h (grub_emu_post_init): New proto. - * include/grub/mips/time.h (grub_cpu_idle) [GRUB_MACHINE_EMU]: New - function. - -2010-09-10 Colin Watson - - * util/grub-install.in: Don't try to verify core.img until after - running grub-mkimage to create it. - -2010-09-10 Robert Millan - - * util/grub.d/10_hurd.in: Add misc readability checks. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - -2010-09-10 Colin Watson - - * util/grub-install.in: ${imgext} won't be defined here until the - install branch is merged. For the meantime, only verify core.img on - i386-pc and sparc64-ieee1275 platforms. - -2010-09-10 Robert Millan - - Solaris support in grub_find_zpool_from_dir(). Thanks - Seth Goldberg for referring to getextmntent() facility. - - * configure.ac: Check for getextmntent(), `sys/mnttab.h' and - `sys/mkdev.h'. - * grub-core/kern/emu/misc.c [HAVE_SYS_MNTTAB_H]: Include - `'. - [HAVE_SYS_MKDEV_H]: Include `'. - [HAVE_GETEXTMNTENT] (grub_find_zpool_from_dir): Add getextmntent() - method for finding zpool name. - -2010-09-10 Colin Watson - - grub-fstest needs the host and hostfs modules while other utilities - actively require those modules to be absent, so grub-fstest needs - its own initialisation and finalisation code. - - * Makefile.am (grub_fstest.pp): New target. - (grub_fstest_init.lst): Likewise. - (grub_fstest_init.c): Likewise. - * Makefile.util.def (grub-fstest): Add grub_fstest_init.c. - -2010-09-10 Robert Millan - - * configure.ac: Check for `struct statfs.f_fstypename' and - `struct statfs.f_mntfromname'. - - * grub-core/kern/emu/misc.c (grub_find_zpool_from_dir): Conditionalize - kFreeBSD-specific code. - -2010-09-10 Robert Millan - - * util/grub.d/10_kfreebsd.in: Fix ${kfreebsd_device} initialization - on ZFS. Now non-main filesystems are supported as / too. - -2010-09-09 Colin Watson - - * Makefile.util.def (libgrub.a): Move grub-core/kern/emu/hostfs.c - and grub-core/disk/host.c to ... - (grub-fstest): ... here. Having the host disk implementation - present confuses grub-probe and other utility programs. - - * util/grub-mkconfig.in: Only verify readability of grub.cfg.new - when writing to a file, not when writing to stdout. - -2010-09-09 BVK Chaitanya - - * tests/partmap_test.in: New test for partitions. - * Makefile.util.def: Rules for new test. - -2010-09-09 Robert Millan - - * util/grub-probe.c (probe): Fix a pair of unhandled error - conditions. - -2010-09-09 Robert Millan - - Basic Btrfs support (detection and UUID). - - * grub-core/fs/btrfs.c: New file. - * Makefile.util.def (library): Register btrfs.c. - * grub-core/Makefile.core.def: Likewise. - -2010-09-08 Robert Millan - - * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Improve - with (optional) parameters to specify device and relative path. - * util/grub-install.in: Use is_path_readable_by_grub() to - verify readability of a few critical files. - * util/grub-mkconfig.in: Use is_path_readable_by_grub() to - verify readability of grub.cfg.new. - -2010-09-08 Vladimir Serbinenko - - Split minix.mod into minix.mod and minix2.mod. - - * Makefile.util.def (libgrub.a): Add grub-core/fs/minix2.c. - * grub-core/Makefile.core.def (minix2): New module. - * grub-core/fs/minix.c: Use definitions instead of runtime version - checking. - * grub-core/fs/minix2.c: New file. - -2010-09-08 Yves Blusseau - - Add new --boot-directory option to replace --root-directory - - * util/grub-install.in: Add new --boot-directory option - * util/grub-reboot.in: Likewise. - * util/grub-set-default.in: Likewise. - -2010-09-08 Yves Blusseau - - * util/grub-mkconfig.in: Use new variable. - -2010-09-08 Yves Blusseau - - * configure.ac: Define some useful variables. - -2010-09-08 Vladimir Serbinenko - - * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set - GRUB_IEEE1275_FLAG_HAS_CURSORONOFF when appropriate. - * grub-core/term/ieee1275/ofconsole.c (grub_ofconsole_setcursor): - Use terminfo and don't use cursor-on/cursor-off unless it's known - to work. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New element - GRUB_IEEE1275_FLAG_HAS_CURSORONOFF. - -2010-09-08 Colin Watson - - * grub-core/kern/efi/init.c (grub_efi_set_prefix): If the prefix - starts with "(,", fill the drive containing the loaded image in - between those two characters, but expect that a full partition - specification including partition map names will follow. - -2010-09-08 Robert Millan - - * configure.ac: Remove `--enable-grub-fstest' option. - * Makefile.util.def (grub-fstest): Remove COND_GRUB_FSTEST condition. - - * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Use - `grub-fstest' instead of `grub-probe' for readability verification. - * util/grub-probe.c (probe): Remove readability verification kludge. - -2010-09-08 Robert Millan - - * util/grub-mkconfig.in: Pass `--device ${GRUB_DEVICE}' when - initializing `GRUB_FS'. - -2010-09-08 BVK Chaitanya - - Not command (!) support to GRUB script. - - * tests/grub_script_not.in: New test. - * Makefile.util.def: Rules for new test. - - * grub-core/script/execute.c (grub_script_execute_cmdline): Handle - ! command as a special case. - * grub-core/script/yylex.l (GRUB_PARSER_TOKEN_NOT): Removed. - -2010-09-07 BVK Chaitanya - - * grub-core/commands/wildcard.c (wildcard_expand): Fix wrong - grub_free. - -2010-09-07 BVK Chaitanya - - * docs/grub.texi (Shell-like scripting): Fix @dots to @dots{}. - -2010-09-07 BVK Chaitanya - - * docs/grub.texi (Shell-like scripting): Documentation for break, - continue, shift and return commands. - -2010-09-06 Vladimir Serbinenko - - Rename CD-ROM to cd on BIOS. - - * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_get_drive): Recognise - "cd". - (grub_biosdisk_call_hook): Call with "cd" instead of arbitrary hdX. - -2010-09-05 Vladimir Serbinenko - - * grub-core/kern/emu/main.c (main): Reinit LVM and RAID. - * util/grub-probe.c (main): Likewise. - * util/i386/pc/grub-setup.c (main): Likewise. - * util/sparc64/ieee1275/grub-setup.c (main): Likewise. - Reported and debugged by: alexxy - -2010-09-05 Vladimir Serbinenko - - * grub-core/disk/lvm.c (grub_lvm_scan_device) [GRUB_UTIL]: Output more - diagnostic info. - -2010-09-05 Jo Shields - - * util/grub.d/30_os-prober.in: Add missing classes. - -2010-09-05 Vladimir Serbinenko - - * docs/grub.texi (Theme file format): Document new position format. - -2010-09-05 Vladimir Serbinenko - - * docs/grub.texi (Theme file format): Replace Box_slice_names.png with - a table. Use @code instead of @verbatim. - -2010-09-05 Colin D Bennett - - Gfxmenu documentation. - - * docs/grub.texi (Theme file format): New chapter. - -2010-09-05 Szymon Janc - - * grub-core/Makefile.core.def (xzio): New module. - * grub-core/io/xzio.c: New file. - * grub-core/lib/xzembed/xz.h: New file (from xembed). - * grub-core/lib/xzembed/xz_config.h: Likewise. - * grub-core/lib/xzembed/xz_dec_bcj.c: Likewise. - * grub-core/lib/xzembed/xz_dec_lzma2.c: Likewise. - * grub-core/lib/xzembed/xz_dec_stream.c: Likewise. - * grub-core/lib/xzembed/xz_lzma2.h: Likewise. - * grub-core/lib/xzembed/xz_private.h: Likewise. - * grub-core/lib/xzembed/xz_stream.h: Likewise. - * include/grub/file.h (grub_file_filter_id): New compression filter - GRUB_FILE_FILTER_XZIO. - -2010-09-05 Vladimir Serbinenko - - * include/grub/file.h (GRUB_FILE_SIZE_UNKNOWN): New definition. - * grub-core/disk/loopback.c (grub_loopback_open): Handle unknown file - size. - -2010-09-05 Vladimir Serbinenko - - * include/grub/err.h (grub_err_t): Replace GRUB_ERR_BAD_GZIP_DATA with - GRUB_ERR_BAD_COMPRESSED_DATA. All users updated. - -2010-09-05 Vladimir Serbinenko - - Uncompressed checksum support. - - * grub-core/commands/hashsum.c (options): Add option --uncompress. - (check_list): New parameter uncompress. - (grub_cmd_hashsum): Handle --uncompress. - -2010-09-05 Vladimir Serbinenko - - Reintroduce testload. - - * grub-core/commands/minicmd.c (grub_rescue_cmd_testload) [0]: Moved - from here ... - * grub-core/commands/testload.c (grub_cmd_testload): ... here. - (GRUB_MOD_INIT): New function. - (GRUB_MOD_FINI): Likewise. - * grub-core/Makefile.core.def (testload): New module. - -2010-09-05 Szymon Janc - - * grub-core/lib/posix_wrap/sys/types.h (bool): Transform into an enum. - (uint8_t): New type. - (uint16_t): Likewise. - (uint32_t): Likewise. - (uint64_t): Likewise. - -2010-09-05 Szymon Janc - - * include/grub/crypto.h (GRUB_MD_CRC32): New definition. - -2010-09-05 Vladimir Serbinenko - - * grub-core/io/gzio.c (grub_gzio_open): Removed "transparent" parameter. - Made static. - (grub_gzfile_open): Removed. All users updated. - (GRUB_MOD_INIT): New function. - (GRUB_MOD_FINI): Likewise. - * grub-core/kern/file.c (grub_file_filters_all): New variable. - (grub_file_filters_enabled): Likewise. - (grub_file_open): Handle filters. - * grub-core/loader/i386/bsd.c (GRUB_MOD_INIT): Load gzio. - * grub-core/normal/main.c (GRUB_MOD_INIT): Likewise. - * include/grub/file.h (grub_file_filter_id_t): New type. - (grub_file_filter_t): Likewise. - (grub_file_filters_all): New extern variable. - (grub_file_filters_enabled): Likewise. - (grub_file_filter_register): New inline function. - (grub_file_filter_unregister): Likewise. - (grub_file_filter_disable): Likewise. - (grub_file_filter_disable_compression): Likewise. - * include/grub/gzio.h: Removed. - -2010-09-04 BVK Chaitanya - - Filename expansion support for wildcards in GRUB script. - - * tests/grub_script_expansion.in: New test. - * Makefile.util.def: Rule for new test. - - * grub-core/commands/wildcard.c: New file, implements filename - expansion support for GRUB script. - * grub-core/Makefile.core.def: Rule update for regexp.mod. - * grub-core/script/argv.c: Cosmetic changes. - * grub-core/script/execute.c (grub_script_arglist_to_argv): - Refactored to perform wildcard expansion on arguments. - * include/grub/script_sh.h (grub_script_wildcard_translator): New - struct. - - * tests/util/grub-shell.in: Fix quoting for read input. - -2010-09-04 BVK Chaitanya - - Support for updating environment variables with matched substrings - of regexp. - - * tests/grub_cmd_regexp.in: New test. - * Makefile.util.def: Rule for new test. - - * grub-core/commands/regexp.c: New option -s to update environment - variables with regexp matches. - -2010-09-04 Szymon Janc - - * include/grub/file.h (grub_file): New member not_easly_seekable. - (grub_file_seekable): New inline function. - * grub-core/io/gzio.c (test_header): Don't test end magic if file isn't - easily seekable. - (grub_gzio_open): Set not_easly_seekable. - * grub-core/fs/i386/pc/pxe.c (grub_pxefs_open): Set not_easily_seekable. - * grub-core/io/bufio.c (grub_bufio_open): Propagate not_easily_seekable. - -2010-09-04 BVK Chaitanya - - Support for options to appear multiple times on cmdline. - - * include/grub/lib/arg.h (grub_arg_list_alloc): New prototype. - * grub-core/commands/extcmd.c: Support for repeatable option. - * grub-core/lib/arg.c (grub_arg_list_alloc): New function for - repeatable option support. - - Refactor menuentry into a regular command. - - * grub-core/commands/menuentry.c: New file, menuentry command - implementation. - * grub-core/Makefile.core.def: Rule update for normal.mod. - * grub-core/normal/main.c: Moved menuentry creation to - grub-core/commands/menuentry.c. - * grub-core/normal/menu.c (grub_menu_execute_entry): Removed. - (grub_menu_execute_entry_real): Removed. - * grub-core/script/execute.c (grub_script_execute_sourcecode): New - function. - (grub_script_execute_menuentry): Removed. - * grub-core/script/parser.y (menuentry): Removed. - * grub-core/script/script.c (grub_script_create_cmdmenu): Removed. - * grub-core/script/yylex.l (menuentry): Removed. - * include/grub/menu.h (grub_menu_init): New prototype. - (grub_menu_fini): New prototype. - * include/grub/normal.h (grub_normal_add_menu_entry): Removed. - * include/grub/script_sh.h (grub_script_cmd_menuentry): Removed. - (grub_script_execute_sourcecode): New prototype. - -2010-09-04 BVK Chaitanya - - "return" command for GRUB script functions. - - * tests/grub_script_return.in: New test. - * Makefile.util.def: Rules for new test. - - * grub-core/script/execute.c (grub_script_return): New function. - * grub-core/script/main.c: Register/unregister return commaond. - * include/grub/script_sh.h (grub_script_return): New prototype. - -2010-09-04 BVK Chaitanya - - "setparams" command to update positional parameters. - - * tests/grub_script_setparams.in: New test. - * Makefile.util.def: Rules for new test. - - * grub-core/script/argv.c (grub_script_argv_make): New function. - * grub-core/script/execute.c (replace_scope): New function. - (grub_script_setparams): New function. - * grub-core/script/lexer.c: Remove unused variables. - * grub-core/script/main.c: Register/unregister setparams command. - * include/grub/script_sh.h (grub_script_argv_make): New prototype. - (grub_script_setparams): New prototype. - -2010-09-04 BVK Chaitanya - - * grub-core/normal/completion.c (grub_normal_do_completion): Fix - grub_free order. - -2010-09-04 BVK Chaitanya - - Support for passing block of commands as an argument to extcmds. - - * Makefile.util.def: Rules for new test. - * tests/grub_script_blockarg.in: New test. - * grub-core/tests/test_blockarg.c: New file, block argument - command used in the test. - - * include/grub/extcmd.h (grub_extcmd_context): New struct. - (grub_register_extcmd_prio): New function prototype. - (grub_extcmd_dispatcher): New function prototype. - * include/grub/command.h (GRUB_COMMAND_FLAG_BLOCKS): New command - type. - * include/grub/script_sh.h (struct grub_script): New members - `children', `next_siblings' and `refcnt' for block arguments and - reference counting. - (GRUB_SCRIPT_ARG_TYPE_BLOCK): New argument type. - (grub_script_arg): New member `script' for block argument. - (grub_script_argv): New member `script' for block argument. - (grub_parser_param): New member `scripts' for block argument. - (grub_script_mem_free): New extern function prototype. - (grub_script_ref): New function prototype. - (grub_script_unref): New function prototype. - - * grub-core/normal/dyncmd.c (grub_dyncmd_dispatcher): Moved to - extcmd form to support block arguments. - * grub-core/script/argv.c: Block arguments support. - * grub-core/script/execute.c: Likewise. - * grub-core/script/lexer.c: Likewise. - * grub-core/script/main.c: Likewise. - * grub-core/script/script.c: Likewise. - * grub-core/script/parser.y: Likewise. New `block' and `block0' - non-terminals. - - * grub-core/commands/acpi.c: Update extcmd implementations with - grub_extcmd_context_t. - * grub-core/commands/cat.c: Likewise. - * grub-core/commands/echo.c: Likewise. - * grub-core/commands/extcmd.c: Likewise. - * grub-core/commands/hashsum.c: Likewise. - * grub-core/commands/hdparm.c: Likewise. - * grub-core/commands/help.c: Likewise. - * grub-core/commands/hexdump.c: Likewise. - * grub-core/commands/i386/cpuid.c: Likewise. - * grub-core/commands/i386/pc/drivemap.c: Likewise. - * grub-core/commands/i386/pc/halt.c: Likewise. - * grub-core/commands/i386/pc/sendkey.c: Likewise. - * grub-core/commands/iorw.c: Likewise. - * grub-core/commands/keystatus.c: Likewise. - * grub-core/commands/loadenv.c: Likewise. - * grub-core/commands/ls.c: Likewise. - * grub-core/commands/lspci.c: Likewise. - * grub-core/commands/memrw.c: Likewise. - * grub-core/commands/probe.c: Likewise. - * grub-core/commands/search_wrap.c: Likewise. - * grub-core/commands/setpci.c: Likewise. - * grub-core/commands/sleep.c: Likewise. - * grub-core/disk/loopback.c: Likewise. - * grub-core/hello/hello.c: Likewise. - * grub-core/loader/i386/bsd.c: Likewise. - * grub-core/loader/xnu.c: Likewise. - * grub-core/term/gfxterm.c: Likewise. - * grub-core/term/serial.c: Likewise. - * grub-core/tests/lib/functional_test.c: Likewise. - -2010-09-04 BVK Chaitanya - - Multi-line quoted strings support. - - * grub-core/script/lexer.c (append_newline): Removed. - (grub_script_lexer_yywrap): Refactored. - (grub_script_lexer_init): Refactored. - * grub-core/script/yylex.l (yywrap): New function. - (grub_lexer_resplit): New function. - (grub_lexer_unput): New function. - * include/grub/script_sh.h (grub_lexer_param): New members, unput - and resplit. - * tests/grub_script_echo1.in: Added few more testcases. - -2010-09-04 Vladimir Serbinenko - - * grub-core/kern/misc.c: Don't add abort alias in utils. - Reported by: echoline. - -2010-09-03 BVK Chaitanya - - Add missing files into "make dist" tarball for other platforms. - - * gentpl.py (script): Use dist_noinst_DATA instead of EXTRA_DIST. - * conf/Makefile.common (dist_noinst_DATA): New variable. - * conf/Makefile.extra-dist: Added missing make dist files. - * grub-core/Makefile.core.def: Likewise. - -2010-09-03 Vladimir Serbinenko - - Compress grub_prefix. - - * grub-core/boot/i386/pc/lnxboot.S: Use - GRUB_KERNEL_I386_PC_MULTIBOOT_SIGNATURE. - * grub-core/kern/i386/pc/startup.S: Move grub_prefix to compressed part. - * include/grub/offsets.h: Rename GRUB_MACHINE_DATA_END to - GRUB_MACHINE_PREFIX_END. All users updated. - (GRUB_KERNEL_I386_PC_PREFIX): Set to GRUB_KERNEL_I386_PC_RAW_SIZE. - (GRUB_KERNEL_I386_PC_PREFIX_END): Set to GRUB_KERNEL_I386_PC_PREFIX - + 0x40. - (GRUB_KERNEL_I386_PC_RAW_SIZE): Decrease. - * util/grub-mkimage.c (image_target_desc): Change data_end to - prefix_end. All users updated. - -2010-09-03 Vladimir Serbinenko - - * grub-core/loader/i386/bsd.c (grub_freebsd_boot): Set %ebp to sane - value. - (grub_openbsd_boot): Likewise. - (grub_netbsd_boot): Likewise. - * grub-core/loader/i386/xnu.c (grub_xnu_boot_resume): Likewise. - (grub_xnu_boot): Likewise. - -2010-09-02 Vladimir Serbinenko - - * configure.ac: Clean LIBS variable after tests. - -2010-09-02 Colin Watson - - * INSTALL: Document that libdevmapper needs to be 1.02.34 or later. - -2010-09-02 Vladimir Serbinenko - - * configure.ac: Check for dm_log_with_errno_init in libdevmapper and - echo if libdevmapper will be used. - -2010-09-02 Ian Turner - - * grub-core/fs/i386/pc/pxe.c (grub_pxefs_read): Keep the blocksize - constant for the same file. - -2010-09-02 Vladimir Serbinenko - - * grub-core/kern/i386/multiboot_mmap.c: Remove leftover include. - -2010-09-02 Colin Watson - - * .bzrignore: Add *.pp, **/.dirstamp, grub-core/*.module, and - grub-core/*.pp. - -2010-09-02 Colin Watson - - Zero %ebp and %edi when entering Linux's 32-bit entry point, as - required by the boot protocol. - - * include/grub/i386/relocator.h (struct grub_relocator32_state): Add - ebp and edi members. - * grub-core/lib/i386/relocator.c (grub_relocator_boot): Handle - state.ebp and state.edi. - * grub-core/lib/i386/relocator32.S (grub_relocator32_start): Set - %ebp and %edi according to grub_relocator32_ebp and - grub_relocator32_edi respectively. - * grub-core/loader/i386/linux.c (grub_linux_boot): Zero state.ebp - and state.edi. - -2010-09-02 Vladimir Serbinenko - - Add i386-pc-pxe image target. - - * util/grub-mkimage.c (image_target_desc): New enum value - IMAGE_I386_PC_PXE. - (image_targets): New target i386-pc-pxe. - (generate_image): Handle i386-pc-pxe image. - -2010-09-02 Vladimir Serbinenko - - Fix grub_pxe_scan. - - * grub-core/fs/i386/pc/pxe.c (grub_pxe_pxenv): Put correct type bangpxe. - (grub_pxe_scan): Fix types and pxe_rm_entry computation. - All users updated. - * include/grub/i386/pc/pxe.h (grub_pxe_bangpxe): New struct. - (grub_pxe_pxenv): Correct type. - -2010-09-01 Colin Watson - - * NEWS: Document most of the important changes since 1.98. - -2010-09-01 Colin Watson - - * util/grub-mkrescue.in (usage): Tidy up usage output (and hence - generated manual page) a little. - -2010-09-01 Colin Watson - - * docs/grub.texi: Add myself as an author. - -2010-09-01 Vladimir Serbinenko - - * Makefile.util.def (libgrub.a): Add missing sunpc. - Reported by: Seth Goldberg. - -2010-08-30 Vladimir Serbinenko - - Interrupt wrapping and code simplifications. - - * Makefile.util.def (grub-mkrescue): Use x86 tg instead of - x86_noieee1275 which are functionaly equivalent in this case. - (grub-install): Make source on each platform explicit. Enable on - all noemu. - * gentpl.py (x86_efi_pc): Removed group. - (x86_noefi): Likewise. - (i386_noefi): Likewise. - (x86_noieee1275): Likewise. - (i386_noieee1275): Likewise. - (i386_noefi_noieee1275): Likewise. - (i386_pc_qemu_coreboot): Likewise. - (i386_coreboot_multiboot): Likewise. - (i386_pc_coreboot_multiboot_qemu): Likewise. - (x86_noefi_mips): Likewise. - (noieee1275): Likewise. - (ieee1275_mips): Likewise. - (noemu_noieee1275): Likewise. - (cmos): New group. - (usb): Likewise. - (videoinkernel): Likewise. - (videomodules): Likewise. - * grub-core/Makefile.am (KERNEL_HEADER_FILES): Remove - include/grub/elf.h, include/grub/elfload.h, include/grub/net.h, - include/grub/reader.h, include/grub/symbol.h, include/grub/types.h, - include/grub/loader.h, include/grub/msdos_partition.h, - include/grub/machine/biosdisk.h, include/grub/machine/boot.h, - include/grub/machine/console.h, include/grub/machine/vga.h, - include/grub/machine/vbe.h, include/grub/machine/init.h, - include/grub/machine/kernel.h, include/grub/cpu/time.h, - include/grub/cpu/types.h, include/grub/gzio.h and include/grub/menu.h - (KERNEL_HEADER_FILES) [i386-pc]: Add include/grub/machine/int.h. - (KERNEL_HEADER_FILES) [i386-ieee1275]: Add include/grub/i386/pit.h - * grub-core/Makefile.core.def (kernel): Explicit the source for - startup. Explicit the platforms using kern/generic/rtc_get_time_ms.c. - Split ieee1275_mips. Remove kern/i386/halt.c. Remove kern/i386/misc.S. - Enable kern/i386/pit.c on all x86. Remove kern/i386/ieee1275/init.c. - Use videoinkernel tag. - (usb): Enable on all usb. - (usbserial_common): Likewise. - (usbserial_pl2303): Likewise. - (usbserial_ftdi): Likewise. - (uhci): Enable on all x86. - (ohci): Enable on all pci. - (cmostest): Enable on all CMOS. - (acpi): Include commands/acpi.c on all platforms. - (halt): Add relevant lib/*/halt.c. - (hdparm): Enable on all pci. - (lspci): Likewise. - (usbtest): Enable on all usb. - (ata): Enable on all pci. - (ata_pthru): Likewise. - (usbms): Enable on all usb. - (usb_keyboard): Likewise. - (font): Use tag videomodules. - (bufio): Likewise. - (datetime): Use tag cmos. Enable on all noemu. - (mmap): Use tags common and x86. - (gfxterm): Use tag videomodules. - (bitmap): Likewise. - (bitmap_scale): Likewise. - (video_fb): Likewise. - (video): Likewise. - * grub-core/bus/usb/ohci.c (grub_ohci_td): Make link_td a pointer and - adjust padding accordingly. All users updated. - (grub_ohci_transaction): Fix bad format specification. - (GRUB_MOD_INIT): Add asserts for struct size. - * grub-core/bus/usb/uhci.c (grub_uhci_pci_iter): Add explicit casts. - (grub_alloc_td): Likewise. - (grub_free_queue): Likewise. - (grub_uhci_transfer): Likewise. - (grub_uhci_transaction): Fix bad format specification. - * grub-core/bus/usb/usbtrans.c (grub_usb_control_msg): Likewise. - (grub_usb_bulk_readwrite): Likewise. - * grub-core/kern/i386/misc.S (grub_stop): Moved from here ... - * grub-core/commands/i386/pc/halt.c (stop): ...here. Transformed into C. - Made static. - * grub-core/lib/i386/halt.c (stop): ... and here. Transformed into C. - Made static. - * grub-core/kern/i386/pc/startup.S (grub_halt): Moved from here ... - * grub-core/commands/i386/pc/halt.c (grub_halt): ...here. - Transformed into C. - * grub-core/kern/i386/pc/startup.S (grub_biosdisk_rw_int13_extensions): - Moved from here ... - * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_rw_int13_extensions): - ... here. Transformed into C. Made static. - * grub-core/kern/i386/pc/startup.S (grub_biosdisk_rw_standard): - Moved from here ... - * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_rw_standard): - ... here. Transformed into C. Made static. - * grub-core/kern/i386/pc/startup.S - (grub_biosdisk_check_int13_extensions): Moved from here ... - * grub-core/disk/i386/pc/biosdisk.c - (grub_biosdisk_check_int13_extensions): ... here. Transformed into C. - Made static. - * grub-core/kern/i386/pc/startup.S - (grub_biosdisk_get_cdinfo_int13_extensions): Moved from here ... - * grub-core/disk/i386/pc/biosdisk.c - (grub_biosdisk_get_cdinfo_int13_extensions): ... here. - Transformed into C. Made static. - * grub-core/kern/i386/pc/startup.S - (grub_biosdisk_get_diskinfo_int13_extensions): Moved from here ... - * grub-core/disk/i386/pc/biosdisk.c - (grub_biosdisk_get_diskinfo_int13_extensions): ... here. - Transformed into C. Made static. - * grub-core/kern/i386/pc/startup.S - (grub_biosdisk_get_diskinfo_standard): Moved from here ... - * grub-core/disk/i386/pc/biosdisk.c - (grub_biosdisk_get_diskinfo_standard): ... here. - Transformed into C. Made static. - * grub-core/kern/i386/pc/startup.S - (grub_biosdisk_get_num_floppies): Moved from here ... - * grub-core/disk/i386/pc/biosdisk.c - (grub_biosdisk_get_num_floppies): ... here. - Transformed into C. Made static. - * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_get_diskinfo_real): - New function. - * grub-core/kern/i386/pc/startup.S (grub_pxe_scan): Moved from here ... - * grub-core/fs/i386/pc/pxe.c (grub_pxe_scan): ... here. - Transformed into C. Made static. - * grub-core/kern/i386/pc/startup.S (grub_rm_entry): Moved from here ... - * grub-core/fs/i386/pc/pxe.c (grub_rm_entry): ... here. - Transformed into C. Made static. - * grub-core/kern/i386/ieee1275/init.c: Removed. - * grub-core/kern/i386/misc.S: Likewise. - * grub-core/kern/i386/pc/startup.S (grub_get_memsize): - Splitted from here ... - * grub-core/kern/i386/pc/init.c (grub_get_conv_memsize): ... here. - Transformed into C. Made static. All users updated. - * grub-core/kern/i386/pc/mmap.c (grub_get_ext_memsize): ... and here. - Transformed into C. Made static. All users updated. - * grub-core/kern/i386/pc/startup.S (grub_get_eisa_mmap): - Moved from here... - * grub-core/kern/i386/pc/mmap.c (grub_get_eisa_mmap): ... here. - Transformed into C. Made static. All users updated. - * grub-core/kern/i386/pc/startup.S (grub_get_mmap_entry): - Moved from here... - * grub-core/kern/i386/pc/mmap.c (grub_get_mmap_entry): ... here. - Transformed into C. Made static. All users updated. - * grub-core/kern/i386/pc/startup.S (grub_stop_floppy): - Removed (replaced by C version). - * grub-core/kern/i386/pc/startup.S (grub_vga_set_mode): - Moved from here... - * grub-core/video/i386/pc/vga.c (grub_vga_set_mode): ...here. - Transformed into C. Made static. - * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_controller_info): - Moved from here... - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_controller_info): - ... here. Transformed into C. - * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_mode_info): - Moved from here... - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_mode_info): - ... here. Transformed into C. - * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_set_mode): - Moved from here... - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_set_mode): - ... here. Transformed into C. Made static. - * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_mode): - Moved from here... - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_mode): - ... here. Transformed into C. - * grub-core/kern/i386/pc/startup.S - (grub_vbe_bios_getset_dac_palette_width):Moved from here... - * grub-core/video/i386/pc/vbe.c - (grub_vbe_bios_getset_dac_palette_width):... here. Transformed into C. - * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_set_memory_window): - Moved from here... - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_set_memory_window): - ... here. Transformed into C. - * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_memory_window): - Moved from here... - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_memory_window): - ... here. Transformed into C. - * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_set_scanline_length): - Moved from here... - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_set_scanline_length): - ... here. Transformed into C. - * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_scanline_length): - Moved from here... - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_scanline_length): - ... here. Transformed into C. - * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_set_display_start): - Moved from here... - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_set_display_start): - ... here. Transformed into C. Made static. - * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_get_display_start): - Moved from here... - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_display_start): - ... here. Transformed into C. Made static. - * grub-core/kern/i386/pc/startup.S (grub_vbe_bios_set_palette_data): - Moved from here... - * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_set_palette_data): - ... here. Transformed into C. Made static. - * grub-core/kern/i386/pc/startup.S (grub_pxe_call): Receive - pxe_rm_entry as third argument. - (grub_bios_interrupt): New function. - * grub-core/kern/i386/qemu/mmap.c: Remove useless include. - * grub-core/kern/i386/qemu/startup.S (codestart): Do cli;hlt instead - of calling grub_stop. - * grub-core/kern/efi/efi.c (grub_halt): Moved from here ... - * grub-core/lib/efi/halt.c (grub_halt): ...here. - * grub-core/kern/emu/main.c (grub_halt): Moved from here ... - * grub-core/lib/emu/halt.c (grub_halt): ... here. - * grub-core/lib/i386/halt.c: Moved from here ... - * grub-core/lib/i386/halt.c: ... here. - * grub-core/kern/ieee1275/openfw.c (grub_halt): Moved from here ... - * grub-core/lib/ieee1275/halt.c (grub_halt): ... here. - * grub-core/loader/i386/pc/linux.c (grub_linux16_boot): Call - grub_stop_floppy. - * grub-core/loader/i386/xnu.c (guessfsb) [IEEE1275]: Enable. - * include/grub/i386/coreboot/init.h: Removed. - * include/grub/i386/multiboot/init.h: Likewise. - * include/grub/i386/pc/biosdisk.h: Removed all function prototypes. - * include/grub/i386/pc/init.h: Likewise except grub_gate_a20. - * include/grub/i386/pc/int.h: New file. - * include/grub/i386/pc/pxe.h (GRUB_PXE_SIGNATURE): New definition. - (grub_pxe_scan): Removed. - (grub_pxe_call): Update prototype. - * include/grub/i386/pc/vbe.h: Removed EXPORT_FUNC and useless - prototypes. - * include/grub/i386/pc/vga.h (grub_vga_set_mode): Removed. - * include/grub/i386/qemu/init.h: Removed. - * include/grub/mips/yeeloong/kernel.h (grub_reboot): Add missing - noreturn. - (grub_halt): Likewise. - * include/grub/misc.h (grub_halt): Removed EXPORT_FUNC. - (grub_reboot): Likewise. - * grub-core/kern/i386/coreboot/init.c (grub_stop_floppy): Moved from here... - * include/grub/i386/floppy.h (grub_stop_floppy): ...here. Inlined. - * grub-core/kern/i386/pc/startup.S (grub_hard_stop): Removed. - -2010-08-30 Robert Millan - - * NEWS: Document addition of ZFS support in `grub-install' and - `grub-mkconfig'. - -2010-08-30 BVK Chaitanya - - * conf/Makefile.common (CPPFLAGS_DEFAULT): Remove leading / from - dprintf output. - -2010-08-30 Vladimir Serbinenko - - Remove leftover embedding of font objects. - - * include/grub/kernel.h (OBJ_TYPE_FONT): Removed. - * util/grub-install.in (font): Removed. - * util/grub-mkimage.c (generate_image): Remove font support. All users - updated. - -2010-08-30 Vladimir Serbinenko - - Remove leftover embedding of font objects. - - * include/grub/kernel.h (OBJ_TYPE_FONT): Removed. - * util/grub-install.in (font): Removed. - * util/grub-mkimage.c (generate_image): Remove font support. All users - updated. - -2010-08-30 Vladimir Serbinenko - - * docs/grub.texi (Network): Fix reference to pxe_blksize. - Reported by: Ian Turner - -2010-08-30 Vladimir Serbinenko - - * grub-core/normal/menu.c (grub_wait_after_message): Add a 10 second - timeout to avoid indefinite boot stalling. - -2010-08-30 Vladimir Serbinenko - - * grub-core/normal/color.c (grub_env_write_color_normal): Fix a warning. - (grub_env_write_color_highlight): Likewise. - -2010-08-30 Vladimir Serbinenko - - * grub-core/normal/term.c (print_more): Return to normal and not - to standard state after printing "---MORE---". - -2010-08-30 Vladimir Serbinenko - - * grub-core/term/i386/vga_common.c (grub_console_setcolorstate): - Mask out the bit 0x80 since it has other meaning that specifiing color. - -2010-08-29 Vladimir Serbinenko - - New relocator. Allows for more kernel support and more straightforward - loader writing. - - * Makefile.am (BOOTTARGET): New variable. - (QEMU32): Likewise. - (linux.init.x86_64): New target. - (linux.init.i386): Likewise. - (multiboot.elf): Likewise. - (kfreebsd.elf): Likewise. - (kfreebsd.aout): Likewise. - (pc-chainloader.elf): Likewise. - (pc-chainloader.bin): Likewise. - (ntldr.elf): Likewise. - (ntldr.bin): Likewise. - (multiboot2.elf): Likewise. - (kfreebsd.init.x86_64): Likewise. - (kfreebsd.init.i386): Likewise. - (knetbsd.init.i386): Likewise. - (kopenbsd.init.i386): Likewise. - (knetbsd.init.x86_64): Likewise. - (kopenbsd.init.x86_64): Likewise. - (linux-initramfs.i386): Likewise. - (linux-initramfs.x86_64): Likewise. - (kfreebsd-mfsroot.i386.img): Likewise. - (knetbsd.image.i386): Likewise. - (kopenbsd.image.i386): Likewise. - (kopenbsd.image.x86_64): Likewise. - (knetbsd.miniroot-image.i386.img): Likewise. - (kfreebsd-mfsroot.x86_64.img): Likewise. - (knetbsd.image.x86_64): Likewise. - (knetbsd.miniroot-image.x86_64.img): Likewise. - (kfreebsd-mfsroot.i386.gz): Likewise. - (bootcheck-kfreebsd-i386): Likewise. - (kfreebsd-mfsroot.x86_64.gz): Likewise. - (bootcheck-kfreebsd-x86_64): Likewise. - (knetbsd.miniroot-image.i386.gz): Likewise. - (bootcheck-knetbsd-i386): Likewise. - (bootcheck-kopenbsd-i386): Likewise. - (bootcheck-kopenbsd-x86_64): Likewise. - (knetbsd.miniroot-image.x86_64.gz): Likewise. - (bootcheck-knetbsd-x86_64): Likewise. - (bootcheck-linux-i386): Likewise. - (bootcheck-linux-x86_64): Likewise. - (bootcheck-linux16-i386): Likewise. - (bootcheck-linux16-x86_64): Likewise. - (bootcheck-multiboot): Likewise. - (bootcheck-multiboot2): Likewise. - (bootcheck-kfreebsd-aout): Likewise. - (bootcheck-pc-chainloader): Likewise. - (bootcheck-ntldr): Likewise. - (CLEANFILES): Add new targets. - (BOOTCHECKS): New variable. - (.PHONY): Add bootchecks. - (SUCCESSFUL_BOOT_STRING): New variable. - (BOOTCHECK_TIMEOUT): Likewise. - (bootcheck): New target - * Makefile.util.def (grub-mkrescue): Enable on i386-multiboot. - * configure.ac: Correct efiemu excuse. - * docs/grub.texi (Supported kernels): New chapter. - * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add - include/grub/mm_private.h. Simplify inclusion of - include/grub/boot.h, include/grub/loader.h - and include/grub/msdos_partition.h - (KERNEL_HEADER_FILES) [i386_coreboot]: - Remove include/grub/machine/loader.h. Add include/grub/i386/pit.h. - (KERNEL_HEADER_FILES) [i386_multiboot]: Likewise. - (KERNEL_HEADER_FILES) [i386_qemu]: Likewise. - (KERNEL_HEADER_FILES) [i386_ieee1275]: Remove - include/grub/machine/loader.h. - (KERNEL_HEADER_FILES) [x86_64-efi]: Likewise. - * grub-core/Makefile.core.def (kernel): Remove kern/i386/loader.S from - extra_dist. - (pci.mod): Enable on i386-multiboot. - (acpi.mod): Enable on i386-multiboot and i386-coreboot. - (efiemu.mod): Enable on i386-coreboot, i386-ieee1275, i386-multiboot and - i386-qemu. - (relocator.mod): Rewritten. - (aout.mod): Enable on all x86. - (bsd.mod): Likewise. - (ntldr.mod): New module. - (linux.mod): Use loader/i386/linux.c on all x86. - (xnu.mod): Enable on all x86. - (vga_text.mod): disable on EFI and QEMU. - * grub-core/efiemu/i386/coredetect.c: Remove useless include. - * grub-core/efiemu/i386/pc/cfgtables.c: Likewise. - * grub-core/efiemu/loadcore.c: Likewise. - * grub-core/efiemu/main.c: Likewise. - (grub_efiemu_exit_boot_services): Removed. - (grub_efiemu_finish_boot_services): Likewise. - * grub-core/efiemu/mm.c (grub_efiemu_finish_boot_services): New - function. - * grub-core/efiemu/i386/nocfgtables.c: New file. - * grub-core/kern/dl.c (grub_dl_unload_all): Removed. - * grub-core/kern/efi/efi.c (grub_efi_exit_boot_services): Removed. - (grub_efi_finish_boot_services): Moved from here ... - * grub-core/kern/efi/mm.c (grub_efi_finish_boot_services): ...here. - Fille finish memory map and related data. - (finish_mmap_buf): New variable. - (grub_efi_uintn_t finish_mmap_size): Likewise. - (grub_efi_uintn_t finish_key): Likewise. - (grub_efi_uintn_t finish_desc_size): Likewise. - (grub_efi_uint32_t finish_desc_version): Likewise. - (grub_efi_is_finished): Likewise. - (grub_efi_get_memory_map): Use saved memory map if EFI is already - finished. - * grub-core/kern/elf.c (grub_elf32_phdr_iterate): Make global. - (grub_elf64_phdr_iterate): Likewise. - * grub-core/kern/i386/coreboot/init.c (grub_os_area_addr): Removed. - (grub_os_area_size): Likewise. - (grub_machine_init): Don't reserve os area. - * grub-core/kern/i386/coreboot/startup.S: Don't include loader.S. - * grub-core/kern/i386/ieee1275/startup.S: Likewise. - * grub-core/kern/i386/loader.S: Removed. - * grub-core/kern/i386/pc/init.c (grub_os_area_addr): Removed. - (grub_os_area_size): Likewise. - (grub_machine_init): Don't reserve os area. - * grub-core/kern/i386/pc/startup.S (grub_chainloader_real_boot): - Don't call grub_dl_unload_all. - Don't include loader.S. - * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_iterate): - Declare the memory after _end as available. - * grub-core/kern/mm.c (GRUB_MM_FREE_MAGIC): Moved from here... - * include/grub/mm_private.h (GRUB_MM_FREE_MAGIC): ... here. - (GRUB_MM_ALLOC_MAGIC): Moved from here... - * include/grub/mm_private.h (GRUB_MM_ALLOC_MAGIC): ... here. - * grub-core/kern/mm.c (grub_mm_header): Moved from here... - * include/grub/mm_private.h (grub_mm_header): ... here. - * grub-core/kern/mm.c (GRUB_MM_ALIGN): Moved from here... - * include/grub/mm_private.h (GRUB_MM_ALIGN): ... here. - * grub-core/kern/mm.c (grub_mm_region): Moved from here ... - (grub_mm_region): ..here. Removed addr. Added pre_size. - All users updated. - * grub-core/kern/mm.c (base): Renamed to ... - (grub_mm_base): ... this. Made global. - (grub_real_malloc): Alloc from end of region. - (grub_memalign): Don't attempt to malloc if grub_mm_base is NULL. - * grub-core/kern/powerpc/cache.S (grub_arch_sync_caches): Move to ... - * grub-core/kern/powerpc/cache_flush.S: ... here. - * grub-core/lib/efi/relocator.c: New file. - * grub-core/lib/i386/relocator.c: Rewritten. - * grub-core/lib/i386/relocator16.S: New file. - * grub-core/lib/i386/relocator32.S: Likewise. - * grub-core/lib/i386/relocator64.S: Likewise. - * grub-core/lib/i386/relocator_asm.S: Rewritten. - * grub-core/lib/i386/relocator_common.S: New file. - * grub-core/lib/ieee1275/relocator.c: Likewise. - * grub-core/lib/mips/relocator.c: Rewritten. - * grub-core/lib/mips/relocator_asm.S: Renamed variables and minor - stylistic adjustments. - * grub-core/lib/powerpc/relocator.c: New file. - * grub-core/lib/powerpc/relocator_asm.S: Likewise. - * grub-core/lib/relocator.c: Rewritten. - * grub-core/lib/x86_64/relocator_asm.S: New file. - * grub-core/loader/aout.c (grub_aout_load): Make load_addr a void *. - * grub-core/loader/i386/bsd.c (NETBSD_DEFAULT_VIDEO_MODE): New const. - (bsd_tag): New struct. - (tags): New variable. - (tags_last): Likewise. - (netbsd_module): New struct. - (netbsd_mods): New variable. - (netbsd_mods_last): Likewise. - (openbsd_opts): New parameter "serial". - (OPENBSD_SERIAL_ARG): New definition. - (netbsd_opts): New parameter "serial". - (NETBSD_SERIAL_ARG): New definition. - (grub_freebsd_add_meta): Reorganised into ... - (grub_bsd_add_meta): ...this. All users updated. - (grub_freebsd_add_mmap): Reorganised into ... - (generate_e820_mmap): ...this... - (grub_bsd_add_mmap): ...and this. All users updated. - (grub_freebsd_list_modules): Use tags. - (grub_netbsd_add_meta_module): New function. - (grub_netbsd_list_modules): Likewise. - (grub_freebsd_boot): Use relocator and finish EFI. - (grub_openbsd_boot): Likewise. - (grub_netbsd_setup_video): New function. - (grub_netbsd_add_modules): Likewise. - (grub_netbsd_boot): Use grub_netbsd_add_modules, relocator, netbsd_tags - and finish EFI. - (grub_bsd_unload): Unload tags. - (grub_bsd_load_aout): Use relocator. - (grub_bsd_elf32_size_hook): New function. - (grub_bsd_elf32_hook): Use relocator. - (grub_bsd_elf64_size_hook): New function. - (grub_bsd_elf64_hook): Use relocator. - (grub_bsd_load_elf): Use relocator and call grub_openbsd_find_ramdisk. - (grub_bsd_load): Zero-out openbsd_ramdisk. - (grub_bsd_load): Use relocator. - (grub_cmd_openbsd): Support serial. - (grub_cmd_netbsd): Support modules. - (grub_cmd_freebsd_module): Use relocator. - (grub_netbsd_module_load): New function. - (grub_cmd_netbsd_module): Likewise. - (grub_cmd_openbsd_ramdisk): Likewise. - (GRUB_MOD_INIT): Register knetbsd_module, knetbsd_module_elf and - kopenbsd_ramdisk. - (GRUB_MOD_FINI): Unregister new commands. - * grub-core/loader/i386/bsdXX.c (load): Remove useless checks. - (grub_freebsd_load_elfmodule_obj): Use relocator. - (grub_freebsd_load_elfmodule): Likewise. - (grub_freebsd_load_elf_meta): Likewise. - (grub_netbsd_load_elf_meta): New function. - (grub_openbsd_find_ramdisk): Likewise. - * grub-core/loader/i386/bsd_helper.S: Removed. - * grub-core/loader/i386/bsd_pagetable.c: Support relocator. - * grub-core/loader/i386/bsd_trampoline.S: Removed. - * grub-core/loader/i386/efi/linux.c: Likewise. - * grub-core/loader/i386/ieee1275/linux.c: Likewise. - * grub-core/loader/i386/linux.c (HAS_VGA_TEXT): New const. - (DEFAULT_VIDEO_MODE): Likewise. - (real_mode_target): New variable. - (prot_mode_target): Likewise. - (initrd_mem_target): Likewise. - (relocator): Likewise. - (efi_mmap_buf): Likewise. - (efi_mmap_size): Likewise. - (find_efi_mmap_size): Moved from grub-core/loader/i386/efi/linux.c. - (free_pages): Use relocator. - (allocate_pages): Account for efi_mmap and use relocator. Return error. - (grub_linux_setup_video): Return error. - (grub_linux_trampoline_start): Removed. - (grub_linux_trampoline_end): Likewise. - (grub_linux_boot): Use relocator and DEFAULT_VIDEO_MODE. Pass console - andd video parameters depending on firmware. - [GRUB_MACHINE_IEEE1275]: Pass OFW parameters. - [GRUB_MACHINE_EFI]: Pass EFI parameters. - (grub_cmd_linux) [GRUB_MACHINE_EFI]: Likewise. - (grub_cmd_initrd): Use relocator. - * grub-core/loader/i386/linux_trampoline.S: Removed. - * grub-core/loader/i386/multiboot_mbi.c (elf_sec_num): New variable. - (elf_sec_entsize): Likewise. - (elf_sec_shstrndx): Likewise. - (elf_sections): Likewise. - (grub_multiboot_load): Use relocator. - (grub_multiboot_get_mbi_size): Account for sections. - (grub_multiboot_make_mbi): Use relocator and support sections. - (grub_multiboot_add_elfsyms): New function. - (grub_multiboot_free_mbi): Free sections. - * grub-core/loader/i386/pc/linux.c (relocator): New variable. - (grub_linux_real_target): Likewise. - (grub_linux_real_chunk): Likewise. - (grub_linux16_prot_size): Likewise. - (grub_linux16_boot): Use relocator. - (grub_linux_unload): Unload relocator. - (grub_cmd_linux): Use relocator. - (grub_cmd_initrd): Likewise. - * grub-core/loader/i386/pc/ntldr.c: New file. - * grub-core/loader/i386/xnu.c (guessfsb) [GRUB_MACHINE_IEEE1275]: - Don't try to guess CPU frequency. - (grub_xnu_set_video): Stretch bitmap. - (grub_xnu_boot): Use relocator. - * grub-core/loader/mips/linux.c (grub_linux_boot): Use relocator. - (grub_linux_unload): Free relocator. - (grub_linux_load32): Use relocator. - (grub_linux_load64): Likewise. - (grub_cmd_initrd): Likewise. - * grub-core/loader/multiboot.c (grub_multiboot_boot): Use relocator. - (grub_multiboot_unload): Unload relocator. - (grub_cmd_multiboot): Use relocator. - (grub_cmd_module): Likewise. - * grub-core/loader/multiboot_elfxx.c (grub_multiboot_load_elfXX): - Use relocator and support sections. - * grub-core/loader/multiboot_mbi2.c(elf_sec_num): New variable. - (elf_sec_entsize): Likewise. - (elf_sec_shstrndx): Likewise. - (elf_sections): Likewise. - (grub_multiboot_load): Use relocator. - (grub_multiboot_get_mbi_size): Account for sections. - (grub_multiboot_make_mbi): Use relocator and support sections. - (grub_multiboot_add_elfsyms): New function. - * grub-core/loader/powerpc/ieee1275/linux.c: Remove useless include. - * grub-core/loader/sparc64/ieee1275/linux.c: Likewise. - * grub-core/loader/xnu.c (grub_xnu_heap_malloc): Use relocator. - Prototype changed. All users updated. - (grub_xnu_align_heap): Simplified. - (grub_xnu_writetree_toheap): Likewise. - (grub_xnu_unload): Unload relocator. - (grub_cmd_xnu_kernel): Use relocator. - (grub_cmd_xnu_kernel64): Likewise. - (grub_xnu_register_memory): Simplified. - * grub-core/loader/xnu_resume.c (grub_xnu_resume): Use relocator. - * grub-core/term/efi/console.c (grub_console_putchar): Abort if - EFI is finished. - (grub_console_checkkey): Likewise. - (grub_console_getkey): Likewise. - (grub_console_getwh): Likewise. - (grub_console_getxy): Likewise. - (grub_console_gotoxy): Likewise. - (grub_console_cls): Likewise. - (grub_console_setcolorstate): Likewise. - (grub_console_setcursor): Likewise. - * grub-core/term/ns8250.c (grub_ns8250_hw_get_port): New function. - * grub-core/tests/boot/kbsd.init-i386.S: New file. - * grub-core/tests/boot/kbsd.init-x86_64.S: Likewise. - * grub-core/tests/boot/kbsd.spec.txt: Likewise. - * grub-core/tests/boot/kernel-8086.S: Likewise. - * grub-core/tests/boot/kernel-i386.S: Likewise. - * grub-core/tests/boot/kfreebsd-aout.cfg: Likewise. - * grub-core/tests/boot/kfreebsd.cfg: Likewise. - * grub-core/tests/boot/kfreebsd.init-i386.S: Likewise. - * grub-core/tests/boot/kfreebsd.init-x86_64.S: Likewise. - * grub-core/tests/boot/knetbsd.cfg: Likewise. - * grub-core/tests/boot/kopenbsd.cfg: Likewise. - * grub-core/tests/boot/kopenbsdlabel.txt: Likewise. - * grub-core/tests/boot/linux.cfg: Likewise. - * grub-core/tests/boot/linux.init-i386.S: Likewise. - * grub-core/tests/boot/linux.init-x86_64.S: Likewise. - * grub-core/tests/boot/linux16.cfg: Likewise. - * grub-core/tests/boot/multiboot.cfg: Likewise. - * grub-core/tests/boot/multiboot2.cfg: Likewise. - * grub-core/tests/boot/ntldr.cfg: Likewise. - * grub-core/tests/boot/pc-chainloader.cfg: Likewise. - * include/grub/aout.h (grub_aout_load): Make load_addr a void *. - * include/grub/autoefi.h (grub_autoefi_finish_boot_services): - New definition. - * include/grub/dl.h (grub_dl_unload_all): Removed. - * include/grub/efi/efi.h (grub_efi_exit_boot_services): Likewise. - (grub_efi_finish_boot_services): Change prototype. - (grub_efi_is_finished): New variable. - * include/grub/efiemu/efiemu.h (grub_efiemu_finish_boot_services): - Changed prototype. - (grub_efiemu_finish_boot_services): Removed. - (grub_machine_efiemu_init_tables): New prototype. - * include/grub/elfload.h (grub_elf32_phdr_iterate): Likewise. - (grub_elf64_phdr_iterate): Likewise. - * include/grub/i386/bsd.h: Include relocator.h. - (freebsd_tag_header): New struct. - (grub_openbsd_bios_mmap): Removed. - (grub_unix_real_boot): Removed. - (grub_freebsd_load_elfmodule32): Changed prototype. - (grub_freebsd_load_elfmodule_obj64): Likewise. - (grub_freebsd_load_elf_meta32): Likewise. - (grub_freebsd_load_elf_meta64): Likewise. - (grub_freebsd_add_meta): Removed. - (grub_netbsd_load_elf_meta32): New prototype. - (grub_netbsd_load_elf_meta64): Likewise. - (grub_bsd_add_meta): Likewise. - (grub_openbsd_ramdisk_descriptor): New struct. - (grub_openbsd_find_ramdisk32): New prototype. - (grub_openbsd_find_ramdisk64): Likewise. - * include/grub/i386/coreboot/loader.h: Removed. - * include/grub/i386/efi/loader.h: Likewise. - * include/grub/i386/ieee1275/loader.h: Likewise. - * include/grub/i386/linux.h (linux_kernel_header): Change void * - to grub_uint32_t. - * include/grub/i386/loader.h: Removed. - * include/grub/i386/memory.h (GRUB_MEMORY_CPU_CR4_PAE_ON): Correct the - value. - (GRUB_MEMORY_CPU_CR4_PSE_ON): New definition. - (grub_phys_addr_t): New type. - (grub_vtop): New inline function. - (grub_map_memory): Likewise. - (grub_unmap_memory): Likewise. - * include/grub/i386/multiboot/loader.h: Removed. - * include/grub/i386/netbsd_bootinfo.h (NETBSD_BTINFO_BOOTDISK): Removed. - (NETBSD_BTINFO_CONSOLE): New definition. - (NETBSD_BTINFO_SYMTAB): Likewise. - (NETBSD_BTINFO_MODULES): Likewise. - (NETBSD_BTINFO_FRAMEBUF): Likewise. - (grub_netbsd_bootinfo): New struct. - (grub_netbsd_btinfo_common): Use explicit bitsize. - (grub_netbsd_btinfo_mmap_entry): Removed. - (GRUB_NETBSD_MAX_BOOTPATH_LEN): New definition. - (grub_netbsd_btinfo_bootdisk): New struct. - (grub_netbsd_btinfo_symtab): Likewise. - (grub_netbsd_btinfo_serial): Likewise. - (grub_netbsd_btinfo_modules): Likewise. - (grub_netbsd_btinfo_framebuf): Likewise. - (GRUB_NETBSD_MAX_ROOTDEVICE_LEN): New definition. - * include/grub/i386/openbsd_bootarg.h (OPENBSD_BOOTARG_CONSOLE): - Likewise. - (grub_openbsd_bootargs): Use explicit bitsize. - (grub_openbsd_bootarg_console): New struct. - (GRUB_OPENBSD_COM_MAJOR): New definition. - (GRUB_OPENBSD_VGA_MAJOR): Likewise. - * include/grub/i386/pc/efiemu.h: Removed. - * include/grub/i386/pc/loader.h: Don't include cpu/loader.h. - * include/grub/i386/qemu/loader.h: Removed. - * include/grub/i386/relocator.h: Rewritten. - * include/grub/i386/xnu.h (grub_xnu_heap_will_be_at): Removed. - * include/grub/mips/memory.h: New file. - * include/grub/mips/multiboot.h: Rewritten. - * include/grub/mips/relocator.h: Rewritten. - * include/grub/mips/yeeloong/memory.h (grub_phys_addr_t): New type. - (grub_vtop): New function. - (grub_map_memory): Likewise. - (grub_unmap_memory): Likewise. - * include/grub/misc.h (ALIGN_DOWN): New definition. - * include/grub/mm.h (grub_mm_check_real): New proto. - (GRUB_MM_CHECK): New definition. - * include/grub/mm_private.h: New file. - * include/grub/multiboot.h (grub_multiboot_relocator): New variable. - (grub_multiboot_get_mbi_size): Removed. - (grub_multiboot_make_mbi): Change prottype. - (grub_multiboot_set_accepts_video): New proto. - (grub_multiboot_add_elfsyms): Likewise. - (grub_multiboot_payload_eip): New variable. - * include/grub/ns8250.h (grub_ns8250_hw_get_port) [!ASM_FILE]: - New prototype. - * include/grub/offsets.h (GRUB_KERNEL_I386_MULTIBOOT_PREFIX): - New definition. - (GRUB_KERNEL_I386_MULTIBOOT_DATA_END): Likewise. - (GRUB_KERNEL_I386_MULTIBOOT_MOD_ALIGN): Likewise. - * include/grub/powerpc/ieee1275/loader.h: Removed. - * include/grub/powerpc/memory.h: New file. - * include/grub/powerpc/relocator.h: Likewise. - * include/grub/relocator.h: Likewise. - * include/grub/relocator_private.h: Likewise. - * include/grub/sparc64/ieee1275/loader.h: Removed. - * include/grub/x86_64/memory.h: New file. - * include/grub/xnu.h (grub_xnu_writetree_toheap): Changed prototype. - (grub_xnu_heap_malloc): Likewise. - (grub_xnu_heap_real_start): Removed. - (grub_xnu_heap_start): Likewise. - (grub_xnu_relocator): New variable. - (grub_xnu_heap_target_start): Likewise. - * tests/util/grub-shell.in: Support non-pc. - * util/grub-mkimage.c (image_targets): Fix multiboot target. - -2010-08-29 Vladimir Serbinenko - - * grub-core/normal/charset.c (grub_utf8_to_ucs4_alloc): Avoid deadloop - on malloc error. - (grub_bidi_logical_to_visual): Check that malloc succeded. - * grub-core/normal/term.c (grub_puts_terminal): Fix fallback to dumb - puts. - (grub_xputs_normal): Likewise. - -2010-08-29 Vladimir Serbinenko - - * grub-core/Makefile.core.def (kernel): Add kern/mips/cache_flush.S to - extra_dist. - -2010-08-29 Vladimir Serbinenko - - * grub-core/efiemu/runtime/efiemu.sh: Removed. - -2010-08-29 Vladimir Serbinenko - - * Makefile.util.def (grub-ofpathname): Add missing ldadd. - -2010-08-29 Vladimir Serbinenko - - * grub-core/kern/misc.c (grub_real_dprintf): Always refresh after - dprintf. - -2010-08-29 BVK Chaitanya - - * Makefile.util.def: Use ldadd instead of ldflags for libraries. - -2010-08-28 Vladimir Serbinenko - - * grub-core/normal/term.c (print_more): Fix a memory leak. - (grub_puts_terminal): Revert to dumb puts if memory allocation fails. - (grub_xputs_normal): Likewise. - -2010-08-28 Vladimir Serbinenko - - * grub-core/script/lexer.c (grub_script_lexer_init): Don't look before - the begining of the string - -2010-08-28 Vladimir Serbinenko - - * grub-core/script/script.c (grub_script_parse): Free parsed on - failure. - -2010-08-28 Vladimir Serbinenko - - * grub-core/normal/completion.c (grub_normal_do_completion): Free argv - on failure. - -2010-08-28 Vladimir Serbinenko - - * grub-core/normal/cmdline.c (grub_cmdline_get): Free cl_terms on - return. - -2010-08-28 Vladimir Serbinenko - - * grub-core/term/gfxterm.c (grub_gfxterm_term_fini): Free the text buffer. - (scroll_up): Fix a memory leak. - -2010-08-28 Vladimir Serbinenko - - * grub-core/fs/nilfs2.c (grub_nilfs2_load_sb): Handle grub_disk_read - errors. - -2010-08-27 Vladimir Serbinenko - - Handle USB pendrives exposed as floppies. - - * grub-core/boot/i386/pc/boot.S: Check LBA even on what appears to be - floppy. - * grub-core/disk/i386/pc/biosdisk.c (grub_biosdisk_open): Likewise. - Check for partitions on all devices. - -2010-08-25 Vladimir Serbinenko - - * grub-core/term/ieee1275/ofconsole.c (put): Correct prototype. - (readkey): Likewise. - -2010-08-25 BVK Chaitanya - - Multiple variable names support to "export" command. - - * normal/context.c (grub_cmd_export): "export" command supports - multiple variable names. - -2010-08-23 Samuel Thibault - - * util/grub.d/30_os-prober.in: Fix conversion from grub-probe - --target=drive output to Mach device name. - -2010-08-23 BVK Chaitanya - - New Automake based build system for GRUB. - - * ABOUT-NLS: New file. - * Makefile.am: New file. GRUB host utils' rules that doesn't fit - in Makefile.util.def file. - * Makefile.util.def: New file. Autogen build definitions file for - GRUB host utils. - * conf/Makefile.common: New file. Common variables for GRUB host - utils and target modules. - * conf/Makefile.extra-dist: New file. Extra files for make dist. - * docs/Makefile.am: New file. Automake file for docs. - * gentpl.py: New file. Python script to generate Autogen - template. - * grub-core/Makefile.am: New file. GRUB target modules' rules - that doesn't fit in Makefile.core.def file. - * grub-core/Makefile.core.def: New file. Autogen build - definitions file for GRUB target modules. - * grub-core/lib/setjmp.S: New file. Wrapper for target_cpu - specific setjmp.S file. - * po/Makefile.am: New file. - - * .bzrignore: New ignores. - * INSTALL: New requirements, without Ruby. - * acinclude.m4: Use TARGET_IMG_BASE_LDOPT variable instead. - * autogen.sh: Updated to invoke autogen as necessary. - * configure.ac: Separate *FLAGS with HOST_ and TARGET_ prefixes, - and defines for Automake conditionals. - * geninit.sh: Refactoring. - - * include/grub/dl.h: Allow build rules to define GRUB_MOD_* if - necessary. - * include/grub/emu/getroot.h (grub_make_system_path_relative_to_its_root): - New prototype. - - * include/grub/test.h: Fix functional test modules' naming. - * grub-core/tests/example_functional_test.c: Fix test module name. - - * util/misc.c: Hosted versions' of grub functions for libgrub.a - * tests/lib/unit_test.c: Remove hosted versions of grub functions. - * util/grub-editenv.c: Likewise. - * util/grub-fstest.c: Likewise. - * util/grub-mkdevicemap.c: Likewise. - * util/grub-mkfont.c: Likewise. - * util/grub-mkimage.c: Likewise. - * util/grub-mkpasswd-pbkdf2.c: Likewise. - * util/grub-probe.c: Likewise. - * util/grub-script-check.c: Likewise. - * util/i386/pc/grub-setup.c: Likewise. - * util/sparc64/ieee1275/grub-setup.c: Likewise. - - * tests/util/grub-shell.in: Fix override directory path. - * util/grub-mkrescue.in: Replace @pkglib_DATA@ with files. - * util/import_gcry.py: Create Makefile.gcry.def file instead. - - * util/lvm.c: Update #includes. - * util/raid.c: Likewise. - * util/resolve.c: Likewise. - * grub-core/bus/emu/pci.c: Likewise. - * grub-core/lib/posix_wrap/stdlib.h: Likewise. - * grub-core/lib/posix_wrap/string.h: Likewise. - * grub-core/kern/emu/main.c: Likewise. - - * grub-core/gensymlist.sh: New file. Script for generating kernel - symbols file. - * grub-core/genmoddep.awk: Support new kernel_syms.lst format. - - * grub-core/gentrigtables.c: Fix unused variable warnings. - - * Makefile.in: Removed. - * conf/any-emu.rmk: Removed. - * conf/common.rmk: Removed. - * conf/i386-coreboot.rmk: Removed. - * conf/i386-efi.rmk: Removed. - * conf/i386-ieee1275.rmk: Removed. - * conf/i386-multiboot.rmk: Removed. - * conf/i386-pc.rmk: Removed. - * conf/i386-qemu.rmk: Removed. - * conf/i386.rmk: Removed. - * conf/mips-yeeloong.rmk: Removed. - * conf/mips.rmk: Removed. - * conf/powerpc-ieee1275.rmk: Removed. - * conf/sparc64-ieee1275.rmk: Removed. - * conf/tests.rmk: Removed. - * conf/x86-efi.rmk: Removed. - * conf/x86_64-efi.rmk: Removed. - * gendistlist.sh: Removed. - * geninitheader.sh: Removed. - * genkernsyms.sh.in: Removed. - * genmk.rb: Removed. - * gensymlist.sh.in: Removed. - * mkinstalldirs: Removed. - * boot: Moved ... - * grub-core/boot: ... to here. - * bus: Moved ... - * grub-core/bus: ... to here. - * commands: Moved ... - * grub-core/commands: ... to here. - * disk: Moved ... - * grub-core/disk: ... to here. - * efiemu: Moved ... - * grub-core/efiemu: ... to here. - * font: Moved ... - * grub-core/font: ... to here. - * fs: Moved ... - * grub-core/fs: ... to here. - * gencmdlist.sh: Moved ... - * grub-core/gencmdlist.sh: ... to here. - * genemuinit.sh: Moved ... - * grub-core/genemuinit.sh: ... to here. - * genemuinitheader.sh: Moved ... - * grub-core/genemuinitheader.sh: ... to here. - * genfslist.sh: Moved ... - * grub-core/genfslist.sh: ... to here. - * genhandlerlist.sh: Moved ... - * grub-core/genhandlerlist.sh: ... to here. - * genmoddep.awk: Moved ... - * grub-core/genmoddep.awk: ... to here. - * genmodsrc.sh: Moved ... - * grub-core/genmodsrc.sh: ... to here. - * genpartmaplist.sh: Moved ... - * grub-core/genpartmaplist.sh: ... to here. - * genparttoollist.sh: Moved ... - * grub-core/genparttoollist.sh: ... to here. - * genterminallist.sh: Moved ... - * grub-core/genterminallist.sh: ... to here. - * gentrigtables.c: Moved ... - * grub-core/gentrigtables.c: ... to here. - * genvideolist.sh: Moved ... - * grub-core/genvideolist.sh: ... to here. - * gettext: Moved ... - * grub-core/gettext: ... to here. - * gfxmenu: Moved ... - * grub-core/gfxmenu: ... to here. - * gnulib: Moved ... - * grub-core/gnulib: ... to here. - * hello: Moved ... - * grub-core/hello: ... to here. - * hook: Moved ... - * grub-core/hook: ... to here. - * io: Moved ... - * grub-core/io: ... to here. - * kern: Moved ... - * grub-core/kern: ... to here. - * lib: Moved ... - * grub-core/lib: ... to here. - * loader: Moved ... - * grub-core/loader: ... to here. - * mmap: Moved ... - * grub-core/mmap: ... to here. - * normal: Moved ... - * grub-core/normal: ... to here. - * partmap: Moved ... - * grub-core/partmap: ... to here. - * parttool: Moved ... - * grub-core/parttool: ... to here. - * script: Moved ... - * grub-core/script: ... to here. - * term: Moved ... - * grub-core/term: ... to here - * tests/example_functional_test.c: Moved ... - * grub-core/tests/example_functional_test.c: ... to here. - * tests/lib/functional_test.c: Moved ... - * grub-core/tests/lib/functional_test.c: ... to here. - * tests/lib/test.c: Moved ... - * grub-core/tests/lib/test.c: ... to here. - * video: Moved ... - * grub-core/video: ... to here. - -2010-08-23 BVK Chaitanya - - Replace --enable-grub-emu-modules with grub-emu-lite. - - * kern/emu/cache.S: New file. Wrapper for $target_cpu specific - cache.S. - - * include/grub/emu/misc.h (grub_emu_init): New prototype. - * kern/emu/full.c: New file. For grub-emu specific initialization. - * kern/emu/lite.c: New file. For grub-emu-lite initialization. - * kern/emu/main.c: Call initialization function grub_emu_init. - - * Makefile.in: Include grub-emu-lite in install. - * commands/parttool.c: Use grub_no_autoload to differentiate - between grub-emu and grub-emu-lite. - * include/grub/misc.h: New variable grub_no_autoload. - - * conf/any-emu.rmk: New rules for grub-emu-lite. - * configure.ac: Remove --enable-grub-emu-modules. - * genmk.rb: Cleanup unnecessary rules. - * include/grub/dl.h: Remove GRUB_NO_MODULES macro. - - * normal/main.c: Don't load list files on grub-emu-lite. - * util/misc.c (grub_arch_sync_caches): Removed. - -2010-08-23 Colin Watson - - * kern/mips/startup.S (grub_prefix): Update comment to refer to - grub-mkimage rather than grub-mkelfimage. - * kern/powerpc/ieee1275/startup.S (grub_prefix): Likewise. - -2010-08-22 Vladimir Serbinenko - - * term/at_keyboard.c (grub_at_keyboard_getkey_noblock): Don't discard - a key after CapsLock or NumLock. It's just a qemu bug. - -2010-08-21 Vladimir Serbinenko - - * include/grub/usb.h (grub_usb_device): Add 'data' field back. It's - needed by libusb wrapper. - -2010-08-21 Samuel Thibault - - * docs/grub.texi (GNU/Hurd): Document booting GNU/Hurd. - -2010-08-21 Vladimir Serbinenko - - * loader/multiboot.c (grub_cmd_module): Don't unzip module if - --nounzip is passed. - -2010-08-20 Vladimir Serbinenko - - USB hotunplugging and USB serial support. - - * bus/usb/ohci.c (grub_ohci_transfer): Fill *actual and respect timeout. - * bus/usb/uhci.c (grub_free_queue): Compute *actual. - (grub_uhci_transfer): Respect timeout and set *actual. - * bus/usb/usb.c (grub_usb_device_initialize): Correctly skip fields of - non-standard length. - (grub_usb_device_attach): Autoload modules. - (GRUB_MOD_INIT): Set grub_term_poll_usb. - (GRUB_MOD_FINI): Unset grub_term_poll_usb. - * bus/usb/usbhub.c (grub_usb_hub): Replace speed with devices. All - users updated. - (grub_usb_add_hub): Fill nports and children. - (attach_root_port): Receive hub instead of controller. - All users updated. Fill hub->devices. - (grub_usb_root_hub): Allocate hub->devices. - (detach_device): New function. - (poll_nonroot_hub): Fill children and detach devices. - * bus/usb/usbtrans.c (grub_usb_bulk_readwrite): Accept timeout and - actual arguments. All users updated. - (grub_usb_bulk_read_extended): New function. - * bus/usb/serial/common.c: New file. - * bus/usb/serial/ftdi.c: Likewise. - * bus/usb/serial/pl2303.c: Likewise. - * commands/terminal.c (handle_command): Support wildcard. - * commands/usbtest.c: Output "Unknown" instead of empty string. - * conf/any-emu.rmk (pkglib_MODULES): Add usbserial_common.mod. - (usbserial_common_mod_SOURCES): New variable. - (usbserial_common_mod_CFLAGS): Likewise. - (usbserial_common_mod_LDFLAGS): Likewise. - (pkglib_MODULES): Add usbserial_pl2303.mod. - (usbserial_pl2303_mod_SOURCES): New variable. - (usbserial_pl2303_mod_CFLAGS): Likewise. - (usbserial_pl2303_mod_LDFLAGS): Likewise. - (pkglib_MODULES): Add usbserial_ftdi.mod. - (usbserial_ftdi_mod_SOURCES): New variable. - (usbserial_ftdi_mod_CFLAGS): Likewise. - (usbserial_ftdi_mod_LDFLAGS): Likewise. - (pkglib_MODULES): Add serial.mod. - (serial_mod_SOURCES): New variable. - (serial_mod_CFLAGS): Likewise. - (serial_mod_LDFLAGS): Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/mips-yeeloong.rmk: Likewise. - * conf/i386.rmk (serial_mod_SOURCES): Add term/ns8250.c. - * conf/mips-yeeloong.rmk (kernel_img_SOURCES): Likewise. - * disk/usbms.c (first_available_slot): New variable. - (grub_usbms_attach): Don't reuse free slots due to potential cache - problems. - * include/grub/serial.h: Moved to .. - * include/grub/ns8250.h: ...this. - * include/grub/serial.h: New file. - * include/grub/term.h (grub_term_poll_usb): New variable. - * include/grub/terminfo.h (grub_terminfo_input_state): Pass term to - readkey. All users updated. - (grub_terminfo_output_state): Pass term to put. - * include/grub/usb.h (GRUB_USB_REQTYPE): New enum. - (grub_usb_controller_dev): Add timeout and actual arguments to - transfer. All users updated. - (grub_usb_interface): New field detach_data. - (grub_usb_device): New fields children and nports. - (grub_usb_ep_type_t): New type. - (grub_usb_get_ep_type): New function. - (grub_usb_bulk_read_extended): Likewise. - * include/grub/usbdesc.h (grub_usb_desc): New type. - * include/grub/usbserial.h: New file. - * include/grub/usbtrans.h (grub_usb_transaction): New field preceding. - * kern/term.c (grub_term_poll_usb): New variable. - (grub_getkey): Call grub_term_poll_usb if set. - (grub_checkkey): Likewise. - (grub_getkeystatus): Likewise. - * term/serial.c: Moved controller-specific parts to ... - * term/ns8250.c: ... here. - * term/serial.c: Mostly rewritten. - * term/usb_keyboard.c: Reorganised to use GET_REPORT only on attaching - according to spec. - -2010-08-20 Robert Millan - - Make kFreeBSD code more generic to support ext2fs as root, ufs as - a separate module and maybe other interesting combinations. - - * util/grub.d/10_kfreebsd.in (load_kfreebsd_module): New function. - (kfreebsd_entry): Use load_kfreebsd_module() to load modules. - (kfreebsd_entry): Add generic filesystem module load routine. - Map GRUB `ext2' to kFreeBSD `ext2fs'. - -2010-08-20 Colin Watson - - * commands/i386/pc/sendkey.c (keysym_table): Rename "numlock" to - "numcenter" (I misunderstood the purpose of this entry). - * docs/grub.texi (sendkey): Likewise. - -2010-08-20 Colin Watson - - * commands/i386/pc/sendkey.c (options): Remove "keep" from all - status flag options; simply omitting the option is equivalent and - simpler. Rename "wait" to "pause". Rename "sysreq" to "sysrq". - (keysym_table): Rename "num5numlock" to "numlock". - (grub_cmd_sendkey): Reinitialise `andmask' and `ormask', so that we - can uniformly say that only the last of multiple `sendkey' - invocations has any effect. - * docs/grub.texi (sendkey): New section. - -2010-08-19 Colin Watson - - * commands/i386/pc/sendkey.c (options): Fix three typos. - -2010-08-19 Vladimir Serbinenko - - Implement sendkey support. - - * commands/i386/pc/sendkey.c: New file. - * conf/i386-pc.rmk (pkglib_MODULES): Add sendkey.mod. - (sendkey_mod_SOURCES): New variable. - (sendkey_mod_CFLAGS): Likewise. - (sendkey_mod_LDFLAGS): Likewise. - -2010-08-18 Colin Watson - - * configure.ac: Move AM_INIT_AUTOMAKE after AC_CANONICAL_TARGET to - fix warnings from Autoconf. - -2010-08-18 Colin Watson - - * acinclude.m4 (grub_ASM_USCORE): Use a more accurate grep pattern, - to avoid false positives with some assemblers that output things - like "someprefix_func" as part of their output. - -2010-08-15 Robert Millan - - * kern/emu/misc.c (grub_get_libzfs_handle): Handle libzfs_init() - errors. - * kern/emu/getroot.c (find_root_device_from_libzfs): Handle - grub_get_libzfs_handle() errors. - -2010-08-14 Robert Millan - - * kern/emu/misc.c (grub_find_zpool_from_dir): Abort function if - filesystem is not ZFS. - -2010-08-12 BVK Chaitanya - - Fix for misspelled color names defaulting to black/black (bug - reported by Doug Nazar) - - * include/grub/normal.h (grub_parse_color_name_pair): Add return - status to prototype. - * normal/color.c (grub_parse_color_name_pair): Return failure - status. - (grub_env_write_color_normal): Ignore bad color names. - (grub_env_write_color_highlight): Likewise. - * normal/main.c (GRUB_MOD_INIT): Set default color names. - -2010-08-12 BVK Chaitanya - - "shift" command support to GRUB script. - - * include/grub/script_sh.h (grub_script_shift): New prototype. - * script/execute.c (grub_script_shift): New function. - * script/main.c (grub_script_init): Register shift command. - (grub_script_fini): Unregister shift command. - * util/grub-script-check.c (grub_script_cmd_shift): New function. - - * tests/grub_script_shift.in: New testcase. - * conf/tests.rmk: Rules for new testcase. - -2010-08-12 BVK Chaitanya - - "continue" command support to GRUB script. - - * script/execute.c (grub_script_execute_cmdwhile): Continue support. - (grub_script_break): Continue support. - * script/main.c (grub_script_init): Register continue command. - (grub_script_fini): Unregister continue command. - - * tests/grub_script_continue.in: New testcase. - * conf/tests.rmk: Rules for new testcase. - -2010-08-12 BVK Chaitanya - - "break" command support to GRUB script. - - * conf/common.rmk: Rule updates to grub-script-check. - * include/grub/misc.h (grub_min): New function. - * include/grub/script_sh.h (grub_script_init): New prototype. - (grub_script_fini): New prototype. - (grub_script_break): New prototype. - * script/main.c (grub_script_init): New function. - (grub_script_fini): New function. - * script/execute.c (grub_script_break): New function. - * normal/main.c: Calls to grub_script_{init,fini}. - * util/grub-script-check.c (grub_script_break): New function. - - * tests/grub_script_break.in: New testcase. - * conf/tests.rmk: Rules for new test case. - -2010-08-12 BVK Chaitanya - - Function parameters support to GRUB script. - - * script/yylex.l (VARIABLE): Regular expression update. - * script/function.c (grub_script_function_call): Moved ... - * script/execute.c (grub_script_function_call): ... to here. - (grub_script_execute_arglist_to_argv): Removed. - (grub_script_arglist_to_argv): New function. - * script/argv.c: New file. - (grub_script_argv_free): New function. - (grub_script_argv_next): Likewise. - (grub_script_argv_append): Likewise. - (grub_script_argv_split_append): Likewise. - * include/grub/script_sh.h (grub_script_argv): New struct. - (grub_script_argv_free): New function. - (grub_script_argv_next): Likewise. - (grub_script_argv_append): Likewise. - (grub_script_argv_split_append): Likewise. - - * conf/common.rmk (normal.mod): New source script/argv.c. - - * tests/grub_script_echo1.in: More tests. - * tests/grub_script_vars1.in: Likewise. - * tests/grub_script_functions.in: New test case. - * conf/tests.rmk: Rules for new testcase. - -2010-08-12 BVK Chaitanya - - Remove grub_script_cmdblock struct. - - * include/grub/script_sh.h: Remove grub_script_cmdblock. - * script/parser.y: Likewise. - * script/execute.c: Rename cmdblock suffix to cmdlist. - * script/script.c: Likewise. - * util/grub-script-check.c: Likewise. - -2010-08-11 Yves Blusseau - - * .bzrignore: add grub-macho2img - -2010-08-11 Vladimir Serbinenko - - * kern/i386/qemu/init.c (grub_qemu_init_cirrus): Fix compilation error. - -2010-08-11 Vladimir Serbinenko - - Remove the dump of sm712 initialisation sequence. - - * include/grub/pci.h (GRUB_PCI_CLASS_SUBCLASS_VGA): New const. - * include/grub/vga.h (GRUB_VGA_IO_ARX_READ): New register. - (GRUB_VGA_IO_MISC_WRITE): Likewise. - (GRUB_VGA_CR_*): Added many registers. - (GRUB_VGA_SR_*): Likewise. - (GRUB_VGA_GR_*): Likewise. - (grub_vga_write_arx): New function. - (grub_video_hw_config): New struct. - (grub_vga_set_geometry): New function. - * kern/i386/qemu/init.c (load_palette): Use grub_vga_write_arx and - GRUB_PCI_CLASS_SUBCLASS_VGA. - * video/cirrus.c (grub_video_cirrus_setup): Use grub_vga_set_geometry. - * video/sm712.c (grub_sm712_write_reg): New function - (grub_sm712_read_reg): Likewise. - (grub_sm712_sr_write): Likewise. - (grub_sm712_gr_write): Likewise. - (grub_sm712_cr_write): Likewise. - (grub_sm712_write_arx): Likewise. - (grub_sm712_cr_shadow_write): Likewise. - (grub_sm712_write_dda_lookup): Likewise. - (grub_video_sm712_setup): Initialise the video rather then - blindly replay the dump. - (main) [TEST]: Add a routine to be able to compile as standalone for - tests. - * video/sm712_init.c (sm712_init): Removed. - (sm712_sr_seq1): New array. - (sm712_sr_seq2): Likewise. - -2010-08-10 Vladimir Serbinenko - - * include/grub/vga.h: Add missing grub/pci.h include. - -2010-08-10 Yves Blusseau - - * util/grub-macho2img.c (main): fix typo - -2010-08-10 Vladimir Serbinenko - - * include/grub/vga.h (grub_vga_gr_write): Add GRUB_MACHINE_PCI_IO_BASE. - (grub_vga_gr_read): Likewise. - (grub_vga_cr_write): Likewise. - (grub_vga_cr_read): Likewise. - (grub_vga_sr_write): Likewise. - (grub_vga_sr_read): Likewise. - (grub_vga_palette_read): Likewise. - (grub_vga_palette_write): Likewise. - * video/sm712.c (GRUB_SM712_REG_BASE): New definition. - (grub_sm712_sr_read): New function. - (grub_video_sm712_setup): Use grub_vga_sr_write and grub_sm712_sr_read. - * video/sm712_init.c (sm712_init): Substract GRUB_MACHINE_PCI_IO_BASE. - -2010-08-09 Robert Millan - - * kern/emu/misc.c (grub_make_system_path_relative_to_its_root): Filter - out unused variables on non-ZFS build. - -2010-08-08 Robert Millan - - Fix path generation for sub-filesystems in ZFS. - - * kern/emu/misc.c (grub_make_system_path_relative_to_its_root): Add - missing slash. - -2010-08-08 Robert Millan - - * util/grub-fstest.c (read_file, cmd_cmp): Improve error message. - -2010-08-08 Robert Millan - - * util/grub.d/10_kfreebsd.in: When files required for ZFS do not - exist, issue a proper error message (rely on `ls' for translated - strings). - -2010-08-08 Robert Millan - - Fix grub-probe invocation. - - * util/grub.d/10_kfreebsd.in: s/label/fs_label/g. - -2010-08-04 Robert Millan - - * configure.ac: Remove checks for getfsstat() and getmntany(). - Add checks for `' and `'. - * kern/emu/misc.c [HAVE_GETMNTANY]: Remove `'. - [HAVE_SYS_PARAM_H]: Include `'. - [HAVE_SYS_MOUNT_H]: Include `'. - [HAVE_LIBZFS && HAVE_LIBNVPAIR] (find_mount_point_from_dir): Remove - function. - (grub_find_zpool_from_dir): Use statfs() instead of indirect matching - via find_mount_point_from_dir() and getfsstat() / getmntany(). - -2010-08-04 Robert Millan - - * include/grub/emu/misc.h (grub_find_mount_point_from_dir) - (grub_find_zpool_from_mount_point): Merge into ... - (grub_find_zpool_from_dir): ... this. - * kern/emu/misc.c: Likewise. - - * kern/emu/misc.c - (grub_make_system_path_relative_to_its_root): Replace - grub_find_mount_point_from_dir() / grub_find_zpool_from_mount_point() - with grub_find_zpool_from_dir(). - * kern/emu/getroot.c (find_root_device_from_libzfs): Likewise. - -2010-08-04 Robert Millan - - Support OpenSolaris in ZFS device resolution. - - * configure.ac: Check for getmntany(). - * kern/emu/misc.c [HAVE_GETMNTANY]: Include `'. - [HAVE_GETMNTANY] (grub_find_zpool_from_mount_point): Add OpenSolaris - support. - -2010-08-03 Robert Millan - - Fix grub-emu build. - - * include/grub/util/misc.h: Move `' to ... - * include/grub/emu/misc.h: ... here. - - * include/grub/util/misc.h (grub_get_libzfs_handle): Move function ... - * include/grub/emu/misc.h (grub_get_libzfs_handle): ... here. - - * util/misc.c: Remove `'. - [HAVE_LIBZFS] (libzfs_handle, fini_libzfs) - (grub_get_libzfs_handle): Move to ... - * kern/emu/misc.c [HAVE_LIBZFS] (__libzfs_handle, fini_libzfs) - (grub_get_libzfs_handle): ... here. - -2010-08-03 BVK Chaitanya - - * script/execute.c (grub_script_execute_cmdline): Check for NULL - as command name case. - -2010-08-02 Colin Watson - - * disk/raid.c (insert_array): Select unique numbers for named arrays - as well, for use as keys in the disk cache. - -2010-08-01 Robert Millan - - * util/grub.d/10_kfreebsd.in: Initialize ${kfreebsd_device} as the - kFreeBSD device name, except on ZFS where the filesystem label is - used. - (kfreebsd_entry): On ZFS root, load `opensolaris.ko', `zfs.ko' and - `/boot/zfs/zpool.cache'. - Set mountfrom kernel variable using ${kfreebsd_device}. - -2010-08-01 Robert Millan - - Make it even harder to use uninitialized `libzfs_handle' (and - make the interface a bit simpler). - - * include/grub/util/misc.h (grub_util_init_libzfs) - (libzfs_handle): Remove. - (grub_get_libzfs_handle): New prototype. - - * util/misc.c [HAVE_LIBZFS] (libzfs_handle): Add `static' - attribute. - (grub_util_init_libzfs): Remove. - (grub_get_libzfs_handle): New function. - - * kern/emu/getroot.c (find_root_device_from_libzfs): Use - grub_get_libzfs_handle() to obtain a libzfs handle instead of - accessing `libzfs_handle' directly. - -2010-08-01 Robert Millan - - * include/grub/emu/misc.h (grub_find_mount_point_from_dir) - (grub_find_zpool_from_mount_point): New function prototypes. - - * kern/emu/getroot.c [HAVE_GETFSSTAT]: Move `' to ... - * kern/emu/misc.c [HAVE_GETFSSTAT]: ... here. - - * kern/emu/getroot.c (find_mount_point_from_dir): Move to ... - * kern/emu/misc.c (grub_find_mount_point_from_dir): ... this. Remove - `static' attribute. - - * kern/emu/getroot.c (find_root_device_from_libzfs): Split code for - finding zpool from mount point into ... - * kern/emu/misc.c (grub_find_zpool_from_mount_point): ... this. - - * kern/emu/misc.c (grub_make_system_path_relative_to_its_root): When - requested path is part of a ZFS pool, use - grub_find_zpool_from_mount_point() to detect its filesystem name, - and generate a path with `/fsname@path' syntax. - -2010-08-01 Colin Watson - - * include/grub/util/libzfs.h (libzfs_init): Set argument list to - (void) rather than () so that this is a proper prototype. - -2010-08-01 Vladimir Serbinenko - - * lib/arg.c (grub_arg_show_help): Add the necessary spacing. - -2010-08-01 Vladimir Serbinenko - - * kern/emu/getroot.c (find_mount_point_from_dir): Compile only if - [HAVE_LIBZFS && HAVE_LIBNVPAIR] - -2010-08-01 Colin Watson - - * util/grub-mkrescue.in: Remove ${efi_dir} after building efi.img. - -2010-08-01 Colin Watson - - * script/yylex.l (NAME): Remove [:digit:], redundant with [:alnum:]. - -2010-08-01 Colin Watson - - * docs/grub.texi (Simple configuration): Document GRUB_CMDLINE_XEN - and GRUB_CMDLINE_XEN_DEFAULT. Recommend setting - GRUB_GFXPAYLOAD_LINUX=text rather than unsetting it in order to - disable gfxpayload. - (Shell-like scripting): Add real content. - (Serial terminal): Suggest `terminal_input serial; terminal_output - serial' rather than putting the two commands on separate lines, - since console input will be inoperative after the first command. - (menuentry): Document --class, --users, and --hotkey options. - (terminfo): Describe what `visually-ordered UTF-8' means (thanks, - Vladimir Serbinenko). - -2010-08-01 Vladimir Serbinenko -2010-08-01 Colin Watson - - * kern/misc.c (grub_memset): Optimise to reduce cache stalls. - -2010-08-01 Robert Millan - - * include/grub/emu/misc.h (grub_find_mount_point_from_dir) - (grub_find_zpool_from_mount_point): New function prototypes. - - * kern/emu/getroot.c [HAVE_GETFSSTAT]: Move `' to ... - * kern/emu/misc.c [HAVE_GETFSSTAT]: ... here. - - * kern/emu/getroot.c (find_mount_point_from_dir): Move to ... - * kern/emu/misc.c (grub_find_mount_point_from_dir): ... this. Remove - `static' attribute. - - * kern/emu/getroot.c (find_root_device_from_libzfs): Split code for - finding zpool from mount point into ... - * kern/emu/misc.c (grub_find_zpool_from_mount_point): ... this. - - * kern/emu/misc.c (grub_make_system_path_relative_to_its_root): When - requested path is part of a ZFS pool, use - grub_find_zpool_from_mount_point() to detect its filesystem name, - and generate a path with `/fsname@path' syntax. - -2010-08-01 Robert Millan - - Prevent accidental use of uninitialized libzfs_handle. - - * util/grub-probe.c (main): Move grub_util_init_libzfs() call to ... - * kern/emu/getroot.c (find_root_device_from_libzfs): ... here. - * util/misc.c (grub_util_init_libzfs): Make this function idempotent. - -2010-08-01 Colin Watson - - * util/grub.d/20_linux_xen.in: Don't use UUID for LVM root (matching - util/grub.d/10_linux.in). Fixes Debian bug #591093. - -2010-08-01 Robert Millan - - * kern/emu/getroot.c: Include `'. - -2010-07-31 Robert Millan - - * util/grub.d/10_kfreebsd.in: Make module handling more generic. - -2010-07-31 Robert Millan - - * kern/emu/misc.c: Add missing license header. - -2010-07-31 Robert Millan - - * configure.ac: Check for `libzfs.h' and `libnvpair.h'. - - * include/grub/util/libnvpair.h: Include `'. - [HAVE_LIBNVPAIR_H]: Include `' instead of - declaring libnvpair prototypes ourselves. - * include/grub/util/libzfs.h: Include `'. - [HAVE_LIBZFS_H]: Include `' instead of - declaring libzfs prototypes ourselves. - - (libzfs_handle): Moved to ... - * include/grub/util/misc.h (libzfs_handle): ... here. - Include `'. - -2010-07-30 Robert Millan - - * include/grub/emu/misc.h: Add missing license header. - -2010-07-30 Robert Millan - - Enable `grub-probe -t device' resolution on ZFS. - - * configure.ac: Check for getfsstat(), libzfs and libnvpair. - * include/grub/util/libnvpair.h: New file. - * include/grub/util/libzfs.h: New file. - - * kern/emu/getroot.c: Include `' and `'. - [HAVE_LIBZFS && HAVE_LIBNVPAIR]: Include `' and - `'. - [HAVE_GETFSSTAT]: Include `'. - - (find_mount_point_from_dir): New static function. - [HAVE_LIBZFS && HAVE_LIBNVPAIR] (find_root_device_from_libzfs): New - function. - [HAVE_LIBZFS && HAVE_LIBNVPAIR] (grub_guess_root_device): Use - find_root_device_from_libzfs() before ressorting to find_root_device(). - - * include/grub/util/misc.h (grub_util_init_libzfs): New function - prototype. - * util/misc.c: Include `'. - (grub_util_init_libzfs): New function. - [HAVE_LIBZFS] (libzfs_handle): New global variable. - [HAVE_LIBZFS] (fini_libzfs): New static function. - (grub_util_init_libzfs): New function. - * util/grub-probe.c (main): Call grub_util_init_libzfs(). - -2010-07-30 Robert Millan - - * include/grub/emu/misc.h (grub_make_system_path_relative_to_its_root) - (xmalloc, xrealloc, xstrdup, xasprintf): Add - `warn_unused_result' attribute. - * include/grub/misc.h (grub_strdup, grub_strndup, grub_strlen) - (grub_xasprintf, grub_xvasprintf): Likewise. - * include/grub/emu/misc.h (xasprintf): Remove duplicate prototype. - -2010-07-29 Robert Millan - - * util/grub-probe.c (PRINT_FS_LABEL): New enum value. - (probe): Handle `PRINT_FS_LABEL'. - (main): Handle `-t fs_label'. - -2010-07-29 Robert Millan - - * configure.ac: Remove grub-mkisofs checks. - -2010-07-28 Vladimir Serbinenko - - * util/ieee1275/grub-install.in: Don't use empty grub_device. - Reported by: Lennart Sorensen. - -2010-07-20 Vladimir Serbinenko - - * util/grub.d/00_header.in: Remove compatibility with terminal.mod - prior to terminal_input/terminal_output separation. It's been over 1.5 - years and those versions weren't widely deployed. - -2010-07-22 Colin Watson - - * disk/raid.c (insert_array): Don't count named arrays when looking - for unused array numbers. - Reported and tested by: Michael Guntsche. - -2010-07-20 Colin Watson - - * bus/usb/emu/usb.c (grub_usb_poll_devices): Add a dummy - implementation of this so that grub-emu links again, with a note - that this should support hotplugging in the future. - -2010-07-20 Colin Watson - - * kern/emu/getroot.c (grub_util_get_grub_dev): Use xasprintf. - -2010-07-20 Colin Watson - - * disk/loopback.c (grub_cmd_loopback): Don't leak a grub_file_t - handle on failure. - (grub_loopback_close): Remove empty function. - (grub_loopback_dev): Remove close method. - -2010-07-20 Colin Watson - - Disable EFI cursor when the EFI console becomes inactive. - - * term/efi/console.c (grub_efi_console_init): New function. - (grub_efi_console_fini): New function. - (grub_console_term_output): Register init and fini methods. - -2010-07-20 Vladimir Serbinenko - - * tests/util/grub-shell-tester.in: Remove bashism and declare as - sh script. - -2010-07-20 Vladimir Serbinenko - - * disk/loopback.c (grub_loopback): Replace filename with file. - (delete_loopback): Handle new semantics. - (grub_cmd_loopback): Likewise. - (grub_loopback_iterate): Likewise. - (grub_loopback_close): Likewise. - -2010-07-20 Vladimir Serbinenko - - * util/i386/efi/grub-install.in: Revert to platform-specific behaviour - with -p "". - Reported by: Tito Keitel. - -2010-07-20 Vladimir Serbinenko - - * docs/grub.texi (Naming convention): Document new naming convention. - -2010-07-20 Vadim Solomin -2010-07-20 Colin Watson - - Generate device.map in something closer to the old ordering. - - * util/deviceiter.c (struct device): New declaration. - (compare_file_names): Rename to ... - (compare_devices): ... this. Sort by kernel name in preference to - the stable by-id name, but keep the latter as a fallback comparison. - Update header comment. - (grub_util_iterate_devices) [__linux__]: Construct and sort an array - of `struct device' rather than of plain file names. - -2010-07-20 Thomas Frauendorfer - - * lib/i386/relocator_asm.S [! __x86_64__]: Don't try to disable amd64 - on i386. - -2010-07-20 Vladimir Serbinenko - - * commands/acpi.c (setup_common_tables): Use sizeof instead of - hardcoding size. - (setv1table): Likewise. - -2010-07-20 Colin Watson - - * disk/raid.c (insert_array): Use md/%s to name mdadm 1.x devices, - removing the homehost if present. - * kern/emu/getroot.c (get_mdadm_name) [__linux__]: New function. - (grub_util_get_grub_dev): Use md/%s to name mdadm 1.x devices, - removing the homehost if present. - (grub_util_get_grub_dev) [__linux__]: Get the array name from mdadm - if possible. - * util/i386/pc/grub-setup.c (main): Handle md/* devices. - - * disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Add start_sector - parameter. Set its pointer target to 0. - * disk/mdraid_linux.c (grub_mdraid_detect): Add start_sector - parameter. Set its pointer target to 0 for 0.9 metadata, or to the - `data_offset' value from the superblock for 1.x metadata. - * disk/raid.c (grub_raid_read): Offset reads by the start sector of - data on the device. - (insert_array): Record the start sector of data on the device. - (grub_raid_register): Pass start_sector parameters to - grub_raid_list->detect and insert_array. - * include/grub/raid.h (struct grub_raid_array): Add start_sector - member. - (struct grub_raid): Add start_sector parameter to `detect'. - - * disk/mdraid_linux.c (struct grub_raid_super_1x): Remove - __attribute__ ((packed)), leaving a comment. - (grub_mdraid_detect): Split out 0.9 and 1.x detection to ... - (grub_mdraid_detect_09): ... here and ... - (grub_mdraid_detect_1x): ... here. - -2010-07-20 Peter Henn - - * disk/mdraid_linux.c (grub_mdraid_detect): Fix calculation of 1.x - chunk size and disk size, which are already given as sector counts - as distinct from the 0.90 units. Fetch the correct device number - from the role table instead of using the table index. - -2010-07-20 Felix Zielcke - - * disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Set array->name to NULL. - * disk/mdraid_linux.c (grub_raid_super_1x): New structure. - (WriteMostly1): New macro. - Set array->name to NULL for metadata format 0.90. Add support for - metadata 1.x. Fix some comments. - * disk/raid.c (): Add support for name based RAID arrays. Fix a - few comments. - * util/getroot.c (grub_util_get_grub_dev): Add support for - /dev/md/name style devices. - -2010-07-20 Colin Watson - - * .bzrignore: Ignore 20_linux_xen. - -2010-07-17 Colin Watson - - * util/import_unicode.py: Remove unnecessary imports. - -2010-07-17 AleÅ¡ Nesrsta - - Hotplugging and USB hub support. - - * bus/usb/ohci.c (grub_ohci_td): Add convenience fields. - (grub_ohci): Likewise. - (GRUB_OHCI_REG_CONTROL_BULK_ENABLE): New definition. - (GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE): Likewise. - (GRUB_OHCI_RESET_CONNECT_CHANGE): Likewise. - (GRUB_OHCI_CTRL_EDS): Likewise. - (GRUB_OHCI_BULK_EDS): Likewise. - (GRUB_OHCI_TDS): Likewise. - (GRUB_OHCI_ED_ADDR_MASK): Likewise. - (grub_ohci_ed_phys2virt): New function. - (grub_ohci_virt_to_phys): Likewise. - (grub_ohci_td_phys2virt): Likewise. - (grub_ohci_td_virt2phys): Likewise. - (grub_ohci_pci_iter): Allocate memory and don't wait for stable - attachment. - (grub_ohci_find_ed): New function. - (grub_ohci_alloc_td): Likewise. - (grub_ohci_free_td): Likewise. - (grub_ohci_free_tds): Likewise. - (grub_ohci_transfer): Use previously allocated memory. - (grub_ohci_portstatus): Reset status changed bit. - (grub_ohci_detect_dev): Supply status changed. - (grub_ohci_fini_hw): Free memory. - (grub_ohci_restore_hw): Reallocate memory. - * bus/usb/uhci.c (grub_uhci_portstatus): Don't reset on disable. - Reset status change. - (grub_uhci_detect_dev): Supply status_change. - * bus/usb/usb.c (attach_hooks): New var. - (grub_usb_device_attach): New function. - (grub_usb_register_attach_hook_class): Likewise. - (grub_usb_unregister_attach_hook_class): Likewise. - * bus/usb/usbhub.c (grub_usb_hub_add_dev): Handle errors correctly. - (grub_usb_add_hub): Reset connection changed bit. - (attach_root_port): New function. - (grub_usb_root_hub): Likewise. - (poll_nonroot_hub): Likewise. - (grub_usb_poll_devices): Likewise. - * commands/usbtest.c (grub_cmd_usbtest): Poll devices before listing. - * disk/usbms.c (grub_usbms_open): Use device hooks. - (grub_usbms_iterate) :Poll devices. - (grub_usbms_finddevs): Split into ... - (grub_usbms_attach): ... this ... - (grub_usbms_attach): ... and this. - * include/grub/usb.h (grub_usb_controller_dev): Supply status_changed - in detect_dev. - (grub_usb_interface): New fields attached and detach_hook. - (grub_usb_attach_hook_class): New type. - (grub_usb_attach_desc): New struct. - (grub_usb_register_attach_hook_class): New function. - (grub_usb_unregister_attach_hook_class): Likewise. - (grub_usb_poll_devices): Likewise. - (grub_usb_device_attach): Likewise. - * include/grub/usbtrans.h (GRUB_USB_HUB_FEATURE_C_CONNECTED): New const. - (GRUB_USB_HUB_STATUS_C_CONNECTED): Likewise. - -2010-07-17 Vladimir Serbinenko - - * include/grub/bsdlabel.h (GRUB_PC_PARTITION_BSD_LABEL_WHOLE_DISK_PARTITION): New definition. - * partmap/bsdlabel.c (bsdlabel_partition_map_iterate): Use FreeBSD - delta determination style. Works with most NetBSD partitions too. - -2010-07-17 Vladimir Serbinenko - - * kern/partition.c [GRUB_UTIL]: Add missing util/misc.h inclusion. - * partmap/bsdlabel.c [GRUB_UTIL]: Likewise. - -2010-07-17 Vladimir Serbinenko - - * disk/scsi.c (grub_scsi_open): Fix incorrect pointer dereference. - -2010-07-14 Anton Blanchard - - * loader/powerpc/ieee1275/linux.c (grub_cmd_linux): Do not reject - ET_DYN files. - -2010-07-14 GrĂ©goire Sutre - - * Makefile.in: Use the substituted @USE_NLS@ instead of ENABLE_NLS. - -2010-07-14 GrĂ©goire Sutre - - * kern/partition.c (grub_partition_check_containment): New function to - check that a partition is physically contained in a parent. Since - offsets are relative (and non-negative), this reduces to checking that - the partition ends before its parent. - (grub_partition_map_probe): Discard out-of-range sub-partitions. - (grub_partition_iterate): Likewise. - * include/grub/partition.h (grub_partition_map): Slightly more detailed - comments. - * partmap/bsdlabel.c (bsdlabel_partition_map_iterate): Discard - partitions that start before their parent, and add debug printfs. - -2010-07-13 Colin Watson - - * Makefile.in (.SUFFIX): Spell correctly, as ... - (.SUFFIXES): ... this. Fixes bug where `make foo' (where foo is a - bare module name without `.mod', e.g. `test') tried to invoke a - Modula-2 compiler. - -2010-07-13 Colin Watson - - * README: Point to the Info manual. - -2010-07-13 Jiro SEKIBA - - * fs/nilfs2.c: fix macro NILFS_2ND_SUPER_BLOCK to calculate - 2nd superblock position from partition size. - -2010-07-10 Colin Watson - - * Makefile.in (MAINTAINER_CLEANFILES): Remove - unicode/UnicodeData.txt, unicode/BidiMirroring.txt, and - unicode/ArabicShaping.txt again; these are inputs to autogen.sh, not - outputs. - -2010-07-10 Vladimir Serbinenko - - Restructure SCSI .id handling. - Reported and tested by: AleÅ¡ Nesrsta. - - * disk/ata.c (grub_atapi_close): Removed. All users updated. - (grub_atapi_dev): Changed .name to "ata". New field .id. - * disk/usbms.c (grub_usbms_close): Removed. All users updated. - (grub_usbms_dev): New field .id. - * disk/scsi.c (grub_scsi_iterate): Generate name. - (grub_scsi_open): Parse name. - * include/grub/scsi.h (grub_make_scsi_id): New function. - (grub_scsi_dev): Change iterate and open to number instead of naming - busses. All users updated. - (grub_scsi): Remove name. Add .bus. - -2010-07-10 Vladimir Serbinenko - - * commands/help.c (grub_cmd_help): Fix a typo. - -2010-07-10 Vladimir Serbinenko - - * normal/term.c (put_glyphs_terminal): Fix state->num_lines counting. - Reported and tested by: Colin Watson. - -2010-07-10 Vladimir Serbinenko - - * util/grub-mkrescue.in: Don't use tar GNU-ism since it's not necessary - in this context. - -2010-07-07 Vladimir Serbinenko - - * tests/util/grub-shell.in: Remove bashisms and declare as sh script. - -2010-07-07 Colin Watson - - * term/gfxterm.c (grub_gfxterm_background_image_cmd): Fix - indentation. - -2010-07-06 Colin Watson - - * conf/common.rmk (grub_probe_SOURCES): Add disk/raid5_recover.c - and disk/raid6_recover.c. - * conf/i386-pc.rmk (grub_setup_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_setup_SOURCES): Likewise. - -2010-07-06 Colin Watson - - * term/gfxterm.c (repaint_schedulded): Rename to ... - (repaint_scheduled): ... this. Update all callers. - (repaint_was_schedulded): Rename to ... - (repaint_was_scheduled): ... this. Update all callers. - -2010-07-06 Colin Watson - - * util/deviceiter.c (grub_util_iterate_devices): Skip MD devices, - which we expect to be handled by upper layers. - -2010-07-06 BVK Chaitanya - - * bus/usb/usbhub.c: #include time.h header. - -2010-07-06 Colin Watson - - * fs/reiserfs.c (grub_reiserfs_iterate_dir): Zero out first byte of - entry_name also for entries without stat blocks (e.g. ".."); fixes - corruption of the first entry in a directory. - -2010-07-06 Colin Watson - - * util/grub.d/00_header.in: Process GRUB_THEME and GRUB_BACKGROUND - after setting gfxterm as the active terminal. GRUB_BACKGROUND - doesn't work otherwise. - -2010-07-05 Colin Watson - - * docs/grub.texi (Features): Update list of supported file systems. - (GNU/Linux): Update for GRUB 2. - (Serial terminal): Remove mention of --disable-serial, which was a - GRUB Legacy configure option. Update instructions to use - `terminal_input' and `terminal_output' rather than `terminal'. - (Vendor power-on keys): Copy-edit. Add cross-references to `Simple - configuration' and `Installing GRUB using grub-install'. - (Menu entry editor): Update for GRUB 2. - (terminfo): Add vt100-color, ieee1275, and dumb terminal types. - Document new -a, -u, and -v options. - (initrd): New section. - (initrd16): New section. - (linux): New section. - (linux16): New section. - (search): The `var' argument to `--set' is optional. - (GRUB only offers a rescue shell): Go into a little more detail on - drive ordering. - -2010-07-05 Colin Watson - - * Makefile.in: Set LINGUAS to empty if ENABLE_NLS is undefined. - -2010-07-05 Colin Watson - - * Makefile.in (MAINTAINER_CLEANFILES): Add unicode/UnicodeData.txt, - unicode/BidiMirroring.txt, unicode/ArabicShaping.txt, and unidata.c. - -2010-07-05 Colin Watson - - * util/i386/pc/grub-setup.c (setup): Rename prefix to - install_prefix, in line with install_dos_part and install_bsd_part. - Add new prefix variable, which is copied to install_prefix after - comparing core.img in memory with the one read from disk in the - no-embedding case, and use that rather than overwriting - install_prefix immediately when installing to a partition. - Fixes Debian bug #586621; based on patches by Matt Kraai and M. Vefa - Bicakci. - -2010-07-04 GrĂ©goire Sutre - - * configure.ac: Avoid == in test command, it's not portable. - * util/grub.d/30_os-prober.in: Likewise. - -2010-07-04 Colin Watson - - * kern/emu/getroot.c [__GNU__]: Include for munmap. - -2010-07-04 GrĂ©goire Sutre - - * util/i386/pc/grub-setup.c (setup): Do not embed when there are - multiple (top-level) partmaps. - -2010-07-02 Vladimir Serbinenko - - * util/i386/efi/grub-install.in: Don't use empty grub_device. - Reported by: Tino Keitel. - -2010-07-02 Vladimir Serbinenko - - Bidi and diacritics support. - - * Makefile.in (widthspec.bin): New target. - (widthspec.h): Likewise. - (TARGET_CFLAGS): Add -DHAVE_UNIFONT_WIDTHSPEC=1 if font was available. - * autogen.sh: Generate unidata.c. - * commands/cat.c (grub_cmd_cat): Don't use grub_putchar. - * commands/ls.c (grub_ls_list_devices): Likewise. - (grub_ls_list_files): Likewise. - * commands/minicmd.c (grub_mini_cmd_cat): Likewise. - (grub_mini_cmd_lsmod): Likewise. - * commands/read.c: Likewise. - * kern/corecmd.c (grub_core_cmd_ls): Likewise. - * kern/rescue_reader.c (grub_rescue_read_line): Likewise. - * lib/arg.c (grub_arg_show_help): Likewise. - * lib/crypto.c (grub_password_get): Likewise. - * normal/auth.c (grub_username_get): Likewise. - * normal/misc.c (grub_normal_print_device_info): Likewise. - * commands/help.c (grub_cmd_help): Use grub_unicode_aglomerate_comb. - * conf/common.rmk (grub_mkfont_SOURCES): Add unidata.c. - (gfxmenu_mod_SOURCES): Add gfxmenu/font.c. - (normal/charset.c_DEPENDENCIES): New variable. - (normal_mod_SOURCES): Add normal/charset.c and unidata.c. - (pkglib_MODULES): Remove charset.mod. - (charset_mod_SOURCES): Removed. - (charset_mod_CFLAGS): Likewise. - (charset_mod_LDFLAGS): Likewise. - (pkglib_MODULES) [ieee1275]: Remove terminfo.mod. - * conf/powerpc-ieee1275.rmk (kernel_img_SOURCES): Add term/terminfo.c - and term/tparm.c. - * conf/sparc64-ieee1275.rmk (kernel_img_SOURCES): Likewise. - * conf/i386-ieee1275.rmk (kernel_img_SOURCES): Likewise. - (kernel_img_HEADERS): Add terminfo.h. - * font/font.c (ascii_glyph_lookup): Return NULL on failure. - Fill ->font. Reverse ascii bitmaps. - (grub_font_get_xheight): New function. - * font/font.c (grub_font_get_string_width): Moved from here ... - * gfxmenu/font.c (grub_font_get_string_width): ... here. - * font/font.c (grub_font_draw_string): Moved from here ... - * gfxmenu/font.c (grub_font_draw_string): ... here. - * font/font.c (grub_font_dup_glyph): New function. - (grub_font_blit_glyph): Likewise. - (grub_font_blit_glyph_mirror): Likewise. - (blit_comb): Likewise. - (grub_font_construct_dry_run): Likewise. - (grub_font_get_constructed_device_width): Likewise. - (grub_font_construct_glyph): Likewise. - * include/grub/charset.h (grub_ucs4_to_utf8): New proto. - * include/grub/misc.h (grub_utf8_to_ucs4): Moved from here ... - * include/grub/charset.h (grub_utf8_to_ucs4): ... here. - * include/grub/font.h (GRUB_FONT_CODE_CHAR_MASK): New constant. - (GRUB_FONT_CODE_RIGHT_JOINED): Likewise. - (GRUB_FONT_CODE_LEFT_JOINED): Likewise. - (grub_font_get_xheight): New proto. - (grub_font_get_constructed_device_width): Likewise. - (grub_font_construct_glyph): Likewise. - * include/grub/font.h (grub_font_get_string_width): Moved from here ... - * include/grub/gfxmenu_view.h (grub_font_get_string_width): ... here. - * include/grub/font.h (grub_font_draw_string): Moved from here ... - * include/grub/gfxmenu_view.h (grub_font_draw_string): ... here. - * include/grub/i386/vga_common.h (grub_console_putchar): Moved from here.. - * include/grub/i386/pc/console.h (grub_console_putchar): ... here. - * include/grub/i386/vga_common.h (grub_console_real_putchar): Removed. - (grub_console_getcharwidth): Likewise. - * include/grub/misc.h (grub_xputs): New proto. - (grub_puts): Inlined. - * include/grub/normal.h (grub_print_ucs4): Add margin specification. - (grub_normal_get_line_counter): Removed. - (grub_install_newline_hook): Likewise. - (grub_normal_get_char_counter): New proto. - (grub_normal_reset_more): Likewise. - (grub_xputs_normal): Likewise. - * include/grub/powerpc/ieee1275/console.h: Removed. - * include/grub/sparc64/ieee1275/console.h: Likewise. - * include/grub/term.h (GRUB_TERM_CODE_TYPE_MASK): New definition. - (GRUB_TERM_CODE_TYPE_ASCII): Likewise. - (GRUB_TERM_CODE_TYPE_CP437): Likewise. - (GRUB_TERM_CODE_TYPE_UTF8_LOGICAL): Likewise. - (GRUB_TERM_CODE_TYPE_UTF8_VISUAL): Likewise. - (GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS): Likewise. - (grub_term_input): Pass reference to self. All users updated. - (grub_term_output): Pass grub_unicode_glyph to putchar and getcharwidth. - Pass reference to self. New fields normal_color, highlight_color and - data. All users updated. - (grub_putchar): Removed. - (grub_putcode): Remove EXPORT_FUNC since it's not in kernel anymore. - (grub_unicode_estimate_width): New function. - (grub_term_getcharwidth): Add defaults. - (GRUB_TERM_DEFAULT_NORMAL_COLOR): New definition. - (GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR): Likewise. - (GRUB_TERM_DEFAULT_STANDARD_COLOR): Likewise. - (grub_cls): Remove EXPORT_FUNC. - (grub_setcolorstate): Inline. - (grub_newline_hook): Removed. - * include/grub/terminfo.h: Rewritten. All users updated. - * include/grub/unicode.h: New file. - * include/grub/video.h (grub_video_signed_rect): New type. - * kern/emu/console.c (grub_console_highlight_color): Removed. - (grub_console_normal_color): Likewise. - (grub_console_standard_color): Made static. - (grub_ncurses_putchar): Remove mapping. - (grub_ncurses_getcharwidth): Removed. - (grub_ncurses_term_output): Declare as GRUB_TERM_CODE_TYPE_ASCII. - (grub_ncurses_setcolor): Removed. - (grub_ncurses_getcolor): Likewise. - * kern/i386/pc/startup.S (grub_console_real_putchar): Renamed to ... - (grub_console_putchar): ... this. - (grub_console_putchar): Handle argument difference. - * kern/ieee1275/init.c (grub_machine_init): Split console_init into - console_init_early and console_init_lately. - * kern/sparc64/ieee1275/init.c (grub_machine_init): Likewise. - * kern/misc.c (grub_puts): Removed. - (grub_vprintf): Store UTF-8 string instead of outputting it directly. - (grub_vsnprintf_real): Remove str = NULL support. - * kern/misc.c (grub_utf8_to_ucs4): Move from here ... - * normal/charset.c (grub_utf8_to_ucs4): ... here. - * kern/term.c (grub_putcode): Renamed to ... - (grub_putcode_dumb): ... this. Pass grub_unicode_glyph instead of code. - (grub_putchar): Removed. - (grub_xputs_dumb): New function. - (grub_xputs): New variable. - * lib/charset.c: Move from here ... - * normal/charset.c: ... to here. - (grub_ucs4_to_utf8): New function. - (grub_ucs4_to_utf8_alloc): Use grub_ucs4_to_utf8. - (join_types): New variable. - (unpack_join): New function. - (bidi_types): New variable. - (unpack_bidi): New function. - (get_bidi_type): Likewise. - (get_join_type): Likewise. - (is_mirrored): Likewise. - (grub_unicode_get_comb_type): Likewise. - (grub_unicode_estimate_width) [HAVE_UNIFONT_WIDTHSPEC]: Likewise. - (is_type_after): Likewise. - (grub_unicode_aglomerate_comb): Likewise. - (bidi_line_wrap): Likewise. - (grub_bidi_line_logical_to_visual): Likewise. - (grub_bidi_logical_to_visual): Likewise. - (grub_unicode_mirror_code): Likewise. - (grub_unicode_shape_code): Likewise. - * normal/cmdline.c (grub_cmdline_get): Reset more counter. - Don't use grub_putchar. - * normal/main.c (grub_normal_init_page): Use grub_putcode. - (grub_normal_reader_init): Likewise. - (grub_xputs_saved): New variable. - (GRUB_MOD_INIT): Set grub_xputs. - (GRUB_MOD_FINI): Restore grub_xputs. - * normal/menu.c (grub_wait_after_message): Don't use grub_putchar. - (menu_init): Avoid printing gfxmenu error. - (show_menu): Use grub_normal_get_char_counter. - * normal/menu_entry.c (update_screen): Fix out-of-array. - (complete): Avoid NULL dereferencing. - * grub_menu_entry_run (grub_menu_entry_run): Don't use putchar. - * normal/menu_text.c (print_spaces): Removed. - (grub_print_ucs4): Likewise. - (grub_print_message_indented): Use grub_print_ucs4. - (print_message): Use grub_putcode. - (print_entry): Hanlde diacritics. - * normal/term.c (term_state): New type. - (grub_more_lines): Removed. - (term_states): New variable. - (grub_normal_line_counter): Renamed to .. - (grub_normal_char_counter): ...this. All users updated. - (grub_normal_get_line_counter): Renamed to ... - (grub_normal_get_char_counter): ... this. - (grub_normal_reset_more): New function. - (process_newline): Removed. - (print_more): New function. - (grub_install_newline_hook): Removed. - (map_code): New function. - (grub_puts_terminal): Use grub_print_ucs4. - (putglyph): New function. - (putcode_real): Likewise. - (grub_putcode): Use putcode_real. - (get_maxwidth): New function. - (get_startwidth): Likewise. - (print_ucs4_terminal): Likewise. - (find_term_state): Likewise. - (put_glyphs_terminal): Likewise. - (print_backlog): Likewise. - (print_ucs4_real): Likewise. - (grub_print_ucs4): Likewise. - (grub_xputs_normal): Likewise. - * term/efi/console.c (grub_console_putchar): Output diacritics. - (grub_console_getcharwidth): Removed. - (grub_console_term_output): Declare as GRUB_TERM_CODE_TYPE_UCS4_VISUAL. - * term/gfxterm.c (clear_char): Free chars. - (scroll_up): Avoid leaking memory. - (grub_gfxterm_putchar): Support diacritics. - (grub_video_term): Declare as GRUB_TERM_CODE_TYPE_UCS4_VISUAL. - * term/i386/pc/console.c (grub_console_term_output): Declare as - GRUB_TERM_CODE_TYPE_VGA. - * term/i386/pc/vga.c (grub_vga_term): Declare as - GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS. - * term/i386/pc/vga_text.c (grub_vga_text_term): Declare as - GRUB_TERM_CODE_TYPE_VGA. - * term/i386/vga_common.c (map_char): Removed. - (grub_console_putchar): Likewise. - (grub_console_getcharwidth): Likewise. - * term/ieee1275/ofconsole.c: Simplify using terminfo. - (colors): Reordered to match terminfo. - (grub_ofconsole_normal_color): Removed. - (grub_ofconsole_writeesc): Likewise. - (grub_ofconsole_highlight_color): Likewise. - (grub_ofconsole_getcharwidth): Likewise. - (grub_ofconsole_setcolorstate): Likewise. - (grub_ofconsole_setcolor): Likewise. - (grub_ofconsole_getcolor): Likewise. - (grub_ofconsole_readkey): Renamed to ... - (readkey): ... this. Remove escape sequence handling. Return -1 on no - key. - (grub_ofconsole_checkkey): Removed. - (grub_ofconsole_getkey): Likewise. - (grub_ofconsole_getxy): Likewise. - (grub_ofconsole_gotoxy): Likewise. - (grub_ofconsole_cls): Likewise. - (grub_ofconsole_refresh): Likewise. - (grub_ofconsole_terminfo_input): New struct. - (grub_ofconsole_terminfo_output): Likewise. - (grub_ofconsole_term_input): Use terminfo. - (grub_ofconsole_term_output): Likewise. - (grub_console_init): Split into ... - (grub_console_init_early): ...this and ... - (grub_console_init_lately): ...this. Use terminfo. - (grub_ofconsole_putchar): Renamed to ... - (put): ... this. Remove mapping. - (grub_ofconsole_term_output): Declare as GRUB_TERM_CODE_TYPE_ASCII. - * term/serial.c: Simplify using terminfo. - (xpos): Removed. - (ypos): Likewise. - (keep_track): Likewise. - (registered): Likewise. - (input_buf): Likewise. - (npending): Likewise. - (serial_translate_key_sequence): Likewise. - (fill_input_buf): Likewise. - (grub_serial_checkkey): Likewise. - (grub_serial_getkey): Likewise. - (grub_serial_getxy): Likewise. - (grub_serial_gotoxy): Likewise. - (grub_serial_putchar): Likewise. - (grub_serial_cls): Likewise. - (grub_serial_setcolorstate): Likewise. - (grub_serial_setcursor): Likewise. - (serial_hw_init): Use serial_hw_fetch. - (grub_serial_terminfo_input): New variable. - (grub_serial_terminfo_output): Likewise. - (grub_serial_term_input): Use terminfo. - (grub_serial_term_output): Likewise. - * term/terminfo.c (putstr): Use put. - (grub_terminfo_all_free): New function - (grub_terminfo_set_current): New types vt100-color, ieee1275 and dumb. - (grub_terminfo_output_register): New function. - (grub_terminfo_output_unregister): Likewise. - (grub_terminfo_getxy): Likewise. - (grub_terminfo_readkey): Likewise. - (grub_terminfo_checkkey): Likewise. - (grub_terminfo_getkey): Likewise. - (grub_terminfo_input_init): Likewise. - (print_terminfo): Likewise. - (grub_cmd_terminfo): Handle encoding. - (grub_terminfo_gotoxy): Track position. - (grub_terminfo_cls): Likewise. - (grub_terminfo_putchar): Likewise. - (grub_terminfo_setcolorstate): Handle colors - (grub_terminfo_cursor_on): This ... - (grub_terminfo_cursor_off): ... and this merged into ... - (grub_terminfo_setcursor): ... this. - * term/tparm.c (grub_terminfo_tparm): Avoid NULL dereferencing. - * unicode/ArabicShaping.txt: New file (imported from Unicode). - * unicode/BidiMirroring.txt: Likewise. - * unicode/UnicodeData.txt: Likewise. - * unicode/COPYING: Likewise. - * util/grub-editenv.c (grub_putchar): Removed. - (grub_xputs_real): New function. - (grub_xputs): New variable. - * util/grub-fstest.c (grub_putchar): Removed. - (grub_xputs_real): New function. - (grub_xputs): New variable. - * util/grub-mkdevicemap.c (grub_putchar): Removed. - (grub_xputs_real): New function. - (grub_xputs): New variable. - * util/grub-probe.c (grub_putchar): Removed. - (grub_xputs_real): New function. - (grub_xputs): New variable. - * util/grub-script-check.c (grub_putchar): Removed. - (grub_xputs_real): New function. - (grub_xputs): New variable. - * util/i386/pc/grub-setup.c (grub_putchar): Removed. - (grub_xputs_real): New function. - (grub_xputs): New variable. - * util/import_unicode.py: New file. - * util/grub-mkfont.c (ft_errmsgs): New array. - (grub_glyph_info): Make bitmap a pointer. - (file_formats): New type WIDTH_SPEC. - (grub_font_info): New members glyphs_unsorted, glyphs_sorted, num_glyphs. - (options): Add width-spec. - (help): Likewise. - (add_char): Renamed to ... - (add_glyph): ... this. - (add_glyph): Use index. Show freetype errors. Cut blank space at borders. - (glyph_replace): New type. - (subst_rightjoin), (subst_leftjoin), (subst_medijoin): New variables. - (add_char): New function. - (add_subst): Likewise. - (process_cursive): Likewise. - (add_font): Handle GSUB. - (write_font_width_spec): New function. - (main): Sort glyphs. - * commands/minicmd.c (grub_mini_cmd_clear): Moved from here ... - * normal/main.c (grub_mini_cmd_clear): ..here. All users updated. - * kern/term.c (grub_cls): Moved from here... - * normal/term.c (grub_cls): ... here. - -2010-07-02 Colin Watson - - * include/grub/types.h: Define the C99-style PRIxGRUB_SIZE macro, - suitable for using within the format argument of printf when - converting grub_size_t. - * disk/usbms.c (grub_usbms_transfer): Use PRIxGRUB_SIZE rather than - "x" to convert grub_size_t arguments. - -2010-07-02 Vladimir Serbinenko - - * gfxmenu/gui_list.c (draw_menu): Use viewport to simplify code and fix - too long captions. - (list_get_minimal_size): Take selection box into account. - -2010-07-02 Vladimir Serbinenko - - * font/font.c (grub_font_get_glyph_with_fallback): Avoid dereferencing - NULL font. - -2010-07-02 Colin Watson - - * util/deviceiter.c (grub_util_iterate_devices): Skip device-mapper - devices when iterating over /dev/disk/by-id; they will be handled - later if appropriate, which they aren't always (e.g. LVM). - -2010-07-02 Colin Watson - - * include/grub/misc.h (grub_reboot): Declare as noreturn. - * kern/efi/efi.c (grub_reboot): Don't return, even if reset_system - fails. - (grub_halt): Likewise. - * kern/ieee1275/openfw.c (grub_reboot): Don't return, even if - reset-all fails. - (grub_halt): Don't return, even if all of shut-down, power-off, and - poweroff fail. - -2010-07-02 Colin Watson - - * kern/efi/init.c (grub_efi_init): set_watchdog_timer takes four - arguments, not three. - -2010-07-02 Colin Watson - - * util/grub-mkconfig_lib.in (uses_abstraction): New function. - * util/grub.d/10_linux.in: Use it to check for LVM, so that - LVM-on-RAID is handled correctly. - -2010-07-02 Colin Watson - - * docs/grub.texi (Changes from GRUB Legacy): New section. - (Future): Fix typo. - -2010-07-02 Colin Watson - - * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Sometimes - grub.d/README accidentally ends up executable for one reason or - another. Ignore it. - -2010-07-02 Vladimir Serbinenko - - * partmap/gpt.c (MAX_SECTOR_LOG): New definition. - (gpt_partition_map_iterate): Support non-512B sectors. - -2010-07-02 Vladimir Serbinenko - - * kern/efi/init.c (grub_efi_init): Disable watchdog. - Tested by: Seth Goldberg. - -2010-07-02 Vladimir Serbinenko - - * loader/multiboot.c (grub_multiboot_boot) [GRUB_USE_MULTIBOOT2]: - Properly align mbi. - Reported by: Seth Goldberg. - -2010-07-01 Vladimir Serbinenko - - * util/grub-mkrescue.in: Avoid module duplication. - -2010-07-01 Sean Finney - - * util/grub.d/10_linux.in: Don't use UUID for LVM root. - -2010-07-01 Sean Finney - - * disk/lvm.c (grub_lvm_scan_device): Skip snapshots. - -2010-07-01 Vladimir Serbinenko - - * disk/lvm.c (grub_lvm_checkvalue): New function. - (grub_lvm_check_flag): Likewise. - -2010-07-01 Robert Millan - - * kern/emu/hostdisk.c (convert_system_partition_to_system_disk): - Support 'p' as partition separator on kernel of FreeBSD (used - with GPT labels). - (grub_util_biosdisk_get_grub_dev): Likewise. - -2010-07-01 Vladimir Serbinenko - - Yeeloong firmware port. - - * boot/mips/yeeloong/fwstart.S: New file. - * bus/cs5536.c (gpiodump): New const. - (set_io_space): New function. - (set_iod): Likewise. - (set_p2d): Likewise. - (grub_cs5536_init_geode): Likewise. - * commands/mips/yeeloong/lsspd.c: New file. - * conf/mips-qemu-mips.rmk (pkglib_MODULES): Add serial.mod. - (serial_mod_SOURCES): New variable. - (serial_mod_CFLAGS): Likewise. - (serial_mod_LDFLAGS): Likewise. - * conf/mips-yeeloong.rmk (kernel_img_SOURCES): Add term/serial.c, - term/terminfo.c and term/tparm.c. - (pkglib_IMAGES): Add fwstart.img. - (fwstart_img_SOURCES): New variable. - (fwstart_img_CFLAGS): Likewise. - (fwstart_img_ASFLAGS): Likewise. - (fwstart_img_LDFLAGS): Likewise. - (fwstart_img_FORMAT): Likewise. - (pkglib_MODULES): Add lsspd.mod. - (lsspd_mod_SOURCES): New variable. - (lsspd_mod_CFLAGS): Likewise. - (lsspd_mod_LDFLAGS): Likewise. - (pkglib_MODULES): Add halt.mod. - (halt_mod_SOURCES): New variable. - (halt_mod_CFLAGS): Likewise. - (halt_mod_LDFLAGS): Likewise. - * conf/mips.rmk (pkglib_MODULES): Remove serial.mod. - (serial_mod_SOURCES): Removed. - (serial_mod_CFLAGS): Likewise. - (serial_mod_LDFLAGS): Likewise. - * disk/ata.c (check_device): New function. - (grub_ata_device_initialize): Use check_device. - (grub_ata_iterate): Recheck devices. - (grub_ata_open): Likewise. - (grub_atapi_iterate): Likewise. - (grub_atapi_open): Likewise. - * include/grub/ata.h (GRUB_ATA_CH0_PORT1): New macro. - (GRUB_ATA_CH1_PORT1): Likewise. - (GRUB_ATA_CH0_PORT2): Likewise. - (GRUB_ATA_CH1_PORT2): Likewise. - * include/grub/mips/loongson.h: New file. - * include/grub/mips/yeeloong/ec.h: Likewise. - * include/grub/mips/yeeloong/serial.h (GRUB_MACHINE_SERIAL_PORT): New definition. - (GRUB_MACHINE_SERIAL_DIVISOR_115200): Likewise. - (GRUB_MACHINE_SERIAL_PORTS) [ASM_FILE]: Remove. - * include/grub/misc.h (grub_halt): Declare as noreturn. - * include/grub/serial.h (UART_ENABLE_FIFO): Renamed to ... - (UART_ENABLE_FIFO_TRIGGER14): ... this. All users updated. - (UART_ENABLE_FIFO_TRIGGER1): New definition. - (UART_ENABLE_DTRRTS): Likewise. - (UART_ENABLE_MODEM): Removed. - (UART_ENABLE_OUT2): New const. - * include/grub/term.h (grub_term_register_input_active): New function. - (grub_term_register_output_active): Likewise. - * kern/mips/startup.S [GRUB_MACHINE_MIPS_YEELOONG]: Handle 0xffffffff - argument. - * kern/mips/yeeloong/init.c (grub_get_rtc): Macroify. - (init_pci): New function. - (grub_machine_init): Execute platform init when firmware. Init serial. - (grub_halt): Implement. - (grub_exit): Likewise. - (grub_reboot): Likewise. - * term/serial.c (serial_hw_init): Update macros. - [GRUB_MACHINE_MIPS_YEELOONG]: Init on startup. - * util/grub-mkimage.c (image_target_desc): New id IMAGE_YEELOONG_FLASH. - (image_targets): New target mipsel-yeeloong-flash. - (generate_image): Support IMAGE_YEELOONG_FLASH. - * video/sm712.c (GRUB_SM712_TOTAL_MEMORY_SPACE): New definition. - (grub_video_sm712_setup): Init card. - (grub_video_sm712_set_palette): Removed. - * video/sm712_init.c: New file. - -2010-06-30 Colin Watson - - * Makefile.in (install-local): Temporarily prepend $(builddir) to - PATH when running help2man and then run it on the unadorned - executable names, rather than passing $(builddir)/* paths to - help2man. This avoids the build directory ending up in generated - manual pages. - -2010-06-29 Colin Watson - - * util/grub-mkconfig.in: Use 'set -e' rather than '#! /bin/sh -e', - to avoid accidents when debugging with 'sh -x'. - * util/grub-mkrescue.in: Likewise. - * util/grub.d/00_header.in: Likewise. - * util/grub.d/10_hurd.in: Likewise. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/10_netbsd.in: Likewise. - * util/grub.d/10_windows.in: Likewise. - * util/grub.d/20_linux_xen.in: Likewise. - * util/grub.d/30_os-prober.in: Likewise. - * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. - -2010-06-29 Colin Watson - - * commands/cat.c (grub_cmd_cat): Fix buffer overrun if '\r' is the - last character in the buffer. - Reported by: Vladimir Serbinenko. - -2010-06-29 Robert Millan - - * docs/grub.texi (Simple configuration): Document ${GRUB_BADRAM}. - (Command-line and menu entry commands): Document `badram' command. - -2010-06-28 Robert Millan - - * util/grub-mkconfig.in: Export `GRUB_BADRAM' variable. - * util/grub.d/00_header.in: When `GRUB_BADRAM' is set, issue badram - command using ${GRUB_BADRAM} as parameter. - -2010-06-28 Colin Watson - - * docs/grub.texi (Device map): New section. - (Themes): New section (stub). - * Makefile.in (docs/grub.info): The info documentation now builds - without errors. Make sure it stays that way. - -2010-06-28 Vladimir Serbinenko - - Use normal parser for menu entries. - Reported by: Thomas Frauendorfer - - * include/grub/parser.h (grub_parser_execute): Don't export. - * normal/menu.c (grub_menu_execute_entry_real): New function. - (grub_menu_execute_entry): Use grub_menu_execute_entry_real. - -2010-06-28 Colin Watson - - * docs/grub.texi (Embedded configuration): New section (replacing - old "Preset Menu" stub). - (Images): New section. - (configfile): Note that any menu entries defined in `file' are shown - immediately. - -2010-06-28 Josh Triplett - - * mmap/i386/pc/mmap_helper.S: Set CF on return. - -2010-06-28 Colin Watson - - * util/grub-install.in: Add --debug-image= option. - -2010-06-28 Colin Watson - - Change grub-mkdevicemap to emit /dev/disk/by-id/ names where - possible on Linux. - - * util/deviceiter.c (check_device): Rename to ... - (check_device_readable_unique): ... this. Update all callers. - Maintain and check a list of which devices (by canonicalized name) - have already been seen. - (clear_seen_devices): New function. - (compare_file_names) [__linux__]: New function. - (grub_util_iterate_devices): Clear the list of seen devices on exit - and (just in case) on entry. - (grub_util_iterate_devices) [__linux__]: Iterate over non-partition - devices in /dev/disk/by-id/, in sorted order. Remove DM-RAID - seen-devices list, superseded by general code in check_device. - -2010-06-28 Colin Watson - - * commands/cat.c (options): New variable. - (grub_cmd_cat): Parse options. If the --dos option is given, print - DOS-style "\r\n" line endings as simple newlines (Debian bug - #586358). - (GRUB_MOD_INIT): Use extcmd. - (GRUB_MOD_FINI): Likewise. - * docs/grub.texi (cat): Document --dos. - -2010-06-28 Vladimir Serbinenko - - XEN with Linux grub-mkconfig support. - - * conf/common.rmk (grub-mkconfig_SCRIPTS) [linux]: Add 20_linux_xen. - * util/grub-mkconfig.in: Export GRUB_CMDLINE_XEN and - GRUB_CMDLINE_XEN_DEFAULT. - * util/grub.d/20_linux_xen.in: New file. - -2010-06-28 Vladimir Serbinenko - - Initialise VGA video on qemu ourselves. - - * boot/i386/qemu/boot.S: Don't call 0xc000. - * conf/i386-qemu.rmk (kern/i386/qemu/init.c_DEPENDENCIES): New variable. - (kernel_img_SOURCES): Add kern/i386/qemu/init.c and bus/pci.c. - (kernel_img_HEADERS): Add pci.h. - * conf/i386.rmk (pkglib_MODULES) [qemu]: Remove pci.mod. - * configure.ac: Force unifont on qemu and yeeloong. - * include/grub/i386/qemu/kernel.h (grub_qemu_init_cirrus): New proto. - (grub_vga_palette_write): Use correct register. - * kern/i386/coreboot/init.c (grub_machine_init) [GRUB_MACHINE_QEMU]: - Call grub_qemu_init_cirrus. - * kern/i386/qemu/init.c: New file. - * term/i386/pc/vga_text.c (inc_y): Never read outside the screen. - - * commands/videotest.c (grub_cmd_videotest): Handle double buffering. - -2010-06-26 Pavel Roskin - - * util/grub.d/10_linux.in: Add support for initrd images on Fedora - 13. - -2010-06-26 Colin Watson - - * docs/grub.texi (Simple configuration): Explain that - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY must be - set to `true' to disable their respective recovery entries, not - merely set. - -2010-06-26 Colin Watson - - Make the `source' command slightly faster. - - * normal/main.c (grub_normal_execute): Don't re-read list files when - nested. - -2010-06-23 Colin Watson - - * loader/i386/multiboot_mbi.c (retrieve_video_parameters): Set red - field position and mask size to red fields from mode_info, not - green. - * loader/multiboot_mbi2.c (retrieve_video_parameters): Likewise. - Remove redundant tag->common.framebuffer_type assignment. - Reported by: Seth Goldberg. - -2010-06-23 Colin Watson - - Sync up other versions of the Linux loader with Robert Millan's - change of 2010-01-09, "Make loader output a bit more user-friendly". - - * loader/i386/efi/linux.c (grub_linux_boot): Move debug info to - grub_dprintf(). - (grub_cmd_linux): Likewise. - (grub_cmd_initrd): Likewise. - * loader/i386/ieee1275/linux.c (grub_cmd_linux): Likewise. - * loader/i386/pc/linux.c (grub_cmd_linux): Likewise. - -2010-06-21 Colin Watson - - * kern/efi/mm.c (grub_efi_mm_init): Handle systems with memory maps - larger than MEMORY_MAP_SIZE. - -2010-06-21 BVK Chaitanya - - Fix parallel build. - - * conf/common.rmk: Add grub_script.tab.h as a grub-script-check - dependency. - * script/parser.y: #include grub_script.tab.h header. - -2010-06-20 Vladimir Serbinenko - - Support >3GiB and <16MiB RAM in i386-qemu. - - * kern/i386/qemu/mmap.c (QEMU_CMOS_MEMSIZE2_HIGH): New const. - (QEMU_CMOS_MEMSIZE2_LOW): Likewise. - (grub_lower_mem): Removed. - (grub_upper_mem): Likewise. - (mem_size): Made static. - (above_4g): New variable. - (grub_machine_mmap_init): Detect small mem_size and above_4g. - (grub_machine_mmap_iterate): Order in ascending order and add above_4g - support. - -2010-06-20 Vladimir Serbinenko - - Cirrus 5446 and Bochs video cards support. - - * conf/i386.rmk (pkglib_MODULES): Add video_cirrus.mod and - video_bochs.mod - (video_cirrus_mod_SOURCES): New variable. - (video_cirrus_mod_CFLAGS): Likewise. - (video_cirrus_mod_LDFLAGS): Likewise. - (video_bochs_mod_SOURCES): Likewise. - (video_bochs_mod_CFLAGS): Likewise. - (video_bochs_mod_LDFLAGS): Likewise. - * include/grub/vga.h: New file. - * include/grub/video_fb.h (grub_video_fb_doublebuf_blit_init): Removed. - (grub_video_fb_set_page_t): New type. - (grub_video_fb_setup): New prototype. - (grub_video_fb_swap_buffers): Likewise. - (grub_video_fb_get_info_and_fini): Likewise. - * term/i386/pc/vga_text.c (CRTC_ADDR_PORT): Moved to include/grub/vga.h. - (CRTC_DATA_PORT): Likewise. - (CRTC_CURSOR): Likewise. - (CRTC_CURSOR_ADDR_HIGH): Likewise. - (CRTC_CURSOR_ADDR_LOW): Likewise. - (CRTC_CURSOR_DISABLE): Likewise. - (update_cursor): Use grub_vga_cr_write. - (grub_vga_text_setcursor): Likewise. - * video/bochs.c: New file. - * video/fb/video_fb.c (render_target): Moved into framebuffer variable. - (palette): Likewise. - (palette_size): Likewise. - (framebuffer): New variable. - (grub_video_fb_init): Use 'framebuffer'. - (grub_video_fb_fini): Likewise. - (grub_video_fb_get_info): Likewise. - (grub_video_fb_get_palette): Likewise. - (grub_video_fb_set_palette): Likewise. - (grub_video_fb_set_viewport): Likewise. - (grub_video_fb_get_viewport): Likewise. - (grub_video_fb_map_color): Likewise. - (grub_video_fb_map_rgb): Likewise. - (grub_video_fb_map_rgba): Likewise. - (grub_video_fb_unmap_color): Likewise. - (grub_video_fb_unmap_color_int): Likewise. - (grub_video_fb_fill_rect): Likewise. - (grub_video_fb_blit_bitmap): Likewise. - (grub_video_fb_blit_render_target): Likewise. - (grub_video_fb_scroll): Likewise. - (grub_video_fb_create_render_target): Likewise. - (grub_video_fb_doublebuf_blit_init): Likewise. - (grub_video_fb_set_active_render_target): Handle doublebuffering. - (doublebuf_pageflipping_update_screen): New function. - (doublebuf_pageflipping_init): Likewise. - (grub_video_fb_setup): Likewise. - (grub_video_fb_swap_buffers): Likewise. - (grub_video_fb_get_info_and_fini): Likewise. - * video/i386/pc/vbe.c (framebuffer): Remove all doublebuffering fields. - All users updated. - (doublebuf_pageflipping_commit): Restructured into ... - (doublebuf_pageflipping_set_page): ... this. - (doublebuf_pageflipping_update_screen): Removed. - (doublebuf_pageflipping_init): Likewise. - (double_buffering_init): Likewise. - (grub_video_vbe_setup): Use grub_video_fb_setup. - (grub_video_vbe_swap_buffers): Removed. - (grub_video_vbe_set_active_render_target): Likewise. - (grub_video_vbe_get_active_render_target): Likewise. - (grub_video_vbe_get_info_and_fini): Use grub_video_fb_get_info_and_fini. - (grub_video_vbe_adapter): Use grub_video_fb_swap_buffers, - grub_video_fb_set_active_render_target and - grub_video_fb_get_active_render_target. - * video/i386/pc/vga.c (SEQUENCER_ADDR_PORT): Move to include/grub/vga.h. - (SEQUENCER_DATA_PORT): Likewise. - (MAP_MASK_REGISTER): Likewise. - (CRTC_ADDR_PORT): Likewise. - (CRTC_DATA_PORT): Likewise. - (START_ADDR_HIGH_REGISTER): Likewise. - (START_ADDR_LOW_REGISTER): Likewise. - (GRAPHICS_ADDR_PORT): Likewise. - (GRAPHICS_DATA_PORT): Likewise. - (READ_MAP_REGISTER): Likewise. - (INPUT_STATUS1_REGISTER): Likewise. - (INPUT_STATUS1_VERTR_BIT): Likewise. - (get_map_mask): Use grub_vga_sr_read. - (set_map_mask): Use grub_vga_sr_write. - (set_read_map): Use grub_vga_gr_write. - (set_start_address): Use grub_vga_cr_write. - * video/sm712.c (framebuffer): Remove leftover fields. - -2010-06-20 Colin Watson - - * util/grub-mkconfig.in: Capitalise and export GRUB_PREFIX. Stop - setting GRUB_VIDEO_BACKEND. Make it available as a user override - instead. Replace the gfxterm backend check with a check that - ${GRUB_PREFIX}/video.lst is non-empty. - * util/grub.d/00_header.in: Use GRUB_PREFIX rather than computing it - again. - (load_video): New generated function. Call it before loading - gfxterm rather than loading ${GRUB_VIDEO_BACKEND}. - * util/grub.d/10_linux.in (linux_entry): Call load_video. - * util/grub.d/30_os-prober.in (osx_entry): Likewise. - * docs/grub.texi (Simple configuration): Document - GRUB_VIDEO_BACKEND. - -2010-06-20 Vladimir Serbinenko - - Use video functions in linux and xnu loaders. - - * conf/i386-pc.rmk (xnu_mod_SOURCES): Remove loader/i386/pc/xnu.c. - * conf/x86-efi.rmk (xnu_mod_SOURCES): Remove loader/i386/efi/xnu.c. - * include/grub/i386/xnu.h (grub_xnu_set_video): Removed. - * loader/i386/efi/linux.c (grub_linux_setup_video): Copied from - loader/i386/pc/linux.c. - (grub_linux_boot): Resynced with loader/i386/pc/linux.c. - (find_line_len): Removed. - (find_framebuf): Likewise. - (grub_cmd_linux): Declare grub_linux_boot as possibly returning. - * loader/i386/efi/xnu.c: Removed. - * loader/i386/pc/xnu.c: Moved from here... - * loader/i386/xnu.c: ...here. - - Enable priorities in video drivers. - - * include/grub/video.h (grub_video_adapter_prio_t): New type. - (grub_video_adapter): New field prio. - (grub_video_register): Respect prio when inserting. - * video/efi_gop.c (grub_video_gop_adapter): Add prio. - * video/efi_uga.c (grub_video_uga_adapter): Likewise. - * video/emu/sdl.c (grub_video_sdl_adapter): Likewise. - * video/i386/pc/vbe.c (grub_video_vbe_adapter): Likewise. - * video/i386/pc/vga.c (grub_video_vga_adapter): Likewise. - * video/ieee1275.c (grub_video_ieee1275_adapter): Likewise. - * video/sm712.c (grub_video_sm712_adapter): Likewise. - - Fix SDL driver ID. - - * include/grub/video.h (grub_video_driver_id_t): New value - GRUB_VIDEO_DRIVER_SDL. - * video/emu/sdl.c (grub_video_sdl_adapter): Add id. - -2010-06-17 Colin Watson - - * util/i386/pc/grub-setup.c (usage): Pass an extra `program_name' - argument to printf. - * util/sparc64/ieee1275/grub-setup.c (usage): Likewise. - -2010-06-17 Colin Watson - - * util/i386/pc/grub-setup.c (usage): Fix syntax error. - * util/sparc64/ieee1275/grub-setup.c (usage): Likewise. - -2010-06-17 Colin Watson - - * util/i386/pc/grub-setup.c (usage): Warn against running grub-setup - directly, and recommend grub-install instead. - * util/sparc64/ieee1275/grub-setup.c (usage): Likewise. - -2010-06-17 Colin Watson - - Fix i386-pc prefix handling with nested partitions (Debian bug - #585068). Note that the case where the core image is booted using - multiboot and relocated from its original location still requires - more work. - - * kern/i386/pc/init.c (make_install_device): If the prefix starts - with "(,", fill the boot drive in between those two characters, but - expect that a full partition specification including partition map - names will follow. - * util/i386/pc/grub-setup.c (setup): Unless an explicit prefix was - specified, write a prefix without the drive name but including a - full partition specification. - -2010-06-16 Colin Watson - - * util/grub-mkconfig.in: Ignore non-option arguments, for - compatibility with older versions (before 2010-06-12) which did the - same. In particular, this makes it easier to ship an update-grub - wrapper which is compatible with that used with GRUB Legacy (Debian - bug #586056). - -2010-06-14 GrĂ©goire Sutre - - * Makefile.in (install-local): Use $$file.h2m instead of $$dest.h2m - for manual page generation. - -2010-06-14 GrĂ©goire Sutre - - * po/POTFILES: Remove leftover commands/handler.c. - -2010-06-14 Colin Watson - - * util/grub-mkconfig.in: Remove vestige of old argument parsing that - left this script non-functional. - -2010-06-14 Colin Watson - - * docs/man/grub-emu.h2m: New file. - -2010-06-13 Colin Watson - - * docs/grub.texi (Commands): Document reduced command set in rescue - mode. - (cpuid): New section. - -2010-06-13 GrĂ©goire Sutre - - * kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev): Use the - new partition naming style. - * util/grub-install.in: Adapt sed subtitutions in grub-probe calls. - -2010-06-12 BVK Chaitanya - - Add "-o grub.iso" like cmdline options support. - - * util/grub-install.in: Improve cmdline option parsing. - * util/grub-mkconfig.in: Likewise. - * util/grub-mkrescue.in: Likewise. - * util/grub-reboot.in: Likewise. - * util/grub-set-default.in: Likewise. - * util/i386/efi/grub-install.in: Likewise. - * util/ieee1275/grub-install.in: Likewise. - * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. - -2010-06-12 Colin Watson - - * .bzrignore: Ignore 41_custom. - -2010-06-12 Thomas Schmitt - - * util/grub-mkrescue.in: Pass unrecognized options to xorriso. - -2010-06-12 Colin Watson - - Avoid false positives in fs.lst, partmap.lst, and video.lst due to - prototype declarations. - - * genmk.rb (PModule::rule): Define GRUB_LST_GENERATOR when - generating fs, partmap, and video lists. - * include/grub/fs.h (grub_fs_register): Omit prototype if - GRUB_LST_GENERATOR is defined. - * include/grub/partition.h (grub_partition_map_register): Likewise. - * include/grub/video.h (grub_video_register): Likewise. - -2010-06-12 Javier MartĂ­n - - * include/grub/types.h: Check for GRUB_CPU_SIZEOF_LONG when appropriate. - -2010-06-12 Thomas Schmitt - - * util/grub-mkrescue.in: Support --xorriso argument. - -2010-06-12 Vladimir Serbinenko - - * util/grub-mkrescue.in: Use -graft-points instead of -pathspecs. - Suggested by: Thomas Schmitt. - -2010-06-12 Vladimir Serbinenko - - * util/grub-mkrescue.in: Add --sort-weight arguments to xorriso. - Suggested by: Thomas Schmitt. - -2010-06-12 Vladimir Serbinenko - - custom.cfg support. - - * conf/common.rmk (grub-mkconfig_SCRIPTS): Add 41_custom. - * util/grub.d/41_custom.in: New file. - -2010-06-12 Colin Watson - - * util/grub-mkrescue.in (make_image): Remove sh module, which has - been merged back into normal. - -2010-06-11 Colin Watson - - * include/grub/efi/uga_draw.h (GRUB_EFI_UGA_GLT_MAX): Rename to ... - (GRUB_EFI_UGA_BLT_MAX): ... this (typo fix). - -2010-06-11 Colin Watson - - * Makefile.in (install-local): Include $(srcdir)/docs/man/$$dest.h2m - when generating manual pages. - * docs/man/grub-bin2h.h2m: New file. - * docs/man/grub-editenv.h2m: New file. - * docs/man/grub-fstest.h2m: New file. - * docs/man/grub-install.h2m: New file. - * docs/man/grub-macho2img.h2m: New file. - * docs/man/grub-mkconfig.h2m: New file. - * docs/man/grub-mkdevicemap.h2m: New file. - * docs/man/grub-mkfont.h2m: New file. - * docs/man/grub-mkimage.h2m: New file. - * docs/man/grub-mkpasswd-pbkdf2.h2m: New file. - * docs/man/grub-mkrelpath.h2m: New file. - * docs/man/grub-mkrescue.h2m: New file. - * docs/man/grub-ofpathname.h2m: New file. - * docs/man/grub-pe2elf.h2m: New file. - * docs/man/grub-probe.h2m: New file. - * docs/man/grub-reboot.h2m: New file. - * docs/man/grub-script-check.h2m: New file. - * docs/man/grub-set-default.h2m: New file. - * docs/man/grub-setup.h2m: New file. - -2010-06-10 Vladimir Serbinenko - - Use FOR_* macros instead of *_iterate whenever possible. - - * commands/handler.c: Removed. - * commands/help.c (grub_cmd_help): Use FOR_COMMANDS. - * commands/minicmd.c (grub_mini_cmd_lsmod): Use FOR_DL_MODULES. - * conf/any-emu.rmk (kernel_img_SOURCES): Remove kern/handler.c. - * conf/common.rmk (script/lexer.c_DEPENDENCIES): Add grub_script.yy.h. - (grub_probe_SOURCES): Remove kern/parser.c. - (util/grub-script-check.c_DEPENDENCIES): Removed. - (grub_script_check_SOURCES): Remove kern/handler.c, kern/parser.c - and grub_script_check_init.c. - (grub_script_check_init.lst): Removed. - (grub_script_check_init.h): Likewise. - (grub_script_check_init.c): Likewise. - (pkglib_MODULES): Remove handler.mod and sh.mod. - (handler_mod_SOURCES): Removed. - (handler_mod_CFLAGS): Likewise. - (handler_mod_LDFLAGS): Likewise. - (normal_mod_SOURCES): Remove normal/handler.c. - Add script/main.c, script/script.c, script/execute.c, - script/function.c, script/lexer.c, grub_script.tab.c - and grub_script.yy.c. - * conf/i386-coreboot.rmk (kernel_img_SOURCES): Remove kern/handler.c. - * conf/i386-ieee1275.rmk (kernel_img_SOURCES): Likewise. - * conf/i386-pc.rmk (kernel_img_SOURCES): Likewise. - (grub_setup_SOURCES): Remove kern/parser.c. - * conf/i386-qemu.rmk (kernel_img_SOURCES): Remove kern/handler.c. - * conf/mips-qemu-mips.rmk (kernel_img_SOURCES): Likewise. - * conf/mips-yeeloong.rmk (kernel_img_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (kernel_img_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (kernel_img_SOURCES): Likewise. - (grub_setup_SOURCES): Remove kern/parser.c. - * conf/x86-efi.rmk (kernel_img_SOURCES): Remove kern/handler.c. - * gettext/gettext.c (grub_gettext_delete_list): Don't use grub_list_pop. - * include/grub/command.h (grub_command_iterate): Removed. - (FOR_COMMANDS): New macro. - * include/grub/dl.h (grub_dl): New member next. - (grub_dl_iterate): Removed. - (grub_dl_head): New variable declaration. - (FOR_DL_MODULES): New macro. - * include/grub/fs.h: Include list.h. - (grub_fs): Make next first element. - (grub_fs_list): New variable declaration. - (grub_fs_register): Make inline. - (grub_fs_unregister): Likewise. - (grub_fs_iterate): Removed. - (FOR_FILESYSTEMS): New macro. - * include/grub/handler.h: Removed. - * include/grub/list.h (grub_list_hook_t): Removed. - (grub_list_test_t): Likewise. - (grub_list_pop): Likewise. - (grub_list_iterate): Likewise. - (grub_list_insert): Likewise. - (FOR_LIST_ELEMENTS): New macro. - * include/grub/parser.h (grub_parser_class): Removed. - (grub_parser_register): Likewise. - (grub_parser_unregister): Likewise. - (grub_parser_get_current): Likewise. - (grub_parser_set_current): Likewise. - (grub_register_rescue_parser): Likewise. - (grub_rescue_parse_line): New function. - * include/grub/partition.h (FOR_PARTITION_MAPS): Use FOR_LIST_ELEMENTS. - * include/grub/script_sh.h (grub_script_function_list): New variable - declaration. - (FOR_SCRIPT_FUNCTIONS): New macro. - (grub_script_function_iterate): Removed. - (grub_normal_parse_line): New prototype. - * include/grub/term.h (FOR_ACTIVE_TERM_INPUTS): Use FOR_LIST_ELEMENTS. - (FOR_DISABLED_TERM_INPUTS): Likewise. - (FOR_ACTIVE_TERM_OUTPUTS): Likewise. - (FOR_DISABLED_TERM_OUTPUTS): Likewise. - * include/grub/video.h (grub_video_adapter): Move 'next' to first - element. - (grub_video_register): Inline. - (grub_video_unregister): Likewise. - (grub_video_adapter_list): New variable declaration. - (grub_video_iterate): Removed. - (FOR_VIDEO_ADAPTERS): New macro. - * kern/dl.c (grub_dl_list): Removed. All users updated. - (grub_dl_iterate): Removed. - * kern/fs.c (grub_fs_list): Make global. - (grub_fs_register): Removed. - (grub_fs_unregister): Likewise. - (grub_fs_iterate): Likewise. - * kern/handler.c: Removed. - * kern/list.c (grub_list_pop): Removed. - (grub_list_iterate): Likewise. - (grub_list_insert): Likewise. - (grub_named_list_find): Use FOR_LIST_ELEMENTS. - (grub_prio_list_insert): Don't use grub_list_insert. - * kern/main.c (grub_register_rescue_parser): Don't call - grub_register_rescue_parser. - * kern/parser.c (grub_parser_class): Removed. - (grub_parser_execute): Use grub_rescue_parse_line. - * kern/rescue_parser.c (grub_rescue_parse_line): Make global. - (grub_rescue_parser): Removed. - (grub_register_rescue_parser): Likewise. - * kern/rescue_reader.c (grub_rescue_run): Use grub_rescue_parse_line. - * normal/auth.c (is_authenticated): Use FOR_LIST_ELEMENTS. - (grub_auth_check_authentication): Likewise. - * normal/completion.c (iterate_command): Removed. - (grub_normal_do_completion): Use FOR_COMMANDS. - * normal/handler.c: Removed. - * normal/main.c (read_config_file): Remove parser changing. - (grub_normal_execute): Don't call read_handler_list. - (grub_normal_read_line_real): Statically allocate prompt. - (grub_cmdline_run): Use grub_normal_parse_line. - (GRUB_MOD_FINI): Don't call free_handler_list. - * normal/menu_entry.c (run): Likewise. - * script/function.c (grub_script_function_list): Make global. - (grub_script_function_iterate): Removed. - * script/main.c (grub_normal_parse_line): Make global. - (grub_sh_parser): Removed. - (GRUB_MOD_INIT): Likewise. - (GRUB_MOD_FINI): Likewise. - * tests/lib/functional_test.c (grub_functional_test): Use - FOR_LIST_ELEMENTS. - * tests/lib/test.c (free_failures): Don't use grub_list_pop. - (grub_test_run): Use FOR_LIST_ELEMENTS. - * tests/lib/unit_test.c (main): Likewise. - * util/deviceiter.c (grub_util_iterate_devices): Don't use - grub_list_pop. - * util/grub-fstest.c (grub_term_input_class): Removed. - (grub_term_output_class): Likewise. - * util/grub-probe.c: Likewise. - * util/i386/pc/grub-setup.c: Likewise. - * util/sparc64/ieee1275/grub-setup.c: Likewise. - * util/grub-script-check.c (main): Don't call grub_init_all and - grub_fini_all. - * video/video.c (grub_video_adapter_list): Make global. - (grub_video_register): Removed. - (grub_video_unregister): Likewise. - (grub_video_iterate): Likewise. - -2010-06-09 Vladimir Serbinenko - - * docs/grub.texi (Vendor power-on button): Add Asus EeePC 1005PE as - reported by Henrique Ferreiro. - -2010-06-09 Robert Millan - - * util/grub.d/10_linux.in: Prefer compressed images over non-compressed - ones, when both are available. - -2010-06-08 GrĂ©goire Sutre - - Make --version uniform and avoid hard-coded program name. - - * util/grub-mkimage.c (main): Use `program_name' instead of - hard-coded string. - * util/i386/pc/grub-setup.c (main): Likewise. - * util/sparc64/ieee1275/grub-setup.c (parse_options): Likewise. - * util/grub-install.in: Save the basename of $0 in $self, and use the - latter in informational messages. Use the same format for --version - as the binary programs. - * util/grub-mkconfig.in: Likewise. - * util/grub-mkrescue.in: Likewise. - * util/grub-reboot.in: Likewise. - * util/grub-set-default.in: Likewise. - * util/i386/efi/grub-install.in: Likewise. - * util/ieee1275/grub-install.in: Likewise. - * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. - -2010-06-08 GrĂ©goire Sutre - - * util/i386/pc/grub-setup.c (setup): Use absolute offsets for start of - embedding area. Use <= instead of == when checking for non-emptiness. - -2010-06-08 GrĂ©goire Sutre - - * configure.ac: Add `.' to the directories searched for unifont. - -2010-06-08 Colin Watson - - * .bzrignore: Add ascii.bitmaps, ascii.h, grub_script.yy.c, and - grub_script.yy.h. - -2010-06-08 Colin Watson - - * docs/grub.texi (History): Expand to cover GRUB 2. - (Serial terminal): Refer to `terminal_input' and `terminal_output' - commands, not `terminal'. - (serial): Likewise. - (terminal_input): New section. - (terminal_output): New section. - (uppermem): New section (stub). - (Obtaining and Building GRUB): Refer to Bazaar, not Subversion. - -2010-06-08 Colin Watson - - * docs/grub.texi (Security): Menu entries are unrestricted by - default, not restricted to superusers as I had previously thought. - Reword to account for this. - -2010-06-07 Colin Watson - - * kern/emu/misc.c (device_mapper_null_log): New function. - (grub_device_mapper_supported): New function. - * include/grub/emu/misc.h (grub_device_mapper_supported): Add - prototype. - * kern/emu/hostdisk.c (find_partition_start): Check whether - device-mapper is supported before trying to use it. - * util/deviceiter.c (grub_util_iterate_devices): Likewise. - -2010-06-07 Colin Watson - - * docs/grub.texi (Naming convention): Use GRUB 2 syntax. - (File name syntax): Likewise. - (help): --all is no longer supported in GRUB 2. Be more precise - about pattern matching. - -2010-06-07 Colin Watson - - * normal/completion.c (grub_normal_do_completion): When completing - arguments to "set" and the current word contains an equals sign, - skip to after the equals sign before starting completion. - -2010-06-07 Colin Watson - - * fs/i386/pc/pxe.c (grub_pxe_open): Fix parsing of gateway_ip. - -2010-06-07 Colin Watson - - * docs/grub.texi (Network): New section. - (Device syntax): The network device is called `(pxe)' in GRUB 2, not - `(nd)' as in GRUB Legacy. - (pxe_unload): New section. - -2010-06-07 Colin Watson - - * docs/grub.texi (Troubleshooting): `echo' is not usually available - in the rescue shell, so recommend using `set' instead. Thanks, - Jordan Uggla. - -2010-06-07 Colin Watson - - * docs/grub.texi (Filesystem): Refer to `search' instead of `find'. - (password): New section. - (password_pbkdf2): New section. - (search): New section. - (Security): New section. - (Troubleshooting): New section, currently very incomplete. - (Invoking grub-mkpasswd-pbkdf2): New section. - (Internals): New section, currently very incomplete. - -2010-06-07 Colin Watson - - * util/grub.d/00_header.in: Add some more quoting (of - "${prev_saved_entry}" and "${boot_once}") needed to make savedefault - work again. - Reported by: Mario 'BitKoenig' Holbe (Debian bug #584812). - -2010-06-07 Colin Watson - - * util/grub-mkpasswd-pbkdf2.c (main): Rename top-level `c' variable - to `count', fixing variable shadowing that broke the -c option. - -2010-06-05 Colin Watson - - * util/grub.d/00_header.in: Quote values assigned to `saved_entry', - in case they contain spaces. - -2010-06-04 Colin Watson - - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Prepend - "part_" to partmap module names, in line with grub-install. - Reported by: JindÅ™ich MakoviÄka (Debian bug #584426). - -2010-06-04 Colin Watson - - * util/grub-mkimage.c: Make target-related error messages slightly - more helpful; -O talks about "format". Explicitly point to the use - of -O if no target is specified. - Reported by: Didier Raboud (Debian bug #584415). - -2010-06-03 Colin Watson - - * INSTALL: Document several build requirements for optional features - (libdevmapper, ncurses, libusb, SDL, FreeType, GNU Unifont). - -2010-06-02 GrĂ©goire Sutre - - * kern/emu/hostdisk.c (convert_system_partition_to_system_disk) - [__NetBSD__]: Handle all device names matching /dev/r[a-z]+[0-9][a-z]. - (find_partition_start) [__NetBSD__]: Correct error messages for NetBSD. - -2010-06-02 Colin Watson - - * docs/grub.texi (Simple configuration): Fix copy-and-paste typo. - Thanks to Jordan Uggla for spotting this. - -2010-06-02 AleÅ¡ Nesrsta - - Finally make USB usable. - - * bus/usb/ohci.c (grub_ohci_reg_t): Add missing values. - (GRUB_OHCI_RHUB_PORT_POWER_MASK): New macro. - (GRUB_OHCI_RHUB_PORT_ALL_POWERED): Likewise. - (GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK): Likewise. - (GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT): Likewise. - (GRUB_OHCI_REG_FRAME_INTERVAL_FI_SHIFT): Likewise. - (GRUB_OHCI_FSMPS): Likewise. - (GRUB_OHCI_PERIODIC_START): Likewise. - (GRUB_OHCI_FRAME_INTERVAL): Likewise. - (GRUB_OHCI_SET_PORT_ENABLE): Likewise. - (GRUB_OHCI_CLEAR_PORT_ENABLE): Likewise. - (GRUB_OHCI_SET_PORT_RESET): Likewise. - (GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE): Likewise. - * bus/usb/ohci.c (grub_ohci_pci_iter): Various important fixups. - (grub_ohci_transaction): Likewise. - (grub_ohci_transfer): Improve condition detection algorithms. - Handle toggle property. Program the transactions correctly. - Improve error handling. Various important fixups. - (grub_ohci_portstatus): Put register writes in right order. - * bus/usb/uhci.c (grub_free_queue): Compute last_trans. - (grub_uhci_transfer): Don't show "failed" message on success. - * bus/usb/usb.c (grub_usb_set_configuration): Zero-fill whole "toggle" - array. - (grub_usb_device_initialize): Read first 8 bytes of descriptor to - determine its size. - * bus/usb/usbtrans.c (grub_usb_control_msg): Use descdev.maxsize0 even - before initialization is completed. Use IN direction for empty - transfers. Use last_trans and compute toggle. - * include/grub/usbtrans.h (grub_usb_transfer): New field last_trans. - (GRUB_USB_FEATURE_ENDP_HALT): Correct the value. - (GRUB_USB_FEATURE_DEV_REMOTE_WU): Likewise. - (GRUB_USB_FEATURE_TEST_MODE): Likewise. - * include/grub/usb.h (grub_usb_err_t): New value GRUB_USB_ERR_UNRECOVERABLE. - (grub_usb_device): Increase toggle to 256. - (grub_usbms_subclass_t): New values GRUB_USBMS_SUBCLASS_RBC, - GRUB_USBMS_SUBCLASS_MMC2, GRUB_USBMS_SUBCLASS_UFI and - GRUB_USBMS_SUBCLASS_SFF8070. - * include/grub/scsicmd.h (grub_scsi_test_unit_ready): New structure. - (grub_scsi_inquiry): New member page and alloc_length. - (grub_scsi_request_sense): New structure. - (grub_scsi_request_sense_data): Likewise. - (grub_scsi_read_capacity): New fields logical_block_addr, PMI and - control. - * disk/scsi.c (grub_scsi_request_sense): New function. - (grub_scsi_test_unit_ready): Likewise. - (grub_scsi_inquiry): Fill new fields. - (grub_scsi_read_capacity): Likewise. - (grub_scsi_read10): Add request sense at the end. - (grub_scsi_read12): Likewise. - (grub_scsi_write10): Likewise. - (grub_scsi_write12): Likewise. - (grub_scsi_open): Add Test Unit Ready. - * disk/usbms.c (grub_usbms_finddevs): Check configcnt. - Support additional subclasses. Con't clear halt yet. Activate the - proper config. Calculate LUNs correctly. - (grub_usbms_transfer): Various important fixups. - -2010-06-02 Vladimir Serbinenko - - * bus/pci.c (grub_pci_iterate) [GRUB_MACHINE_MIPS_YEELOONG]: Skip ghosts. - * bus/usb/ohci.c (grub_ohci_portstatus): Handle R/WC correctly. - (grub_ohci_fini_hw): New function. - (grub_ohci_restore_hw): Likewise. - (GRUB_MOD_INIT(ohci)): Register preboot hook. - (GRUB_MOD_FINI(ohci)): Shutdown OHCI. - * term/usb_keyboard.c: Remove include of grub/machine/console.h. - -2010-06-02 Vladimir Serbinenko - - Dedicated DMA allocations. - - * bus/pci.c (grub_memalign_dma32): New function - (grub_dma_free): Likewise. - (grub_dma_get_virt): Likewise. - (grub_dma_get_phys): Likewise. - * bus/usb/ohci.c (grub_ohci): New members hcca_addr and hcca_chunk. - (grub_ohci_pci_iter): Use dma32_alloc. - (grub_ohci_transfer): Likewise. - * bus/usb/usbtrans.c (grub_usb_control_msg): Likewise. - (grub_usb_bulk_readwrite): Likewise. - * include/grub/pci.h: Add declarations. - -2010-06-02 Vladimir Serbinenko - - CS5536 support. - - * bus/cs5536.c: New file. - * bus/usb/ohci.c (grub_ohci_pci_iter): Check for CS5536. - * conf/i386.rmk (pkglib_MODULES): Add cs5536.mod. - (cs5536_mod_SOURCES): New variable. - (cs5536_mod_CFLAGS): Likewise. - (cs5536_mod_LDFLAGS): Likewise. - * conf/mips-yeeloong.rmk (kernel_img_HEADERS): Add cs5536.h and - machine/pci.h. - (kernel_img_SOURCES): Add bus/cs5536.c. - (pkglib_MODULES): Add usb.mod, usbtest.mod, ohci.mod, usbms.mod and - usb_keyboard.mod. - (usb_mod_SOURCES): New variable. - (usb_mod_CFLAGS): New variable. - (usb_mod_LDFLAGS): New variable. - (usbtest_mod_SOURCES): New variable. - (usbtest_mod_CFLAGS): New variable. - (usbtest_mod_LDFLAGS): New variable. - (ohci_mod_SOURCES): New variable. - (ohci_mod_CFLAGS): New variable. - (ohci_mod_LDFLAGS): New variable. - (usbms_mod_SOURCES): New variable. - (usbms_mod_CFLAGS): New variable. - (usbms_mod_LDFLAGS): New variable. - (usb_keyboard_mod_SOURCES): New variable. - (usb_keyboard_mod_CFLAGS): New variable. - (usb_keyboard_mod_LDFLAGS): New variable. - * include/grub/smbus.h: New file. - * include/grub/cs5536.h: New file. - -2010-06-02 Colin Watson - - * util/grub.d/00_header.in: Add safety check to make sure that - ${locale_dir} exists before trying to probe it. - -2010-06-02 Colin Watson - - * docs/grub.texi (SCO UnixWare): Remove, at Vladimir's request and - per the GNU Coding Standards; this is now too obscure to be worth - documenting. - (QNX): Likewise. - (chainloader): Remove cross-reference to `SCO UnixWare'. - -2010-06-02 Colin Watson - - * docs/grub.texi (Chain-loading): New section. - (DOS/Windows): New section, borrowed from GRUB Legacy with details - adjusted for GRUB 2. - (SCO UnixWare): Likewise. - (QNX): Likewise. - (chainloader): Add reference to `Block list syntax'. - (drivemap): New section. - (parttool): New section. - -2010-06-02 Colin Watson - - * docs/grub.texi (GNU GRUB manual): Remove reference to `Invoking - the grub shell'. - (Installation): Add reference to `Making a GRUB bootable CD-ROM'. - (Installing GRUB using grub-install): Remove reference to the grub - shell; mention `grub-mkimage' and `grub-setup' instead. - (Invoking grub-install): Likewise. - (Interface): Add reference to `Menu entry editor'. - (serial): Remove `--device' option. - -2010-06-02 Colin Watson - - * docs/grub.texi (Configuration): New section, documenting - configuration file generation using grub-mkconfig. I've left a slot - for documenting the full shell scripting format but have not yet - started on writing that up. - (Invoking grub-mkconfig): New section. - -2010-06-02 Colin Watson - - * docs/grub.texi (direntry): Remove grub-terminfo reference. - (GNU GRUB manual): Likewise. - (General commands): Update description of `terminfo' for GRUB 2. - -2010-06-02 Colin Watson - - * commands/gptsync.c (grub_cmd_gptsync): Fix typos. - (GRUB_MOD_INIT): Fix capitalisation. - * docs/grub.texi (Command-line and menu entry commands): Document - gettext and gptsync commands. - -2010-06-02 Colin Watson - - * conf/any-emu.rmk (kernel_img_SOURCES) [!x86]: Include - kern/$(target_cpu)/cache.S even if TARGET_NO_MODULES = yes. - -2010-06-01 Colin Watson - - Add btrfs probing support, currently only in the single-device case. - - * kern/emu/getroot.c (find_root_device_from_mountinfo): New - function. - (grub_guess_root_device): Call find_root_device_from_mountinfo - before looking in /dev. - -2010-05-31 Vladimir Serbinenko - - * disk/i386/pc/biosdisk.c (grub_biosdisk_open): Use - GRUB_DISK_SIZE_UNKNOWN. - * disk/ieee1275/ofdisk.c (grub_ofdisk_open): Likewise. - -2010-05-31 Jiro SEKIBA - - * include/grub/disk.h (GRUB_DISK_SIZE_UNKNOWN): New macro. - * fs/nilfs.c: Support 2nd super block in case 1st one is accidently - corrupted or not synced properly. - -2010-05-31 Vladimir Serbinenko - - * normal/main.c (grub_normal_add_menu_entry): Avoid going out of args. - Reported by: Seth Goldberg. - -2010-05-31 Vladimir Serbinenko - - * loader/multiboot_mbi2.c (grub_multiboot_make_mbi): Fix incorrect - addition of dest. - Reported by: Seth Goldberg. - -2010-05-31 Vladimir Serbinenko - - * commands/setpci.c (grub_setpci_iter): Fix an incorrect function check. - Reported by: Seth Goldberg. - -2010-05-31 Vladimir Serbinenko - - * loader/multiboot_elfxx.c (grub_multiboot_load_elfXX) [__mips]: Check - 64-bit address as signed on MIPS. - -2010-05-28 Colin Watson - - * configure.ac: AC_PROG_LEX sets LEX to ":" if lex is missing, not - to the empty string. - -2010-05-28 BVK Chaitanya - - Fix grub-emu issues on NetBSD, with gcc 4.1.3. - - * conf/any-emu.rmk: Remove unnecessary COMMON_CFLAGS. - * include/grub/emu/misc.h (canonicalize_file_name): New Prototype. - * kern/misc.c (__enable_execute_stack): Disable on - GRUB_MACHINE_EMU. - -2010-05-28 Colin Watson - - Make grub-probe work with symbolic links under /dev/mapper as well - as with real block devices. The Linux world seems to be (at best) - in transition here, and GRUB shouldn't get caught in the middle. - - * kern/emu/getroot.c (find_root_device): Follow symbolic links under - /dev/mapper. - -2010-05-27 Colin Watson - - * util/grub-script-check.c (main): Ensure defined behaviour on empty - input files (in which case exit zero). - -2010-05-27 Colin Watson - - * kern/emu/misc.c (canonicalize_file_name): realpath can still - return NULL for various reasons even if it has a maximum-length - buffer: for example, there might be a symlink loop, or the path - might exceed PATH_MAX. If this happens, return NULL. - -2010-05-27 Robert Millan - - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Insert - partmap module to handle cross-partmap setups. - Reported by Orestes Mas. GrĂ cies! - -2010-05-27 Colin Watson - - * util/grub-mkrescue.in: Initialise override_dir rather than - assuming that it's unset or empty in the environment. - -2010-05-26 GrĂ©goire Sutre - - * kern/emu/hostdisk.c (find_partition_start) [__NetBSD__]: Renamed - variable index into p_index to suppress a warning with -Wshadow. - -2010-05-25 BVK Chaitanya - - * INSTALL: Added flex >= 2.5.35 requirement. - -2010-05-23 Vladimir Serbinenko - - * commands/usbtest.c (grub_usb_get_string): Properly support UTF-16. - -2010-05-23 Vladimir Serbinenko - - cmostest support. - - * commands/i386/cmostest.c: New file. - * conf/i386-coreboot.rmk (pkglib_MODULES): Add cmostest.mod. - (cmostest_mod_SOURCES): New variable. - (cmostest_mod_CFLAGS): Likewise. - (cmostest_mod_LDFLAGS): Likewise. - * conf/i386-pc.rmk: Likewise. - * docs/grub.texi (Vendor power-on keys): New section. - * util/grub-mkconfig.in: export GRUB_DEFAULT_BUTTON, - GRUB_HIDDEN_TIMEOUT_BUTTON, GRUB_TIMEOUT_BUTTON - and GRUB_BUTTON_CMOS_ADDRESS. - * util/grub.d/00_header.in: Handle powering-on by separate button. - -2010-05-23 Vladimir Serbinenko - - * gfxmenu/gui_list.c (draw_menu): Don't add scrollbar width to padding. - Removed drawing_scrollbar argument. All users updated - Fixes #29792. - Reported by Jo Shields - -2010-05-23 Vladimir Serbinenko - - * gfxmenu/view.c (grub_gfxmenu_draw_terminal_box): Apply only to current - buffer since gfxterm handles double repaint. - -2010-05-23 Vladimir Serbinenko - - * gfxmenu/gfxmenu.c (grub_gfxmenu_try): Change viewport on both buffers. - * term/gfxterm.c (real_scroll): Likewise. - -2010-05-21 Vladimir Serbinenko - - * kern/i386/pc/mmap.c (grub_machine_mmap_iterate): Zero-fill entry - before calling BIOS. - -2010-05-21 Vladimir Serbinenko - - * include/grub/i18n.h: Always enable grub_gettext. - -2010-05-21 Vladimir Serbinenko - - * kern/i386/pc/init.c (make_install_device): Fix a leftover usage of old - partition naming style. - -2010-05-21 Colin Watson - - * util/grub-mkconfig.in: Fix handling of -o so that it works when - not the first option. - -2010-05-20 Colin Watson - - * util/grub-mkrelpath.c (usage): Remove excess apostrophe. - -2010-05-20 Colin Watson - - * util/misc.c: Move inclusion of to ... - * kern/emu/misc.c: ... here. Needed for canonicalize_file_name. - -2010-05-20 GrĂ©goire Sutre - - * kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev) [__NetBSD__]: - Fix merge error in NetBSD code. - (find_partition_start) [__NetBSD__]: Likewise. - -2010-05-19 BVK Chaitanya - - Fix grub-mkrescue usage unit testing. - - * tests/util/grub-shell.in: Use --grub-mkimage with grub-mkrescue. - -2010-05-18 Christian Franke - - * util/grub.d/10_windows.in: Use path names instead of - drive letters to prevent warning from Cygwin 1.7. - Add drivemap command to menuentry if needed. - -2010-05-18 Justus Winter <4winter@informatik.uni-hamburg.de> - - * util/grub.d/10_hurd.in: Include all gnumach* kernels, not only - gnumach and gnumach.gz. - -2010-05-18 Vladimir Serbinenko - - * include/grub/i18n.h (gettext): Inline instead of using #define. - (grub_gettext): Likewise. - (_): Likewise. - -2010-05-18 Vladimir Serbinenko - - * Makefile.in (CPPFLAGS): Replace -DGRUB_LIBDIR with - -DGRUB_PKGLIBROOTDIR= and prepend @PACKAGE_TARNAME@. All users updated. - * util/grub-mkimage.c (image_targets): Add i386-multiboot. - (main): Add a slash after pkglibdirroot. - -2010-05-18 Vladimir Serbinenko - - * util/grub-install.in: Add missing "in" keyword. - -2010-05-18 Vladimir Serbinenko - - * util/grub-mkrescue.in: Remove -O i386-pc duplication. - Reported by: Seth Goldberg. - -2010-05-18 Vladimir Serbinenko - - * po/POTFILES: Rename util/grub-mkrawimage.c to util/grub-mkimage.c. - -2010-05-18 Colin Watson - - * configure.ac: Check for Linux device-mapper support. - - * util/hostdisk.c (device_is_mapped): New function. - (find_partition_start): New function, partly broken out from - linux_find_partition and grub_util_biosdisk_get_grub_dev but with - device-mapper support added. - (linux_find_partition): Use find_partition_start. - (convert_system_partition_to_system_disk): Add `st' argument. - Support Linux /dev/mapper/* devices if device-mapper support is - available; only DM-RAID devices are understood at present. - (find_system_device): Add `st' argument. Pass it to - convert_system_partition_to_system_disk. - (grub_util_biosdisk_get_grub_dev): Pass stat result to - find_system_device and convert_system_partition_to_system_disk. Use - find_partition_start. - - * conf/common.rmk (grub_mkdevicemap_SOURCES): Add kern/env.c, - kern/err.c, kern/list.c, kern/misc.c, and kern/emu/mm.c. - * util/deviceiter.c [__linux__]: Define MINOR. - (grub_util_iterate_devices): Add support for DM-RAID disk devices. - * util/mkdevicemap.c (grub_putchar): New function. - (grub_getkey): New function. - (grub_refresh): New function. - (main): Set debug=all if -v -v is used. - -2010-05-18 Colin Watson - - Fix build with non-GNU libcs. - - * util/misc.c (canonicalize_file_name): Move to ... - * kern/emu/misc.c (canonicalize_file_name): ... here. Needed by - grub_make_system_path_relative_to_its_root. - -2010-05-18 Colin Watson - - * util/grub-mkrescue.in: Sync up with grub-install in terms of how - we handle finding grub-mkimage. Default to finding grub-mkimage in - ${bindir} with program_transform_name applied, and provide a - --grub-mkimage option to override this. - -2010-05-17 Vladimir Serbinenko - - Remove grub-mkisofs. - - * conf/common.rmk (bin_UTILITIES): Remove grub-mkisofs. - (grub_mkisofs_SOURCES): Removed. - (grub_mkisofs_CFLAGS): Removed. - * util/mkisofs/defaults.h: Removed. - * util/mkisofs/eltorito.c: Likewise. - * util/mkisofs/exclude.h: Likewise. - * util/mkisofs/hash.c: Likewise. - * util/mkisofs/include/: Likewise. - * util/mkisofs/include/fctldefs.h: Likewise. - * util/mkisofs/include/mconfig.h: Likewise. - * util/mkisofs/include/prototyp.h: Likewise. - * util/mkisofs/include/statdefs.h: Likewise. - * util/mkisofs/iso9660.h: Likewise. - * util/mkisofs/joliet.c: Likewise. - * util/mkisofs/match.c: Likewise. - * util/mkisofs/match.h: Likewise. - * util/mkisofs/mkisofs.c: Likewise. - * util/mkisofs/mkisofs.h: Likewise. - * util/mkisofs/msdos_partition.h: Likewise. - * util/mkisofs/multi.c: Likewise. - * util/mkisofs/name.c: Likewise. - * util/mkisofs/rock.c: Likewise. - * util/mkisofs/tree.c: Likewise. - * util/mkisofs/write.c: Likewise. - -2010-05-17 Vladimir Serbinenko - - Unify grub-mkimage accross platforms. - - * Makefile.in (CPPFLAGS): Set GRUB_LIBDIR to $(libdir). - * conf/common.rmk (bin_UTILITIES): Removed grub-mkelfimage. - (grub_mkelfimage_SOURCES): Removed. - (util/elf/grub-mkimage.c_DEPENDENCIES): Renamed to .. - (util/grub-mkimage.c_DEPENDENCIES): .. this. - (bin_UTILITIES): Add grub-mkimage. - (grub_mkimage_SOURCES): New variable. - (kernel_img_HEADERS): Remove machine/kernel.h. - * conf/i386-pc.rmk (pkglib_IMAGES): Remove kernel.img. - (pkglib_PROGRAMS): Add kernel.img. - (kernel_img_HEADERS): Add machine/kernel.h. - (kernel_img_FORMAT): Removed. - (bin_UTILITIES): Remove grub-mkimage. - (grub_mkimage_SOURCES): Removed. - (grub_mkimage_CFLAGS): Likewise. - (util/grub-mkrawimage.c_DEPENDENCIES): Likewise. - * conf/i386-qemu.rmk (pkglib_IMAGES): Remove kernel.img. - (pkglib_PROGRAMS): Add kernel.img. - (bin_UTILITIES): Remove grub-mkimage. - (grub_mkimage_SOURCES): Removed. - (grub_mkimage_CFLAGS): Likewise. - (util/grub-mkrawimage.c_DEPENDENCIES): Likewise. - * conf/mips-qemu-mips.rmk (pkglib_IMAGES): Remove kernel.img. - (pkglib_PROGRAMS): Add kernel.img. - * conf/mips-yeeloong.rmk (pkglib_IMAGES): Remove kernel.img. - (pkglib_PROGRAMS): Add kernel.img. - * conf/mips.rmk (bin_UTILITIES): Remove grub-mkimage. - (grub_mkimage_SOURCES): Removed. - (grub_mkimage_CFLAGS): Likewise. - (util/grub-mkrawimage.c_DEPENDENCIES): Likewise. - * conf/sparc64-ieee1275.rmk (pkglib_IMAGES): Remove kernel.img. - (pkglib_PROGRAMS): Add kernel.img. - (bin_UTILITIES): Remove grub-mkimage. - (grub_mkimage_SOURCES): Removed. - (grub_mkimage_CFLAGS): Likewise. - (util/grub-mkrawimage.c_DEPENDENCIES): Likewise. - * conf/x86-efi.rmk (bin_UTILITIES): Remove grub-mkimage. - (grub_mkimage_SOURCES): Removed. - (grub_mkimage_CFLAGS): Likewise. - (util/grub-mkrawimage.c_DEPENDENCIES): Likewise. - * configure.ac (machine_CFLAGS): Add "-DMACHINE". - * include/grub/efi/pe32.h (grub_pe32_optional_header): Split into ... - (grub_pe32_optional_header): ... this. - (grub_pe64_optional_header): ... and this. All users updated. - (GRUB_PE32_PE32_MAGIC): Split into .. - (GRUB_PE32_PE32_MAGIC): .. this. - (GRUB_PE32_PE64_MAGIC): .. and this. - (GRUB_PE32_SIGNATURE_SIZE): New definition. - * include/grub/elf.h (PT_GNU_STACK): New definition. - * include/grub/i386/coreboot/kernel.h: Merged into include/grub/offsets.h. All users updated. - * include/grub/i386/efi/kernel.h: Likewise. - * include/grub/i386/kernel.h: Likewise. - * include/grub/i386/pc/kernel.h: Likewise. - * include/grub/i386/qemu/boot.h: Likewise. - * include/grub/mips/kernel.h: Likewise. - * include/grub/mips/qemu-mips/kernel.h: Likewise. - * include/grub/powerpc/ieee1275/kernel.h: Likewise. - * include/grub/powerpc/kernel.h: Likewise. - * include/grub/sparc64/ieee1275/boot.h: Likewise. - * include/grub/sparc64/ieee1275/kernel.h: Likewise. - * include/grub/sparc64/kernel.h: Likewise. - * include/grub/x86_64/efi/kernel.h: Likewise. - * include/grub/x86_64/kernel.h: Likewise. - * include/grub/offsets.h: New file. - * include/grub/kernel.h (grub_module_info): Split into ... - (grub_module_info32): ... this. - (grub_module_info64): ... and this. - * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_KERNEL_SEG): Moved from here ... - * include/grub/offsets.h (GRUB_BOOT_I386_PC_KERNEL_SEG): ... here. - (grub_boot_blocklist): Moved from here ... - * include/grub/offsets.h (grub_pc_bios_boot_blocklist): ... here. - * include/grub/i386/pc/memory.h (GRUB_MEMORY_MACHINE_UPPER): Moved from here. - * include/grub/offsets.h (GRUB_MEMORY_I386_PC_UPPER): .. here. - * include/grub/types.h (grub_target_to_host16): Removed. - (grub_target_to_host32): Likewise. - (grub_target_to_host64): Likewise. - (grub_host_to_target16): Likewise. - (grub_host_to_target32): Likewise. - (grub_host_to_target64): Likewise. - (grub_host_to_target_addr): Likewise. - - Support grub-mkrescue for efi, coreboot and qemu. - - * conf/x86-efi.rmk (bin_SCRIPTS): Add grub-mkrescue. - * kern/efi/init.c (grub_efi_set_prefix): Handle baked in prefix. - * util/elf/grub-mkimage.c: Merged into util/grub-mkimage.c. - * util/grub-mkrawimage.c: Moved from here ... - * util/grub-mkimage.c: ... here. All users updated. - (ALIGN_ADDR): Use image_target. - (TARGET_NO_FIELD): New const. - (image_target_desc): New type. - (image_targets): New array. - (grub_target_to_host64): Use image_target. - (grub_target_to_host32): Likewise. - (grub_target_to_host16): Likewise. - (grub_host_to_target64): Likewise. - (grub_host_to_target32): Likewise. - (grub_host_to_target16): Likewise. - (grub_host_to_target_addr): Likewise. - (generate_image): Handle multiimage. - (main): Require -O parameter. All users updated. - * util/grub-mkimagexx.c: New file. Based on util/grub-mkrawimage.c and - util/efi/grub-mkimage.c - * util/grub-mkrescue.in: Handle coreboot, efi and qemu. - New option --rom-directory. - Use xorriso. - * util/i386/efi/grub-mkimage.c: Removed. - * util/i386/pc/grub-setup.c (grub_target_to_host16): New definition. - (grub_target_to_host32): Likewise. - (grub_target_to_host64): Likewise. - (grub_host_to_target16): Likewise. - (grub_host_to_target32): Likewise. - (grub_host_to_target64): Likewise. - * util/sparc64/ieee1275/grub-setup.c (grub_target_to_host16): New definition. - (grub_target_to_host32): Likewise. - (grub_target_to_host64): Likewise. - (grub_host_to_target16): Likewise. - (grub_host_to_target32): Likewise. - (grub_host_to_target64): Likewise. - -2010-05-17 BVK Chaitanya - - Source tree is reorganized for emu build. - - * include/grub/util/console.h: Move from here... - * include/grub/emu/console.h: ...to here. - * include/grub/util/getroot.h: Move from here... - * include/grub/emu/getroot.h: ...to here. - * include/grub/util/hostdisk.h: Move from here... - * include/grub/emu/hostdisk.h: ...to here. - * util/console.c: Move from here... - * kern/emu/console.c: ...to here. - * util/getroot.c: Move from here... - * kern/emu/getroot.c: ...to here. - * util/grub-emu.c: Move from here... - * kern/emu/main.c: ...to here. - * util/hostdisk.c: Move from here... - * kern/emu/hostdisk.c: ...to here. - * util/hostfs.c: Move from here... - * kern/emu/hostfs.c: ...to here. - * util/mm.c: Move from here... - * kern/emu/mm.c: ...to here. - * util/pci.c: Move from here... - * bus/emu/pci.c: ...to here. - * util/sdl.c: Move from here... - * video/emu/sdl.c: ...to here. - * util/time.c: Move from here... - * kern/emu/time.c: ...to here. - * util/usb.c: Move from here... - * bus/usb/emu/usb.c: ...to here. - - * include/grub/emu/misc.h: New header for grub-emu functions. - * kern/emu/misc.c: grub-emu functions separated from util/misc.c - - * conf/any-emu.rmk: Rule updates for above renames. - * conf/common.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/i386-qemu.rmk: Likewise. - * conf/mips.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * conf/x86-efi.rmk: Likewise. - - * disk/lvm.h: #include updates for above renames. - * util/grub-mkrelpath.c: Likewise. - * util/grub-probe.c: Likewise. - * util/i386/pc/grub-setup.c: Likewise. - * util/sparc64/ieee1275/grub-setup.c: Likewise. - * kern/emu/console.c: Likewise. - * kern/emu/getroot.c: Likewise. - * kern/emu/hostdisk.c: Likewise. - * kern/emu/main.c: Likewise. (was grub-emu.c earlier) - - * include/grub/dl.h: Remove grub_dl_{ref,unref}. - * include/grub/util/misc.h: Move grub-emu functions to emu/misc.h. - * kern/dl.c: Handle null mod in grub_dl_{ref,unref}. - * util/misc.c: Remove grub-emu functions. - -2010-05-13 Vladimir Serbinenko - - Fix gfxmenu crash. - Reported by: Thorsten GrĂ¼tzmacher. - - * gfxmenu/gui_circular_progress.c (circprog_destroy): Unregister - timeout hook. - (circprog_set_property): Register and unregister timeout hook. - * gfxmenu/gui_label.c (grub_gui_label): New fields template and value. - (label_destroy): Free template. and unregister hook. - (label_set_state): New function. - (label_set_property): Handle templates and hooks. - * gfxmenu/gui_progress_bar.c (progress_bar_destroy): Unregister - timeout hook. - (progress_bar_set_property): Register and unregister timeout hook. - * gfxmenu/view.c (TIMEOUT_COMPONENT_ID): Move from here ... - * include/grub/gui.h (GRUB_GFXMENU_TIMEOUT_COMPONENT_ID): ...to here - * gfxmenu/view.c (grub_gfxmenu_timeout_notifications): New variable. - (update_timeout_visit): Removed. - (update_timeouts): New function. - (redraw_timeouts): Likewise. - (grub_gfxmenu_print_timeout): Use update_timeouts and redraw_timeouts. - (grub_gfxmenu_clear_timeout): Likewise. - * include/grub/gui.h (grub_gfxmenu_set_state_t): New type. - (grub_gfxmenu_timeout_notify): Likewise. - (grub_gfxmenu_timeout_notifications): New external variable. - (grub_gfxmenu_timeout_register): New function. - (grub_gfxmenu_timeout_unregister): Likewise. - -2010-05-09 Vladimir Serbinenko - - Transform (broken) vga terminal into (working) vga video driver. - - * conf/i386-pc.rmk (vga_mod_SOURCES): Change term/i386/pc/vga.c to - video/i386/pc/vga.c. - * include/grub/video.h (grub_video_driver_id): - Add GRUB_VIDEO_DRIVER_VGA. - * term/i386/pc/vga.c: Renamed to ... - * video/i386/pc/vga.c: ...this - (DEBUG_VGA): Removed. - (CHAR_WIDTH): Likewise. - (CHAR_HEIGHT): Likewise. - (TEXT_WIDTH): Likewise. - (TEXT_HEIGHT): Likewise. - (DEFAULT_FG_COLOR): Likewise. - (DEFAULT_BG_COLOR): Likewise. - (colored_char): Likewise. - (xpos): Likewise. - (ypos): Likewise. - (cursor_state): Likewise. - (fg_color): Likewise. - (bg_color): Likewise. - (text_buf): Likewise. - (page): Likewise. - (font): Likewise. - (framebuffer): New variable. - (set_read_map): Disabled. - (setup): New variable. - (is_target): Likewise. - (grub_vga_mod_init): Likewise. - (grub_vga_mod_fini): Likewise. - (check_vga_mem): Likewise. - (write_char): Likewise. - (write_cursor): Likewise. - (scroll_up): Likewise. - (grub_vga_putchar): Likewise. - (grub_vga_getcharwidth): Likewise. - (grub_vga_getwh): Likewise. - (grub_vga_getxy): Likewise. - (grub_vga_gotoxy): Likewise. - (grub_vga_cls): Likewise. - (grub_vga_setcolorstate): Likewise. - (grub_vga_setcursor): Likewise. - (grub_video_vga_init): New function. - (grub_video_vga_setup): Likewise. - (grub_video_vga_fini): Likewise. - (update_target): Likewise. - (grub_video_vga_blit_bitmap): Likewise. - (grub_video_vga_blit_render_target): Likewise. - (grub_video_vga_set_active_render_target): Likewise. - (grub_video_vga_get_active_render_target): Likewise. - (grub_video_vga_swap_buffers): Likewise. - (grub_video_vga_set_palette): Likewise. - (grub_video_vga_get_info_and_fini): Likewise. - (grub_vga_term): Removed. - (grub_video_vga_adapter): New variable. - (GRUB_MOD_INIT): Register a video driver instead of terminal. - (GRUB_MOD_FINI): Unrefister a video driver instead of terminal. - -2010-05-05 Vladimir Serbinenko - - * video/readers/jpeg.c: Indented. - -2010-05-05 Vladimir Serbinenko - - Various jpeg cleanups. - - * video/readers/jpeg.c (grub_jpeg_get_huff_code): Use ARRAY_SIZE. - (grub_jpeg_decode_quan_table): Use sizeof. - (grub_jpeg_decode_du): Use ARRAY_SIZE. - -2010-05-05 Peter Hurley (tiny change) - - * video/readers/jpeg.c (grub_jpeg_decode_huff_table): Loop over all - tables. Ignore non-last ac bit. - (grub_jpeg_decode_quan_table): Likewise. - -2010-05-05 Vladimir Serbinenko - - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New value - GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM. - * kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set - GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM on qemu. - * kern/ieee1275/init.c (grub_claim_heap): Don0t allocate below - 1.5MiB if GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM is set. - -2010-05-05 Vladimir Serbinenko - - * term/ieee1275/ofconsole.c (grub_ofconsole_getkey): Fix off-by-one - error. - -2010-05-05 Vladimir Serbinenko - - * term/ieee1275/ofconsole.c (grub_ofconsole_readkey): Support C0 code. - -2010-05-03 Vladimir Serbinenko - - * commands/parttool.c (grub_cmd_parttool): Fix #if !GRUB_NO_MODULES - condition. - -2010-05-03 Vladimir Serbinenko - - * kern/mm.c (grub_real_malloc): Put magic and size assignment in common - part. - -2010-05-03 Vladimir Serbinenko - - * kern/mm.c (grub_mm_init_region): Check for region size after aligning - pointers. - -2010-05-03 Vladimir Serbinenko - - * kern/mm.c (grub_real_malloc): Fix size calculation when extra == 0. - -2010-05-01 Christian Franke - - * util/grub-mkconfig_lib.in (make_system_path_relative_to_its_root): - Remove broken Cygwin path conversion. - * util/misc.c: [__CYGWIN__] Add include and define. - [__CYGWIN__] (get_win32_path): Copy function from getroot.c, modify - for Cygwin 1.7. - (make_system_path_relative_to_its_root): Simplify loop, replace early - return by break. - [__CYGWIN__] Add conversion to win32 path. - Include "/" case in trailing slash removal. - -2010-05-01 Vladimir Serbinenko - - * kern/main.c (grub_load_config): Fix copy-pasted comment. - Reported by: Seth Goldberg - -2010-05-01 Vladimir Serbinenko - - * commands/help.c (grub_cmd_help): Fix a typo. - Reported by: Seth Goldberg - -2010-05-01 Vladimir Serbinenko - - * commands/hashsum.c (GRUB_MOD_INIT): Remove duplication of command - name and add N_. - * commands/i386/pc/drivemap.c (GRUB_MOD_INIT): Likewise. - * commands/iorw.c (GRUB_MOD_INIT): Likewise. - * commands/password_pbkdf2.c (GRUB_MOD_INIT): Likewise. - * commands/regexp.c (GRUB_MOD_INIT): Likewise. - * commands/setpci.c (GRUB_MOD_INIT): Likewise. - * commands/terminal.c (GRUB_MOD_INIT): Likewise. - * efiemu/main.c (GRUB_MOD_INIT): Likewise. - * font/font_cmd.c (GRUB_MOD_INIT): Likewise. - * kern/corecmd.c (GRUB_MOD_INIT): Likewise. - * mmap/mmap.c (GRUB_MOD_INIT): Likewise. - * normal/context.c (GRUB_MOD_INIT): Likewise. - * normal/main.c (GRUB_MOD_INIT): Likewise. - * term/gfxterm.c (GRUB_MOD_INIT): Likewise. - * term/serial.c (GRUB_MOD_INIT): Likewise. - * term/terminfo.c (GRUB_MOD_INIT): Likewise. - -2010-05-01 Vladimir Serbinenko - - * kern/mm.c (grub_real_malloc): Satisfy alignment requirement when - extra == 0. - -2010-05-01 Vladimir Serbinenko - - * commands/iorw.c: New file. - * conf/i386.rmk (pkglib_MODULES): Add iorw.mod. - (iorw_mod_SOURCES): New variable. - (iorw_mod_CFLAGS): Likewise. - (iorw_mod_LDFLAGS): Likewise. - -2010-05-01 Vladimir Serbinenko - - Hotkey support - - * include/grub/menu.h (grub_menu_entry): New field 'hotkey'. - * normal/main.c (hotkey_aliases): New variable. - (grub_normal_add_menu_entry): Parse "--hotkey". - * normal/menu_text.c (run_menu): Handle hotkeys. - -2010-05-01 Vladimir Serbinenko - - * kern/i386/coreboot/init.c (grub_machine_init): Call - grub_machine_mmap_init on qemu. - -2010-05-01 Vladimir Serbinenko - - * boot/i386/qemu/boot.S: Add a missing .code16. - -2010-05-01 Vladimir Serbinenko - - Use LBIO on coreboot. - - * conf/i386-coreboot.rmk (kernel_img_SOURCES): Change - kern/i386/multiboot_mmap.c to kern/i386/coreboot/mmap.c. - * include/grub/i386/coreboot/memory.h (GRUB_LINUXBIOS_MEMBER_LINK): - New declaration. - * kern/i386/coreboot/init.c (grub_machine_init): Don't call - grub_machine_mmap_init on coreboot. - * kern/i386/coreboot/mmap.c (grub_linuxbios_table_iterate): Handle - GRUB_LINUXBIOS_MEMBER_LINK. - (grub_machine_mmap_iterate): Fix declaration. - * kern/i386/coreboot/startup.S: Don't save mbi location on coreboot. - -2010-05-01 Vladimir Serbinenko - - Split coreboot and multiboot ports. - - * conf/i386-multiboot.rmk: New file. - * configure.ac: Add multiboot port. - * include/grub/i386/multiboot/boot.h: New file. - * include/grub/i386/multiboot/console.h: Likewise. - * include/grub/i386/multiboot/init.h: Likewise. - * include/grub/i386/multiboot/kernel.h: Likewise. - * include/grub/i386/multiboot/loader.h: Likewise. - * include/grub/i386/multiboot/memory.h: Likewise. - * include/grub/i386/multiboot/serial.h: Likewise. - * include/grub/i386/multiboot/time.h: Likewise. - * include/grub/multiboot.h: Add GRUB_MACHINE_MULTIBOOT to ifdef. - * loader/multiboot.c: Likewise. - * loader/multiboot_mbi2.c: Likewise. - * util/grub-mkrescue.in: Generate multiboot rescue. - -2010-05-01 Vladimir Serbinenko - - * kern/parser.c (grub_parser_execute): Cope with read-only config. - -2010-05-01 Vladimir Serbinenko - - Merge handling of input and output terminals. Fix a hang. - - * commands/terminal.c (abstract_terminal): New struct. - (handle_command): New function. Based on grub_cmd_terminal_input. - (grub_cmd_terminal_input): Use handle_command. - (grub_cmd_terminal_output): Use handle_command. - -2010-05-01 BVK Chaitanya - - Fix comment handling. - - * tests/grub_script_comments.in: New testcase. - * conf/tests.rmk: Rules for new testcase. - * script/yylex.l: Updated flex rules. - -2010-04-28 Samuel Thibault - - * docs/grub.texi (play): Document that zero pitches produce rests. - * commands/i386/pc/play.c (grub_cmd_play): Call 'grub_file_open' only - if argc is 1. - -2010-04-27 Vladimir Serbinenko - - * conf/x86-efi.rmk (linux_mod_SOURCES): Write explicitly to avoid - autogen issues. - -2010-04-26 Christian Franke - - * include/grub/util/getroot.h (grub_get_prefix): Remove prototype. - * util/getroot.c [__CYGWIN__] (get_win32_path): Remove function. - (grub_get_prefix): Remove function. - * util/grub-emu.c (main): Replace grub_get_prefix () call by - make_system_path_relative_to_its_root (). - * util/sparc64/ieee1275/grub-setup.c (main): Likewise. - -2010-04-24 Christian Franke - - * Makefile.in (TARGET_LDFLAGS): Add -static-libgcc. - (kernel_img_LDFLAGS): Remove -static-libgcc. - -2010-04-24 Christian Franke - - * configure.ac: Do not CHECK_BSS_START_SYMBOL - and CHECK_END_SYMBOL if grub-emu is built. - Unset TARGET_OBJ2ELF if grub-emu is built - without module support. - -2010-04-24 Jiro SEKIBA - - Nilfs2 support. - - * conf/common.rmk (grub_probe_SOURCES): Add fs/nilfs2.c. - (grub_fstest_SOURCES): Likewise. - (pkglib_MODULES): Add nilfs2.mod. - (nilfs2_mod_SOURCES): New variable. - (nilfs2_mod_CFLAGS): Likewise. - (nilfs2_mod_LDFLAGS): Likewise. - * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/nilfs2.c. - * conf/sparc64-ieee1275.rmk (grub_setup_SOURCES): Add fs/nilfs2.c. - * fs/nilfs2.c: New file. - -2010-04-21 Vladimir Serbinenko - - * configure.ac: Refuse to compile for x86_64-efi is mcmodel=large - is not supported. - -2010-04-19 GrĂ©goire Sutre - - Add grub-mkconfig support for NetBSD. - - * util/grub.d/10_netbsd.in: grub-mkconfig helper script for NetBSD. - * util/grub-mkconfig.in: export new NetBSD specific variables. - * po/POTFILES-shell: added 10_netbsd.in. - * util/grub-mkconfig_lib.in: check for gettext binary, default to echo. - -2010-04-19 BVK Chaitanya - - Fix emu build with grub-emu-pci and grub-emu-modules. - - * include/grub/util/misc.h: Export grub_util_{info,error,warn} - functions. - * include/grub/libpciaccess.h: New file. - * conf/any-emu.rmk: Update kernel headers for emu build. - -2010-04-19 Vladimir Serbinenko - - * fs/udf.c (grub_udf_iterate_dir): Silence a spurious warning. - -2010-04-19 Vladimir Serbinenko - - * fs/udf.c (grub_udf_iterate_dir): Decode the Unicode filenames. - -2010-04-18 Vladimir Serbinenko - - * boot/sparc64/ieee1275/boot.S: Various size-reducing changes. - Retrieve chosen/bootpath if bootpath isn't hardcoded. - * conf/sparc64-ieee1275.rmk (grub_setup_SOURCES): Add - util/ieee1275/ofpath.c. - * util/sparc64/ieee1275/grub-ofpathname.c: Renamed to ... - * util/ieee1275/grub-ofpathname.c: ... this. All users updated - * include/grub/sparc64/ieee1275/boot.h - (GRUB_BOOT_MACHINE_KERNEL_SECTOR): Renamed to ... - (GRUB_BOOT_MACHINE_KERNEL_BYTE): ...this. Moved 8 bytes lower. - * util/hostdisk.c (grub_util_biosdisk_get_osdev): New function. - * util/ieee1275/ofpath.c (grub_util_devname_to_ofpath): Make argument - const char *. - * util/sparc64/ieee1275/grub-setup.c (compute_dest_ofpath): Removed. - (setup): Use KERNEL_BYTE instead of KERNEL_SECTOR. - Use grub_util_devname_to_ofpath. Zero-fill boot_devpath on same disk - install. - -2010-04-18 GrĂ©goire Sutre - - * util/grub-mkconfig.in: Corrected two == equality tests. - Set grub_prefix as in grub-install for NetBSD and OpenBSD. - * configure.ac: All definitions and uses of TARGET_IMG_LDFLAGS_AC now - expect a number appended to it. - * acinclude.m4 (grub_PROG_OBJCOPY_ABSOLUTE): ${TARGET_IMG_LDFLAGS_AC} - expects a number appended to it. - -2010-04-18 Vladimir Serbinenko - - * po/POTFILES: Renamed multiboot_loader.c to multiboot.c - -2010-04-18 Vladimir Serbinenko - - * util/hostdisk.c (make_device_name): Change to new partition naming. - -2010-04-17 Vladimir Serbinenko - - * disk/lvm.c (grub_lvm_memberlist): Issue an error if pv->disk = 0. - -2010-04-17 Christian Franke - - * Makefile.in: Add missing localedir setting. - -2010-04-14 Colin Watson - - Restore TEXTDOMAINDIR correction from r1889, lost apparently by - mistake in r2156. Noticed by Anthony Fok. - - * util/grub.d/10_kfreebsd.in (TEXTDOMAINDIR): Set to lowercased - @localedir@. - * util/grub.d/10_linux.in (TEXTDOMAINDIR): Likewise. - -2010-04-14 BVK Chaitanya - - Fix a spurious, uninitialized variable warning. - - * loader/i386/bsdXX.c (grub_freebsd_load_elfmodule_obj): - Initialize variable, shdr. - (grub_freebsd_load_elfmodule): Likewise. - (grub_freebsd_load_elf_meta): Likewise. - -2010-04-13 BVK Chaitanya - - Fix for escaped dollar in double quoted strings. - - * script/yylex.l: Updated flex rules. - * conf/tests.rmk: Rule for new testcase. - * tests/grub_script_dollar.in: New testcase. - -2010-04-13 Carles Pina i Estany -2010-04-13 Colin Watson - - Enclose all translated strings in grub.cfg in single quotes, and - escape them appropriately (Ubuntu bug #552921). - - * util/grub-mkconfig_lib.in (gettext_quoted): New function. - * util/grub.d/10_hurd.in: Use it. - * util/grub.d/10_kfreebsd.in (kfreebsd_entry): Likewise. - * util/grub.d/10_linux.in (linux_entry): Likewise. - -2010-04-11 Vladimir Serbinenko - - Fix cygwin compilation. - - * configure.ac: Define NEED_REGISTER_FRAME_INFO. - * include/grub/misc.h (__register_frame_info) - [NEED_REGISTER_FRAME_INFO && !UTIL]: New export. - (__deregister_frame_info) [NEED_REGISTER_FRAME_INFO && !UTIL]: Likewise. - * kern/misc.c (__register_frame_info) - [NEED_REGISTER_FRAME_INFO && !UTIL]: New empty function. - (__deregister_frame_info) [NEED_REGISTER_FRAME_INFO && !UTIL]: Likewise. - -2010-04-11 Vladimir Serbinenko - - * configure.ac: Respect grub_cv_asm_uscore when defining dummy symbols. - -2010-04-11 Vladimir Serbinenko - - Unify libgcc processing. - - * Makefile.in (kernel_img_LDFLAGS): New variable. - * conf/common.rmk (kernel_img_HEADERS): Add libgcc.h. - * conf/i386-coreboot.rmk (kernel_img_LDFLAGS): Append instead of - overwriting. - * conf/i386-ieee1275.rmk (kernel_img_LDFLAGS): Likewise. - * conf/i386-pc.rmk (kernel_img_LDFLAGS): Likewise. - * conf/i386-qemu.rmk (kernel_img_LDFLAGS): Likewise. - * conf/x86-efi.rmk (kernel_img_LDFLAGS): Likewise. - * conf/mips-qemu-mips.rmk (kernel_img_LDFLAGS): Append instead of - overwriting. Remove -lgcc and -static-libgcc - * conf/mips-yeeloong.rmk (kernel_img_LDFLAGS): Likewise. - * conf/mips.rmk (kernel_img_HEADERS): Remove cpu/libgcc.h - * conf/powerpc-ieee1275.rmk (kernel_img_HEADERS): Remove cpu/libgcc.h - (kernel_img_LDFLAGS): Append instead of overwriting. - Remove -lgcc and -static-libgcc - * conf/sparc64-ieee1275.rmk: Likewise. - * include/grub/powerpc/libgcc.h: Move to ... - * include/grub/libgcc.h: .. this. - * include/grub/libgcc.h: Don't export most of the function on x86. - (__bswapsi2): New export. - (__bswapdi2): Likewise. - * include/grub/mips/libgcc.h: Removed. - * include/grub/sparc64/libgcc.h: Likewise. - -2010-04-10 Vladimir Serbinenko - - * util/hostdisk.c (grub_util_biosdisk_get_grub_dev): Remove - disk_info_msg (conflicts with gettexting into languages with cases). - -2010-04-10 GrĂ©goire Sutre - - Add grub-probe support for NetBSD. - - * util/getroot.c (find_root_device): Convert block device to - character device on NetBSD. - * util/probe.c (probe): Require character device on NetBSD. - * util/hostdisk.c: NetBSD specific headers. - (configure_device_driver): new function to tune device driver - parameters (currently only for NetBSD floppy driver). - (grub_util_biosdisk_open): NetBSD specific code (get disk size - via disklabel ioctl). - (open_device): call configure_device_driver on NetBSD. - (convert_system_partition_to_system_disk): NetBSD specific code. - (device_is_wholedisk): Likewise. - (grub_util_biosdisk_get_grub_dev): Likewise. - (make_device_name): Fixed a typo in bsd_part_str. - * configure.ac: check for opendisk() and getrawpartition() on - NetBSD and set LIBUTIL. - * Makefile.in: add LIBUTIL to LIBS. - -2010-04-10 BVK Chaitanya - - Documentation fix. - - * util/grub-script-check.c: Better help message. - -2010-04-10 BVK Chaitanya - - Fix FreeBSD build. - - * configure.ac: Flex version check. - * conf/common.rmk: Add -Wno-error to sh.mod. - * script/yylex.l: Remove all #pragma. - -2010-04-10 Vladimir Serbinenko - - * include/grub/util/misc.h (canonicalise_file_name): Add missing - prototype. - Reported by: Seth Goldberg. - -2010-04-10 Vladimir Serbinenko - - * loader/multiboot.c (GRUB_MOD_INIT) [GRUB_USE_MULTIBOOT2]: - Rename "module" to "module2". - Reported by: Seth Goldberg. - -2010-04-10 Vladimir Serbinenko - - * include/grub/efi/memory.h (grub_machine_mmap_iterate): Remove - EXPORT_FUNC. - Reported by: Seth Goldberg. - -2010-04-10 Vladimir Serbinenko - - * lib/posix_wrap/locale.h: Add missing file. - Reported by: Seth Goldberg. - -2010-04-10 Vladimir Serbinenko - - grub-emu module load support. - - * Makefile.in (TARGET_NO_MODULES): New variable. All users of - NO_DYNAMIC_MODULES switched to this. - (TARGET_CFLAGS): Add -DGRUB_TARGET_NO_MODULES=1 if applicable. - (CFLAGS): Likewise. - * conf/any-emu.rmk: Generate symlist. - (kernel_img_HEADERS): Add util/datetime.h. - (kernel_img_HEADERS) [sdl]: Add sdl.h. - (kernel_img_HEADERS) [libusb]: Add libusb.h. - (kernel_img_SOURCES) [TARGET_NO_MODULES = no && !x86]: Add - kern/$(target_cpu)/cache.S. - * configure.ac (grub-emu-modules): New option. - * genmk.rb: Handle multiple source lists. - * include/grub/sdl.h: New file. - * include/grub/libusb.h: Likewise. - * util/grub-emu.c (main): Hanle (host) root. - * util/hostdisk.c (grub_util_biosdisk_get_grub_dev): Error with - GRUB_ERR_UNKNOWN_DEVICE. - * util/misc.c: Move mm functions to ... - * util/mm.c: ... here. All users updated. - -2010-04-09 Vladimir Serbinenko - - * Makefile.in (RMKFILES): Search in srcdir and not current directory. - (MAINTAINER_CLEANFILES): Don't add $(srcdir) to MKFILES. Add few - missing files. - (maintainer-clean): Remove libgcrypt-grub. - -2010-04-09 Vladimir Serbinenko - - * term/efi/console.c (grub_console_checkkey): Macroify key contants. - -2010-04-09 EFI Coder - - * normal/menu_text.c (print_message): Clean up the message and show - the Fn information when on EFI - * term/efi/console.c (grub_console_checkkey): Add F4 support. - -2010-04-09 Vladimir Serbinenko - - * normal/autofs.c (read_fs_list): New parameter 'prefix'. - All users updated. - * normal/crypto.c (read_crypto_list): Likewise. - * normal/dyncmd.c (read_command_list): Likewise. - * normal/term.c (read_terminal_list): Likewise. - * normal/main.c (read_lists): Use explicit prefix. - (read_lists_hook): Use read_lists. - (grub_normal_execute): Likewise. - -2010-04-09 Vladimir Serbinenko - - * util/grub-mkrescue.in: Fix incorrect path in coreboot part. - Reported by: Thomas Schmitt. - Add -no-emul-boot to grub-mkisofs parameters. - -2010-04-09 Vladimir Serbinenko - - * font/font.c: Indented. - -2010-04-09 BVK Chaitanya - - Elif support to GRUB script (by Deepak Vankadaru). - - * tests/grub_script_if.in: New testcase. - * conf/tests.rmk: Rule for new testcase. - * script/parser.y: Grammar rules for elif. - -2010-04-09 BVK Chaitanya - - While and until loops support to GRUB script. - - * include/grub/script_sh.h (grub_script_cmdwhile): New struct. - (grub_script_create_cmdwhile): New function prototype. - (grub_script_execute_cmdwhile): New function prototype. - * script/execute.c (grub_script_execute_cmdwhile): New function. - * script/parser.y (command): New commands. - (whilecmd): New grammar rule. - (untilcmd): New grammar rule. - * script/script.c (grub_script_create_cmdwhile): New function. - * util/grub-script-check.c (grub_script_execute_cmdwhile): New - function. - - * tests/grub_script_while1.in: New testcase. - * conf/tests.rmk: Rule for new testcase. - -2010-04-09 Vladimir Serbinenko - - * util/grub.d/00_header.in: Add few missing quotes. Recognise *.jpeg - as *.jpg. - -2010-04-09 Mario Vazquez - - GRUB_BACKGROUND support. - - * util/grub-mkconfig.in: Export GRUB_BACKGROUND. - * util/grub.d/00_header.in: Parse GRUB_BACKGROUND. - -2010-04-09 Vladimir Serbinenko - - Load fonts and modules for gfxmenu in grub-mkconfig. - Idea by: Mario Vazquez - - * util/grub.d/00_header.in: Load pf2 and image modules. - -2010-04-09 Vladimir Serbinenko - - grub-mkconfig multiple terminal support. - - * util/grub-mkconfig.in: Handle multiple terminals correctly. - * util/grub.d/00_header.in: Likewise. - -2010-04-09 Vladimir Serbinenko - - * Makefile.in: Specify files explicitly instead of using $< and $@ since - we use cd $(srcdir). - -2010-04-08 Colin Watson - - * util/grub.d/10_linux.in: Only use the first word of - GRUB_DISTRIBUTOR for --class, to avoid problems if somebody puts - spaces in GRUB_DISTRIBUTOR. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_hurd.in: Likewise. - -2010-04-06 BVK Chaitanya - - Fix unit testing framework for Qemu 0.12. - - * tests/util/grub-shell.in: Remove -serial stdio option. - -2010-04-06 Vladimir Serbinenko - - POSIX header file wrappers. - - * lib/posix_wrap/assert.h: New file. Wrapper for its POSIX - equivalents. - * lib/posix_wrap/ctype.h: Likewise. - * lib/posix_wrap/errno.h: Likewise. - * lib/posix_wrap/langinfo.h: Likewise. - * lib/posix_wrap/limits.h: Likewise. - * lib/posix_wrap/localcharset.h: Likewise. - * lib/posix_wrap/stdint.h: Likewise. - * lib/posix_wrap/stdio.h: Likewise. - * lib/posix_wrap/stdlib.h: Likewise. - * lib/posix_wrap/string.h: Likewise. - * lib/posix_wrap/sys/types.h: Likewise. - * lib/posix_wrap/unistd.h: Likewise. - * lib/posix_wrap/wchar.h: Likewise. - * lib/posix_wrap/wctype.h: Likewise. - * conf/common.rmk (grub_script.yy.c): Remove #include elimination. - (grub_script.yy.h): Likewise. - * script/yylex.l: Remove POSIX emulation #defines. - * Makefile.in (POSIX_CFLAGS): New variable. - (GNULIB_UTIL_CFLAGS): Likewise. - - Regexp support. - - * conf/common.rmk (pkglib_MODULES): Add regexp.mod. - (regexp_mod_SOURCES): New variable. - (regexp_mod_CFLAGS): Likewise. - (regexp_mod_LDFLAGS): Likewise. - * commands/regexp.c: New file. - * gnulib/regcomp.c: New file. Imported from gnulib. - * gnulib/regex.c: Likewise. - * gnulib/regex_internal.c: Likewise. - * gnulib/regex_internal.h: Likewise. - * gnulib/regexec.c: Likewise. - * gnulib/regex.h: Likewise. - -2010-04-05 Vladimir Serbinenko - - * loader/i386/multiboot_mbi.c (grub_multiboot_load): Correctly report - unsupported video mode types. - -2010-04-05 Vladimir Serbinenko - - * kern/i386/pc/startup.S (grub_getrtsecs): Removed (dead code). - -2010-04-05 Vladimir Serbinenko - - * include/grub/i386/pc/init.h (grub_get_mmap_entry): Don't export. - * conf/i386-pc.rmk (kernel_img_HEADERS): Remove machine/init.h. - -2010-04-04 Vladimir Serbinenko - - Remove unused grub_vga_get_font. - - * kern/i386/pc/startup.S (grub_vga_get_font): Removed. - * include/grub/i386/pc/vga.h (grub_vga_get_font): Likewise. - -2010-04-03 GrĂ©goire Sutre - - * kern/misc.c: Disable the __enable_execute_stack hack for utilities. - * include/grub/misc.h: Likewise. - -2010-04-03 GrĂ©goire Sutre - - * util/grub-install.in: Add `|| exit 1' to all grub-probe calls - for which failure is fatal. - -2010-04-03 GrĂ©goire Sutre - - * util/grub-install.in: Use mkdir -p to create grub directory. - * util/i386/efi/grub-install.in: Likewise. - * util/ieee1275/grub-install.in: Likewise. - -2010-04-03 GrĂ©goire Sutre - - * Makefile.in (LEX): new variable. - -2010-04-03 GrĂ©goire Sutre - - * util/i386/efi/grub-dumpdevtree: replaced the non-portable `==' by - `=' and added double quotes on operands of this equality test. - -2010-04-03 Vladimir Serbinenko - - * Makefile.in (uninstall): Remove a leftover debug echo. - Reported by: GrĂ©goire Sutre - -2010-04-03 Vladimir Serbinenko - - MIPS multiboot2 support. - - * conf/mips.rmk (pkglib_MODULES): Add multiboot2.mod. - (multiboot2_mod_SOURCES): New variable. - (multiboot2_mod_CFLAGS): Likewise. - (multiboot2_mod_LDFLAGS): Likewise. - (multiboot2_mod_ASFLAGS): Likewise. - * include/grub/i386/multiboot.h (MULTIBOOT_INITIAL_STATE): New - definition. - (MULTIBOOT_ENTRY_REGISTER): Likewise. - (MULTIBOOT_MBI_REGISTER): Likewise. - (MULTIBOOT_ARCHITECTURE_CURRENT): Likewise. - (MULTIBOOT_ELF32_MACHINE): Likewise. - (MULTIBOOT_ELF64_MACHINE): Likewise. - * include/grub/mips/multiboot.h: New file. - * include/grub/video.h (grub_video_driver_id): New type - GRUB_VIDEO_DRIVER_SM712. - (grub_video_get_info_and_fini): Export. - (grub_video_get_palette): Likewise. - (grub_video_get_driver_id): Likewise. - * include/multiboot2.h: Resynced with spec. - * loader/i386/multiboot.c: Moved from here ... - * loader/multiboot.c: ... here. All users updated. - (grub_multiboot_boot): Use platform-specific macros. - * loader/i386/multiboot_elfxx.c: Moved from here ... - * loader/multiboot_elfxx.c: ... here. All users updated. - (E_MACHINE): Use MULTIBOOT_ELF32_MACHINE and MULTIBOOT_ELF64_MACHINE. - * loader/i386/multiboot_mbi2.c (grub_multiboot_load): Check arcitecture. - * video/sm712.c (grub_video_sm712_adapter): Add missing id field. - -2010-04-02 Vladimir Serbinenko - - Import gnulib argp module. - - * gnulib/argp-ba.c: New file. - * gnulib/argp-eexst.c: Likewise. - * gnulib/argp-fmtstream.c: Likewise. - * gnulib/argp-fmtstream.h: Likewise. - * gnulib/argp-fs-xinl.c: Likewise. - * gnulib/argp-help.c: Likewise. - * gnulib/argp-namefrob.h: Likewise. - * gnulib/argp-parse.c: Likewise. - * gnulib/argp-pin.c: Likewise. - * gnulib/argp-pv.c: Likewise. - * gnulib/argp-pvh.c: Likewise. - * gnulib/argp-version-etc.c: Likewise. - * gnulib/argp-version-etc.h: Likewise. - * gnulib/argp-xinl.c: Likewise. - * gnulib/argp.h: Likewise. - -2010-03-31 Vladimir Serbinenko - - * kern/device.c (grub_device_iterate): Clear errors after failed - opening device. - -2010-03-31 Vladimir Serbinenko - - * kern/ieee1275/openfw.c (grub_children_iterate): Skip device itself if - returned by firmware. - -2010-03-30 Vladimir Serbinenko - - * loader/i386/multiboot_mbi2.c (retrieve_video_parameters): Fix - compilation on coreboot and qemu - -2010-03-28 Vladimir Serbinenko - - * include/multiboot2.h: Resync with spec. - -2010-03-28 Vladimir Serbinenko - - Multiboot2 tag support - - * conf/i386.rmk (multiboot2_mod_SOURCES): Replace - loader/i386/multiboot_mbi.c with loader/i386/multiboot_mbi2.c. - Remove loader/multiboot_loader.c. - * include/grub/i386/multiboot.h (grub_multiboot_real_boot): Removed. - (grub_multiboot2_real_boot): Likewise. - * include/grub/multiboot.h (grub_multiboot_set_accepts_video): Removed. - (grub_get_multiboot_mmap_count): New proto. - (grub_fill_multiboot_mmap): Likewise. - (grub_multiboot_set_video_mode): Likewise. - (grub_multiboot_set_console): Likewise. - (grub_multiboot_load): Likewise. - (grub_multiboot_load_elf): Likewise. - (GRUB_MULTIBOOT_CONSOLE_EGA_TEXT): New definition. - (GRUB_MULTIBOOT_CONSOLE_FRAMEBUFFER): Likewise. - * include/multiboot.h: Resynced with specification. - * include/multiboot2.h: Resynced with specification. - * loader/i386/multiboot_mbi.c (DEFAULT_VIDEO_MODE): Moved from here... - * loader/i386/multiboot.c (DEFAULT_VIDEO_MODE): ... here. - * loader/i386/multiboot_mbi.c (HAS_VGA_TEXT): Moved from here .. - * include/grub/multiboot.h (GRUB_MACHINE_HAS_VGA_TEXT): ... here. All - users updated. - * loader/i386/multiboot_mbi.c (accepts_video): Moved from here... - * loader/i386/multiboot.c (accepts_video): ... here. All users updated. - * loader/i386/multiboot_mbi.c (grub_multiboot_set_accepts_video): - Removed. - * loader/i386/multiboot_mbi.c (grub_get_multiboot_mmap_len): - Moved from here... - * loader/i386/multiboot.c (grub_get_multiboot_mmap_len): ... here. - * loader/i386/multiboot_mbi.c (grub_fill_multiboot_mmap): - Moved from here... - * loader/i386/multiboot.c (grub_fill_multiboot_mmap): ... here. - * loader/i386/multiboot_mbi.c (set_video_mode): Moved from here... - * loader/i386/multiboot.c (grub_multiboot_set_video_mode): ... here. - All users updated. - * loader/i386/multiboot_mbi2.c: New file. - -2010-03-27 Vladimir Serbinenko - - Resync with gnulib. - - * Makefile.in (GNULIB_CFLAGS): New variable. - * conf/common.rmk (grub_mkisofs_CFLAGS): Add GNULIB_CFLAGS. - (grub_script_check_CFLAGS): New variable. - * gnulib/alloca.h: Resync with gnulib. - * gnulib/error.c: Likewise. - * gnulib/error.h: Likewise. - * gnulib/fnmatch.c: Likewise. - * gnulib/fnmatch_loop.c: Likewise. - * gnulib/getdelim.c: Likewise. - * gnulib/getline.c: Likewise. - * gnulib/getopt.c: Likewise. - * gnulib/getopt1.c: Likewise. - * gnulib/getopt_int.h: Likewise. - * gnulib/gettext.h: Likewise. - * gnulib/progname.c: Likewise. - * gnulib/progname.h: Likewise. - -2010-03-27 GrĂ©goire Sutre - - Fix a build failure (-Wundef -Werror) when ENABLE_NLS is not defined, - which is the case with --disabled-nls. - - * include/grub/i18n.h: Use (defined(ENABLE_NLS) - && ENABLE_NLS) instead of ENABLE_NLS in all #if preprocessor macros. - * util/misc.c: Likewise. - * util/mkisofs/mkisofs.c: Likewise. - * util/mkisofs/mkisofs.h: Likewise. - -2010-03-27 Vladimir Serbinenko - - Simplify Apple CC support. - - * commands/i386/pc/drivemap_int13h.S: Use LOCAL when possible. - Add 0 byte at the end not to have a symbol with empty target. - * mmap/i386/pc/mmap_helper.S: Likewise. - * genmk.rb: Ignore errors 2030 and 2050. - * kern/i386/pc/startup.S: Use LOCAL when possible. - -2010-03-26 BVK Chaitanya - - Testcase and the fix for final semicolon on cmdline. - - * tests/grub_script_final_semicolon.in: New testcase. - * conf/tests.rmk: Rules for the new testcase. - * script/parser.y: Grammar fix. - -2010-03-26 BVK Chaitanya - - Blank lines testcase for GRUB script. - - * tests/grub_script_blanklines.in: New testcase. - * conf/tests.rmk: Rules for the new testcase. - -2010-03-26 Vladimir Serbinenko - - Don't use __FILE__. - - * genmk.rb: Add -DGRUB_FILE to all C targets. - * fs/reiserfs.c: Replace __FILE__ with GRUB_FILE. - * include/grub/list.h: Likewise. - * include/grub/misc.h: Likewise. - * include/grub/mm.h: Likewise. - * include/grub/test.h: Likewise. - * kern/mm.c: Likewise. - * lib/libgcrypt_wrap/cipher_wrap.h: Likewise. - -2010-03-26 Vladimir Serbinenko - - Sunpc partitions support. - - * conf/common.rmk (grub_probe_SOURCES): Add partmap/sunpc.c. - (grub_fstest_SOURCES): Likewise. - (pkglib_MODULES): Add part_sunpc.mod. - (part_sunpc_mod_SOURCES): New variable. - (part_sunpc_mod_CFLAGS): Likewise. - (part_sunpc_mod_LDFLAGS): Likewise. - * conf/i386-pc.rmk (grub_setup_SOURCES): Add partmap/sunpc.c. - * partmap/sunpc.c: New file. - -2010-03-26 BVK Chaitanya - - For loop support to GRUB script. - - * include/grub/script_sh.h (grub_script_cmdfor): New struct. - (grub_script_create_cmdfor): New function prototype. - (grub_script_execute_cmdfor): New function prototype. - * script/execute.c (grub_script_execute_cmdfor): New function. - * script/parser.y (command): New for command. - (forcmd): New grammar rule. - * script/script.c (grub_script_create_cmdfor): New function. - * util/grub-script-check.c (grub_script_execute_cmdfor): New - function. - * tests/grub_script_for1.in: New testcase. - * conf/tests.rmk: Rules for new testcase. - -2010-03-26 Vladimir Serbinenko - - Nested partitions - - * commands/blocklist.c (grub_cmd_blocklist): Don't check whether - 'partition' is NULL, grub_partition_get_start already does that. - * commands/loadenv.c (check_blocklists): Likewise. - (write_blocklists): Likewise. - * conf/common.rmk (grub_probe_SOURCES): Add partmap/bsdlabel.c. - (grub_fstest_SOURCES): Likewise. - (pkglib_MODULES): Add part_bsd.mod. - (part_bsd_mod_SOURCES): New variable. - (part_bsd_mod_CFLAGS): Likewise. - (part_bsd_mod_LDFLAGS): Likewise. - * conf/i386-pc.rmk (grub_setup_SOURCES): Add partmap/bsdlabel.c. - (grub_emu_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * include/grub/bsdlabel.h: New file. - * include/grub/partition.h (grub_partition_map): Remove 'probe' and - 'get_name'. - (grub_partition): Add 'parent' and 'number'. Remove 'data'. - (grub_partition_map_list): New variable. - (grub_partition_map_register): Inline. - (grub_partition_map_unregister): Likewise. - (FOR_PARTITION_MAPS): New macro. - (grub_partition_map_iterate): Removed. - (grub_partition_get_start): Handle nested partitions. - * include/grub/msdos_partition.h: Remove bsd-related entries. - (grub_pc_partition): Remove. - * kern/disk.c (grub_disk_close): Free partition data. - (grub_disk_adjust_range): Handle nested partitions. - * kern/partition.c (grub_partition_map_probe): New function. - (grub_partition_probe): Parse name to number, handle subpartitions. - (get_partmap): New function. - (grub_partition_iterate): Handle subpartitions. - (grub_partition_get_name): Likewise. - * loader/i386/pc/bsd.c (grub_bsd_get_device): Likewise. - * loader/i386/multiboot.c (grub_multiboot_get_bootdev): Likewise. - * loader/i386/pc/chainloader.c (grub_chainloader_cmd): Likewise. - * partmap/acorn.c (acorn_partition_map_iterate): Don't force raw access. - Set 'number'. - (acorn_partition_map_probe): Remove. - (acorn_partition_map_get_name): Likewise. - * partmap/amiga.c (amiga_partition_map_iterate): Don't force raw access. - Set 'number'. - Set 'index' to 0 since there can be only one partition entry per sector. - (amiga_partition_map_probe): Remove. - (amiga_partition_map_get_name): Likewise. - * partmap/apple.c (apple_partition_map_iterate): Don't force raw access. - Set 'number'. - Set 'offset' and 'index' to real positions of partitions. - (apple_partition_map_probe): Remove. - (apple_partition_map_get_name): Likewise. - * partmap/bsdlabel.c: New file. - * partmap/gpt.c (gpt_partition_map_iterate): Don't force raw access. - Set 'number'. - Allocate 'data' so it can be correctly freed. - Set 'index' to offset inside sector. - (gpt_partition_map_probe): Remove. - (gpt_partition_map_get_name): Likewise. - * partmap/msdos.c (grub_partition_parse): Remove. - (pc_partition_map_iterate): Don't force raw access. - Set 'number'. - Make 'ext_offset' a local variable. - (pc_partition_map_probe): Remove. - (pc_partition_map_get_name): Remove. - * partmap/sun.c (sun_partition_map_iterate): Don't force raw access. - Set 'number'. - (sun_partition_map_probe): Remove. - (sun_partition_map_get_name): Likewise. - * parttool/msdospart.c (grub_pcpart_boot): Handle nested partitions. - (grub_pcpart_type): Likewise. - * util/hostdisk.c (open_device): Handle new numbering scheme. - (grub_util_biosdisk_get_grub_dev): Handle nested partitions. - * util/i386/pc/grub-setup.c (setup): Handle new numbering scheme. - * util/grub-probe.c (probe_partmap): Handle nested paritions. - * util/grub-install.in: Insert all subpartition modules. - * util/ieee1275/grub-install.in: Likewise. - -2010-03-24 Adrian Glaubitz - - * kern/dl.c (grub_dl_resolve_symbols): Improve error message - grammar. - -2010-03-24 Colin Watson - - * .bzrignore: Add grub-bin2h, grub-reboot, and grub-set-default. - -2010-03-21 Colin Watson - - * util/grub-install.in: Copy .mo files from @datadir@/locale, to - match where 'make install' puts them. - * util/i386/efi/grub-install.in: Likewise. - -2010-03-19 Colin Watson - - * .bzrignore: Add gentrigtables, grub-script-check, - grub_script_check_init.c, grub_script_check_init.h, and - trigtables.c. - -2010-03-18 Vladimir Serbinenko - - * kern/parser.c: Indented. - -2010-03-17 Vladimir Serbinenko - - * term/i386/pc/vesafb.c: Removed (orphaned, deprecated and broken). - -2010-03-17 Vladimir Serbinenko - - * video/fb/fbblit.c (grub_video_fbblit_blend_XXXA8888_1bit): Handle - alpha_mask_size == 0 case. - -2010-03-14 BVK Chaitanya - - GRUB shell lexer and parser improvements. - - * conf/any-emu.rmk: Build rule updates. - * conf/common.rmk: Likewise. - * conf/i386-coreboot.rmk: Likewise. - * conf/i386-efi.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - - * configure.ac: Configure check for flex. - - * include/grub/script_sh.h (grub_script_arg_type_t): More argument - types. - (grub_lexer_param): Struct member updates. - (grub_parser_param): Likewise. - (GRUB_LEXER_TOKEN_MAX): Maximum token size. - (GRUB_LEXER_RECORD_INCREMENT): Memory increments' size. - (grub_script_lexer_init): Prototype update. - (grub_script_lexer_record_start): Likewise. - (grub_script_lexer_record_stop): Likewise. - (grub_script_lexer_yywrap): New function prototype. - (grub_script_lexer_fini): Likewise. - (grub_script_execute_argument_to_string): Removed by... - (grub_script_execute_argument_to_argv): ...better version. - - * script/execute.c (ROUND_UPTO): New macro. - (grub_script_execute_cmdline): Out of memory fixes. - (grub_script_execute_menuentry): Likewise. - (grub_script_execute_argument_to_string): Removed. Update all - users by... - (grub_script_execute_argument_to_argv): ...better version. - * script/function.c (grub_script_function_create): Use - grub_script_execute_argument_to_argv instead of - grub_script_execute_argument_to_string. - - * script/lexer.c (check_varstate): Removed. - (check_textstate): Removed. - (grub_script_lexer_record_start): Likewise. - (grub_script_lexer_record_stop): Likewise. - (recordchar): Replaced with... - (grub_script_lexer_record): ...new function. - (nextchar): Removed. - (grub_script_lexer_init): Rewritten. - (grub_script_yylex): Rewritten. - (append_newline): New function. - (grub_script_lexer_yywrap): New function. - (grub_script_lexer_fini): New function. - (grub_script_yyerror): Sets error flag. - - * script/yylex.l: New file. - (grub_lexer_yyfree): Wrapper for flex yyffre. - (grub_lexer_yyalloc): Likewise. - (grub_lexer_yyrealloc): Likewise. - * script/parser.y: Refactored. - - * script/script.c (grub_script_arg_add): Out of memory fixes. - (grub_script_add_arglist): Likewise. - (grub_script_create_cmdline): Likewise. - (grub_script_create_cmdmenu): Likewise. - (grub_script_add_cmd): Likewise. - (grub_script_parse): Use grub_script_lexer_fini to deallocated. - * util/grub-script-check.c (grub_script_execute_menuentry): Remove - unnecessary code. - - * tests/grub_script_echo1.in: New testcase. - * tests/grub_script_vars1.in: New testcase. - * tests/grub_script_echo_keywords.in: New testcase. - -2010-03-14 Vladimir Serbinenko - - Remove some redundancy in build system. - - * Makefile.in (TARGET_CFLAGS): Add -ffreestanding. - (TARGET_ASFLAGS): Add -nostdinc -fno-builtin. - (TARGET_LDFLAGS): Add -nostdlib. - (TARGET_IMG_LDFLAGS): Likewise. - * commands/lsmmap.c (grub_cmd_lsmmap) [GRUB_MACHINE_EMU]: Don't do - anything since mmap isn't available. - * conf/any-emu.rmk (kernel_img_SOURCES): Remove commands/boot.c. - Add util/time.c. - (pkglib_MODULES): Remove reboot.mod. - (reboot_mod_SOURCES): Removed. - (reboot_mod_CFLAGS): Likewise. - (reboot_mod_LDFLAGS): Likewise. - * conf/common.rmk (script/lexer.c_DEPENDENCIES): New variable. - (MOSTLYCLEANFILES): Add symlist.c kernel_syms.lst. - (DEFSYMFILES): Add kernel_syms.lst. - (kernel_img_HEADERS): Add common headers. - (symlist.c): New target. - (kernel_syms.lst): Likewise. - (pkglib_MODULES): Add memdisk.mod. - (memdisk_mod_SOURCES): New variable. - (memdisk_mod_CFLAGS): Likewise. - (memdisk_mod_LDFLAGS): Likewise. - (pkglib_MODULES): Add reboot.mod. - (reboot_mod_SOURCES): New variable. - (reboot_mod_CFLAGS): Likewise. - (reboot_mod_LDFLAGS): Likewise. - (pkglib_MODULES): Add date.mod. - (date_mod_SOURCES): New variable. - (date_mod_CFLAGS): Likewise. - (date_mod_LDFLAGS): Likewise. - (pkglib_MODULES): Add datehook.mod. - (datehook_mod_SOURCES): New variable. - (datehook_mod_CFLAGS): Likewise. - (datehook_mod_LDFLAGS): Likewise. - (pkglib_MODULES): Add lsmmap.mod. - (lsmmap_mod_SOURCES): New variable. - (lsmmap_mod_CFLAGS): Likewise. - (lsmmap_mod_LDFLAGS): Likewise. - (pkglib_MODULES): Add boot.mod. - (boot_mod_SOURCES): New variable. - (boot_mod_CFLAGS): Likewise. - (boot_mod_LDFLAGS): Likewise. - * conf/i386-coreboot.rmk: Removed redundant parts. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/mips-yeeloong.rmk: Likewise. - * conf/mips.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - * conf/i386-coreboot.rmk: Moved qemu parts .. - * conf/i386-qemu.rmk: ... here - * conf/i386-efi.rmk: Moved common parts to... - * conf/x86-efi.rmk: ... here. - * conf/i386.rmk: Added modules common to all x86 variants. - * configure.ac: Add -m32/-m64 to TARGET_ASFLAGS. - * disk/memdisk.c: Remove grub/machine/kernel.h. - * gensymlist.sh.in: Include symbol.h. - * hook/datehook.c: Correct module name. - * include/grub/datetime.h (grub_get_datetime) [GRUB_MACHINE_EMU]: Export. - (grub_set_datetime) [GRUB_MACHINE_EMU]: Likewise. - * include/grub/i386/efi/serial.h: New file. - * include/grub/x86_64/efi/serial.h: Likewise. - * util/time.c: Likewise. - * video/ieee1275.c (grub_video_ieee1275_setup): Handle 64-bit void *. - -2010-03-14 Colin King -2010-03-14 Colin Watson - - Shrink the pre-partition-table part of boot.img by eight bytes. - - * boot/i386/pc/boot.S (ERR): New macro. - (chs_mode): Use ERR. - (geometry_error): Likewise. - (hd_probe_error): Remove. This is only used once, so we wrwite - it inline instead. - (read_error): Instead of printing read_error_string, just set up - %si and fall through to ... - (error_message): ... this new function, also used by ERR. - -2010-03-14 Colin Watson - - Speed up consecutive hostdisk operations on the same device. - - * util/hostdisk.c (struct grub_util_biosdisk_data): New structure. - (grub_util_biosdisk_open): Initialise disk->data. - (struct linux_partition_cache): New structure. - (linux_find_partition): Cache partition start positions; these are - expensive to compute on every read and write. - (open_device): Cache open file descriptor in disk->data, so that we - don't have to reopen it and flush the buffer cache for consecutive - operations on the same device. - (grub_util_biosdisk_close): New function. - (grub_util_biosdisk_dev): Set `close' member. - - * conf/common.rmk (grub_probe_SOURCES): Add kern/list.c. - * conf/i386-efi.rmk (grub_setup_SOURCES): Likewise. - * conf/i386-pc.rmk (grub_setup_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_setup_SOURCES): Likewise. - * conf/x86_64-efi.rmk (grub_setup_SOURCES): Likewise. - -2010-03-14 Vladimir Serbinenko - - Compile parts of grub-emu as modules. - - * Makefile.in (TARGET_CPPFLAGS) [emu]: Remove -nostdinc -isystem. - (pkglib_DATA) [emu]: Remove moddep.lst command.lst fs.lst - partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst. - (all-local): Add $(GRUB_EMU). - (install-local): Install $(GRUB_EMU). - (uninstall): Uninstall $(GRUB_EMU). - * commands/parttool.c: Replace GRUB_UTIL with GRUB_NO_MODULES. - * kern/dl.c: Likewise. - * commands/sleep.c: Not include machine/time.h. - * conf/any-emu.rmk (COMMON_LDFLAGS): New variable. - (COMMON_CFLAGS): Likewise. - (sbin_UTILITIES): Remove grub-emu. - (grub_emu_SOURCES): Removed. - (kernel_img_RELOCATABLE): New variable. - (pkglib_PROGRAMS): Add kernel.img. - (kernel_img_SOURCES): New variable - (kernel_img_CFLAGS): Likewise. - (kernel_img_LDFLAGS): Likewise. - (TARGET_NO_STRIP): Likewise. - (TARGET_NO_DYNAMIC_MODULES): Likewise. - (pkglib_MODULES): Add progname.mod, hostfs.mod, host.mod, reboot.mod, - halt.mod, cpuid.mod, usb.mod, sdl.mod and pci.mod. - (grub-emu): New target. - (GRUB_EMU): New variable. - * configure.ac: Whitelist -emu as possible x86_64 architecture. - * efiemu/main.c: Replace GRUB_UTIL with GRUB_MACHINE_EMU. - * loader/xnu.c: Likewise. - * include/grub/pci.h: Likewise. - * genemuinit.sh: New file. - * genemuinitheader.sh: Likewise. - * genmk.rb: Don't strip if TARGET_NO_STRIP is yes. - Support TARGET_NO_DYNAMIC_MODULES. - * include/grub/dl.h (GRUB_NO_MODULES): New variable. - * commands/search.c: Fix GRUB_MOD_INIT and GRUB_MOD_FINI arguments. - * disk/loopback.c: Likewise. - * font/font_cmd.c: Likewise. - * partmap/acorn.c: Likewise. - * partmap/amiga.c: Likewise. - * partmap/apple.c: Likewise. - * partmap/gpt.c: Likewise. - * partmap/msdos.c: Likewise. - * partmap/sun.c: Likewise. - * parttool/msdospart.c: Likewise. - * term/gfxterm.c: Likewise. - * video/bitmap.c: Likewise. - * video/readers/jpeg.c: Likewise. - * video/readers/png.c: Likewise. - * video/readers/tga.c: Likewise. - * video/video.c: Likewise. - * util/grub-emu.c (read_command_list): Removed. - (main): Don't call util_init_nls. - * util/misc.c (grub_err_printf) [!GRUB_UTIL]: Removed. - (grub_util_init_nls) [!GRUB_UTIL]: Likewise. - -2010-03-14 Vladimir Serbinenko - - * conf/powerpc-ieee1275.rmk (pkglib_MODULES): Add datetime.mod, - date.mod, datehook.mod. - (datetime_mod_SOURCES): New variable. - (datetime_mod_CFLAGS): Likewise. - (datetime_mod_LDFLAGS): Likewise. - (date_mod_SOURCES): Likewise. - (date_mod_CFLAGS): Likewise. - (date_mod_LDFLAGS): Likewise. - (datehook_mod_SOURCES): Likewise. - (datehook_mod_CFLAGS): Likewise. - (datehook_mod_LDFLAGS): Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * lib/ieee1275/datetime.c: New file. - -2010-03-14 Vladimir Serbinenko - - * conf/powerpc-ieee1275.rmk (pkglib_MODULES): Add ieee1275_fb.mod. - (ieee1275_fb_mod_SOURCES): New variable. - (ieee1275_fb_mod_CFLAGS): Likewise. - (ieee1275_fb_mod_LDFLAGS): Likewise. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_devices_iterate): - New proto. - * kern/ieee1275/init.c (HEAP_MAX_SIZE): Increased. - (HEAP_MAX_ADDR): Likewise. - * kern/ieee1275/openfw.c (grub_children_iterate): Don't skip empty - type. - Correct stop condition. - (grub_ieee1275_devices_iterate): New function. - * video/ieee1275.c: New file. - -2010-03-14 Vladimir Serbinenko - - Merge sparc grub-mkimage into generic grub-mkimage and a.out support. - - * boot/sparc64/ieee1275/boot.S (boot_continue): Use SCRATCH_PAD_BOOT - as scratch. - * boot/sparc64/ieee1275/diskboot.S (after_info_block): Use - SCRATCH_PAD_DISKBOOT as scratch. - (bootit): Pass Openfirmware pointer in %o4. - * conf/sparc64-ieee1275.rmk (kernel_img_LDFLAGS): Link at 0x4400 instead - of 0x200000. - (grub_mkimage_SOURCES): Replace util/sparc64/ieee1275/grub-mkimage.c - with util/grub-mkrawimage.c. - * configure.ac: Handle GRUB_MACHINE_SPARC64 and GRUB_MACHINE_MIPS. - * include/grub/aout.h (AOUT_MID_SUN): New definition. - (grub_aout_get_type) [GRUB_UTIL]: Removed. - (grub_aout_load) [GRUB_UTIL]: Likewise. - * include/grub/kernel.h (grub_modules_get_end): New proto. - * include/grub/sparc64/ieee1275/boot.h (SCRATCH_PAD): Removed. - (SCRATCH_PAD_BOOT): New definition. - (SCRATCH_PAD_DISKBOOT): Likewise. - (GRUB_BOOT_MACHINE_IMAGE_ADDRESS): Set to 0x4400. - * include/grub/sparc64/ieee1275/ieee1275.h - (grub_ieee1275_original_stack): New variable - * include/grub/sparc64/ieee1275/kernel.h (GRUB_KERNEL_MACHINE_RAW_SIZE): - New definition - (GRUB_KERNEL_MACHINE_STACK_SIZE): Likewise. - (GRUB_PLATFORM_IMAGE_FORMATS): Likewise. - (GRUB_PLATFORM_IMAGE_DEFAULT_FORMAT): Likewise. - (GRUB_PLATFORM_IMAGE_DEFAULT): Likewise. - (GRUB_PLATFORM_IMAGE_RAW): Likewise. - (GRUB_PLATFORM_IMAGE_AOUT): Likewise. - (grub_platform_image_format_t): New type. - * kern/mips/yeeloong/init.c (grub_modules_get_end): Move from here ... - * kern/main.c (grub_modules_get_end) - [GRUB_MACHINE_MIPS_YEELOONG || GRUB_MACHINE_SPARC64]: ... here. - * kern/sparc64/ieee1275/crt0.S: Store firmware entry point in %o0. - (codestart): Switch stacks. - * kern/sparc64/ieee1275/init.c (grub_ieee1275_original_stack): New - variable. - (grub_heap_init): Use grub_modules_get_end. - * loader/sparc64/ieee1275/linux.c (grub_linux_boot): Restore original - stack. - * util/grub-mkrawimage.c (generate_image): Support sparc64. - (main): Likewise. - * util/sparc64/ieee1275/grub-mkimage.c: Removed. - -2010-03-14 Thorsten Glaser - - * util/grub-mkrescue.in: Base ISO UUID on UTC. - -2010-03-08 Matt Kraai - - * util/i386/pc/grub-setup.c (setup): Fix a grammatical error (Debian - bug #559005). - -2010-03-07 Vladimir Serbinenko - - * genmoddep.awk: Output all missing symbols and not only first. - -2010-03-06 Vladimir Serbinenko - - * NEWS: Put the date of 1.98 release. - -2010-03-06 Vladimir Serbinenko - - * configure.ac: Update CPPFLAGS and not CFLAGS when checking for - ft2build.h. - -2010-03-06 Vladimir Serbinenko - - * normal/cmdline.c (grub_cmdline_get): Fix gabled line after - completition in the middle of string. - -2010-03-06 Vladimir Serbinenko - - * util/grub-mkrescue.in: Use mktemp with explicit template. - -2010-03-06 Vladimir Serbinenko - - * loader/i386/bsd.c (grub_bsd_get_device): Fix a memory leak. - -2010-03-06 Vladimir Serbinenko - - * loader/i386/multiboot_mbi.c (grub_multiboot_set_bootdev): Free the - right pointer. - -2010-03-05 Vladimir Serbinenko - - Fix FreeBSD compilation. - - * Makefile.in (TARGET_CPPFLAGS): Remove -nostdinc -isystem. - * configure.ac: Add -nostdinc -isystem to TARGET_CPPFLAGS if it works. - -2010-03-05 Vladimir Serbinenko - - * util/import_gcry.py: Add autogenerated files to MAINTAINER_CLEANFILES. - -2010-03-04 Vladimir Serbinenko - - * gettext/gettext.c (grub_gettext_init_ext): Fix a memory leak. - -2010-03-04 Vladimir Serbinenko - - * disk/scsi.c (grub_scsi_iterate): Fix a memory leak. - -2010-03-04 Robert Millan - - Support relative image path in theme file. - - * gfxmenu/gui_image.c (grub_gui_image): New member theme_dir. - (image_set_property): Handle theme_dir and relative path. - -2010-03-04 Vladimir Serbinenko - - * configure.ac: Alias amd64 to x86_64. - -2010-03-04 Vladimir Serbinenko - - * NEWS: mention multiboot on EFI. - -2010-03-04 Vladimir Serbinenko - - * kern/main.c (grub_load_modules): Handle errors from init functions of - embeded modules. - -2010-03-04 Vladimir Serbinenko - - * normal/autofs.c (autoload_fs_module): Handle errors. - -2010-03-04 Vladimir Serbinenko - - Disable linux.mod on qemu-mips since it's not functional and leads - to compilation failure. - - * conf/mips.rmk (pkglib_MODULES): Remove linux.mod. - * conf/mips-yeeloong.rmk (pkglib_MODULES): Add linux.mod. - * conf/mips.rmk (linux_mod_SOURCES): Move from here ... - * conf/mips-yeeloong.rmk (linux_mod_SOURCES): ... here - * conf/mips.rmk (linux_mod_CFLAGS): Move from here ... - * conf/mips-yeeloong.rmk (linux_mod_CFLAGS): ... here - * conf/mips.rmk (linux_mod_ASFLAGS): Move from here ... - * conf/mips-yeeloong.rmk (linux_mod_ASFLAGS): ... here - * conf/mips.rmk (linux_mod_LDFLAGS): Move from here ... - * conf/mips-yeeloong.rmk (linux_mod_LDFLAGS): ... here - Reported by: BVK Chaitanya - -2010-03-04 Jordan Uggla - - * INSTALL: Add gettext as a dependency and add qemu to a new section - "Prerequisites for make-check". - -2010-03-04 Christian Franke - - * util/grub-pe2elf.c: Add missing include "progname.h". - -2010-03-04 Vladimir Serbinenko - - * normal/crypto.c (read_crypto_list): Fix a typo. - Reported by: Seth Goldberg. - -2010-03-04 Vladimir Serbinenko - - * Makefile.in (DISTCLEANFILES): Add stamp-h1. - Reported by: Seth Goldberg. - -2010-03-04 Vladimir Serbinenko - - * Makefile.in (CLEANFILES) [FONT_SOURCE && grub_mkfont]: Add - ascii.bitmaps. - -2010-03-04 Vladimir Serbinenko - - * genmk.rb: Remove terminal*.lst in make clean. - Reported by: Seth Goldberg. - -2010-03-04 Vladimir Serbinenko - - * util/i386/efi/grub-install.in: Copy gettext files. - -2010-03-01 Vladimir Serbinenko - - * fs/ext2.c (grub_ext2_read_block): Fix an integer overflow. - -2010-03-01 Vladimir Serbinenko - - Wait for user entry basing on presence of output rather than on errors. - - * include/grub/normal.h (grub_normal_get_line_counter): New proto. - (grub_install_newline_hook): Likewise. - * normal/main.c (GRUB_MOD_INIT): Call grub_install_newline_hook. - * normal/menu.c (show_menu): Check line_counter to determine presence - of output. - * normal/term.c (grub_normal_line_counter): New variable. - (grub_normal_get_line_counter): New function. - (grub_install_newline_hook): Likewise. - -2010-03-01 Vladimir Serbinenko - - * commands/cat.c (grub_cmd_cat): Propagate grub_gzfile_open error. - -2010-03-01 Vladimir Serbinenko - - * configure.ac: Update version to 1.98. - -2010-02-26 Vladimir Serbinenko - - * util/grub.d/10_linux.in (linux_entry): Don't default to - gfxpayload=keep if Linux doesn't support video handover. - -2010-02-25 Vladimir Serbinenko - - Don't compile video modules on yeeloong since video subsystem is part - of kernel. - - * conf/common.rmk (pkglib_MODULES) [yeeloong]: Remove video.mod, - video_fb.mod, bitmap.mod, font.mod, gfxterm.mod and bufio.mod - * conf/mips-yeeloong.rmk (kernel_img_HEADERS): Add bitmap.h, - video.h, gfxterm.h, font.h, bitmap_scale.h and bufio.h. - * conf/mips.rmk (kernel_img_HEADERS): Add values instead of overwriting. - * include/grub/bitmap.h: Add EXPORT_FUNC and EXPORT_VAR. - * include/grub/bitmap_scale.h: Likewise. - * include/grub/bufio.h: Likewise. - * include/grub/font.h: Likewise. - * include/grub/gfxterm.h: Likewise. - * include/grub/video.h: Likewise. - * include/grub/vbe.h: Don't include video_fb.h. - * video/i386/pc/vbe.c: Include video_fb.h. - * commands/i386/pc/vbetest.c: Include video.h. - -2010-02-25 Jordan Uggla - - * util/grub-mkconfig.in (GRUB_SAVEDEFAULT): Export new variable. - * util/grub-mkconfig_lib.in (save_default_entry): Only save a new - default entry if GRUB_SAVEDEFAULT=true. This allows using - GRUB_DEFAULT=saved on its own to let grub-reboot work, without - saving a new default on every boot. - -2010-02-24 Vladimir Serbinenko - - * normal/crypto.c (read_crypto_list): Fix a memory leak. - * normal/term.c (read_terminal_list): Likewise. - * normal/main.c (grub_normal_init_page): Likewise. - (grub_normal_read_line_real): Likewise. - -2010-02-24 Vladimir Serbinenko - - * loader/i386/multiboot_mbi.c (grub_multiboot_set_bootdev): Fix a - memory leak. - Reported by: Seth Goldberg. - -2010-02-24 Joey Korkames - - * term/ieee1275/ofconsole.c (grub_ofconsole_readkey): Remove - duplicate declaration of `start'. - -2010-02-20 Vladimir Serbinenko - - * fs/iso9660.c (grub_iso9660_iterate_dir): Strip version from joliet - filename. - Reported by: Georgy Buranov - -2010-02-20 Carles Pina i Estany - - * util/grub-mkrawimage.c (usage): Change string formatting to - improve gettext. - -2010-02-20 Manoel Rebelo Abranches - - * term/ieee1275/ofconsole.c (grub_ofconsole_readkey): Add delete and - backspace keys. - -2010-02-20 Vladimir Serbinenko - - * video/fb/video_fb.c (grub_video_fb_scroll): Fix a pixel size bug. - Reported by: Michael Suchanek. - -2010-02-18 Samuel Thibault - - * util/grub-mkconfig.in: Export GRUB_INIT_TUNE. - * util/grub.d/00_header.in: Handle GRUB_INIT_TUNE. - -2010-02-16 Vladimir Serbinenko - - Remove any reference to non-free fonts. - - * commands/videotest.c (grub_cmd_videotest): Use unifont by default. - * docs/gfxmenu-theme-example.txt: Removed. It's both outdated and - uses non-free components. - * font/font.c (grub_font_get_name): Remove example name. - * gfxmenu/gui_label.c (grub_gui_label_new): Use unifont by default. - * gfxmenu/gui_list.c (grub_gui_list_new): Likewise. - * gfxmenu/gui_progress_bar.c (grub_gui_progress_bar_new): Likewise. - * gfxmenu/view.c (grub_gfxmenu_view_new): Likewise. - -2010-02-16 Georgy Buranov - - * disk/efi/efidisk.c (grub_efidisk_get_device_name): Fix a typo. - -2010-02-15 Vladimir Serbinenko - - * term/serial.c (serial_get_divisor) [GRUB_MACHINE_MIPS_YEELOONG]: - Double divisor. - (serial_hw_init) [GRUB_MACHINE_MIPS_YEELOONG]: Don't enable advanced - features. - (GRUB_MOD_INIT) [GRUB_MACHINE_MIPS_YEELOONG]: Default to 115200. - -2010-02-15 Vladimir Serbinenko - - * gensymlist.sh.in: Use TARGET_CC instead of CC. - -2010-02-14 Samuel Thibault - - * commands/i386/pc/play.c (GRUB_MOD_INIT(play)): Fix help. - * docs/grub.texi (Command-line and menu entry commands): Document play - command. - -2010-02-14 Samuel Thibault - - * commands/i386/pc/play.c (grub_cmd_play): If grub_file_open fails, - parse arguments as inline tempo and notes. Move code for playing notes - to... - (play): ... new function. - -2010-02-14 Samuel Thibault - - * commands/i386/pc/play.c (T_REST, T_FINE, struct note, beep_on): Use - grub_uint16_t instead of short. - (grub_cmd_play): Use grub_uint32_t instead of int, convert data from - disk from little endian to cpu endianness. - -2010-02-07 Samuel Thibault - - * commands/i386/pc/play.c (BASE_TEMPO): Set to 60 * - GRUB_TICKS_PER_SECOND instead of 120. - -2010-02-14 Vladimir Serbinenko - - * term/ieee1275/ofconsole.c (grub_ofconsole_readkey): Wait for possible - escape sequence after \e. - -2010-02-14 Vladimir Serbinenko - - * term/ieee1275/ofconsole.c (grub_ofconsole_putchar): Don't output - non-ASCII characters. - -2010-02-14 Vladimir Serbinenko - - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Enclose - set root in single quotes to prevent \, from being unescaped. - -2010-02-14 Vladimir Serbinenko - - Prevent unknown commands from stopping menuentry execution. - - * script/execute.c (grub_script_execute_cmdline): Print error after - unknown command. - -2010-02-14 Vladimir Serbinenko - - * fs/i386/pc/pxe.c (GRUB_MOD_INIT): Fix typo. - Reported by: Pavel Pisa. - -2010-02-13 Vladimir Serbinenko - - * io/gzio.c (grub_gzio_open): Use grub_zalloc. - -2010-02-13 Vladimir Serbinenko - - Merge grub_ieee1275_map_physical into grub_map and rename to - grub_ieee1275_map - - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_map): New proto. - * include/grub/sparc64/ieee1275/ieee1275.h (grub_ieee1275_map_physical): - Remove. - * kern/ieee1275/openfw.c (grub_map): Rename to ... - (grub_ieee1275_map): ... this. All users updated. Add phys_lo when - necessary. - * kern/sparc64/ieee1275/ieee1275.c (grub_ieee1275_map_physical): Remove. - -2010-02-13 Vladimir Serbinenko - - * disk/ieee1275/ofdisk.c (grub_ofdisk_open): Check device type before - opening and not after. - -2010-02-13 Vladimir Serbinenko - - * term/ieee1275/ofconsole.c (grub_ofconsole_readkey): Macroify - constants. - -2010-02-13 Vladimir Serbinenko - - * loader/sparc64/ieee1275/linux.c (align_addr): Remove. - (alloc_phys): Use ALIGN_UP instead of align_addr. - -2010-02-13 Vladimir Serbinenko - - * loader/sparc64/ieee1275/linux.c (alloc_phys): Correct bounds checking. - -2010-02-13 Vladimir Serbinenko - - * kern/sparc64/ieee1275/crt0.S (codestart): Move modules backwards. - -2010-02-13 Vladimir Serbinenko - - * disk/ieee1275/ofdisk.c (grub_ofdisk_read): Remove excessively - verbose dprintf. - -2010-02-13 Vladimir Serbinenko - - Fix over-4GiB seek on sparc64. - - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_seek): - Replace pos_i and pos_lo with pos. All users updated. - * include/grub/powerpc/ieee1275/ieee1275.h (GRUB_IEEE1275_CELL_SIZEOF): - New constant. - * include/grub/sparc64/ieee1275/ieee1275.h (GRUB_IEEE1275_CELL_SIZEOF): - Likewise. - * kern/ieee1275/ieee1275.c (grub_ieee1275_seek): Split pos into pos_hi - and pos_lo. - -2010-02-13 Vladimir Serbinenko - - * util/grub-mkrawimage.c (main): Call set_program_name. - -2010-02-13 Vladimir Serbinenko - - Properly align 64-bit targets. - - * util/grub-mkrawimage.c (ALIGN_ADDR): New macro. - (generate_image): Use ALIGN_ADDR. - -2010-02-13 Vladimir Serbinenko - - Properly create cross-endian images. - - * include/grub/types.h (grub_host_to_target_addr): New macro - * util/grub-mkrawimage.c (generate_image): Add missing host_to_target. - -2010-02-13 Vladimir Serbinenko - - * util/grub-mkrawimage.c (generate_image): Add forgotten ALIGN_UP. - -2010-02-10 Vladimir Serbinenko - - Pass SIMPLE framebuffer size in bytes and not 64K blocks. - - * loader/i386/efi/linux.c (grub_linux_setup_video): Don't divide by 64K. - * loader/i386/linux.c (grub_linux_setup_video): Likewise. - (grub_linux_boot): Divide by 64K when on VESA. - -2010-02-10 Vladimir Serbinenko - - Support GRUB_GFXPAYLOAD_LINUX. - - * util/grub-mkconfig.in: Export GRUB_GFXPAYLOAD_LINUX. - * util/grub.d/10_linux.in (linux_entry): Handle GRUB_GFXPAYLOAD_LINUX. - -2010-02-10 Vladimir Serbinenko - - * script/execute.c (grub_script_execute_cmdline): Use grub_print_error - to show messages instead of discarding them. - Process errors after executing command and not before. Keep old method - too as precaution. - -2010-02-09 Vladimir Serbinenko - - * configure.ac: Check for ft2build.h. - -2010-02-07 Vladimir Serbinenko - - * kern/ieee1275/openfw.c (grub_halt): Try executing "poweroff". - -2010-02-07 Vladimir Serbinenko - - * genkernsyms.sh.in: Use TARGET_CC. - -2010-02-07 Colin Watson - - * NEWS: Update. - -2010-02-07 Vladimir Serbinenko - - * include/grub/multiboot2.h: Remove leftover file. - * include/grub/normal.h [GRUB_UTIL]: Remove leftover declarations. - * include/grub/partition.h [GRUB_UTIL]: Likewise. - -2010-02-07 Yves Blusseau - - * gnulib/getdelim.c: add missing header (type ssize_t must be defined). - -2010-02-07 Vladimir Serbinenko - - Fix warnings in grub-emu when compiling with maximum warning options. - - * util/grub-emu.c (ENABLE_RELOCATABLE): New definition. - (grub_arch_modules_addr): Return 0 and not NULL. - * util/misc.c (ENABLE_RELOCATABLE): New definition. - (xstrdup): Use newstr instead of dup. - * util/hostdisk.c (grub_util_biosdisk_get_grub_dev): Rename one instance - of disk to dsk to avoid shadowing. - (find_free_slot): Fix prototype. - * util/getroot.c (grub_util_is_dmraid): Make static. - * include/grub/time.h (grub_get_rtc) [GRUB_MACHINE_EMU || GRUB_UTIL]: - Add missing prototype. - * util/sdl.c (grub_video_sdl_set_viewport): Remove. - -2010-02-07 Vladimir Serbinenko - - * loader/i386/linux.c (grub_linux_setup_video): Handle error - appropriately. - -2010-02-07 Vladimir Serbinenko - - * fs/reiserfs.c (grub_reiserfs_read): Use #if 0 instead of commenting - code out. - -2010-02-07 Vladimir Serbinenko - - * include/grub/cache.h (grub_arch_sync_caches) [i386 || x86_64]: Inline. - * kern/i386/coreboot/init.c (grub_arch_sync_caches): Remove. - * kern/i386/efi/init.c (grub_arch_sync_caches): Likewise. - * kern/i386/ieee1275/init.c (grub_arch_sync_caches): Likewise. - * kern/i386/pc/init.c (grub_arch_sync_caches): Likewise. - * util/misc.c (grub_arch_sync_caches) [i386 || x86_64]: Likewise. - -2010-02-07 Vladimir Serbinenko - - * include/grub/err.h (grub_err_printf): Don't export. - -2010-02-07 Vladimir Serbinenko - - * include/grub/dl.h (grub_dl_register_symbol): Don't export. - -2010-02-07 Vladimir Serbinenko - - * include/grub/i18n.h (grub_gettext_dummy): Removed. - * kern/misc.c (grub_gettext_dummy): Make static. - -2010-02-06 Vladimir Serbinenko - - * kern/misc.c (grub_utf8_to_ucs4): Don't eat valid characters preceeded - by non-valid ones. - * kern/term.c (grub_putchar): Likewise. - -2010-02-06 Vladimir Serbinenko - - * partmap/sun.c (sun_partition_map_iterate): Restructure flow to fix - buggy hook call and memory leak. - -2010-02-06 Vladimir Serbinenko - - * commands/ls.c (grub_ls_list_files): Free pathname on exit. - -2010-02-06 Vladimir Serbinenko - - * fs/fat.c (grub_fat_iterate_dir): Free unibuf at exit. - -2010-02-06 Vladimir Serbinenko - - * loader/i386/pc/xnu.c (grub_xnu_set_video): Add const qualifier to - modevar. - Return grub_errno on allocation error. - -2010-02-06 Vladimir Serbinenko - - * disk/ieee1275/ofdisk.c (grub_ofdisk_read): Correct error handling. - -2010-02-06 Yves Blusseau - - * conf/common.rmk (grub_script_check_SOURCES): add missing dependencies. - (grub_mkpasswd_pbkdf2_SOURCES): Likewise. - -2010-02-06 Vladimir Serbinenko - - * fs/i386/pc/pxe.c (grub_pxefs_dir): Return with failure on - non-pxe disk. - (grub_pxefs_open): Likewise. - -2010-02-06 Robert Millan - - * util/grub.d/10_hurd.in: Add --class information to menuentries. - * util/grub.d/10_kfreebsd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - -2010-02-06 Colin D Bennett - - * conf/common.rmk (pkglib_MODULES): Add gfxmenu.mod. - (gfxmenu_mod_SOURCES): New variable. - (gfxmenu_mod_CFLAGS): Likewise. - (gfxmenu_mod_LDFLAGS): Likewise. - * include/grub/term.h (grub_term_set_current_output): Declare - argument as const. - * docs/gfxmenu-theme-example.txt: New file. - * gfxmenu/gfxmenu.c: Likewise. - * gfxmenu/gui_box.c: Likewise. - * gfxmenu/gui_canvas.c: Likewise. - * gfxmenu/gui_circular_progress.c: Likewise. - * gfxmenu/gui_image.c: Likewise. - * gfxmenu/gui_label.c: Likewise. - * gfxmenu/gui_list.c: Likewise. - * gfxmenu/gui_progress_bar.c: Likewise. - * gfxmenu/gui_string_util.c: Likewise. - * gfxmenu/gui_util.c: Likewise. - * gfxmenu/icon_manager.c: Likewise. - * gfxmenu/model.c: Likewise. - * gfxmenu/named_colors.c: Likewise. - * gfxmenu/theme_loader.c: Likewise. - * gfxmenu/view.c: Likewise. - * gfxmenu/widget-box.c: Likewise. - * include/grub/gfxmenu_model.h: Likewise. - * include/grub/gfxmenu_view.h: Likewise. - * include/grub/gfxwidgets.h: Likewise. - * include/grub/gui.h: Likewise. - * include/grub/gui_string_util.h: Likewise. - * include/grub/icon_manager.h: Likewise. - -2010-02-06 Vladimir Serbinenko - - Agglomerate scrolling in gfxterm. - - * term/gfxterm.c (grub_virtual_screen): New member 'total_screen'. - (grub_virtual_screen_setup): Initialise 'total_screen'. - (write_char): Split to ... - (paint_char): ... this ... - (write_char): ... and this. - (paint_char): Handle delayed scrolling. - (draw_cursor): Likewise. - (scroll_up): Split to ... - (real_scroll): ... this ... - (scroll_up): ... and this. - (real_scroll): Handle multi-line scroll and draw below-the-bottom - characters. - (grub_gfxterm_refresh): Call real_scroll. - -2010-02-06 Colin D Bennett - - * include/grub/misc.h (grub_iscntrl): New inline function. - (grub_isalnum): Likewise. - (grub_strtol): Likewise. - -2010-02-06 Colin D Bennett - - * normal/menu_text.c (get_entry_number): Move from here ... - * normal/menu.c (get_entry_number): ... moved here. - * include/grub/menu.h (grub_menu_get_default_entry_index): - New prototype. - * normal/menu.c (grub_menu_get_default_entry_index): New function. - * normal/menu_text.c (run_menu): Use grub_menu_get_default_entry_index. - * include/grub/menu_viewer.h (grub_menu_viewer_init): New prototype. - (grub_menu_viewer_should_return): Likewise. - * normal/main.c (GRUB_MOD_INIT (normal)): Call grub_menu_viewer_init. - * normal/menu_text.c (run_menu): Enable menu switching. - * normal/menu_viewer.c (should_return): New variable. - (menu_viewer_changed): Likewise. - (grub_menu_viewer_show_menu): Handle menu viewer changes. - (grub_menu_viewer_should_return): New function. - (menuviewer_write_hook): Likewise. - (grub_menu_viewer_init): Likewise. - -2010-02-06 Colin D Bennet -2010-02-06 Vladimir Serbinenko - - Support for gfxterm in a window. - - * include/grub/gfxterm.h: New file. - * include/grub/video.h (struct grub_video_rect): New declaration. - (grub_video_rect_t): Likewise. - * term/gfxterm.c (struct grub_gfxterm_window): New type. - (refcount): New variable. - (render_target): Likewise. - (window): Likewise. - (repaint_callback): Likewise. - (grub_virtual_screen_setup): Use 'render_target'. - (init_window): New function. - (grub_gfxterm_init_window): Likewise. - (grub_gfxterm_init): Check reference counter. - Use init_window. - (destroy_window): New function. - (grub_gfxterm_destroy_window): Likewise. - (grub_gfxterm_fini): Check reference counter. - Use destroy_window. - (redraw_screen_rect): Restore viewport. - Use 'render_target' and 'window'. - Call 'repaint_callback'. - (write_char): Use 'render_target'. - (draw_cursor): Likewise. - (scroll_up): Restore viewport. - Use 'render_target' and 'window'. - Call 'repaint_callback'. - (grub_gfxterm_cls): Likewise. - (grub_gfxterm_refresh): Use 'window'. - (grub_gfxterm_set_repaint_callback): New function. - (grub_gfxterm_background_image_cmd): Use 'window'. - (grub_gfxterm_get_term): New function. - (GRUB_MOD_INIT(term_gfxterm)): Set 'refcount' to 0. - -2010-02-06 Colin D Bennett - - Bitmap scaling support. - - * conf/common.rmk (pkglib_MODULES): Add bitmap_scale.mod. - (bitmap_scale_mod_SOURCES): New variable. - (bitmap_scale_mod_CFLAGS): Likewise. - (bitmap_scale_mod_LDFLAGS): Likewise. - * include/grub/bitmap_scale.h: New file. - * term/gfxterm.c (BACKGROUND_CMD_ARGINDEX_MODE): New definiton. - (background_image_cmd_options): New variable. - (grub_gfxterm_background_image_cmd): Support bitmap stretching. - (cmd): Rename and change type to ... - (background_image_cmd_handle): ... this. All users updated. - (GRUB_MOD_INIT(term_gfxterm)): Make background_image extended command. - * video/bitmap_scale.c: New file. - -2010-02-06 Vladimir Serbinenko - - SDL support. - - * Makefile.in (LIBSDL): New variable. - (enable_grub_emu_sdl): Likewise. - * conf/i386-pc.rmk (grub_emu_SOURCES): Add video files. - (grub_emu_SOURCES) [enable_grub_emu_sdl]: Add util/sdl.c. - (grub_emu_LDFLAGS) [enable_grub_emu_sdl]: Add $(LIBSDL). - * configure.ac: Detect SDL availability and add --enable-grub-emu-sdl - * util/sdl.c: New file. - -2010-02-06 Colin D Bennett -2010-02-06 Vladimir Serbinenko - - Double buffering support. - - * commands/i386/pc/videotest.c (grub_cmd_videotest): Swap doublebuffers. - * include/grub/video.h: Update comment. - * include/grub/video_fb.h (grub_video_fb_doublebuf_update_screen_t): - New type. - (grub_video_fb_doublebuf_blit_init): New prototype. - * term/gfxterm.c (scroll_up): Support double buffering. - (grub_gfxterm_refresh): Likewise. - * video/fb/video_fb.c (doublebuf_blit_update_screen): New function. - (grub_video_fb_doublebuf_blit_init): Likewise. - * video/i386/pc/vbe.c (framebuffer): Remove 'render_target'. Add - 'front_target', 'back_target', 'offscreen_buffer', 'page_size', - 'displayed_page', 'render_page' and 'update_screen'. - (grub_video_vbe_fini): Free offscreen buffer. - (doublebuf_pageflipping_commit): New function. - (doublebuf_pageflipping_update_screen): Likewise. - (doublebuf_pageflipping_init): Likewise. - (double_buffering_init): Likewise. - (grub_video_vbe_setup): Enable doublebuffering. - (grub_video_vbe_swap_buffers): Implement. - (grub_video_vbe_set_active_render_target): Handle double buffering. - (grub_video_vbe_get_active_render_target): Likewise. - (grub_video_vbe_get_info_and_fini): Likewise. Free offscreen_buffer. - (grub_video_vbe_adapter): Use grub_video_vbe_get_active_render_target. - (grub_video_vbe_enable_double_buffering): Likewise. - (grub_video_vbe_swap_buffers): Use update_screen. - (grub_video_set_mode): Use double buffering. - -2010-02-06 Robert Millan - - * maintainance/gentrigtables.py: Remove. - * lib/trig.c: Likewise. - - * gentrigtables.c: New file. C rewrite of gentrigtables.py. - - * conf/common.rmk (trig_mod_SOURCES): Replace `lib/trig.c' with - `trigtables.c'. - (trigtables.c): New rule. - (gentrigtables): Likewise. - (DISTCLEANFILES): Add `trigtables.c' and `gentrigtables'. - -2010-02-06 Robert Millan - - * maintainance/gentrigtables.py: Avoid duplicate hardcoding of - integer constants. - -2010-02-06 Colin D Bennet - - Trigonometry support. - - * include/grub/trig.h: New file. - * lib/trig.c: Likewise. - * maintainance/gentrigtables.py: Likewise. - * conf/common.rmk (pkglib_MODULES): Add trig.mod. - (trig_mod_SOURCES): New variable. - (trig_mod_CFLAGS): Likewise. - (trig_mod_LDFLAGS): Likewise. - -2010-02-06 Vladimir Serbinenko - - * kern/ieee1275/openfw.c (grub_ieee1275_encode_devname): Support whole - disk devices. - -2010-02-06 Vladimir Serbinenko - - * kern/ieee1275/openfw.c (grub_devalias_iterate): Stop iterating on - error. - -2010-02-03 Vladimir Serbinenko - - * util/hostdisk.c (open_device): Don't use partition device when reading - before the partition. - (grub_util_biosdisk_read): Don't read from partition and before the - partition in single operation. - (grub_util_biosdisk_write): Don't write to partition and before the - partition in single operation. - -2010-02-03 Torsten Landschoff - - * kern/disk.c (grub_disk_read): Fix offset computation when reading - last sectors. - -2010-02-03 Vladimir Serbinenko - - * disk/i386/pc/biosdisk.c (grub_biosdisk_read): Handle non-2048 aligned - CDROM reads. - (grub_biosdisk_write): Refuse to write to CDROM. - -2010-01-31 Vladimir Serbinenko - - * disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): Fix off-by-one error. - -2010-01-31 Vladimir Serbinenko - - * font/font.c (find_glyph): Check that bmp_idx is available before - using it. - (grub_font_get_string_width): Never call grub_font_get_glyph_internal - with (font == NULL). - -2010-01-28 Christian Schmitt - - * util/ieee1275/grub-install.in: Fix nvsetenv arguments. - -2010-01-28 BVK Chaitanya - - * include/grub/script_sh.h (sourcecode): Add const qualifier. - * util/grub-script-check.c (getline): Fix empty lines case. - -2010-01-28 Robert Millan - - * Makefile.in (check): Exit with fail status when one of the tests - fails. - * tests/example_functional_test.c (example_test): Fix reversed assert. - * tests/example_unit_test.c (example_test): Likewise. - -2010-01-28 Colin Watson - - * util/grub.d/10_linux.in: This script does not use any of the - contents of gettext.sh, only the external command `gettext', so stop - sourcing it. (Moreover, gettext.sh isn't necessarily installed in - the same prefix as GRUB.) - * util/grub.d/10_kfreebsd.in: Likewise. - -2010-01-27 Vladimir Serbinenko - - * normal/cmdline.c (grub_cmdline_get): Fix completion in the middle - of the line. - -2010-01-27 Vladimir Serbinenko - - * kern/disk.c (grub_disk_read): Fix offset computation when reading - last sectors. - -2010-01-27 Vladimir Serbinenko - - * commands/hashsum.c (hash_file): Avoid possible stack overflow by - having a 4KiB and not 32KiB buffer size. - -2010-01-27 Robert Millan - - * util/hostfs.c: Include `'. - (grub_hostfs_read): Handle errors from fseeko() and fread(). - -2010-01-27 Robert Millan - - * kern/disk.c (grub_disk_read): Fix bug that would cause infinite - loop when using read hooks on files whose size isn't sector-aligned. - -2010-01-27 Robert Millan - - Remove unused parameter. - - * fs/iso9660.c (struct grub_iso9660_data): Remove `length' parameter. - (grub_iso9660_open): Remove initialization of `data->length'. - -2010-01-27 Robert Millan - - * util/grub-fstest.c (fstest): Rewrite allocation, fixing a few - memleak conditions. - -2010-01-27 Carles Pina i Estany - - * util/lvm.c: New macro LVM_DEV_MAPPER_STRING. - (grub_util_lvm_isvolume): Use LVM_DEV_MAPPER_STRING. - -2010-01-26 Carles Pina i Estany - - * util/bin2h.c (usage): Fix warning (space after backslash). - -2010-01-26 Carles Pina i Estany - - * font/font.c: Include `grub/fontformat.h. - Remove font file format constants. - (grub_font_load): Use the new macros. - * include/grub/fontformat.h: New file. - * util/grub-mkfont.c: Include `grub/fontformat.c'. - (write_font_pf2): Use the new macros. - -2010-01-26 Robert Millan - - * util/bin2h.c (usage): Make --help actually explain what `grub-bin2h' - does. - -2010-01-26 Robert Millan - - * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_PXE_DL): New macro. - - * boot/i386/pc/pxeboot.S: Include `'. - (_start): Macroify `0x7F'. - - * kern/i386/pc/init.c: Include `'. - (make_install_device): Use "(pxe)" as fallback prefix when booting - via PXE. - -2010-01-26 Vladimir Serbinenko - - * configure.ac: Reset LIBS after check for libgcc symbols. - -2010-01-25 Colin Watson - - * util/hostdisk.c (open_device): Add trailing newline to debug - message. - -2010-01-25 GrĂ©goire Sutre - - * configure.ac: Check for `limits.h'. - * util/misc.c: Include `' (for PATH_MAX). - -2010-01-24 Robert Millan - - * loader/mips/linux.c (grub_cmd_linux, grub_cmd_initrd): Don't - capitalize error strings. - -2010-01-24 Samuel Thibault - - * util/grub.d/10_hurd.in: Add a recovery mode. - -2010-01-23 Vladimir Serbinenko - - * configure.ac: Check for libgcc symbols with -nostdlib. - -2010-01-23 BVK Chaitanya - - * acinclude.m4: Quote underquoted AC_DEFUN parameters. - -2010-01-22 Vladimir Serbinenko - - * term/ieee1275/ofconsole.c (grub_ofconsole_setcolorstate): Allocate on - stack since heap may be unavailable at that point. - (grub_ofconsole_gotoxy): Likewise. - -2010-01-22 Vladimir Serbinenko - - * configure.ac: Check for _restgpr_14_x. - * include/grub/powerpc/libgcc.h [HAVE__RESTGPR_14_X]: Add _restgpr_*_x - and _savegpr_* prototypes. - -2010-01-22 Robert Millan - - Use generic grub_reboot() for i386-efi. - - * kern/efi/efi.c [__i386__] (grub_reboot): Remove. - * kern/i386/efi/startup.S: Include `"../realmode.S"'. - * kern/i386/realmode.S: Include `'. - -2010-01-22 Vladimir Serbinenko - - * kern/ieee1275/init.c (grub_machine_set_prefix): Don't check for - presence of "prefix" variable as it breaks when normal.mod is - embedded. - -2010-01-21 Vladimir Serbinenko - - * term/ieee1275/ofconsole.c (grub_ofconsole_dimensions): Allocate on - stack since heap is unavailable at that point. - -2010-01-21 Vladimir Serbinenko - - * include/grub/i386/bsd.h (FREEBSD_N_BIOS_GEOM): Removed. - (grub_freebsd_bootinfo): Rewritten. - * loader/i386/bsd.c (grub_freebsd_boot): Use new grub_freebsd_bootinfo. - -2010-01-21 Vladimir Serbinenko - - * util/misc.c (make_system_path_relative_to_its_root): Fix typo. - -2010-01-21 Robert Millan - - * po/POTFILES: Remove mkisofs-related files. They have their own TLP - domain now. - -2010-01-20 Felix Zielcke - - * util/misc.c (make_system_path_relative_to_its_root): Change the work - around for handling "/" to the correct fix. Fix a memory leak. Use - xstrdup instead of strdup. - -2010-01-20 Vladimir Serbinenko - - * conf/mips.rmk (kernel_img_HEADERS): Add env_private.h - -2010-01-20 Vladimir Serbinenko - - Optimise glyph lookup by Basic Multilingual Plane lookup array. - - * font/font.c (struct grub_font): New member 'bmp_idx'. - (font_init): Initialise 'bmp_idx'. - (load_font_index): Fill 'bmp_idx'. - (find_glyph): Make inline. Use bmp_idx for BMP characters. - -2010-01-20 Vladimir Serbinenko - - * video/fb/video_fb.c (grub_video_fb_scroll): Optimise by avoiding - unnecessary calls. - -2010-01-20 Vladimir Serbinenko - - Move context handling out of the kernel. - - * conf/any-emu.rmk (grub_emu_SOURCES): Add normal/context.c. - * conf/common.rmk (normal_mod_SOURCES): Add normal/context.c. - * conf/i386-coreboot.rmk (kernel_img_HEADERS): Add env_private.h. - * conf/i386-efi.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - * include/grub/env.h: Include grub/menu.h. - (grub_env_var_type): Removed. - (grub_env_var): Replaced field 'type' with 'global'. - (grub_env_find): New prototype. - (grub_env_context_open): Remove EXPORT_FUNC. - (grub_env_context_close): Likewise. - (grub_env_export): Likewise. - (grub_env_set_data_slot): Removed. - (grub_env_get_data_slot): Likewise. - (grub_env_unset_data_slot): Likewise. - (grub_env_unset_menu): New prototype. - (grub_env_set_menu): Likewise. - (grub_env_get_menu): Likewise. - * include/grub/env_private.h: New file. - * include/grub/normal.h (grub_context_init): New prototype. - (grub_context_fini): Likewise. - * kern/corecmd.c (grub_core_cmd_export): Moved from here ... - * normal/context.c (grub_cmd_export): ... to here. - * kern/env.c: Include env_private.h. - (HASHSZ): Moved to include/grub/env_private.h. - (grub_env_context): Likewise. - (grub_env_sorted_var): Likewise. - (current_context): Renamed from this ... - (grub_current_context): ...to this. 'static' removed. All users updated. - (grub_env_find): Removed 'static'. - (grub_env_context_open): Moved to normal/context.c. - (grub_env_context_close): Likewise. - (grub_env_export): Likewise. - (mangle_data_slot_name): Removed. - (grub_env_set_data_slot): Likewise. - (grub_env_get_data_slot): Likewise. - (grub_env_unset_data_slot): Likewise. - * kern/main.c (grub_set_root_dev): Don't export root. - It will be done later. - (grub_main): Don't export prefix. - It will be done later. - * normal/context.c: New file. - * normal/main.c (free_menu): Use grub_env_unset_menu. - (grub_normal_add_menu_entry): Use grub_env_get_menu. - (read_config_file): Use grub_env_get_menu and grub_env_set_menu. - (GRUB_MOD_INIT(normal)): Call grub_context_init. - (GRUB_MOD_FINI(normal)): Call grub_context_fini. - -2010-01-20 Vladimir Serbinenko - - setpci support. - - * commands/setpci.c: New file. - * conf/i386.rmk (pkglib_MODULES): Add setpci.mod. - (setpci_mod_SOURCES): New variable. - (setpci_mod_CFLAGS): Likewise. - (setpci_mod_LDFLAGS): Likewise. - -2010-01-20 Vladimir Serbinenko - - Byte-addressable PCI configuration space. - - * bus/pci.c (grub_pci_make_address): Use byte address instead of - dword address. - (grub_pci_iterate): Use macroses GRUB_PCI_REG_PCI_ID and - GRUB_PCI_REG_CACHELINE. - * bus/usb/ohci.c (grub_ohci_pci_iter): Use macroses - GRUB_PCI_REG_CLASS and GRUB_PCI_REG_ADDRESS_REG0. - * bus/usb/uhci.c (grub_ohci_pci_iter): Use macroses - GRUB_PCI_REG_CLASS and GRUB_PCI_REG_ADDRESS_REG4. - * commands/efi/fixvideo.c (scan_card): Use macros GRUB_PCI_REG_CLASS. - * commands/efi/loadbios.c (enable_rom_area): Pass byte-address to - grub_pci_make_address. - (lock_rom_area): Likewise. - * commands/lspci.c (grub_lspci_iter): Use macroses - GRUB_PCI_REG_CLASS and GRUB_PCI_REG_ADDRESSES. Handle byte-addressing - of grub_pci_make_address. - * disk/ata.c (grub_ata_pciinit): Likewise. - * include/grub/pci.h (GRUB_PCI_REG_PCI_ID): New macro. - (GRUB_PCI_REG_VENDOR): Likewise. - (GRUB_PCI_REG_DEVICE): Likewise. - (GRUB_PCI_REG_COMMAND): Likewise. - (GRUB_PCI_REG_STATUS): Likewise. - (GRUB_PCI_REG_REVISION): Likewise. - (GRUB_PCI_REG_CLASS): Likewise. - (GRUB_PCI_REG_CACHELINE): Likewise. - (GRUB_PCI_REG_LAT_TIMER): Likewise. - (GRUB_PCI_REG_HEADER_TYPE): Likewise. - (GRUB_PCI_REG_BIST): Likewise. - (GRUB_PCI_REG_ADDRESSES): Likewise. - (GRUB_PCI_REG_ADDRESS_REG): Likewise. - (GRUB_PCI_REG_ADDRESS_REG): Likewise. - (GRUB_PCI_REG_ADDRESS_REG): Likewise. - (GRUB_PCI_REG_ADDRESS_REG): Likewise. - (GRUB_PCI_REG_ADDRESS_REG): Likewise. - (GRUB_PCI_REG_ADDRESS_REG): Likewise. - (GRUB_PCI_REG_CIS_POINTER): Likewise. - (GRUB_PCI_REG_SUBVENDOR): Likewise. - (GRUB_PCI_REG_SUBSYSTEM): Likewise. - (GRUB_PCI_REG_ROM_ADDRESS): Likewise. - (GRUB_PCI_REG_CAP_POINTER): Likewise. - (GRUB_PCI_REG_IRQ_LINE): Likewise. - (GRUB_PCI_REG_IRQ_PIN): Likewise. - (GRUB_PCI_REG_MIN_GNT): Likewise. - (GRUB_PCI_REG_MAX_LAT): Likewise. - * loader/i386/efi/linux.c (find_framebuf): Use GRUB_PCI_REG_CLASS. - * loader/i386/efi/xnu.c (find_framebuf): Likewise. - * video/efi_uga.c (find_framebuf): Likewise. - * video/sm712.c (grub_video_sm712_setup): Likewise. - * util/pci.c (grub_pci_make_address): Use byte-addressed configuration - space. - -2010-01-20 Robert Millan - - * util/grub.d/10_linux.in (linux_entry): Set gfxpayload=keep when it - can be reliably determined to be supported. - -2010-01-20 Robert Millan - - * loader/i386/linux.c (grub_cmd_linux): If `vga=' was used, write down - that VESA is supported. - (grub_linux_boot): Use generic framebuffer unless VESA is known to be - supported. - -2010-01-20 Vladimir Serbinenko - - * conf/common.rmk (font/font.c_DEPENDENCIES): Condition on FONT_SOURCE. - -2010-01-20 Robert Millan - - * util/misc.c (make_system_path_relative_to_its_root): Work around - special-casing of "/", as previous incarnation of this routine did. - -2010-01-20 Vladimir Serbinenko - - Fix any-emu compilation. - - * conf/any-emu.rmk (bin_UTILITIES): Add grub-bin2h. - * grub_bin2h_SOURCES: New variable. - -2010-01-20 Robert Millan - - * util/grub.d/00_header.in: Fix stupid mistake from last commit. - -2010-01-20 Robert Millan - - * util/grub.d/00_header.in: Fix handling of locale_dir. - -2010-01-20 Vladimir Serbinenko - - * configure.ac: Add /usr/share/fonts/unifont/unifont.pcf.gz - as possible unifont location (Gentoo). - Reported by: Alexander BrĂ¼ning - -2010-01-20 Vladimir Serbinenko - - Don't try to generate lists for kernel.img. - - * conf/i386-efi.rmk (pkglib_PROGRAMS): New variable. - (pkglib_MODULES): Remove kernel.img. - (kernel_img_EXPORTS): Removed. - (kernel_img_RELOCATABLE): New variable. - * conf/x86_64-efi.rmk: Likewise. - * genmk.rb: Remove *_EXPORTS support and add *_RELOCATABLE support. - -2010-01-20 Vladimir Serbinenko - - * include/grub/misc.h (grub_sprintf): Removed. All users switched to - grub_xasprintf or grub_snprintf. - (grub_vsprintf): Likewise. - (grub_snprintf): New proto. - (grub_vsnprintf): Likewise. - (grub_xasprintf): Likewise. - (grub_xvasprintf): Likewise. - * kern/misc.c (grub_vprintf): Use grub_vsnprintf_real. - (grub_sprintf): Removed. - (grub_vsnprintf): New function. - (grub_snprintf): Likewise. - (grub_xvasprintf): Likewise. - (grub_xasprintf): Likewise. - (grub_vsprintf): Renamed to ... - (grub_vsnprintf_real): ...this. New argument max_len. - -2010-01-20 BVK Chaitanya - - * include/grub/script_sh.h (sourcecode): Remove const qualifier to - fix grub-script-check warning. - -2010-01-20 Vladimir Serbinenko - - * include/grub/font.h (grub_font_load): Fix prototype. - -2010-01-20 Vladimir Serbinenko - - * conf/mips.rmk (kernel_img_HEADERS) [yeeloong]: Add pci.h. - -2010-01-20 Vladimir Serbinenko - - * include/grub/x86_64/at_keyboard.h: New file. - -2010-01-20 Vladimir Serbinenko - - * loader/mips/linux.c: Include missing grub/i18n.h. - -2009-12-20 Robert Millan - - * normal/menu.c (notify_execution_failure): Clarify error message. - -2009-12-20 Robert Millan - - * commands/loadenv.c (check_blocklists): Use `grub_err_t' as - return value (and revert all return statements). Update users. - -2010-01-20 Dan Merillat - - * kern/device.c (grub_device_iterate): Allocate new part_ent - structure based on sizeof (*p) rather than sizeof (p->next), to - account for structure padding. - - * util/grub-probe.c (probe_raid_level): Return -1 immediately if - disk is NULL, which might happen for LVM physical volumes with no - LVM signature. - -2009-12-20 Robert Millan - - * loader/mips/linux.c (grub_cmd_initrd) - (GRUB_MOD_INIT(linux)): Adjust and gettextize a few strings. - -2009-12-20 Robert Millan - - * kern/mips/yeeloong/init.c (grub_video_sm712_init) - (grub_video_video_init, grub_video_bitmap_init) - (grub_font_manager_init, grub_term_gfxterm_init) - (grub_at_keyboard_init): New extern declarations. - (grub_machine_init): Initialize gfxterm and at_keyboard. - - * kern/main.c (grub_main): Revert grub_printf delay kludge. - - * util/grub-install.in: Revert embed of `at_keyboard.mod' and - `gfxterm.mod' into core image. - - * conf/mips.rmk (pkglib_IMAGES, kernel_img_SOURCES) - (kernel_img_CFLAGS, kernel_img_ASFLAGS, kernel_img_LDFLAGS) - (kernel_img_FORMAT): Copy to ... - - * conf/mips-qemu-mips.rmk (pkglib_IMAGES, kernel_img_SOURCES) - (kernel_img_CFLAGS, kernel_img_ASFLAGS, kernel_img_LDFLAGS) - (kernel_img_FORMAT): ... here, and ... - - * conf/mips-yeeloong.rmk (pkglib_IMAGES, kernel_img_SOURCES) - (kernel_img_CFLAGS, kernel_img_ASFLAGS, kernel_img_LDFLAGS) - (kernel_img_FORMAT): ... here. - - (kernel_img_SOURCES): Add files necessary for output (gfxterm) - and input (at_keyboard) terminals in kernel. - (kernel_img_CFLAGS): Add `-DUSE_ASCII_FAILBACK'. - - (pkglib_MODULES): Remove `pci.mod'. - (pci_mod_SOURCES, pci_mod_CFLAGS, pci_mod_LDFLAGS) - (sm712_mod_SOURCES, sm712_mod_CFLAGS, sm712_mod_LDFLAGS) - (at_keyboard_mod_SOURCES, at_keyboard_mod_CFLAGS) - (at_keyboard_mod_LDFLAGS): Remove variables. - -2010-01-11 Felix Zielcke - - * po/POTFILES: Replace `term/i386/pc/serial.c' with `term/serial.c'. - -2009-12-10 Robert Millan - - * include/grub/mips/libgcc.h: Only export symbols for functions - that libgcc provides. - -2009-12-02 Vladimir Serbinenko - - MIPS support. - - * bus/bonito.c: New file. - * bus/pci.c (grub_pci_iterate): Use GRUB_PCI_NUM_BUS and - GRUB_PCI_NUM_DEVICES. - * term/i386/pc/serial.c: Move to ... - * term/serial.c: ... here. All users updated. - * util/i386/pc/grub-mkimage.c: Move to ... - * util/grub-mkrawimage.c: ... here. All users updated. - * term/i386/pc/at_keyboard.c: Move to ... - * term/at_keyboard.c: ... here. All users updated. - * conf/mips-qemu-mips.rmk: New file. - * conf/mips-yeeloong.rmk: Likewise. - * conf/mips.rmk: Likewise. - * configure.ac: New platforms mipsel-yeeloong, mips-qemu-mips and - mipsel-qemu-mips. - * disk/ata.c (grub_ata_device_initialize): Add GRUB_MACHINE_PCI_IO_BASE - to port addresses. - (grub_ata_pciinit): Support CS5536. - * font/font.c (grub_font_load): Use grub_file_t instead of filename. - * font/font_cmd.c (loadfont_command): Open file before passing it to - grub_font_load. - (pseudo_file_read): New function. - (pseudo_file_close): Likewise. - (pseudo_fs): New structure. - (load_font_module): New function. - (GRUB_MOD_INIT(font_manager)): Load embedded font. - * fs/cpio.c (grub_cpio_open): Handle partial matches correctly. - * genmk.rb: Strip .rel.dyn, .reginfo, .note and .comment. - * genmoddep.awk: Ignore __gnu_local_gp. It's defined by linker. - * include/grub/i386/at_keyboard.h: Split into ... - * include/grub/at_keyboard.h: ... this ... - * include/grub/i386/at_keyboard.h: ... and this. - * include/grub/dl.h (grub_arch_dl_init_linker) [_mips && !GRUB_UTIL]: - New prototype. - * include/grub/elfload.h (grub_elf32_size): New parameter. All users - updated. - (grub_elf64_size): Likewise. - * include/grub/font.h (grub_font_load): Use grub_file_t instead of - filename. - * include/grub/i386/io.h (grub_port_t): New type. All users updated. - * include/grub/i386/coreboot/serial.h: Rewritten. - * include/grub/i386/ieee1275/serial.h: Include - grub/i386/coreboot/serial.h instead of grub/i386/pc/serial.h. - * include/grub/i386/pc/serial.h: Moved from here ... - * include/grub/serial.h: ... to here. All users updated. - * include/grub/i386/pci.h (GRUB_MACHINE_PCI_IO_BASE): New definition. - (GRUB_PCI_NUM_BUS): Likewise. - (GRUB_PCI_NUM_DEVICES): Likewise. - (grub_pci_device_map_range): Add missing volatile keyword. - * include/grub/kernel.h (OBJ_TYPE_FONT): New enum value. - * include/grub/mips/at_keyboard.h: New file. - * include/grub/mips/cache.h: Likewise. - * include/grub/mips/io.h: Likewise. - * include/grub/mips/kernel.h: Likewise. - * include/grub/mips/libgcc.h: Likewise. - * include/grub/mips/pci.h: Likewise. - * include/grub/mips/qemu-mips/boot.h: Likewise. - * include/grub/mips/qemu-mips/kernel.h: Likewise. - * include/grub/mips/qemu-mips/loader.h: Likewise. - * include/grub/mips/qemu-mips/memory.h: Likewise. - * include/grub/mips/qemu-mips/serial.h: Likewise. - * include/grub/mips/qemu-mips/time.h: Likewise. - * include/grub/mips/relocator.h: Likewise. - * include/grub/mips/time.h: Likewise. - * include/grub/mips/types.h: Likewise. - * include/grub/mips/yeeloong/at_keyboard.h: Likewise. - * include/grub/mips/yeeloong/boot.h: Likewise. - * include/grub/mips/yeeloong/kernel.h: Likewise. - * include/grub/mips/yeeloong/loader.h: Likewise. - * include/grub/mips/yeeloong/memory.h: Likewise. - * include/grub/mips/yeeloong/pci.h: Likewise. - * include/grub/mips/yeeloong/serial.h: Likewise. - * include/grub/mips/yeeloong/time.h: Likewise. - * kern/dl.c (grub_dl_resolve_symbols): Handle STT_OBJECT correctly. - * kern/elf.c (grub_elf32_size): New parameter. All users - updated. - (grub_elf64_size): Likewise. - * kern/main.c (grub_main): Call grub_arch_dl_init_linker if necessary. - Load modules before saying "Welcome to GRUB!". - Call grub_refresh after saying "Welcome to GRUB!". - * kern/mips/cache.S: New file. - * kern/mips/cache_flush.S: Likewise. - * kern/mips/dl.c: Likewise. - * kern/mips/init.c: Likewise. - * kern/mips/qemu-mips/init.c: Likewise. - * kern/mips/startup.S: Likewise. - * kern/mips/yeeloong/init.c: Likewise. - * kern/term.c (grub_putcode): Handle NULL terminal. - (grub_getcharwidth): Likewise. - (grub_getkey): Likewise. - (grub_checkkey): Likewise. - (grub_getkeystatus): Likewise. - (grub_getxy): Likewise. - (grub_getwh): Likewise. - (grub_gotoxy): Likewise. - (grub_cls): Likewise. - (grub_setcolorstate): Likewise. - (grub_setcolor): Likewise. - (grub_getcolor): Likewise. - (grub_refresh): Likewise. - * lib/mips/relocator.c (JUMP_SIZEOF): Fix incorrect value. - (write_jump): Add hatch nop. - * lib/mips/relocator_asm.S: Use kern/mips/cache_flush.S. - * lib/mips/setjmp.S: New file. - * loader/mips/linux.c: Likewise. - * term/i386/pc/at_keyboard.c: Move from here ... - * term/at_keyboard.c: ... to here. - * term/i386/pc/serial.c: Moved from here ... - * term/serial.c: ... to here. All users updated. - (TEXT_HEIGHT): Set to 24 to fit linux terminal. - (serial_hw_io_addr): Use GRUB_MACHINE_SERIAL_PORTS. - (serial_translate_key_sequence): Avoid deadlock. - (grub_serial_getkey): Handle backspace. - (grub_serial_putchar): Fix newline handling. - * util/i386/pc/grub-mkimage.c: Move from here ... - * util/grub-mkrawimage.c: ... to here. All users updated. - (generate_image): New parameters 'font_path' and 'format'. - Support embedding font. - Use grub_host_to_target* instead of grub_cpu_to_le*. - (generate_image) [GRUB_MACHINE_MIPS]: Support ELF encapsulation. - (options) [GRUB_PLATFORM_IMAGE_DEFAULT]: New option "--format". - (options): New option "--font". - (usage): Likewise. - (main) [GRUB_PLATFORM_IMAGE_DEFAULT]: Handle "--format". - (main): Handle "--font". - * term/gfxterm.c (grub_virtual_screen): New member bg_color_display. - (grub_virtual_screen_setup): Set bg_color_display. - (redraw_screen_rect): Use bg_color_display instead of incorrect - bg_color. - (grub_gfxterm_cls): Likewise. - * util/elf/grub-mkimage.c (load_modules): New parameter 'config_path'. - Support embedding config file. - (add_segments): Likewise. - (options): New option "--config". - (main): Handle "--config". - * video/sm712.c: New file. - -2010-01-18 Robert Millan - - Fix parallel builds. - - * conf/common.rmk (font/font.c_DEPENDENCIES): New variable (makes - font.c depend on ascii.h). - -2010-01-12 Carles Pina i Estany - - * Makefile.in (DUSE_ASCII_FAILBACK): New macro. - -2010-01-11 Carles Pina i Estany - - * font/font.c (GENERATE_ASCII): Change the name to USE_ASCII_FAILBACK. - By default: disabled. - * Makefile.in (ascii.h): Remove the non-needed grub/bin2h size - parameter. - -2010-01-10 Carles Pina i Estany - - * font/font.c: Update copyright years. - * util/grub-mkfont.c (write_font_ascii_bitmap): Change comment format. - -2010-01-10 Carles Pina i Estany - - * font/font.c: Include `ascii.h'. - (ASCII_BITMAP_SIZE): New macro. - (ascii_font_glyph): Define. - (ascii_glyph_lookup): New function. - (grub_font_get_string_width): Change comment. If glyph not found, use - ascii_glyph_lookup. - (grub_font_get_glyph_with_fallback): If glyph not available returns - ascii_glyph_lookup. - * util/grub-mkfont.c (file_formats): New enum. - (options): Add `ascii-bitmaps' new option. - (usage): Add `asii-bitmaps' new option. - (write_font_ascii_bitmap): New function. - (write_font): Rename to ... - (write_font_p2): ... this. Remove print_glyphs call. - (main): Use file_format. Implement code for ranges if ascii-bitmaps is - used. Call print_glyphs. - * Makefile.in (pkgdata_DATA): Add `ascii.h'. - -2010-01-14 Robert Millan - - * conf/common.rmk (bin_UTILITIES): Add `grub-bin2h'. - (grub_bin2h_SOURCES): New variable. - * util/bin2h.c: New file. - -2010-01-20 Vladimir Serbinenko - - * include/multiboot.h: Resynced with spec. - * include/multiboot2.h: Likewise. - * loader/i386/multiboot_mbi.c (grub_fill_multiboot_mmap): Handle - GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE and GRUB_MACHINE_MEMORY_NVS. - -2010-01-18 Robert Millan - - * include/grub/term.h (grub_term_register_input, - grub_term_register_output): Check return of terminal init() - routines, and abort if errors are raised. - - * commands/terminal.c: Update copyright year. - -2010-01-18 Robert Millan - - * commands/terminal.c (grub_cmd_terminal_input) - (grub_cmd_terminal_output): Check return of terminal init() - routines, and abort if errors are raised. - -2010-01-18 Vladimir Serbinenko - - * include/grub/i386/bsd.h: Fix include pathes. - -2010-01-18 Vladimir Serbinenko - - Add missing *BSD copyright headers. - - * include/grub/aout.h: Add BSD licence. - * include/grub/i386/bsd.h: Parts under different licences moved to ... - * include/grub/i386/freebsd_linker.h: ... here, - * include/grub/i386/freebsd_reboot.h: ... here, - * include/grub/i386/netbsd_bootinfo.h: ... here, - * include/grub/i386/netbsd_reboot.h: ... here, - * include/grub/i386/openbsd_bootarg.h: ... here, - * include/grub/i386/openbsd_reboot.h: ... and here. Added appropriate - licence to each file. - -2010-01-18 Robert Millan - - * acinclude.m4: Remove `nop' assembly instruction; it's not - implemented by all architectures. - -2010-01-18 Robert Millan - - * loader/i386/efi/linux.c (grub_cmd_linux): Stop pretending we're - ELILO. This is no longer necessary. - -2010-01-18 BVK Chaitanya - - Added new tool, grub-scrit-check to verify grub.cfg syntax. - - * util/grub-script-check.c: grub-script-check tool. - * conf/common.rmk: Make rules for grub-script-check. - -2010-01-18 Robert Millan - - Fix annoying UI bug in rescue mode. Thanks to Tristan Gingold for - spotting it back in 2008. Shame on me for forgetting he did. - - * kern/rescue_reader.c (grub_rescue_run): Skip zero-length lines. - -2010-01-18 Robert Millan - - * include/grub/i386/linux.h (GRUB_VIDEO_TYPE_TEXT): Rename to ... - (GRUB_VIDEO_LINUX_TYPE_TEXT): ... this. Update all users. - (GRUB_VIDEO_TYPE_VLFB): Rename to ... - (GRUB_VIDEO_LINUX_TYPE_VESA): ... this. Update all users. - (GRUB_VIDEO_TYPE_EFI): Rename to ... - (GRUB_VIDEO_LINUX_TYPE_SIMPLE): ... this. Update all users. - -2010-01-17 Robert Millan - - * include/grub/test.h: Add license header. - * tests/example_functional_test.c: Likewise. - * tests/example_unit_test.c: Likewise. - * tests/lib/functional_test.c: Likewise. - * tests/lib/test.c: Likewise. - * tests/lib/unit_test.c: Likewise. - -2010-01-17 Vladimir Serbinenko - - Use flag-based instead of hook-based video mode selection and "auto" - keyword. - - * include/grub/video.h (grub_video_adapter): Changed 'setup' member. - (grub_video_set_mode): Changed prototype. All users updated. - (grub_video_check_mode_flag): New inline function. - * video/video.c (parse_modespec): New function. - (grub_video_set_mode): Parse flags and keywords. - -2010-01-17 Carles Pina i Estany - - * util/misc.c (grub_util_info): Fix the order of the parameters in a - fprintf call. - -2010-01-16 GrĂ©goire Sutre - - * genmk.rb (class SCRIPT): Replace option -i of sed by a pipe. - -2010-01-16 Carles Pina i Estany - - * util/grub-editenv.c (usage): Use `program_name' instead of hardcoded - string. - * util/grub-emu.c (usage): Likewise. - * util/grub-mkpasswd-pbkdf2.c (usage): Likewise. - * util/i386/efi/grub-mkimage.c (usage): Likewise. - * util/i386/pc/grub-mkimage.c (usage): Likewise. - * util/i386/pc/grub-setup.c (usage): Likewise. - -2010-01-16 Carles Pina i Estany - - * util/misc.c (grub_util_warn): Gettextizze, print full stop after - the message. - (grub_util_info): Likewise. - (grub_util_error): Likewise. - * util/elf/grub-mkimage.c: Fix capitalisation, quotes, full stops - and/or new lines in `grub_util_warna', `grub_util_info', - `grub_util_error' calls. - * util/getroot.c: Likewise. - * util/grub-editenv.c: Likewise. - * util/grub-emu.c: Likewise. - * util/grub-fstest.c: Likewise. - * util/grub-mkdevicemap.c: Likewise. - * util/grub-mkfont.c: Likewise. - * util/grub-mkpasswd-pbkdf2.c: Likewise. - * util/grub-mkrelpath.c: Likewise. - * util/grub-pe2elf.c: Likewise. - * util/grub-probe.c: Likewise. - * util/hostdisk.c: Likewise. - * util/i386/efi/grub-mkimage.c: Likewise. - * util/i386/pc/grub-mkimage.c: Likewise. - * util/i386/pc/grub-setup.c: Likewise. - * util/ieee1275/ofpath.c: Likewise. - * util/mkisofs/eltorito.c: Likewise. - * util/mkisofs/rock.c: Likewise. - * util/mkisofs/write.c: Likewise. - * util/raid.c: Likewise. - * util/sparc64/ieee1275/grub-mkimage.c: Likewise. - * util/sparc64/ieee1275/grub-setup.c: Likewise. - -2010-01-15 Vladimir Serbinenko - - Enable multiboot on non-pc. - - * conf/i386-coreboot.rmk, conf/i386-pc.rmk (pkglib_MODULES): Move - multiboot.mod and multiboot2.mod to ... - * conf/i386.rmk (pkglib_MODULES): ... here. - * conf/i386-coreboot.rmk, conf/i386-pc.rmk (multiboot_mod_SOURCES): - Moved to ... - * conf/i386.rmk (multiboot_mod_SOURCES): .. here. - * conf/i386-coreboot.rmk, conf/i386-pc.rmk (multiboot_mod_CFLAGS): - Moved to ... - * conf/i386.rmk (multiboot_mod_CFLAGS): .. here. - * conf/i386-coreboot.rmk, conf/i386-pc.rmk (multiboot_mod_ASFLAGS): - Moved to ... - * conf/i386.rmk (multiboot_mod_ASFLAGS): .. here. - * conf/i386-coreboot.rmk, conf/i386-pc.rmk (multiboot_mod_LDFLAGS): - Moved to ... - * conf/i386.rmk (multiboot_mod_LDFLAGS): .. here. - * conf/x86_64-efi.rmk (pkglib_MODULES): Remove ata.mod and - relocator.mod. - (ata_mod_SOURCES): Removed. - (ata_mod_CFLAGS): Likewise. - (ata_mod_LDFLAGS): Likewise. - (relocator_mod_SOURCES): Removed. - (relocator_mod_CFLAGS): Likewise. - (relocator_mod_ASFLAGS): Likewise. - (relocator_mod_LDFLAGS): Likewise. - Include i386.mk. - * include/grub/x86_64/multiboot.h: New file. - * loader/i386/multiboot.c (grub_multiboot_boot) [GRUB_MACHINE_EFI]: - Terminate EFI. - -2010-01-15 Vladimir Serbinenko - - Video multiboot support. - - * include/grub/multiboot.h (grub_multiboot_set_accepts_video): - New prototype. - * include/multiboot.h: Resynced with multiboot specification. - * include/multiboot2.h: Likewise. - * loader/i386/multiboot.c (UNSUPPORTED_FLAGS): Support video flags. - (grub_multiboot): Parse MULTIBOOT_VIDEO_MODE fields. - * loader/i386/multiboot_mbi.c (DEFAULT_VIDEO_MODE): New constant. - (HAS_VGA_TEXT): Likewise. - (accepts_video): New variable. - (grub_multiboot_set_accepts_video): New function. - (grub_multiboot_get_mbi_size): Account for video structures. - (set_video_mode): New function. - (retrieve_video_parameters): Likewise. - (grub_multiboot_make_mbi): Fill video fields. - -2010-01-15 Vladimir Serbinenko - - Video driver ids. - - * include/grub/video.h (grub_video_driver_id): New type. - (grub_video_adapter): New member 'id'. All users updated. - (grub_video_get_driver_id): New proto. - * video/video.c (grub_video_get_driver_id): New function. - -2010-01-14 Carles Pina i Estany - - * util/grub.d/30_os-prober.in: Use `set var=val' rather than plain - `var=val'. - -2010-01-14 Carles Pina i Estany - - * normal/cmdline.c (print_completion): Gettextizze. - -2001-01-14 Carles Pina i Estany - - * loader/i386/pc/chainloader.c: Include `'. - -2010-01-14 Carles Pina i Estany - - * gettext/gettext.c (grub_gettext_translate): Push and pop - grub_errno. - (grub_gettext_delete_list): Change comment style. - * kern/err.c (grub_error): Gettextizze. - (grub_fatal): Gettextizze. - -2010-01-14 Robert Millan - - * include/grub/i386/loader.h (grub_linux16_boot): Renamed to ... - (grub_linux16_real_boot): ... this. - * kern/i386/loader.S: Likewise. - * loader/i386/pc/linux.c: Include `' and `'. - (grub_linux16_boot): New function. Switches to text mode and calls - grub_linux16_real_boot(). - - * loader/i386/bsd.c: Include `'. - (grub_freebsd_boot, grub_openbsd_boot, grub_netbsd_boot): Switch to - text mode before calling grub_unix_real_boot(). - - * loader/i386/multiboot.c: Include `'. - (grub_multiboot_boot): Switch to text mode before calling - grub_relocator32_boot(). - - * loader/i386/pc/chainloader.c: Include `'. - (grub_chainloader_boot): Switch to text mode before calling - grub_chainloader_real_boot(). - -2010-01-05 Jordan Uggla -2010-01-05 Colin Watson - - * util/grub-reboot.in: Make sure prev_saved_entry always gets a - non-empty value. - -2010-01-05 Jordan Uggla -2010-01-05 Colin Watson - - * util/grub.d/00_header.in: Define a "savedefault" function for use - in menu entries. - * util/grub-mkconfig_lib.in (save_default_entry): Use it. - -2010-01-05 Jordan Uggla -2010-01-05 Colin Watson - - * util/grub-mkconfig_lib.in (save_default_entry): Only set - saved_entry if boot_once is unset. - * util/grub.d/00_header.in: Set boot_once to "true" if there was a - previous saved entry (i.e. grub-reboot). - -2009-12-08 Colin Watson - - * util/grub.d/30_os-prober.in: Call save_default_entry for hurd. - -2009-12-08 Colin Watson - - * util/grub.d/00_header.in: Use `set var=val' rather than plain - `var=val'. - * util/grub-mkconfig_lib.in (save_default_entry): Likewise. - -2009-12-08 Colin Watson - - * util/grub-reboot.in: Fix --version output. - * util/grub-set-default.in: Likewise. - -2009-12-08 Colin Watson - - * util/grub.d/00_header.in: Silently ignore zero-sized environment - blocks. - -2009-12-08 Colin Watson - - * util/grub.d/00_header.in: Quote the value assigned to `default', - in case it contains spaces. - -2009-12-08 Colin Watson - - * util/grub.d/30_os-prober.in: Fix merge error that moved a - `save_default_entry' call from the macosx case to the linux case. - -2009-10-25 Vladimir Serbinenko -2009-10-25 Colin Watson - - * normal/menu.c (grub_menu_execute_entry): Save selected entry title - in `chosen' environment variable. - * normal/menu_text.c (get_entry_number): Check if the variable - matches the title of a menu entry. - (run_menu): Pass menu to get_entry_number. - - * util/grub-reboot.in: New file. - * util/grub-set-default.in: New file. - * conf/common.rmk (grub-reboot): New utility. - (grub-set-default): New utility. - - * util/grub-mkconfig_lib.in (save_default_entry): New function. - * util/grub.d/00_header.in: If GRUB_DEFAULT is `saved', set - default to `${saved_entry}'. If `${prev_saved_entry}' is non-empty, - move it to `saved_entry' for the next boot. Load environment on - initialisation. - * util/grub.d/10_kfreebsd.in: Call save_default_entry. - * util/grub.d/10_hurd.in: Likewise. - * util/grub.d/10_linux.in (linux_entry): Likewise. - * util/grub.d/10_windows.in: Likewise. - * util/grub.d/30_os-prober.in: Likewise. - - * util/grub-install.in: Create environment block. - * util/i386/efi/grub-install.in: Likewise. - * util/ieee1275/grub-install.in: Likewise. - * util/sparc64/ieee1275/grub-install.in: Likewise. - -2010-01-14 BVK Chaitanya - - Unit testing framework for GRUB. - - * Makefile.in: Test framework build rules for 'make check'. - * conf/tests.rmk: Build rules for individual tests and framework. - - * include/grub/test.h: Header file for whitebox tests. - * tests/lib/functional_test.c: Framework support for whitebox - functional tests. - * tests/lib/test.c: Common whitebox testing code for unit and - functional tests. - * tests/lib/unit_test.c: Framework support for whitebox unit - tests. - - * tests/util/grub-shell-tester.in: Support utility for grub-script - tests. - * tests/util/grub-shell.in: Utility to execute grub-script - commands in a Qemu instance. - - * tests/example_functional_test.c: Example whitebox functional - test. - * tests/example_grub_script_test.in: Example grub-script test. - * tests/example_scripted_test.in: Example scripted test. - * tests/example_unit_test.c: Example whitebox unit test. - -2010-01-14 Vladimir Serbinenko - - * conf/i386-coreboot.rmk (multiboot_mod_SOURCES): - Add loader/i386/multiboot_mbi.c. - (multiboot2_mod_SOURCES): Likewise. - * conf/i386-pc.rmk (multiboot_mod_SOURCES): Likewise. - (multiboot2_mod_SOURCES): Likewise. - * include/grub/multiboot.h (grub_multiboot_get_mbi_size): New proto. - (grub_multiboot_make_mbi): Likewise. - (grub_multiboot_free_mbi): Likewise. - (grub_multiboot_init_mbi): Likewise. - (grub_multiboot_add_module): Likewise. - (grub_multiboot_set_bootdev): Likewise. - * loader/i386/multiboot.c (mbi): Removed. - (mbi_dest): Likewise. - (alloc_mbi): New variable. - (grub_multiboot_payload_size): Removed. All users updated. - (grub_multiboot_pure_size): New variable. - (grub_multiboot_boot): Use grub_multiboot_make_mbi. - (grub_multiboot_unload): Use grub_multiboot_free_mbi. - (grub_get_multiboot_mmap_len): Moved to loader/i386/multiboot_mbi.c. - (grub_fill_multiboot_mmap): Likewise. - (grub_multiboot_get_bootdev): Likewise. - (grub_multiboot): Use multiboot_mbi functions. - * loader/i386/multiboot_mbi.c: New file. - -2010-01-13 Vladimir Serbinenko - - * kern/efi/init.c (grub_efi_fini): Don't call grub_efi_mm_fini as - it would result in module crash. - -2010-01-13 Vladimir Serbinenko - - * term/ieee1275/ofconsole.c (grub_ofconsole_putchar): Handle '\r'. - (grub_ofconsole_getwh): Split to ... - (grub_ofconsole_getwh): ... this. - (grub_ofconsole_dimensions): ...and this. - (grub_ofconsole_init_output): Call grub_ofconsole_dimensions. - -2010-01-13 Robert Millan - - * util/mkisofs/rock.c (generate_rock_ridge_attributes): Fix a typo. - -2010-01-12 Vladimir Serbinenko - - * loader/i386/pc/multiboot2.c: Removed stalled file. - -2010-01-12 Vladimir Serbinenko - - * util/grub-mkpasswd-pbkdf2.c (main): Use grub_util_init_nls. - Reported by: GrĂ©goire Sutre - -2010-01-11 Robert Millan - - * util/misc.c (canonicalize_file_name): New function. - (make_system_path_relative_to_its_root): Use canonicalize_file_name() - instead of realpath(). - -2010-01-11 Colin Watson - - * util/grub-install.in (usage): Clarify meaning of --root-directory, - and make it clearer that it's optional. Based on confusion - witnessed on IRC. - -2010-01-10 Vladimir Serbinenko - - * term/i386/pc/vga_text.c (inc_y): Fix off-by-one error which resulted - in premature implicit newline. - -2010-01-10 Vladimir Serbinenko - - * normal/cmdline.c (grub_cmdline_get): Fix off-by-one error - which resulted in garbled command line at the end of screen. - -2010-01-10 Robert Millan - - * loader/i386/ieee1275/linux.c (grub_linux_boot): Rework video position - initialization with similar approach as with other Linux loaders. - -2010-01-10 Robert Millan - - Fix i386-ieee1275 build. - - * loader/i386/ieee1275/linux.c (grub_linux_boot): Use grub_term_width() - and grub_term_height() for video_{width,height} initialization. - -2010-01-10 Robert Millan - - Fix grub-emu build. - - * conf/any-emu.rmk (grub_emu_SOURCES): Remove `kern/reader.c'. - -2010-01-07 Vladimir Serbinenko -2010-01-09 Robert Millan - - Support for multiple terminals. - - * Makefile.in (pkglib_DATA): terminal.lst. - (terminal.lst): New target. - * commands/handler.c (grub_cmd_handler): Don't handle terminals. - (GRUB_MOD_INIT(handler)): Likewise. - (GRUB_MOD_FINI(handler)): Likewise. - * commands/help.c (grub_cmd_help): Handle multiple terminals. - * commands/keystatus.c (grub_cmd_keystatus): Likewise. - * commands/sleep.c (do_print): Use grub_term_restore_pos. - (grub_cmd_sleep): Use grub_term_save_pos. - * commands/terminal.c: New file. - * conf/any-emu.rmk (grub_emu_SOURCES): Add normal/term.c - commands/terminal.c and lib/charset.c. - * conf/common.rmk (normal_mod_SOURCES): Add normal/term.c. - (pkglib_MODULES): Add terminal.mod. - (terminal_mod_SOURCES): New variable. - (terminal_mod_CFLAGS): Likewise. - (terminal_mod_LDFLAGS): Likewise. - * genhandlerlist.sh: Don't handle terminals. - * genmk.rb: Generate terminal-*.lst. - * genterminallist.sh: New file. - * include/grub/charset.h (grub_ucs4_to_utf8_alloc): New proto. - (grub_is_valid_utf8): Likewise. - (grub_utf8_to_ucs4_alloc): Likewise. - * include/grub/menu_viewer.h (grub_menu_viewer): Rewritten. - (grub_menu_register_viewer): Changed argument. - (grub_menu_try_text): New proto. - (grub_gfxmenu_try_hook): New declaration. - * include/grub/normal.h (grub_normal_exit_level): New declaration. - (grub_menu_init_page): Additional argument term. - (grub_normal_init_page): Likewise. - (grub_cmdline_get): Arguments simplified. - (grub_utf8_to_ucs4_alloc): Removed. - (grub_print_ucs4): Additional argument term. - (grub_getstringwidth): Likewise. - (grub_print_message_indented): Likewise. - (grub_menu_text_register_instances): New proto. - (grub_show_menu): Likewise. - (read_terminal_list): Likewise. - (grub_set_more): Likewise. - * include/grub/parser.h: Include handler.h. - * include/grub/reader.h: Rewritten. - * include/grub/term.h (GRUB_TERM_NEED_INIT): Removed. - (GRUB_TERM_WIDTH): Changed to function. - (GRUB_TERM_HEIGHT): Likewise. - (GRUB_TERM_BORDER_WIDTH): Likewise. - (GRUB_TERM_BORDER_HEIGHT): Likewise. - (GRUB_TERM_NUM_ENTRIES): Likewise. - (GRUB_TERM_ENTRY_WIDTH): Likewise. - (GRUB_TERM_CURSOR_X): Likewise. - (grub_term_input_class): Likewise. - (grub_term_output_class): Likewise. - (grub_term_outputs_disabled): New declaration. - (grub_term_inputs_disabled): Likewise. - (grub_term_outputs): Likewise. - (grub_term_inputs): Likewise. - (grub_term_register_input): Rewritten. - (grub_term_register_output): Likewise. - (grub_term_unregister_input): Likewise. - (grub_term_unregister_output): Likewise. - (FOR_ACTIVE_TERM_INPUTS): New macro. - (FOR_DISABLED_TERM_INPUTS): Likewise. - (FOR_ACTIVE_TERM_OUTPUTS): Likewise. - (FOR_DISABLED_TERM_OUTPUTS): Likewise. - * include/grub/terminfo.h: Add oterm argument to all protypes. - * kern/main.c (grub_main): Don't call grub_register_rescue_reader. - Use grub_rescue_run. - * kern/misc.c (grub_utf8_to_ucs4): Put '?' for invalid characters. - All users updated. - * kern/reader.c: Removed. All users updated. - * kern/rescue_reader.c (grub_rescue_init): Removed. - (grub_rescue_reader): Likewise. - (grub_register_rescue_reader): Likewise. - (grub_rescue_run): New function based on kern/reader.c. - * kern/term.c: Adapted for multiterm. - * lib/charset.c (grub_ucs4_to_utf8_alloc): New function. - (grub_is_valid_utf8): Likewise. - (grub_utf8_to_ucs4_alloc): Moved from normal/menu_text.c. - * loader/i386/efi/linux.c (grub_cmd_linux): Retrieve parameters of - right terminal. - * loader/i386/linux.c (grub_linux_boot): Likewise. - * normal/auth.c (grub_username_get): New function. - (grub_auth_check_authentication): Use grub_username_get. - * normal/cmdline.c: Changed to UCS4. Adapted for multiterm. - * normal/color.c: Adapt for multiterm. - * normal/main.c (read_config_file): Don't use grub_reader_loop. - (grub_normal_init_page): Additional argument term. - (read_lists): Call read_terminal_lists. - (grub_enter_normal_mode): Call grub_cmdline_run. - Handle grub_normal_exit_level. - (grub_cmd_normal): Make reentrant. - (grub_cmd_normal_exit): New function. - (grub_normal_reader_init): Additional argument nested. Handle multiterm. - * normal/menu.c: Adapt for multiterm. - * normal/menu_entry.c: Likewise. - * normal/menu_text.c: Likewise. - * normal/menu_viewer.c: Removed. All users updated. - * normal/term.c: New file. - * util/console.c: Change order of includes to workaround a bug in - ncurses headers. - * term/terminfo.c: New argument oterm on all exported functions. - All users updated. - * util/grub-editenv.c (grub_term_input_class): Removed. - (grub_term_output_class): Likewise. - -2010-01-09 Robert Millan - - Make loader output a bit more user-friendly. - - * util/grub.d/10_hurd.in: Print message indicating that GNU Mach - is being loaded. Likewise for the Hurd. - - * util/grub.d/10_kfreebsd.in (kfreebsd_entry): Print message indicating - that kernel of FreeBSD ${version} is being loaded. - - * loader/i386/linux.c (grub_cmd_linux): Move debug info to - grub_dprintf(). - (grub_cmd_initrd): Likewise. - * util/grub.d/10_linux.in (linux_entry): Print message indicating - that Linux ${version} is being loaded. Likewise for initrd. - -2010-01-09 Carles Pina i Estany - - * gettext/gettext.c (GRUB_MOD_INIT): Gettextizze. - -2010-01-08 Carles Pina i Estany - - * loader/efi/appleloader.c: Include `'. - (GRUB_MOD_INIT): Gettextizze. - * loader/efi/chainloader.c: Include `'. - (GRUB_MOD_INIT): Gettextizze. - * loader/i386/efi/linux.c: Include `'. - (grub_cmd_linux): Capitalise Linux. - (GRUB_MOD_INIT): Gettextizze. - * loader/i386/ieee1275/linux.c: Include `'. - (grub_cmd_linux): Capitalise Linux. - (GRUB_MOD_INIT): Gettextizze. - * loader/i386/linux.c: Include `'. - (grub_cmd_linux): Capitalise Linux. - (GRUB_MOD_INIT): Gettextizze. - * loader/i386/pc/chainloader.c: Include `'. - (GRUB_MOD_INIT): Gettextizze. - * loader/i386/pc/linux.c: Include `'. - (grub_cmd_linux): Capitalise Linux. - (GRUB_MOD_INIT): Gettextizze. - * loader/i386/xnu.c: Include `'. - (grub_cpu_xnu_init): Gettextizze. - * loader/multiboot_loader.c: Include `'. - (GRUB_MOD_INIT): Gettextizze. - * loader/powerpc/ieee1275/linux.c: Include `'. - (GRUB_MOD_INIT): Gettextizze. - * loader/sparc64/ieee1275/linux.c: Include `'. - (grub_linux_load64): Capitalise Linux. - (GRUB_MOD_INIT): Gettextizze. - * loader/xnu.c: Include `'. - (GRUB_MOD_INIT): Gettextizze. - * po/POTFILES: Add `loader/efi/appleloader.c', - `loader/efi/chainloader.c', `loader/i386/efi/linux.c', - `loader/i386/ieee1275/linux.c', `loader/i386/linux.c', - `loader/i386/pc/chainloader.c', `loader/i386/pc/linux.c', - `loader/i386/xnu.c', `loader/multiboot_loader.c', - `loader/powerpc/ieee1275/linux.c', `loader/sparc64/ieee1275/linux.c' - and `loader/xnu.c'. - -2010-01-08 Robert Millan - - * src/mkisofs.c: Remove `ifdef linux' portability kludge. - -2010-01-08 Robert Millan - - * util/mkisofs/defaults.h (APPID_DEFAULT): Redefine using PACKAGE_NAME. - (SYSTEM_ID_DEFAULT): Set to "GNU" unconditionally. - * util/mkisofs/mkisofs.c (main): Readjust --version output. - -2010-01-07 Robert Millan - - Reset Multiboot 2 support. New loader implements the draft in - /branches/multiboot2 and shares as much code as possible with the - production Multiboot 1 implementation. - - * loader/ieee1275/multiboot2.c: Remove file. Update all users. - * loader/multiboot2.c: Likewise. - * loader/i386/multiboot_helper.S: Likewise. - * include/multiboot2.h: Replace with latest version from the draft - in /branches/multiboot2. - - * conf/i386-coreboot.rmk (multiboot_mod_SOURCES): Remove - `loader/i386/multiboot_helper.S', `loader/i386/pc/multiboot2.c' - and `loader/multiboot2.c'. - (pkglib_MODULES): Add `multiboot2.mod'. - (multiboot2_mod_SOURCES): New variable. - (multiboot2_mod_LDFLAGS): Likewise. - (multiboot2_mod_CFLAGS): Likewise. Define `GRUB_USE_MULTIBOOT2'. - - * conf/i386-pc.rmk: Likewise. - - * conf/powerpc-ieee1275.rmk (pkglib_MODULES): Remove `multiboot.mod'. - (multiboot_mod_SOURCES): Remove variable. - (multiboot_mod_LDFLAGS): Likewise. - (multiboot_mod_CFLAGS): Likewise. - - * include/grub/multiboot.h [GRUB_USE_MULTIBOOT2]: Include - `' instead of `'. - [GRUB_USE_MULTIBOOT2] (MULTIBOOT_BOOTLOADER_MAGIC) - (MULTIBOOT_HEADER_MAGIC): New macros. - - * loader/multiboot_loader.c (module_version_status): Remove variable. - (find_multi_boot2_header): Remove function. - (grub_cmd_multiboot_loader): Remove Multiboot 2 / Multiboot 1 selection - logic. Always check for the Multiboot version we're compiling for. - (grub_cmd_module_loader): Likewise. - [GRUB_USE_MULTIBOOT2] (GRUB_MOD_INIT(multiboot)): Register `multiboot2' - command instead of `multiboot'. - -2010-01-07 Robert Millan - - * include/multiboot.h (MULTIBOOT_UNSUPPORTED): Moved from here ... - * loader/i386/multiboot.c (UNSUPPORTED_FLAGS): ... to here. Update - all users. - -2010-01-07 Robert Millan -2010-01-07 Vladimir Serbinenko - - Fix breakage introduced with previous commit. - - * normal/dyncmd.c (read_command_list): Avoid unregistering kernel - commands. - * normal/handler.c (read_handler_list): Revert part of previous commit - affecting this file. - * normal/main.c (read_lists): Move read_handler_list() call back to ... - (grub_normal_execute): ... here. - -2010-01-07 Robert Millan - - Merge prefix-redefinition-fix branch. - - * normal/autofs.c (read_fs_list): Make function capable of being - run multiple times, gracefuly replacing the previous data - structures. - * normal/dyncmd.c (read_command_list): Likewise. - * normal/handler.c (read_handler_list): Likewise. - * normal/main.c (read_lists): New function. Calls all the - list reading functions. - (grub_normal_execute): Use read_lists() instead of calling all - list reading functions explicitly. Register read_lists() as a - variable hook attached to ${prefix}. - -2010-01-07 Vladimir Serbinenko - - Merge crypto branch. - - * Makefile.in (pkglib_DATA): Add crypto.lst. - (crypto.lst): New target. - * commands/hashsum.c: New file. - * commands/password.c (check_password): Use grub_crypto_memcmp. - * commands/password_pbkdf2.c: New file. - * commands/xnu_uuid.c: Remove MD5. Use GRUB_MD_MD5. - * conf/any-emu.rmk (grub_emu_SOURCES): Add lib/crypto.c, - normal/crypto.c and lib/libgcrypt-grub/cipher/md5.c. - (grub_emu_CFLAGS): Add -Wno-missing-field-initializers -Wno-error - -I$(srcdir)/lib/libgcrypt_wrap. - * conf/common.rmk (normal_mod_SOURCES): Add normal/crypto.c. - (pkglib_MODULES): Add crypto.mod, hashsum.mod, pbkdf2.mod and - password_pbkdf2.mod. - (crypto_mod_SOURCES): New variable. - (crypto_mod_CFLAGS): Likewise. - (crypto_mod_LDFLAGS): Likewise. - (hashsum_mod_SOURCES): New variable. - (hashsum_mod_CFLAGS): Likewise. - (hashsum_mod_LDFLAGS): Likewise. - (pbkdf2_mod_SOURCES): New variable. - (pbkdf2_mod_CFLAGS): Likewise. - (pbkdf2_mod_LDFLAGS): Likewise. - (password_pbkdf2_mod_SOURCES): New variable. - (password_pbkdf2_mod_CFLAGS): Likewise. - (password_pbkdf2_mod_LDFLAGS): Likewise. - (bin_UTILITIES): Add grub-mkpasswd-pbkdf2. - (grub_mkpasswd_pbkdf2_SOURCES): New variable. - (grub_mkpasswd_pbkdf2_CFLAGS): Likewise. - Include conf/gcry.rmk. - * include/grub/auth.h: Rewritten. - * include/grub/crypto.h: New file. - * include/grub/disk.h (grub_disk_dev_id): Add GRUB_DISK_DEVICE_LUKS_ID. - * include/grub/normal.h (read_crypto_list): New prototype. - * lib/crypto.c: New file. - * lib/libgcrypt_wrap/cipher_wrap.h: Likewise. - * lib/pbkdf2.c: Likewise. - * normal/auth.c (grub_auth_strcmp): Removed. - (grub_iswordseparator): Likewise. - (grub_auth_strword): Likewise. - (is_authenticated): Use grub_strword. - (grub_auth_check_authentication): Use grub_strcmp, grub_password_get - and grub_strword. Pass entered password to authentication callback. - * normal/crypto.c: New file. - * normal/main.c: Call read_crypto_list. - * util/grub-mkpasswd-pbkdf2.c: New file. - * util/import_gcry.py: Generate crypto.lst. Add hash blocklen. - -2010-01-06 Vladimir Serbinenko - - Fix descent and ascent calculation. - - * util/grub-mkfont.c (grub_font_info): New fields 'asce' and 'max_y'. - (options): New option "asce". - (usage): Likewise. - (add_char): Ignore invalid glyphs for descent calculation. - Calculate ascent from actual content. - (print_glyphs): Use 'asce'. - (write_font): Likewise. Allow ascent override. - (main): Handle "asce" option. - -2010-01-06 Carles Pina i Estany - - * kern/err.c: Include `'. - (grub_print_error): Add full stop. Gettextizze. - * loader/i386/bsd.c (grub_netbsd_boot): Change grub_error description. - (grub_bsd_load_elf): Capitalise ELF. - (grub_cmd_freebsd_loadenv): Add `s' in error string. - (grub_cmd_freebsd_module): Likewise. - (grub_cmd_freebsd_module_elf): Likewise. - * loader/i386/bsdXX.c (SUFFIX): Capitalise ELF. - -2010-01-06 Carles Pina i Estany - - * commands/search.c (GRUB_MOD_INIT): Use HELP_MESSAGE. - * commands/search_file.c (HELP_MESSAGE): New macro. - * commands/search_label.c (HELP_MESSAGE): Likewise. - * commands/search_uuid.c (HELP_MESSAGE): Likewise. - * po/POTFILES: Add `commands/search_file.c', - `commands/search_label.c', `commands_uuid.c'. Remove duplicate - `commands/search.c'. - -2010-01-05 Robert Millan - - * config.rpath: Update from Gnulib. - -2010-01-05 Yves Blusseau - - * commands/acpi.c (grub_acpi_create_ebda): fix incorrect message. - -2010-01-05 Yves Blusseau - - * util/sparc64/ieee1275/grub-mkimage.c (main): Typo fix. - -2010-01-05 Colin Watson - - * util/mkisofs/write.c (padblock_write): Switch size and nmemb - arguments to fread so that we get a return value in bytes, rather - than something that will normally be rounded down to 0. - Adjust error handling to avoid producing garbage when size_t is not - the same size as long long. - -2010-01-05 Colin Watson - - * util/mkisofs/write.c (padblock_write): Check return value of - fread. - -2010-01-05 Robert Millan - - Remove grub-mkfloppy. Images produced by grub-mkrescue are valid - floppy images now. - - * util/i386/pc/grub-mkfloppy.in: Remove. Update all users. - -2010-01-04 Robert Millan - - * disk/i386/pc/biosdisk.c (grub_biosdisk_rw): Use ALIGN_UP macro - instead of manual alignment. - * kern/disk.c (grub_disk_read): Remove grub_dprintf call (excessively - verbose). Avoid attempts to read past end of the device - (grub_disk_adjust_range() guarantees that we can read `size' bytes, - but GRUB_DISK_CACHE_SIZE may exceed that). - -2010-01-04 Robert Millan - - * commands/crc.c (grub_cmd_crc): Abort on read errors. - * fs/iso9660.c (grub_iso9660_read): Check for read error and pass - it to upper layer. - -2010-01-04 Vladimir Serbinenko - - * include/grub/efi/api.h (GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE): - New constant. - (grub_efi_piwg_device_path): New structure - (grub_efi_piwg_device_path_t): New type. - * loader/efi/appleloader.c (piwg_full_device_path): New structure. - (devpath_1): Transform to a structure. All users updated. - (devpath_2): Likewise. - (devpath_3): Likewise. - (devpath_4): Likewise. - (devpath_5): Likewise. - -2010-01-04 Vladimir Serbinenko - - * loader/efi/appleloader.c: Restored. Update all users. - -2010-01-03 Robert Millan - - * boot/i386/pc/diskboot.S: Fix inaccurate comment. - - * util/i386/pc/grub-setup.c: Include `'. - (struct boot_blocklist): Move from here ... - * include/grub/i386/pc/boot.h [ASM_FILE] - (struct grub_boot_blocklist): ... to here. Update all users. - (setup): Only initialize `start' member of `first_block' - structure. Add assert() calls to verify the other members. - - * util/i386/pc/grub-mkimage.c: Include `'. - (generate_image): Fix broken blocklist length initialization. - Add assert() call to verify blocklist `segment' field. - -2010-01-03 Robert Millan - - * loader/efi/appleloader.c: Remove. Update all users. - -2010-01-03 Robert Millan - - * boot/i386/pc/boot.S: Update copyright year. - * boot/i386/pc/cdboot.S: Likewise. - * boot/i386/pc/diskboot.S: Likewise. - * boot/i386/pc/lnxboot.S: Likewise. - * boot/i386/pc/pxeboot.S: Likewise. - * bus/pci.c: Likewise. - * commands/cmp.c: Likewise. - * commands/help.c: Likewise. - * commands/hexdump.c: Likewise. - * commands/i386/pc/halt.c: Likewise. - * commands/i386/pc/play.c: Likewise. - * commands/i386/pc/vbeinfo.c: Likewise. - * commands/ls.c: Likewise. - * commands/test.c: Likewise. - * disk/dmraid_nvidia.c: Likewise. - * disk/i386/pc/biosdisk.c: Likewise. - * disk/ieee1275/nand.c: Likewise. - * disk/ieee1275/ofdisk.c: Likewise. - * disk/lvm.c: Likewise. - * disk/raid.c: Likewise. - * disk/raid6_recover.c: Likewise. - * disk/scsi.c: Likewise. - * fs/affs.c: Likewise. - * fs/cpio.c: Likewise. - * fs/ext2.c: Likewise. - * fs/hfs.c: Likewise. - * fs/iso9660.c: Likewise. - * fs/ntfs.c: Likewise. - * fs/sfs.c: Likewise. - * fs/udf.c: Likewise. - * fs/ufs.c: Likewise. - * fs/xfs.c: Likewise. - * gencmdlist.sh: Likewise. - * genmk.rb: Likewise. - * include/grub/disk.h: Likewise. - * include/grub/efi/api.h: Likewise. - * include/grub/efi/efi.h: Likewise. - * include/grub/efi/pe32.h: Likewise. - * include/grub/elf.h: Likewise. - * include/grub/fs.h: Likewise. - * include/grub/i386/at_keyboard.h: Likewise. - * include/grub/i386/pc/memory.h: Likewise. - * include/grub/i386/pc/vbe.h: Likewise. - * include/grub/i386/pci.h: Likewise. - * include/grub/i386/tsc.h: Likewise. - * include/grub/ieee1275/ieee1275.h: Likewise. - * include/grub/ntfs.h: Likewise. - * include/grub/sparc64/ieee1275/ieee1275.h: Likewise. - * include/grub/sparc64/libgcc.h: Likewise. - * include/grub/symbol.h: Likewise. - * include/grub/types.h: Likewise. - * include/multiboot2.h: Likewise. - * io/gzio.c: Likewise. - * kern/device.c: Likewise. - * kern/disk.c: Likewise. - * kern/efi/efi.c: Likewise. - * kern/efi/mm.c: Likewise. - * kern/elf.c: Likewise. - * kern/file.c: Likewise. - * kern/i386/dl.c: Likewise. - * kern/i386/pc/init.c: Likewise. - * kern/i386/pc/startup.S: Likewise. - * kern/ieee1275/ieee1275.c: Likewise. - * kern/ieee1275/init.c: Likewise. - * kern/main.c: Likewise. - * kern/mm.c: Likewise. - * kern/powerpc/dl.c: Likewise. - * kern/sparc64/dl.c: Likewise. - * kern/x86_64/dl.c: Likewise. - * lib/hexdump.c: Likewise. - * loader/efi/appleloader.c: Likewise. - * loader/i386/ieee1275/linux.c: Likewise. - * loader/i386/pc/chainloader.c: Likewise. - * loader/i386/pc/linux.c: Likewise. - * loader/i386/pc/multiboot2.c: Likewise. - * loader/ieee1275/multiboot2.c: Likewise. - * loader/multiboot2.c: Likewise. - * loader/multiboot_loader.c: Likewise. - * loader/powerpc/ieee1275/linux.c: Likewise. - * normal/completion.c: Likewise. - * normal/menu_entry.c: Likewise. - * partmap/apple.c: Likewise. - * util/grub.d/10_hurd.in: Likewise. - * util/hostfs.c: Likewise. - * video/readers/png.c: Likewise. - -2010-01-03 Colin Watson - - * include/grub/misc.h (GNUC_PREREQ): New macro. - (ATTRIBUTE_ERROR): New macro. - * include/grub/list.h (grub_bad_type_cast_real): Use - ATTRIBUTE_ERROR. - -2010-01-03 Carles Pina i Estany - - * normal/menu_text.c (print_message): Change messages. - -2010-01-03 Carles Pina i Estany - - * normal/menu_entry.c (store_completion): Gettextizze. - -2010-01-03 Carles Pina i Estany - - * kern/env.c (grub_env_unset): Set the variable to "" if has hooks. - -2010-01-03 Carles Pina i Estany - - * po/POTFILES: Sort correctly. - -2010-01-03 Carles Pina i Estany - - * commands/acpi.c (GRUB_MOD_INIT): Capitalise some words from help. - * commands/efi/loadbios.c (GRUB_MOD_INIT): Capitalise BIOS. - * commands/i386/pc/drivemap.c (GRUB_MOD_INIT): Remove space. Add - full stop. - * commands/loadenv.c (GRUB_MOD_INIT): Remove command name from - summary. Gettextizze the strings. - * commands/probe.c (grub_cmd_probe): Capitalise UUID and FS. - * commands/xnu_uuid.c (GRUB_MOD_INIT): Capitalise XNU. - * disk/loopback.c (grub_arg_options): Capitalise first letter. Add - full stop. - (GRUB_MOD_INIT): Remove command name from summary. - * hello/hello.c (GRUD_MOT_INIT): Add missing full stop. Improve the - summary. - * loader/i386/bsd.c (grub_arg_option): Capitalise CDROM. - * term/i386/pc/serial.c (options): Add full stops. - (GRUB_MOD_INIT): Remove command name from the summary. - -2010-01-03 Carles Pina i Estany - - * commands/acpi.c: Gettextizze help strings and/or options. Include - `grub/i18n.h' if needed. - * commands/blocklist.c: Likewise. - * commands/boot.c: Likewise. - * commands/cat.c: Likewise. - * commands/cmp.c: Likewise. - * commands/configfile.c: Likewise. - * commands/crc.c: Likewise. - * commands/date.c: Likewise. - * commands/echo.c: Likewise. - * commands/efi/fixvideo.c: Likewise. - * commands/efi/loadbios.c: Likewise. - * commands/gptsync.c: Likewise. - * commands/halt.c: Likewise. - * commands/handler.c: Likewise. - * commands/hdparm.c: Likewise. - * commands/hexdump.c: Likewise. - * commands/i386/cpuid.c: Likewise. - * commands/i386/pc/drivemap.c: Likewise. - * commands/i386/pc/halt.c: Likewise. - * commands/i386/pc/pxecmd.c: Likewise. - * commands/i386/pc/vbeinfo.c: Likewise. - * commands/i386/pc/vbetest.c: Likewise. - * commands/ieee1275/suspend.c: Likewise. - * commands/keystatus.c: Likewise. - * commands/loadenv.c: Likewise. - * commands/ls.c: Likewise. - * commands/lsmmap.c: Likewise. - * commands/lspci.c: Likewise. - * commands/memrw.c: Likewise. - * commands/minicmd.c: Likewise. - * commands/parttool.c: Likewise. - * commands/password.c: Likewise. - * commands/probe.c: Likewise. - * commands/read.c: Likewise. - * commands/reboot.c: Likewise. - * commands/search.c: Likewise. - * commands/sleep.c: Likewise. - * commands/test.c: Likewise. - * commands/true.c: Likewise. - * commands/usbtest.c: Likewise. - * commands/videotest.c: Likewise. - * commands/xnu_uuid.c: Likewise. - * disk/loopback.c: Likewise. - * hello/hello.c: Likewise. - * loader/i386/bsd.c: Likewise. - * term/i386/pc/serial.c: Likewise. - * po/POTFILES: Add new files. - -2010-01-02 Colin Watson - - * term/i386/pc/at_keyboard.c - (keyboard_controller_wait_untill_ready): Rename to ... - (keyboard_controller_wait_until_ready): ... this. Update all users. - -2010-01-01 Carles Pina i Estany - - * commands/help.c: Include `grub/mm.h' and `grub/normal.h'. - (grub_cmd_help): Print the cmd->name before the cmd->summary. Cut the - string using string width. - * normal/menu_text.c (grub_print_message_indented): Use - grub_print_spaces and not print_spaces. - (print_timeout): Likewise. - (print_spaces): Move to... - * include/grub/term.h: ... here. Change the name to grub_print_spaces. - -2010-01-01 Robert Millan - - Import from Gnulib. - - * gnulib/getdelim.c: New file. - * gnulib/getline.c: Likewise. - -2009-12-31 BVK Chaitanya - - * include/grub/list.h (grub_assert_fail): Removed. - (grub_bad_type_cast_real): New function. - (grub_bad_type_cast): New macro. - (GRUB_AS_LIST): Use grub_bad_type_cast. - (GRUB_AS_LIST_P): Likewise. - (GRUB_AS_NAMED_LIST): Likewise. - (GRUB_AS_NAMED_LIST_P): Likewise. - (GRUB_AS_PRIO_LIST): Likewise. - (GRUB_AS_PRIO_LIST_P): Likewise. - * include/grub/handler.h (GRUB_AS_HANDLER): Likewise. - -2009-12-29 Vladimir Serbinenko - - * loader/sparc64/ieee1275/linux.c (GRUB_MOD_INIT (linux)): - Fix syntax error. - -2009-12-29 Robert Millan - - * configure.ac: Check for TARGET_CFLAGS initialization before we - initialize it ourselves (sigh). - Move a few modifications to TARGET_CFLAGS to be unconditional - (extra warning flags, loop alignment, i386 CPU extensions, GCC 4.4 - eh_frame) - - * gettext/gettext.c (grub_gettext_delete_list): Add `void' argument. - * term/i386/pc/at_keyboard.c - (keyboard_controller_wait_untill_ready): Likewise. - (keyboard_controller_led): Rename `led_status' paramter to avoid - name conflict. - -2009-12-28 Carles Pina i Estany - - * normal/misc.c (grub_normal_print_device_info): Add spaces and double - quotes. - -2009-12-27 Vladimir Serbinenko - - * kern/parser.c (grub_parser_split_cmdline): Don't dereference NULL. - -2009-12-27 Vladimir Serbinenko - - * normal/menu_text.c (grub_print_message_indented): Prevent - past-the-end-of-array dereference. - -2009-12-27 Vladimir Serbinenko - - * video/readers/jpeg.c (GRUB_MOD_FINI (grub_cmd_jpegtest)): Rename to .. - (GRUB_MOD_FINI (video_reader_jpeg)): ...this - -2009-12-27 Carles Pina i Estany - - * normal/cmdline.c (grub_cmdline_get): Print a space after prompt. - * normal/main.c (grub_normal_read_line): Remove a space from the - default prompt. - -2009-12-27 Carles Pina i Estany - - * loader/i386/efi/linux.c (GRUB_MOD_INIT): Improve command summary. - * loader/i386/ieee1275/linux.c (GRUB_MOD_INIT): Likewise. - * loader/i386/linux.c (GRUB_MOD_INIT): Likewise. - * loader/i386/pc/linux.c (GRUB_MOD_INIT): Likewise. - * loader/powerpc/ieee1275/linux.c (GRUB_MOD_INIT): Likewise. - * loader/sparc64/ieee1275/linux.c (GRUB_MOD_INIT): Likewise. - * loader/xnu.c (GRUB_MOD_INIT): Likewise. - -2009-12-26 Carles Pina i Estany - - * video/readers/jpeg.c (cmd): Declare. - (grub_cmd_jpegtest): Use `grub_command_t' type. - (GRUB_MOD_INIT): Fix arguments passed to `grub_register_command'. - Assign to `cmd'. - (GRUB_MOD_FINI): Use `cmd' to unregister. - * video/readers/png.c (cmd): Declare. - (grub_cmd_pngtest): Use `grub_command_t' type. - (GRUB_MOD_INIT): Fix arguments passed to `grub_register_command'. - Assign to `cmd'. - (GRUB_MOD_FINI): Use `cmd' to unregister. - * video/readers/tga.c (cmd): Declare. - (grub_cmd_tgatest): Use `grub_command_t' type. - (GRUB_MOD_INIT): Fix arguments passed to `grub_register_command'. - Assign to `cmd'. - (GRUB_MOD_FINI): Use `cmd' to unregister. - -2009-12-26 Carles Pina i Estany - - * efiemu/main.c (GRUB_MOD_INIT): Fix capitalizations and/or full - stops. - * kern/corecmd.c (grub_register_core_commands): Likewise. - * loader/efi/chainloader.c (GRUB_MOD_INIT): Likewise. - * loader/i386/bsd.c (GRUB_MOD_INIT): Likewise. - * loader/i386/efi/linux.c (GRUB_MOD_INIT): Likewise. - * loader/i386/ieee1275/linux.c (GRUB_MOD_INIT): Likewise. - * loader/i386/linux.c (GRUB_MOD_INIT): Likewise. - * loader/i386/pc/chainloader.c (GRUB_MOD_INIT): Likewise. - * loader/i386/pc/linux.c (GRUB_MOD_INIT): Likewise. - * loader/multiboot_loader.c (GRUB_MOD_INIT): Likewise. - * loader/powerpc/ieee1275/linux.c (GRUB_MOD_INIT): Likewise. - * loader/sparc64/ieee1275/linux.c (GRUB_MOD_INIT): Likewise. - * loader/xnu.c (GRUB_MOD_INIT): Likewise. - * mmap/mmap.c (GRUB_MOD_INIT): Likewise. - * normal/handler.c (insert_handler): Likewise. - * normal/main.c (GRUB_MOD_INIT): Likewise. - * term/gfxterm.c (GRUB_MOD_INIT): Likewise. - -2009-12-26 Carles Pina i Estany - - * commands/help.c (grub_cmd_help): Print the command name before the - summary. - (GRUB_MOD_INIT): Remove command name from the summary. - * kern/command.c (GRUB_MOD_INIT): If summary is null assign an empty - string as summary. - * lib/arg.c (find_long): Print the command name before the summary. - * commands/acpi.c (GRUB_MOD_INIT): Remove command name from the - summary. - * commands/blocklist.c (GRUB_MOD_INIT): Likewise. - * commands/cat.c (GRUB_MOD_INIT): Likewise. - * commands/cmp.c (GRUB_MOD_INIT): Likewise. - * commands/configfile.c (GRUB_MOD_INIT): Likewise. - * commands/crc.c (GRUB_MOD_INIT): Likewise. - * commands/date.c (GRUB_MOD_INIT): Likewise. - * commands/echo.c (GRUB_MOD_INIT): Likewise. - * commands/efi/loadbios.c (GRUB_MOD_INIT): Likewise. - * commands/gptsync.c (GRUB_MOD_INIT): Likewise. - * commands/handler.c (GRUB_MOD_INIT): Likewise. - * commands/hdparm.c (GRUB_MOD_INIT): Likewise. - * commands/hexdump.c (GRUB_MOD_INIT): Likewise. - * commands/i386/cpuid.c (GRUB_MOD_INIT): Likewise. - * commands/i386/pc/halt.c (GRUB_MOD_INIT): Likewise. - * commands/i386/pc/play.c (GRUB_MOD_INIT): Likewise. - * commands/i386/pc/pxecmd.c (GRUB_MOD_INIT): Likewise. - * commands/keystatus.c (GRUB_MOD_INIT): Likewise. - * commands/loadenv.c (GRUB_MOD_INIT): Likewise. - * commands/ls.c (GRUB_MOD_INIT): Likewise. - * commands/lspci.c (GRUB_MOD_INIT): Likewise. - * commands/memrw.c (GRUB_MOD_INIT): Likewise. - * commands/minicmd.c (GRUB_MOD_INIT): Likewise. - * commands/parttool.c (GRUB_MOD_INIT): Likewise. - * commands/password.c (GRUB_MOD_INIT): Likewise. - * commands/probe.c (GRUB_MOD_INIT): Likewise. - * commands/read.c (GRUB_MOD_INIT): Likewise. - * commands/search.c (GRUB_MOD_INIT): Likewise. - * commands/sleep.c (GRUB_MOD_INIT): Likewise. - * commands/test.c (GRUB_MOD_INIT): Likewise. - * commands/xnu_uuid.c (GRUB_MOD_INIT): Likewise. - * efiemu/main.c (GRUB_MOD_INIT): Likewise. - * font/font_cmd.c (GRUB_MOD_INIT): Likewise. - * gettext/gettext.c (GRUB_MOD_INIT): Likewise. - * kern/corecmd.c (GRUB_MOD_INIT): Likewise. - * lib/arg.c (GRUB_MOD_INIT): Likewise. - * loader/efi/appleloader.c (GRUB_MOD_INIT): Likewise. - * loader/i386/bsd.c (GRUB_MOD_INIT): Likewise. - * loader/xnu.c (GRUB_MOD_INIT): Likewise. - * mmap/mmap.c (GRUB_MOD_INIT): Likewise. - * term/terminfo.c (GRUB_MOD_INIT): Likewise. - * video/readers/jpeg.c (GRUB_MOD_INIT): Likewise. - * video/readers/png.c (GRUB_MOD_INIT): Likewise. - * video/readers/tga.c (GRUB_MOD_INIT): Likewise. - -2009-12-25 Vladimir Serbinenko - - Use search command for preliminar UUID search. - - * commands/search.c: Split into ... - * commands/search_wrap.c: ...this - * commands/search.c: ...and this. - * commands/search_file.c: New file. - * commands/search_label.c: New file. - * commands/search_uuid.c: New file. - * conf/any-emu.rmk (grub_emu_SOURCES): Remove commands/search.c. - Add commands/search_wrap.c, commands/search_file.c, - commands/search_label.c and commands/search_uuid.c. - * conf/common.rmk (pkglib_MODULES): Remove fs_uuid.mod and fs_file.mod. - (search_mod_SOURCES): Set to commands/search_wrap.c. - (pkglib_MODULES): Add search_fs_file.mod, search_fs_uuid.mod and - search_label.mod. - (search_fs_file_mod_SOURCES): New variable. - (search_fs_file_mod_CFLAGS): Likewise. - (search_fs_file_mod_LDFLAGS): Likewise. - (search_label_mod_SOURCES): Likewise. - (search_label_mod_CFLAGS): Likewise. - (search_label_mod_LDFLAGS): Likewise. - (search_fs_uuid_mod_SOURCES): New variable. - (search_fs_uuid_mod_CFLAGS): Likewise. - (search_fs_uuid_mod_LDFLAGS): Likewise. - (fs_file_mod_SOURCES): Removed. - (fs_file_mod_CFLAGS): Likewise. - (fs_file_mod_LDFLAGS): Likewise. - (fs_uuid_mod_SOURCES): Removed. - (fs_uuid_mod_CFLAGS): Likewise. - (fs_uuid_mod_LDFLAGS): Likewise. - * conf/sparc64-ieee1275.rmk (grub_install_SOURCES): - Set to util/grub-install.in. - * disk/fs_file.c: Removed. - * disk/fs_uuid.c: Likewise. - * include/grub/search.h: New file. - * util/grub-install.in: Handle sparc64. - Create and use load.cfg. - * util/sparc64/ieee1275/grub-install.in: Removed. - -2009-12-25 Vladimir Serbinenko - - * kern/i386/pc/startup.S (grub_biosdisk_get_diskinfo_int13_extensions): - Ignore return status if CF is cleared. - (grub_biosdisk_get_diskinfo_standard): Likewise. - -2009-12-25 Robert Millan - - * term/i386/pc/at_keyboard.c - (keyboard_controller_wait_untill_ready): New function. - (grub_keyboard_controller_write, grub_keyboard_controller_read) - (keyboard_controller_led): Use keyboard_controller_wait_untill_ready() - for keyboard polling, rather than duplicate the same loop. This - saves a few bytes in code size. - -2009-12-25 Vladimir Serbinenko - - Support for (pxe[:server[:gateway]]) syntax and - use environment variable for PXE. - - * commands/i386/pc/pxecmd.c (options): Removed. - (print_ip): Removed. - (grub_cmd_pxe): Removed - (grub_cmd_pxe_unload): New function. - * fs/i386/pc/pxe.c (grub_pxe_disk_data): New structure. - (grub_pxe_your_ip): Made static. - (grub_pxe_default_server_ip): Likewise. - (grub_pxe_default_gateway_ip): Likewise. - (grub_pxe_blksize): Likewise. - (parse_ip): New function. - (grub_pxe_open): Support server and gateway specification. - (grub_pxe_close): Free disk->data. - (grub_pxefs_open): Use disk->data. - (grub_pxefs_read): Likewise. - (grub_env_write_readonly): New function. - (set_mac_env): Likewise. - (set_env_limn_ro): Likewise. - (parse_dhcp_vendor): Likewise. - (grub_pxe_detect): Set the environment variables. - (set_ip_env): New function. - (write_ip_env): Likewise. - (grub_env_write_pxe_default_server): Likewise. - (grub_env_write_pxe_default_gateway): Likewise. - (grub_env_write_pxe_blocksize): Likewise. - (GRUB_MOD_INIT(pxe)): Set environment variables. - * include/grub/i386/pc/pxe.h (grub_pxe_mac_addr): Rename to ... - (grub_pxe_mac_addr_t): ... this. All users updated. - (grub_pxe_your_ip): Removed. - (grub_pxe_server_ip): Likewise. - (grub_pxe_gateway_ip): Likewise. - (grub_pxe_blksize): Likewise. - -2009-12-25 Carles Pina i Estany - - * commands/help.c: Include `'. - (grub_cmd_help): Gettextizze. - (GRUB_MOD_INIT): Likewise. - * commands/i386/pc/play.c: Include `'. - (GRUB_MOD_INIT): Gettextizze. - * commands/search.c: Include `'. - (options): Gettextizze. - (GRUB_MOD_INIT): Gettextizze. - * lib/arg.c: Include `'. - (help_options): Gettextizze. - (find_long): Likewise. - (grub_arg_show_help): Likewise. - * normal/dyncmd.c: Include `'. - (read_command_list): Gettextizze. - * po/POTFILES: Add `commands/i386/pc/play.c', `commands/search.c', - `commands/help.c', `lib/arg.c' and `normal/dyncmd.c'. - -2009-12-25 Robert Millan - - * include/grub/i386/at_keyboard.h (NUM_LOCK, SCROLL_LOCK): New macros. - * term/i386/pc/at_keyboard.c (KEYBOARD_STATUS_NUM_LOCK) - (KEYBOARD_LED_SCROLL, KEYBOARD_LED_NUM, KEYBOARD_LED_CAPS): New macros. - (led_status): New variable. - (keyboard_controller_led): New function. - (grub_at_keyboard_getkey_noblock): Handle num lock and scroll lock, - update led status for caps lock, num lock and scroll lock. - -2009-12-25 Felix Zielcke - - * util/hostdisk.c (open_device): Fix a comment. - -2009-12-24 Robert Millan - - * util/grub-install.in (host_os): New variable. - * util/i386/efi/grub-install.in (host_os): Likewise. - -2009-12-24 Robert Millan - - * util/mkisofs/write.c (padblock_write): Abort when given an - excedingly large embed image, instead of silently truncating it. - -2009-12-24 Robert Millan - - * include/multiboot.h: Indentation fixes. - -2009-12-24 Robert Millan - - * include/multiboot.h (struct multiboot_aout_symbol_table) - (struct multiboot_elf_section_header_table): New structure - declarations (stolen from GRUB Legacy). - (struct multiboot_info): Replace opaque `syms' with a.out and ELF - table information. - - (multiboot_aout_symbol_table_t, multiboot_elf_section_header_table_t) - (multiboot_info_t, multiboot_memory_map_t, multiboot_module_t): New - type aliases. - -2009-12-24 Robert Millan - - * include/multiboot.h: Make comments src2texi-friendly. - -2009-12-24 Robert Millan - - For consistency with [multiboot]/docs/boot.S. - - * include/multiboot.h (MULTIBOOT_MAGIC): Rename from this ... - (MULTIBOOT_HEADER_MAGIC): ... to this. Update all users. - (MULTIBOOT_MAGIC2): Rename from this ... - (MULTIBOOT_BOOTLOADER_MAGIC): ... to this. Update all users. - -2009-12-24 Robert Millan - - * include/multiboot.h: Remove `'. - (multiboot_uint16_t, multiboot_uint32_t, multiboot_uint64_t): New - types. Update all users. - -2009-12-25 Carles Pina i Estany - - * commands/efi/loadbios.c: Capitalize acronyms, replace `could not' by - `couldn't' and `can not' by `cannot'. - * commands/i386/pc/drivemap.c: Likewise. - * disk/ata.c: Likewise. - * disk/ieee1275/nand.c: Likewise. - * fs/affs.c: Likewise. - * fs/fat.c: Likewise. - * fs/hfs.c: Likewise. - * fs/hfsplus.c: Likewise. - * fs/iso9660.c: Likewise. - * fs/jfs.c: Likewise. - * fs/minix.c: Likewise. - * fs/reiserfs.c: Likewise. - * fs/sfs.c: Likewise. - * fs/udf.c: Likewise. - * fs/ufs.c: Likewise. - * fs/xfs.c: Likewise. - * loader/powerpc/ieee1275/linux.c: Likewise. - * loader/sparc64/ieee1275/linux.c: Likewise. - * util/grub-probe.c: Likewise. - * util/misc.c: Likewise. - -2009-12-24 Carles Pina i Estany - - * bus/usb/usbhub.c: Fix capitalization, fullstop and newlines in - grub_errno calls. - * commands/acpi.c: Likewise. - * commands/blocklist.c: Likewise. - * commands/efi/loadbios.c: Likewise. - * commands/i386/pc/drivemap.c: Likewise. - * commands/loadenv.c: Likewise. - * commands/memrw.c: Likewise. - * commands/password.c: Likewise. - * commands/videotest.c: Likewise. - * disk/ata.c: Likewise. - * disk/ata_pthru.c: Likewise. - * disk/dmraid_nvidia.c: Likewise. - * disk/ieee1275/nand.c: Likewise. - * disk/ieee1275/ofdisk.c: Likewise. - * disk/loopback.c: Likewise. - * disk/lvm.c: Likewise. - * disk/mdraid_linux.c: Likewise. - * disk/raid.c: Likewise. - * disk/raid6_recover.c: Likewise. - * disk/scsi.c: Likewise. - * efiemu/main.c: Likewise. - * efiemu/mm.c: Likewise. - * efiemu/pnvram.c: Likewise. - * efiemu/symbols.c: Likewise. - * font/font.c: Likewise. - * fs/cpio.c: Likewise. - * fs/hfsplus.c: Likewise. - * fs/iso9660.c: Likewise. - * fs/jfs.c: Likewise. - * fs/minix.c: Likewise. - * fs/ntfs.c: Likewise. - * fs/ntfscomp.c: Likewise. - * fs/reiserfs.c: Likewise. - * fs/ufs.c: Likewise. - * fs/xfs.c: Likewise. - * gettext/gettext.c: Likewise. - * include/grub/auth.h: Likewise. - * kern/elf.c: Likewise. - * kern/file.c: Likewise. - * kern/ieee1275/init.c: Likewise. - * kern/ieee1275/mmap.c: Likewise. - * kern/ieee1275/openfw.c: Likewise. - * kern/powerpc/dl.c: Likewise. - * kern/sparc64/dl.c: Likewise. - * lib/arg.c: Likewise. - * loader/i386/bsd.c: Likewise. - * loader/i386/bsdXX.c: Likewise. - * loader/i386/efi/linux.c: Likewise. - * loader/i386/efi/xnu.c: Likewise. - * loader/i386/ieee1275/linux.c: Likewise. - * loader/i386/linux.c: Likewise. - * loader/i386/multiboot.c: Likewise. - * loader/i386/pc/linux.c: Likewise. - * loader/i386/pc/multiboot2.c: Likewise. - * loader/i386/xnu.c: Likewise. - * loader/ieee1275/multiboot2.c: Likewise. - * loader/macho.c: Likewise. - * loader/machoXX.c: Likewise. - * loader/multiboot2.c: Likewise. - * loader/multiboot_loader.c: Likewise. - * loader/powerpc/ieee1275/linux.c: Likewise. - * loader/sparc64/ieee1275/linux.c: Likewise. - * loader/xnu.c: Likewise. - * loader/xnu_resume.c: Likewise. - * mmap/i386/pc/mmap.c: Likewise. - * normal/menu_viewer.c: Likewise. - * partmap/acorn.c: Likewise. - * partmap/amiga.c: Likewise. - * partmap/apple.c: Likewise. - * script/lexer.c: Likewise. - * term/gfxterm.c: Likewise. - * term/i386/pc/serial.c: Likewise. - * term/i386/pc/vga.c: Likewise. - * term/ieee1275/ofconsole.c: Likewise. - * term/terminfo.c: Likewise. - * video/bitmap.c: Likewise. - * video/efi_gop.c: Likewise. - * video/efi_uga.c: Likewise. - * video/fb/video_fb.c: Likewise. - * video/i386/pc/vbe.c: Likewise. - * video/readers/tga.c: Likewise. - * video/video.c: Likewise. - -2009-12-23 Felix Zielcke - - * commands/i386/pc/drivemap.c: Remove all trailing whitespace. - * commands/lspci.c: Likewise. - * commands/probe.c: Likewise. - * commands/xnu_uuid.c: Likewise. - * conf/i386-coreboot.rmk: Likewise. - * conf/i386-efi.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - * fs/i386/pc/pxe.c: Likewise. - * gettext/gettext.c: Likewise. - * include/grub/efi/graphics_output.h: Likewise. - * include/grub/i386/pc/memory.h: Likewise. - * kern/env.c: Likewise. - * kern/i386/qemu/startup.S: Likewise. - * lib/i386/pc/biosnum.c: Likewise. - * lib/i386/relocator.c: Likewise. - * lib/i386/relocator_asm.S: Likewise. - * lib/relocator.c: Likewise. - * loader/i386/bsd.c: Likewise. - * loader/i386/multiboot.c: Likewise. - * loader/i386/pc/chainloader.c: Likewise. - * loader/i386/xnu.c: Likewise. - * loader/xnu.c: Likewise. - * normal/main.c: Likewise. - * normal/menu_text.c: Likewise. - * util/getroot.c: Likewise. - * util/grub-mkconfig_lib.in: Likewise. - * util/grub.d/00_header.in: Likewise. - * util/i386/pc/grub-mkimage.c: Likewise. - * util/mkisofs/eltorito.c: Likewise. - * util/mkisofs/exclude.h: Likewise. - * util/mkisofs/hash.c: Likewise. - * util/mkisofs/iso9660.h: Likewise. - * util/mkisofs/joliet.c: Likewise. - * util/mkisofs/mkisofs.c: Likewise. - * util/mkisofs/mkisofs.h: Likewise. - * util/mkisofs/multi.c: Likewise. - * util/mkisofs/name.c: Likewise. - * util/mkisofs/rock.c: Likewise. - * util/mkisofs/tree.c: Likewise. - * util/mkisofs/write.c: Likewise. - * video/efi_gop.c: Likewise. - -2009-12-23 Vladimir Serbinenko - - * video/efi_gop.c (grub_video_gop_get_bitmask): Fix off-by-one in mask - size counting. - -2009-12-22 Felix Zielcke - - * util/grub-mkrescue.in (pkglib_DATA): Set to @pkglib_DATA@. - * genmk.rb (class SCRIPT): Modify the target file instead of source. - -2009-12-22 Vladimir Serbinenko - - * commands/memrw.c (grub_cmd_write): Support for mask parameter. - (GRUB_MOD_INIT(memrw)): Update help line. - -2009-12-22 Vladimir Serbinenko - - * commands/memrw.c (cmd_read_byte, cmd_read_word, cmd_read_dword): - Use grub_extcmd_t. All users updated. - (options): New variable. - (grub_cmd_read): Restructure for readability. Support "-v" option. - (grub_cmd_write): Restructure for readability. - -2009-12-22 Felix Zielcke - - * genmk.rb (class SCRIPT): Prepend #{src} path with $(srcdir). - -2009-12-22 Felix Zielcke - - * genmk.rb (class SCRIPT): Use sed to substitute @pkglib_DATA@ - with the actual contents of the correspondending make variable. - * util/grub-mkrescue.in (pkglib_DATA): New variable. - (process_input_dir): Copy all $pkglib_DATA files instead of explicitly - specifying `*.lst' and `efiemu??.o' - -2009-12-22 Felix Zielcke - - * util/grub.d/30_os-prober.in (osx_entry): Add round brackets - after function name. - Noticed by Rene Engelhard . - -2009-12-22 Vladimir Serbinenko - - * commands/lspci.c (grub_pci_classes): Add "USB Controller". - (options): New variable. - (iospace): Likewise. - (grub_lspci_iter): List IO spaces if "-i" was given. - (grub_cmd_lspci): Parse options. - (GRUB_MOD_INIT(lspci)): Use extcmd. - (GRUB_MOD_FINI(lspci)): Likewise. - -2009-12-22 Felix Zielcke - - * util/grub.d/30_os-prober.in (osx_entry): Remove non POSIX compliant - `function' keyword. - Patch by Tony Mancill . - -2009-12-22 Vladimir Serbinenko - - * bus/usb/uhci.c (grub_uhci_transfer): Set a limit transaction time. - (grub_uhci_portstatus): Likewise. - (grub_uhci_portstatus): Add necessary delay. - * bus/usb/usbhub.c (grub_usb_hub_add_dev): Fix loop-break condition. - -2009-12-21 Carles Pina i Estany - - * commands/acpi.c (options): Fix capitalizations and/or full stops. - (GRUB_MOD_INIT): Likewise. - * commands/boot.c (GRUB_MOD_INIT): Likewise. - * commands/cmp.c (grub_cmd_cmp): Improve the help message. - * commands/echo.c (options): Fix capitalizations and/or full stops. - * commands/efi/loadbios.c (enable_rom_area): Likewise. - (enable_rom_area): Likewise. - (GRUB_MOD_INIT): Likewise. - * commands/gptsync.c (GRUB_MOD_INIT): Likewise. - * commands/halt.c (GRUB_MOD_INIT): Improve the help message. - * commands/handler.c (GRUB_MOD_INIT): Likewise. - * commands/hdparm.c (options): Fix capitalizations and/or full stops. - * commands/hexdump.c (options): Likewise. - * commands/i386/cpuid.c (options): Likewise. - (GRUB_MOD_INIT): Likewise. - * commands/i386/pc/drivemap.c (options): Likewise. - (GRUB_MOD_INIT): Likewise. - * commands/i386/pc/halt (options): Likewise. - (GRUB_MOD_INIT): Likewise. - * commands/i386/pc/play.c (GRUB_MOD_INIT): Likewise. - * commands/i386/pc/pxecmd.c (options): Likewise. - * commands/i386/pc/vbetest.c (GRUB_MOD_INIT): Likewise. - * commands/ieee1275/suspend.c (GRUB_MOD_INIT): Likewise. - * commands/keystatus.c (options): Likewise. - (GRUB_MOD_INIT): Likewise. - * commands/loadenv.c (options): Likewise. - * commands/ls.c (options): Likewise. - * commands/lspci.c (GRUB_MOD_INIT): Likewise. - * commands/memrw.c (GRUB_MOD_INIT): Likewise. - * commands/minicmd.c (GRUB_MOD_INIT): Likewise. - * commands/parttool.c (helpmsg): Likewise. - * commands/probe.c (options): Likewise. - * commands/read.c (GRUB_MOD_INIT): Likewise. - * commands/reboot.c (GRUB_MOD_INIT): Likewise. - * commands/search.c (options): Likewise. - * commands/sleep.c (options): Likewise. - * commands/test.c (GRUB_MOD_INIT): Likewise. - * commands/true.c (GRUB_MOD_INIT): Likewise. - * commands/usbtest.c (GRUB_MOD_INIT): Likewise. - * commands/videotest.c (GRUB_MOD_INIT): Likewise. - * lib/arg.c (help_options): Likewise. - * Makefile.in ($(srcdir)/po/$(PACKAGE).pot): Pass -ctranslate to - `$(XGETTEXT)'. - * po/POTFILES: Add `commands/loadenv.c'. - -2009-12-21 Felix Zielcke - - * util/grub-mkrescue.in (process_input_dir): Copy `*.lst' files - instead of specifying them explicit. - -2009-12-21 Robert Millan - - * NEWS: Add grub-probe support for GNU/Hurd. - -2009-12-21 Robert Millan - - * NEWS: gettext was added after 1.97. - -2009-12-21 Robert Millan - - * util/mkisofs/msdos_partition.h: New file (based on - include/grub/msdos_partition.h). - * util/mkisofs/mkisofs.c (use_protective_msdos_label): New variable. - (OPTION_PROTECTIVE_MSDOS_LABEL): New macro. - (ld_options, main): Recognize --protective-msdos-label. - * util/mkisofs/mkisofs.h (use_protective_msdos_label): New declaration. - * util/mkisofs/write.c: Include `"msdos_partition.h"'. - (padblock_write): If `use_protective_msdos_label' is set, patch a - protective DOS-style label in the output image. - - * util/grub-mkrescue.in: Use --protective-msdos-label. - -2009-12-21 Robert Millan - - * util/grub-mkrescue.in: Do not zero-pad image for BIOS-based disk - boot. - -2009-12-21 Robert Millan - - * util/mkisofs/mkisofs.c (use_embedded_boot, boot_image_embed): New - variables. - (ld_options, main): Recognize `--embedded-boot'. - * util/mkisofs/mkisofs.h (use_embedded_boot, boot_image_embed): New - declarations. - * util/mkisofs/write.c (PADBLOCK_SIZE): New variable. - (padblock_size): Use `PADBLOCK_SIZE' instead of hardcoding 16. - (padblock_write): Likewise. Rewrite to support embedded boot image. - - * util/grub-mkrescue.in: When building i386-pc images, embed core.img - for BIOS-based disk boot instead of only ElTorito. - -2009-12-21 Robert Millan - - * util/grub-mkrescue.in: Remove `configfile' and `sh' from i386-pc - build (not needed for bootstrap). - -2009-12-21 Robert Millan - - * util/grub-mkrescue.in: Remove `memdisk', `tar' and `search' modules - from i386-pc build (not needed for bootstrap). - Rewrite a pair of strings. - -2009-12-21 Robert Millan - - * normal/main.c (grub_normal_reader_init): Set left margin back to 3. - -2009-12-21 Vladimir Serbinenko - - * video/i386/pc/vbe.c (grub_video_vbe_fini): Set 'last_set_mode'. - -2009-12-21 Andreas Born - - * kern/env.c (grub_env_context_open): Mark exported variable for - reexport. - -2009-12-21 Andreas Born - - * kern/env.c (grub_env_export): Create nonexistent variables before - exporting. - -2009-12-20 Carles Pina i Estany - - * include/grub/auth.h: Include `'. - (GRUB_GET_PASSWORD): Gettextizze string. - * include/grub/normal.h (STANDARD_MARGIN): New macro, moved from - menu_text.c. - (grub_utf8_to_ucs4_alloc): Fix indentation. - (grub_print_ucs4): Likewise. - (grub_getstringwidth): Likewise. - (print_message_indented): New declaration. - * normal/auth.c: Include `'. - (grub_auth_check_authentication): Gettexttize string. - * normal/cmdline.c: Include `'. - (grub_cmdline_get): Gettextizze. - * normal/color.c: Include `'. - (grub_parse_color_name_pair): Gettexttize strings. - * normal/main.c (grub_normal_reader_init): Cleanup gettexttized - string (use `print_message_indented'). - * normal/menu_text.c (STANDARD_MARGIN): Moved from here to - `include/grub/normal.h'. - (print_message_indented): Renamed to ... - (grub_print_message_indented): ... this. Remove `static' qualifer (now - used in normal/main.c). - (print_message): Use `grub_print_message_indented' instead of - `print_message_indented'. - (print_timeout): Likewise. - * normal/misc.c: Include `' and `'. - (grub_normal_print_device_info): Gettexttize strings. - * po/POTFILES: Add `auth.c', `color.c' and `misc.c'. - -2009-12-20 Vladimir Serbinenko - - * kern/parser.c (grub_parser_split_cmdline): Fix incorrect counting - of arguments. Return number of tokens and not arguments. All users - updated. - -2009-12-20 Vladimir Serbinenko - - * util/i386/pc/grub-setup.c (setup): Don't install on non-GPT, - non-MSDOS paritions. - -2009-12-19 Vladimir Serbinenko - - * include/grub/types.h (UNUSED): Removed since it conflicts with - NetBSD headers. All users changed to direct __attribute__ ((unused)). - Reported by GrĂ©goire Sutre. - -2009-12-19 Carles Pina i Estany - - * include/grub/normal.h (grub_utf8_to_ucs4): New declaration. - (grub_print_ucs4_alloc): Likewise. - (grub_getstringwidth): Likewise. - * normal/main.c (grub_normal_init_page): Gettextize version string. - * normal/menu_text.c (grub_utf8_to_ucs4_alloc): New definition. - (getstringwidth): Renamed to ... - (grub_getstringwidth): ... this. Remove `static' qualifier (now used - in normal/main.c). Use `grub_utf8_to_ucs4_alloc'. - (grub_print_ucs4): Remove `static' qualifer (now used in - normal/main.c). - * po/POTFILES: Add normal/main.c. - -2009-12-19 Carles Pina i Estany - - * normal/menu_text.c (STANDARD_MARGIN): New macro. - (print_message_indented): Add `margin_left' and `margin_right' - parameters. - (print_message): Update `print_message_indented' calls. Adds '\n' to the - strings. - (print_timeout): Use `print_message_indented' to print the message. - Deletes `second_stage' parameter. - (run_menu): Update `print_timeout' calls. - -2009-12-18 Vladimir Serbinenko - - Fix console palette on OpenFirmware. - - * term/ieee1275/ofconsole.c (MAX): Removed. - (colors): Redone based on VGA palette. - (grub_ofconsole_setcolor): Discard brightness bit since only 8 - colors are supported. - (grub_ofconsole_init_output): Use ARRAY_SIZE instead of hardcoded size. - -2009-12-18 Vladimir Serbinenko - - Fix potential EfiEmu double prepare. - - * efiemu/main.c (prepared): New variable - (grub_efiemu_unload): Set prepare to '0'. - (grub_efiemu_prepare): Return if already prepared. Set prepared. - - set_virtual_address_map support. - - * include/grub/efi/efi.h (grub_efi_set_virtual_address_map): New - prototype. - * include/grub/efiemu/efiemu.h (grub_efiemu_write_sym_markers): New - prototype. - (grub_efiemu_crc32): Likewise. - (grub_efiemu_crc64): Likewise. - (grub_efiemu_set_virtual_address_map): Likewise. - * include/grub/autoefi.h (grub_autoefi_exit_boot_services): - New definition. - (grub_autoefi_set_virtual_address_map): Likewise. - * kern/efi/efi.c (grub_efi_set_virtual_address_map): New function. - * loader/i386/xnu.c (grub_xnu_boot): Call set_virtual_address_map. - Restructure flow to accomodate it. - * efiemu/prepare.c (grub_efiemu_prepare): Support set_virtual_address_map. - (grub_efiemu_crc): Recompute CRC32. - * efiemu/runtime/efiemu.c (ptv_relocated): Renamed to ... - (efiemu_ptv_relocated): ... this. Made global. All users updated. - * efiemu/symbols.c (relocated_handle): New variable. - (grub_efiemu_free_syms): Free relocated_handle. - (grub_efiemu_alloc_syms): Allocate relocated_handle. - (grub_efiemu_write_sym_markers): New function. - (grub_efiemu_set_virtual_address_map): Likewise. - - Newer XNU parameters. - - * include/grub/i386/xnu.h (GRUB_XNU_BOOTARGS_VERMINOR): Change to 5. - * include/grub/xnu.h (grub_xnu_extheader): Add nameaddr and namesize. - (grub_xnu_fill_devicetree): New prototype. - (grub_xnu_heap_real_start): New variable. - * loader/xnu.c (get_name_ptr): New function. - (grub_xnu_load_driver): Fill namelen and name. - - 64-bit xnu support. - - * conf/i386-efi.rmk (xnu_mod_SOURCES): Add 'loader/macho32.c' - and 'loader/macho64.c'. - * conf/i386-pc.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - * include/grub/i386/macho.h (grub_macho_thread64): New structure. - * include/grub/xnu.h (grub_xnu_is_64bit): New variable. - * include/grub/macho.h (grub_macho_segment64): New structure. - * include/grub/machoload.h (grub_macho32_size): Renamed from ... - (grub_macho_size32): ... to this. - (grub_macho32_get_entry_point): Renamed from ... - (grub_macho_get_entry_point32): ... to this. - (grub_macho_contains_macho64): New prototype. - (grub_macho_size64): Likewise. - (grub_macho_get_entry_point64): Likewise. - (grub_macho32_load): Renamed from ... - (grub_macho_load32): ... to this. - (grub_macho32_filesize): Renamed from ... - (grub_macho_filesize32): ... to this. - (grub_macho32_readfile): Renamed from ... - (grub_macho_readfile32): ... to this. - (grub_macho_filesize64): New prototype. - (grub_macho_readfile64): Likewise. - (grub_macho_parse32): Likewise. - (grub_macho_parse64): Likewise. - * loader/macho.c: Split into ... - * loader/machoXX.c: ... and this. Replace 32 with XX. - * loader/macho32.c: New file. - * loader/macho64.c: Likewise. - * loader/xnu.c (grub_xnu_is_64bit): New variable. - (grub_cmd_xnu_kernel): Make 32-bit only. - (grub_cmd_xnu_kernel64): New function. - (grub_xnu_load_driver): Support Mach-O 64. - (grub_cmd_xnu_mkext): Likewise. - * util/grub.d/30_os-prober.in (osx_entry): New function. - Generate entries for 64-bit boot too. - - Eliminate ad-hoc tree format in XNU and EfiEmu. - - * efiemu/main.c (grub_efiemu_prepare): Update comment. - * efiemu/pnvram.c: Rewritten to use environment variables. - All users updated. - - Inline utf16_to_utf8. - - * kern/misc.c (grub_utf16_to_utf8): Move from here ... - * include/grub/charset.h (grub_utf16_to_utf8): ... to here. Inlined. - All users updated. - * include/grub/misc.h (grub_utf16_to_utf8): Removed. - - * bus/usb/usb.c (grub_usb_get_string): Move from here ... - * commands/usbtest.c (grub_usb_get_string): ... move here. - (usb_print_str): Fix error handling. - * include/grub/usb.h (grub_usb_get_string): Remove. - - UTF-8 to UTF-16 transformation. - - * conf/common.rmk (pkglib_MODULES): Add charset.mod - (charset_mod_SOURCES): New variable. - (charset_mod_CFLAGS): Likewise. - (charset_mod_LDFLAGS): Likewise. - * include/grub/utf.h: New file. - * lib/utf.c: New file. (Based on grub_utf8_to_ucs4 from kern/misc.c) - - Support for device properties. - - * include/grub/i386/xnu.h (grub_xnu_devprop_header): New structure. - (grub_xnu_devprop_device_header): Likewise. - (grub_xnu_devprop_device_descriptor): Likewise. - (grub_xnu_devprop_add_device): New prototype. - (grub_xnu_devprop_remove_device): Likewise. - (grub_xnu_devprop_remove_property): Likewise. - (grub_xnu_devprop_add_property_utf8): Likewise. - (grub_xnu_devprop_add_property_utf16): Likewise. - (grub_cpu_xnu_init): Likewise. - (grub_cpu_xnu_fini): Likewise. - (grub_cpu_xnu_unload): Likewise. - * loader/i386/xnu.c (grub_xnu_devprop_device_descriptor): New structure. - (property_descriptor): Likewise. - (devices): New variable. - (grub_xnu_devprop_remove_property): New function. - (grub_xnu_devprop_add_device): Likewise. - (grub_xnu_devprop_remove_device): Likewise. - (grub_xnu_devprop_add_property): Likewise. - (grub_xnu_devprop_add_property_utf8): Likewise. - (grub_xnu_devprop_add_property_utf16): Likewise. - (hextoval): Likewise. - (grub_cpu_xnu_fill_devprop): Likewise. - (grub_cmd_devprop_load): Likewise. - (grub_xnu_boot): Call grub_cpu_xnu_fill_devprop, - grub_xnu_fill_devicetree, grub_xnu_fill_devicetree - (cmd_devprop_load): New variable. - (grub_cpu_xnu_init): New function. - (grub_cpu_xnu_fini): Likewise. - * loader/i386/xnu.c (grub_xnu_unload): Call grub_cpu_xnu_unload. - * loader/xnu.c (grub_xnu_parse_devtree): Remove. - (grub_cmd_xnu_devtree): Likewise. - (hextoval): New function. - (unescape): Likewise. - (grub_xnu_fill_devicetree): Likewise. - - * util/grub.d/30_os-prober.in: Load devprop.bin. Don't load devtree.txt. - * util/i386/efi/grub-dumpdevtree: Generate devprop.bin. - -2009-12-18 Vladimir Serbinenko - - Workaround for broken ATI VBE. - - * video/i386/pc/vbe.c (last_set_mode): New variable. - (grub_vbe_set_video_mode): Set 'last_set_mode'. - (grub_vbe_get_video_mode): Use 'last_set_mode' if get_mode fails. - (grub_video_vbe_setup): Don't check for reserved flag. - -2009-12-17 Felix Zielcke - - * gendistlist.sh: Use POSIX compliant `!' instead of `-not' in - the `find' command. - -2009-12-16 Vladimir Serbinenko - - UUID support for HFS. - - * fs/hfs.c (grub_hfs_uuid): New function. - (grub_hfs_fs): New value .uuid. - * include/grub/hfs.h (grub_hfs_sblock): New field 'num_serial'. - -2009-12-14 Felix Zielcke - - Fix a segfault with parsing unknown long options. - - * util/grub-mkrelpath.c (options): Zero terminate it. - -2009-12-13 Carles Pina i Estany - - * include/grub/misc.h (grub_puts): New declaration. - (grub_puts_): Likewise. - * kern/misc.c (grub_puts): New definition. - (grub_puts_): Likewise. - -2009-12-13 Robert Millan - - * util/grub-probe.c (probe): Improve error message. - -2009-12-13 Robert Millan - - * loader/i386/multiboot_elfxx.c - (CONCAT(grub_multiboot_load_elf, XX)): Fix `grub_multiboot_payload_eip' - initialization. - -2009-12-13 Vladimir Serbinenko - - Relocator framework - - * loader/i386/xnu_helper.S: Removed. All users updated. - * conf/i386.rmk (pkglib_MODULES): Add relocator.mod. - (relocator_mod_SOURCES): New variable. - (relocator_mod_CFLAGS): Likewise. - (relocator_mod_LDFLAGS): Likewise. - (relocator_mod_ASFLAGS): Likewise. - * conf/x86_64.rmk: Likewise. - * include/grub/i386/multiboot.h (grub_multiboot_payload_orig): Removed. - (grub_multiboot_payload_entry_offset): Likewise. - (grub_multiboot_forward_relocator): Likewise. - (grub_multiboot_forward_relocator_end): Likewise. - (grub_multiboot_backward_relocator): Likewise. - (grub_multiboot_backward_relocator_end): Likewise. - (grub_multiboot_payload_eip): New variable. - (grub_multiboot_payload_orig): Likewise. - * include/grub/i386/pc/memory.h: Include grub/i386/memory.h. - (GRUB_MEMORY_MACHINE_CR0_PE_ON): Move from here ... - * include/grub/i386/memory.h - (GRUB_MEMORY_CPU_CR0_PE_ON): ... to here - (GRUB_MEMORY_CPU_CR4_PAE_ON): New definition. - (GRUB_MEMORY_CPU_CR0_PAGING_ON): Likewise. - (GRUB_MEMORY_CPU_AMD64_MSR): Likewise. - (GRUB_MEMORY_CPU_AMD64_MSR_ON): Likewise. - * include/grub/i386/relocator.h: New file. - * include/grub/x86_64/relocator.h: Likewise. - * include/grub/i386/xnu.h: Include grub/cpu/relocator.h. - (XNU_RELOCATOR): New macro. - (grub_xnu_launcher_start): Remove. - (grub_xnu_launcher_end): Likewise. - * include/grub/xnu.h (grub_xnu_boot_resume): New prototype. - (grub_xnu_heap_real_start): Remove. - (grub_xnu_heap_start): Change to void *. All users updated. - * kern/i386/realmode.S (real_to_prot): Use GRUB_MEMORY_CPU_CR0_PE_ON. - * lib/i386/relocator.c: New file. - * lib/i386/relocator_asm.S: Likewise. - * lib/i386/relocator_backward.S: Likewise. - * lib/mips/relocator.c: Likewise. - * lib/mips/relocator_asm.S: Likewise. - * lib/relocator.c: Likewise. - * loader/i386/multiboot.c: Include grub/i386/relocator.h. - (entry): Removed. - (playground): Likewise. - (grub_multiboot_payload_orig): New variable. - (grub_multiboot_payload_dest): Likewise. - (grub_multiboot_payload_size): Likewise. - (grub_multiboot_payload_eip): Likewise. - (grub_multiboot_payload_esp): Likewise. - (grub_multiboot_boot): Use grub_relocator32_boot. - (grub_multiboot_unload): Free relocators. - (grub_multiboot): Setup stack. Use relocators. - * loader/i386/multiboot_elfxx.c: Include grub/i386/relocator.h. - (grub_multiboot_load_elfXX): Use relocators. - * loader/i386/multiboot_helper.S (grub_multiboot_payload_orig): Removed. - (grub_multiboot_payload_size): Likewise. - (grub_multiboot_payload_dest): Likewise. - (grub_multiboot_payload_entry_offset): Likewise. - (grub_multiboot_forward_relocator): Likewise. - (grub_multiboot_backward_relocator): Likewise. - (grub_multiboot_real_boot): Likewise. - * loader/i386/xnu.c (grub_xnu_heap_will_be_at): New variable. - (grub_xnu_entry_point): Likewise. - (grub_xnu_arg1): Likewise. - (grub_xnu_stack): Likewise. - (grub_xnu_launch): Removed. - (grub_xnu_boot_resume): New function. - (grub_xnu_boot): Use relocators. - * loader/i386/xnu_helper.S: Removed. - * loader/xnu.c (grub_xnu_heap_start): New variable. - (grub_xnu_heap_size): Likewise. - (grub_xnu_heap_malloc): Use relocators. - * loader/xnu_resume.c (grub_xnu_resume): Use relocators. - -2009-12-13 Vladimir Serbinenko - - * kern/i386/pc/startup.S (multiboot_entry): Setup stack before calling - anything. - -2009-12-13 Carles Pina i Estany - - * script/execute.c (grub_script_execute_cmdline): Set grub_errno to - GRUB_ERR_NONE before calling grub_env_set. - -2009-12-12 Robert Millan - - * gendistlist.sh (EXTRA_DISTFILES): Add `genvideolist.sh'. - * genmk.rb (video): New variable. - (CLEANFILES, VIDEOFILES): Add #{video}. - (#{video}): New target rule. - * genvideolist.sh: New file. - * Makefile.in (pkglib_DATA): Add video.lst. - (video.lst): New target rule. - * util/grub-mkconfig.in: Initialize ${GRUB_VIDEO_BACKEND} using - `video.lst'. - * util/grub.d/30_os-prober.in: Replace `vbe' with - ${GRUB_VIDEO_BACKEND}. - -2009-12-11 Robert Millan - - * THANKS: Add David Miller. - -2009-12-11 Vladimir Serbinenko - - libpciaccess support. - - * Makefile.in (LIBPCIACCESS): New variable. - (enable_grub_emu_pci): Likewise. - * conf/any-emu.rmk (grub_emu_SOURCES) [enable_grub_emu_pci]: Add - util/pci.c and commands/lspci.c. - (grub_emu_LDFLAGS) [enable_grub_emu_pci]: Add $(LIBPCIACCESS). - * configure.ac (grub-emu-pci): New option. - * include/grub/i386/pci.h (grub_pci_device_map_range): New function. - (grub_pci_device_unmap_range): Likewise. - * include/grub/pci.h [GRUB_UTIL]: Include grub/pciutils.h. - (grub_pci_device) [!GRUB_UTIL]: New structure. All users updated. - (grub_pci_address_t) [!GRUB_UTIL]: New type. - (grub_pci_device_t) [!GRUB_UTIL]: Likewise. - (grub_pci_get_bus) [!GRUB_UTIL]: New function. - (grub_pci_get_device) [!GRUB_UTIL]: Likewise. - (grub_pci_get_function) [!GRUB_UTIL]: Likewise. - * include/grub/pciutils.h: New file. - * util/pci.c: Likewise. - -2009-12-11 Felix Zielcke - - * util/misc.c: Don't include twice. - -2009-12-10 Felix Zielcke - - * disk/i386/pc/biosdisk.c (grub_biosdisk_open): Show the disk - name in an error message. - (grub_biosdisk_rw): Likewise. - -2009-12-10 Vladimir Serbinenko - - Eliminate NTFS 4Gib barrier. - - * fs/ntfs.c (read_attr): Use grub_disk_addr_t and grub_size_t. - (read_run_data): Likewise. - (grub_ntfs_read_run_list): Likewise. - (grub_ntfs_read_block): Likewise. - (grub_ntfs_iterate_dir): Likewise. - (read_mft): Likewise. - (read_data): Likewise. - Use COM_LOG_LEN. - * fs/ntfscomp.c (read_block): Cast ctx->target_vcn & 0xF to unsigned - to avoid 64-bit division - * include/grub/ntfs.h (COM_LOG_LEN): New definition. - (grub_ntfs_rlst): Use grub_disk_addr_t. - -2009-12-10 Vladimir Serbinenko - - Eliminate grub-fstest 4Gib barrier. - - * util/grub-fstest.c (skip, leng): Use grub_disk_addr_t. - (read_file): Fix error reporting. - -2009-12-10 Vladimir Serbinenko - - Eliminate hexdump 4Gib barrier. - - * commands/hexdump.c (grub_cmd_hexdump): Use grub_disk_addr_t. - * lib/arg.c (grub_arg_parse): Use grub_strtoull. - -2009-12-10 Vladimir Serbinenko - - * kern/device.c (grub_device_iterate): Ignore errors during first scan. - Fixes amarsh bug. - -2009-12-09 Bruce Dubbs - - Remove miscellaneous files in distclean target. - - * Makefile.in: Remove docs/{grub.info,version.texi,stamp-vti} - -2009-12-09 Colin Watson - - * util/grub-mkconfig_lib.in: Don't set grub_probe or grub_mkrelpath - if they're already set. This resolves the conflict between my - grub-install change on 2009-10-06 and Felix' change on 2009-11-11, - fixing the --grub-probe option again. - * util/sparc64/ieee1275/grub-install.in: Revert the last piece of my - change on 2009-10-06, so that we now once again source - `${libdir}/grub/grub-mkconfig_lib' after options have been parsed. - -2009-12-08 Robert Millan - - * conf/common.rmk [sparc64-ieee1275] (grub_mkdevicemap_SOURCES): Use - `util/ieee1275/ofpath.c' and `util/ieee1275/devicemap.c' instead of - `util/devicemap.c'. - -2009-12-08 Carles Pina i Estany - - * include/grub/misc.h (grub_printf_): New declaration. - * kern/misc.c (grub_printf_): New definition. - * normal/main.c (grub_normal_reader_init): Use `grub_printf_' and `N_' - instead of `grub_printf' and `_'. - * normal/menu_entry.c (store_completion): Likewise. - (run): Likewise. - (grub_menu_entry_run): Likewise. - * normal/menu_text.c (grub_wait_after_message): Likewise. - (notify_booting): Likewise. - (notify_fallback): Likewise. - (notify_execution_failure): Likewise. - -2009-12-07 Colin Watson - - * configure.ac: Check for vasprintf. - * util/misc.c (asprintf): Move allocation from here ... - (vasprintf): ... to here. New function. - (xasprintf): New function. - * include/grub/util/misc.h (vasprintf, xasprintf): Add - prototypes. - * util/getroot.c (grub_util_get_grub_dev): Use xasprintf. - * util/grub-mkfont.c (write_font): Likewise. - * util/grub-probe.c (probe): Likewise. - * util/hostdisk.c (make_device_name): Likewise. - -2009-12-06 David S. Miller - - * disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): Recognize - anything even prefixed with 'cdrom' as a cdrom. - -2009-12-06 Felix Zielcke - - * util/misc.c (make_system_path_relative_to_its_root): Correctly cope with - mount points. - -2009-12-05 Carles Pina i Estany - - * gettext/gettext.c: Include `'. Define grub_gettext_msg, - grub_gettext_msg_list. - (grub_gettext_gettranslation_from_position): Return const char * - and not char *. - (grub_gettext_translate): Add the translated strings into a list, - returns from the list if existing there. - (grub_gettext_init_ext): Add \n at the end of grub_dprintf string. - (grub_gettext_delete_list): Delete the list. - (grub_gettext_env_write_lang): Call grub_gettext_delete_list when - lang environment variable is changed. - (GRUB_MOD_FINI): Call grub_gettext_delete_list. - -2009-12-05 Vladimir Serbinenko - - Rename kernel.mod to kernel.img. - - * conf/i386-efi.rmk (pkglib_MODULES): Change kernel.mod to kernel.img. - (kernel_mod_EXPORTS): Rename to ... - (kernel_img_EXPORTS): ... this. - (kernel_mod_SOURCES): Rename to ... - (kernel_img_SOURCES): ... this. - (kernel_mod_HEADERS): Rename to ... - (kernel_img_HEADERS): ... this. All users updated. - (kernel_mod_CFLAGS): Rename to ... - (kernel_img_CFLAGS): ... this. - (kernel_mod_ASFLAGS): Rename to ... - (kernel_img_ASFLAGS): ... this. - (kernel_mod_LDFLAGS): Rename to ... - (kernel_img_LDFLAGS): ... this. - * conf/x86_64-efi.rmk: Likewise. - * util/i386/efi/grub-mkimage.c (read_kernel_module): Rename to ... - (read_kernel_image): ... this. All users updated. - (read_kernel_image): Read "kernel.img" instead of "kernel.mod". - -2009-12-05 Carles Pina i Estany - - * normal/menu_text.c (grub_color_menu_high): Gettexttize string. - (print_spaces): New function. - (grub_print_ucs4): New function. - (getstringwidth): New function. - (print_message_indented): New function. - (print_message): Gettexttize strings using print_message_indented. - (run_menu): Replaces grub_printf by print_spaces and dynamic terminal - width. - (get_entry_number): Gettextize and uses dynamic terminal width. - (notify_booting, notify_fallback, notify_execution_failure): - Gettextize. - * normal/menu_entry.c (store_completion): Cleanup the gettextized - string. - (run): Likewise. - (grub_menu_entry_run): Likewise. - * PO/POTFILES: Add normal/menu_entry.c. - -2009-12-05 Vladimir Serbinenko - - * configure.ac (TARGET_ASFLAGS): Add "-D". - -2009-12-05 Carles Pina i Estany - - * util/grub-install.in: Install gettext .mo files. - * util/grub-mkrescue.in (process_input_dir): Copy gettext .mo files. - -2009-12-05 Carles Pina i Estany - - * gettext/gettext.c (grub_gettext_init_ext): Replace grub_printf with - grub_dprintf. - -2009-12-05 Robert Millan - - * kern/ieee1275/openfw.c (grub_reboot): Disable for i386. The - non-firmware-dependant one in realmode.S takes precedence. - -2009-12-04 Robert Millan - - * commands/halt.c: Replace misc arch-specific headers with - `'. - * commands/reboot.c: Likewise. - * commands/i386/pc/halt.c: Replace `' with - `'. - * conf/i386-coreboot.rmk (kernel_img_HEADERS): Remove `cpu/reboot.h'. - (halt_mod_SOURCES): Move `kern/i386/halt.c' from here ... - (kernel_img_SOURCES): ... to here. - - * include/grub/efi/efi.h (grub_reboot, grub_halt): Remove prototypes. - * include/grub/i386/pc/init.h: Likewise. - * include/grub/powerpc/ieee1275/kernel.h: Likewise. - * include/grub/sparc64/ieee1275/kernel.h: Likewise. - - * include/grub/misc.h (grub_reboot, grub_halt): New prototypes. - - * include/grub/i386/halt.h: Remove. - * include/grub/i386/reboot.h: Likewise. - - * kern/i386/halt.c: Remove `'. - -2009-12-03 David S. Miller - - * conf/sparc64-ieee1275.rmk (grub_mkimage_SOURCES, - grub_setup_SOURCES, grub_ofpathname_SOURCES): Add gnulib/progname.c - * util/sparc64/ieee1275/grub-mkimage.c: Include and - "progname.h" - * util/sparc64/ieee1275/grub-ofpathname.c: Likewise. - * util/sparc64/ieee1275/grub-setup.c: Likewise. - (usage): Add missing comma in printf. - -2009-12-02 Robert Millan - - Use the same reboot approach on i386 coreboot and qemu as we do on - BIOS. - - * conf/i386-coreboot.rmk (kernel_img_HEADERS): Add `cpu/reboot.h'. - (reboot_mod_SOURCES): Remove `kern/i386/reboot.c'. - * kern/i386/reboot.c: Remove. - * include/grub/i386/reboot.h (grub_reboot): Export function. - * kern/i386/pc/startup.S (grub_reboot): Move from here ... - * kern/i386/realmode.S (grub_reboot): ... to here. Jump to - 0xf000:0xfff0 instead of 0xffff:0x0000. - [!GRUB_MACHINE_PCBIOS] (prot_to_real): Do not restore interrupts. - * kern/i386/qemu/startup.S: Include `"../realmode.S"'. - -2009-11-30 Robert Millan - - Fix $srcdir != $objdir build. - - * Makefile.in (po/%.po): Rewrite as ... - ($(foreach lang, $(LINGUAS), $(srcdir)/po/$(lang).po)): ... this. - -2009-11-29 Samuel Thibault - - Fix GNU/Hurd grub-install crash. - * util/grub-probe.c (probe): Try to access `path' only when it is not - NULL. - -2009-11-28 Vladimir Serbinenko - - Correct module naming. - - * video/efi_uga.c (GRUB_MOD_INIT(efi_fb)): Renamed from this ... - (GRUB_MOD_INIT(efi_uga)): ... to this - (GRUB_MOD_FINI(efi_fb)): Renamed from this ... - (GRUB_MOD_FINI(efi_uga)): ... to this - * video/efi_gop.c (GRUB_MOD_INIT(efi_fb)): Renamed from this ... - (GRUB_MOD_INIT(efi_gop)): ... to this - (GRUB_MOD_FINI(efi_fb)): Renamed from this ... - (GRUB_MOD_FINI(efi_gop)): ... to this - -2009-11-28 Robert Millan - - * util/mkisofs/mkisofs.c (ld_options): Mark all `arg' strings as - translatable. - (usage): Translate `arg' strings using gettext(). - Thanks to Jordi Mallach for the suggestion. - -2009-11-28 Vladimir Serbinenko - - GOP support. Based on patch from Bean - (http://lists.gnu.org/archive/html/grub-devel/2009-08/msg00384.html) - - * video/efi_gop.c: New file. - * include/grub/efi/graphics_output.h: Likewise. - * conf/i386-efi.rmk (pkglib_MODULES): Add `efi_gop.mod'. - (efi_fb_mod_SOURCES, efi_fb_mod_CFLAGS, efi_fb_mod_LDFLAGS): New - variables. - * conf/x86_64-efi.rmk: Likewise. - -2009-11-28 Vladimir Serbinenko - - Rename efi_fb to efi_uga. - - * conf/i386-efi.rmk (pkglib_MODULES): Rename 'efi_fb.mod' to - 'efi_uga.mod'. - (efi_fb_mod_SOURCES): Rename this ... - (efi_uga_mod_SOURCES): ... to this. - (efi_fb_mod_CFLAGS): Rename this ... - (efi_uga_mod_CFLAGS): ... to this. - (efi_fb_mod_LDFLAGS): Rename this ... - (efi_uga_mod_LDFLAGS): ... to this. - * conf/x86_64-efi.rmk (pkglib_MODULES): Rename 'efi_fb.mod' to - 'efi_uga.mod'. - (efi_fb_mod_SOURCES): Rename this ... - (efi_uga_mod_SOURCES): ... to this. - (efi_fb_mod_CFLAGS): Rename this ... - (efi_uga_mod_CFLAGS): ... to this. - (efi_fb_mod_LDFLAGS): Rename this ... - (efi_uga_mod_LDFLAGS): ... to this. - * video/efi_fb.c: Move this ... - * video/efi_uga.c: ... to this. Change prefix to 'grub_video_uga_'. - -2009-11-27 Robert Millan - - * po/README: New file. Explain our PO file workflow. - -2009-11-27 Robert Millan - - * po/ChangeLog: Remove. Move relevant entries back to ... - * ChangeLog: ... here. - * po/ca.po: Remove (now handled by TLP). - * po/id.po: Likewise. - * po/zh_CN.po: Likewise. - * Makefile.in (LINGUAS): Initialize in a way that supports - empty set. - -2009-11-27 Robert Millan - - * Makefile.in (LINGUAS): Rewrite by scanning po/ directory instead of - reliing on po/LINGUAS. - ($(foreach lang, $(LINGUAS), $(srcdir)/po/$(lang).po)): Rewrite as ... - (po/%.po): ... this. - -2009-11-26 Felix Zielcke - - * util/i386/efi/grub-mkimage.c: Include "progname.h". - (main): Use `program_name' instead of nonexistent `progname'. - -2009-11-26 Felix Zielcke - - * conf/i386-efi.rmk (grub_mkimage_SOURCES): Add `gnulib/progname.c'. - * conf/x86_64-efi.rmk (grub_mkimage_SOURCES): Likewise. - -2009-11-26 Robert Millan - - * conf/i386-coreboot.rmk: Cleanup stale filenames from my previous - commit. - * conf/i386-efi.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - -2009-11-26 Felix Zielcke - - * conf/any-emu.rmk (grub_emu_SOURCES): Add `gnulib/progname.c'. - -2009-11-26 Felix Zielcke - - * conf/any-emu.rmk (grub_mkfont_SOURCES): Add `gnulib/progname.c'. - -2009-11-26 Robert Millan - - * conf/common.rmk (sbin_UTILITIES): Add `grub-mkdevicemap'. - (grub_mkdevicemap_SOURCES): New variable. - (grub_probe_SOURCES, grub_fstest_SOURCES, grub_mkfont_SOURCES) - (grub_mkrelpath_SOURCES, grub_editenv_SOURCES) - (grub_pe2elf_SOURCES): Add `gnulib/progname.c'. - * conf/i386-coreboot.rmk (sbin_UTILITIES): Remove `grub-mkdevicemap'. - (grub_mkdevicemap_SOURCES): Remove. - * conf/i386-efi.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - * util/elf/grub-mkimage.c: Include `' and `"progname.h"'. - (usage): Fix strings to use `program_name'. - (main): Initialize gettext. - * util/grub-editenv.c: Likewise. - * util/grub-emu.c: Likewise. - * util/grub-fstest.c: Likewise. - * util/grub-mkdevicemap.c: Likewise. - * util/grub-mkfont.c: Likewise. - * util/grub-mkrelpath.c: Likewise. - * util/grub-pe2elf.c: Likewise. - * util/grub-probe.c: Likewise. - * util/sparc64/ieee1275/grub-mkimage.c: Likewise. - * util/sparc64/ieee1275/grub-ofpathname.c: Likewise. - * util/sparc64/ieee1275/grub-setup.c: Likewise. - - * util/misc.c: Include `"progname.h"'. - (progname): Remove variable. - (grub_util_warn, grub_util_info, grub_util_error): Use `program_name'. - -2009-11-25 Felix Zielcke - - * util/grub.d/10_linux.in (linux_entry): Quote the arguments to - printf and print a newline after the menuentry header line. - * util/grub.d/10_kfreebsd.in (kfreebsd_entry): Likewise. - -2009-11-25 Felix Zielcke - - autoconf >= 2.60 support $(localedir). - - * INSTALL: Note that autoconf 2.60 is required. - * configure.ac (AC_PREREQ): Bump to 2.60. - * util/grub.d/10_kfreebsd.in (TEXTDOMAINDIR): Set to lowercased @localedir@. - * util/grub.d/10_linux.in (TEXTDOMAINDIR): Likewise. - -2009-11-25 Yves Blusseau - - * configure.ac: move the call to AM_GNU_GETTEXT to avoid warnings when - aclocal is run. - -2009-11-25 Robert Millan - - * normal/main.c (grub_normal_read_line): Fix off-by-one - buffer overflow. - -2009-11-25 Robert Millan - - * normal/main.c (grub_normal_execute): Replace "parser.sh" with - "parser.grub" in grub_command_execute() call. - -2009-11-24 Carles Pina i Estany - - * conf/i386-coreboot.rmk (kernel_img_HEADERS): Add i18n.h. - * conf/i386-efi.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - * gettext/gettex.c: Include . - * include/grub/misc.h (grub_gettext_dummy, grub_gettext): Move from - here ... - * include/grub/i18n.h: ... to here - * include/grub/i18n.h: ... to here. - * kern/misc.c: Include - (grub_gettext_dummy): Move above user. - -2009-11-24 Felix Zielcke - - * util/Makefile.in (install-local): Convert a `for' into a normal - shell expansion. - -2009-11-24 Robert Millan - - * autogen.sh: Add automake call. - * config.guess: Remove. - * config.sub: Likewise. - * install-sh: Likewise. - -2009-11-24 Felix Zielcke - - * util/Makefile.in (install-local): Fix the use of $lang shell variable. - -2009-11-24 Felix Zielcke - - * util/Makefile.in (install-local): Convert a make `$(foreach)' - function to a normal shell `for'. - -2009-11-24 Felix Zielcke - - * conf/i386-coreboot.rmk (grub_mkimage_SOURCES): Add `gnulib/progname.c'. - -2009-11-24 Felix Zielcke - - * util/grub-mkrelpath.c: New file. - * conf/common.rmk (bin_UTILITIES): Add grub-mkrelpath. - (grub_mkrelpath_SOURCES): New variable. - * include/grub/util/misc.h: New function prototype. - * util/misc.c (make_system_path_relative_to_its_root): New function. - - * util/grub-mkconfig_lib.in (bindir): New variable. - (grub_mkrelpath): Likewise. - (make_system_path_relative_to_its_root): Use grub-mkrelpath. - - * util/probe.c (probe): Make the file path relative to its root. - Change a info message to use the GRUB path. Enable again the - check if we can read the file with GRUB facilities. - - * util/i386/pc/grub-setup.c (setup): Make core.img path relative - to its root. - -2009-11-24 Felix Zielcke - - * Makefile.in: Don't include GRUB_CONTRIB makefiles with emu - platform. - -2009-11-24 Felix Zielcke - - * util/getroot.c (grub_util_get_dev_abstraction): Properly use - strncmp(). - -2009-11-24 Felix Zielcke - - * util/getroot.c (grub_util_is_dmraid): New function. - (grub_util_get_dev_abstraction): Treat dmraid and multipath - devices as normal ones, not as LVM. - -2009-11-23 Carles Pina i Estany - - * conf/common.rmk: Add grub-gettext_lib target and updates - lib_DATA and CLEANFILES. Adds gettext.mod SOURCES, CFLAGS, - LDFLAGS. - * gettext/gettext.c: New file. (Reads mo files). - * include/grub/file.h (grub_file_pread): New prototype. - * include/grub/i18n.h (_): New prototype. - * include/grub/misc.h (grub_gettext_dummy, grub_gettext): New - prototypes. - * kern/misc.c (grub_gettext_dummy): New function. - * normal/menu_text.c: Include . - * normal/menu_text.c (print_timeout): Gettexttize string. - * normal/menu_text.c (print_message): Gettexttize string. - * po/POTFILES: Add `normal/menu_text.c'. - * po/ca.po: Add new translations. - * util/grub.d/00_header.in: Define locale_dir and lang. insmod - gettext module and defines locale_dir and lang in grub.cfg. - * NEWS: Add gettext support. - -2009-11-23 Robert Millan - - * util/hostdisk.c: Include `'. - (find_grub_drive): Use ARRAY_SIZE for map size calculation. - (make_device_name): Rewrite using asprintf. - (convert_system_partition_to_system_disk): Replace 0 with NULL. - (find_system_device): If a device is not found, generate one just - by reusing the OS path name. - (read_device_map): Make it permissible for device.map not to exist. - -2009-11-23 Robert Millan - - * script/sh/execute.c: Move from here ... - * script/execute.c: ... to here. Update all users. - * script/sh/function.c: Move from here ... - * script/function.c: ... to here. Update all users. - * script/sh/lexer.c: Move from here ... - * script/lexer.c: ... to here. Update all users. - * script/sh/main.c: Move from here ... - * script/main.c: ... to here. Update all users. - * script/sh/parser.y: Move from here ... - * script/parser.y: ... to here. Update all users. - * script/sh/script.c: Move from here ... - * script/script.c: ... to here. Update all users. - -2009-11-23 Robert Millan - - * configure.ac: Detect all `emu' platforms. Define - GRUB_MACHINE_* macros in TARGET_CFLAGS. Remove - --enable-grub-emu logic. Disable include/grub/machine - symlink on `emu' platforms. - - * genkernsyms.sh.in: Use @TARGET_CFLAGS@ during symbol generation. - * gensymlist.sh.in: Likewise. - - * include/grub/i386/coreboot/machine.h: Remove file. - * include/grub/i386/efi/machine.h: Likewise. - * include/grub/i386/ieee1275/machine.h: Likewise. - * include/grub/i386/pc/machine.h: Likewise. - * include/grub/i386/qemu/machine.h: Likewise. - * include/grub/powerpc/ieee1275/machine.h: Likewise. - * include/grub/sparc64/ieee1275/machine.h: Likewise. - * include/grub/x86_64/efi/machine.h: Likewise. - - * commands/acpi.c: Remove `'. - * commands/halt.c: Likewise. - * commands/reboot.c: Likewise. - * include/grub/autoefi.h: Likewise. - * include/grub/i386/at_keyboard.h: Likewise. - * include/grub/i386/kernel.h: Likewise. - * include/grub/i386/loader.h: Likewise. - * include/grub/i386/pc/memory.h: Likewise. - * kern/dl.c: Likewise. - * kern/i386/coreboot/init.c: Likewise. - * loader/i386/bsd.c: Likewise. - * loader/i386/linux.c: Likewise. - * loader/multiboot_loader.c: Likewise. - * term/i386/pc/serial.c: Likewise. - * term/usb_keyboard.c: Likewise. - - * include/grub/time.h [!GRUB_MACHINE_EMU]: Remove - `' - [!GRUB_MACHINE_EMU] (GRUB_TICKS_PER_SECOND): New macro. - * util/misc.c: Remove `' and - `'. - - * Makefile.in (enable_grub_emu): Remove variable. - Include $(srcdir)/conf/any-emu.mk for the `emu' platform. - - * conf/any-emu.rmk: New file. - * conf/common.rmk (grub_emu_init.lst, grub_emu_init.h) - (grub_emu_init.c): Move from here ... - * conf/any-emu.rmk: ... to here. - - * conf/i386-coreboot.rmk (sbin_UTILITIES): Remove `grub-emu'. - (grub_emu_SOURCES, grub_emu_LDFLAGS): Move from here ... - * conf/any-emu.rmk: ... to here. - -2009-11-23 Robert Millan - - * include/grub/parser.h (grub_parser_register): Document need - of `name' parameter. - * normal/main.c (grub_normal_read_line): Simplify prompt string. - * script/sh/main.c (grub_sh_parser, GRUB_MOD_INIT(sh)): Rename - "sh" to "grub". - -2009-11-23 Robert Millan - - * Makefile.in ($(srcdir)/po/$(PACKAGE).pot): Pass --keyword=N_ to - `$(XGETTEXT)'. - * include/grub/i18n.h (N_): New macro. - * util/mkisofs/mkisofs.h: Likewise. - * util/mkisofs/mkisofs.c (ld_options): Wrap all translatable strings - around N_(). - (usage): Use gettext() to translate help strings when printing them. - -2009-11-23 Robert Millan - - Based on patch from Bean - (http://lists.gnu.org/archive/html/grub-devel/2009-08/msg00384.html) - - * video/efi_fb.c: New file. - * conf/i386-efi.rmk (pkglib_MODULES): Add `efi_fb.mod'. - (efi_fb_mod_SOURCES, efi_fb_mod_CFLAGS, efi_fb_mod_LDFLAGS): New - variables. - * conf/x86_64-efi.rmk: Likewise. - -2009-11-22 Robert Millan - - * util/i386/pc/grub-mkimage.c: Ungettextize grub_util_info() strings. - * util/i386/pc/grub-setup.c: Likewise. - -2009-11-21 Samuel Thibault - - * util/getroot.c [__GNU__]: Include , , and - - [__GNU__] (grub_guess_root_device): Call file_name_lookup and - file_get_storage_info to implement grub_guess_root_device. - -2009-11-21 Felix Zielcke - - * Makefile.in (target): Use make's builtin $(shell) function - instead of calling directly $(SHELL) to create the locale directories, - inside the $(foreach) function. - -2009-11-21 Felix Zielcke - - * util/grub-mkrescue.in: Print an error and usage if output option - has not been given. - -2009-11-21 Felix Zielcke - - Patch from LoĂ¯c Minier . - * util/grub.d/30_os-prober.in: Cope with Linux entries where - root and /boot are on different devices. - -2009-11-21 Robert Millan - - Fix build for srcdir != objdir. - - * Makefile.in (po/$(PACKAGE).pot): Rename to ... - ($(srcdir)/po/$(PACKAGE).pot): ... this. Run $(XGETTEXT) from - $(srcdir). - ($(foreach lang, $(LINGUAS), po/$(lang).po)): Rename to ... - ($(foreach lang, $(LINGUAS), $(srcdir)/po/$(lang).po): ... this. Use $^ - reference for input. - -2009-11-21 Robert Millan - - * util/grub-mkrescue.in: Use source directory direcly (without copiing - or hardlinking it). Remove -J option, Joliet is not compatible with - multiple source directories. - -2009-11-21 Carles Pina i Estany -2009-11-21 Robert Millan - - * util/grub-mkrescue.in: Recognize `--override-directory' option. - (process_input_dir): New function. Process an arbitrary input - directory. - Misc adjustments to support both "override mode" and system-wide mode. - -2009-11-20 Felix Zielcke - - * configure.ac (UNIFONT_BDF): Rename to ... - (FONT_SOURCE): ... this. Update all users. - -2009-11-20 Felix Zielcke - - * configure.ac: Add `/usr/share/fonts/X11/misc/unifont.pcf.gz' - to the list of unifont files to look for. - -2009-11-19 Robert Millan - - Patch from Joe Auricchio - * commands/minicmd.c (grub_mini_cmd_clear): New function. - (GRUB_MOD_INIT(minicmd)): Register grub_mini_cmd_clear(). - (GRUB_MOD_FINI(minicmd)): Unregister grub_mini_cmd_clear(). - -2009-11-19 Felix Zielcke - - * Makefile.in (install-local): Add a missing backslash. - -2009-11-19 Felix Zielcke - - * include/grub/x86_64/io.h: New file. - -2009-11-19 Robert Millan - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add `gnulib/progname.c'. - * util/i386/pc/grub-setup.c: Include `'. - Include `"progname.h"'. - (main): Initialize gettext. - * util/i386/pc/grub-setup.c: Gettexttize. - * util/i386/pc/grub-mkimage.c: Likewise. - - * Makefile.in (po/*.po): Redefine as ... - ($(foreach lang, $(LINGUAS), po/$(lang).po)): ... this. - - * po/POTFILES: Add `util/i386/pc/grub-setup.c'. - -2009-11-19 Robert Millan - - * conf/common.rmk (grub_mkisofs_SOURCES): Add `gnulib/progname.c'. - * util/mkisofs/mkisofs.c: Include `"progname.h"'. - (program_name): Remove. - (main): Initialize gettext support. - * util/mkisofs/mkisofs.h: Include `'. - Include `'. - (_): New macro. - - * util/mkisofs/eltorito.c: Gettexttize. - * util/mkisofs/joliet.c: Likewise. - * util/mkisofs/mkisofs.c: Likewise. - * util/mkisofs/multi.c: Likewise. - * util/mkisofs/rock.c: Likewise. - * util/mkisofs/tree.c: Likewise. - * util/mkisofs/write.c: Likewise. - - * po/POTFILES: Update with new files. - -2009-11-18 Robert Millan - - * util/mkisofs/eltorito.c: Fix minor mistake in license text. - * util/mkisofs/iso9660.h: Likewise. - * util/mkisofs/joliet.c: Likewise. - * util/mkisofs/mkisofs.c: Likewise. - * util/mkisofs/mkisofs.h: Likewise. - * util/mkisofs/rock.c: Likewise. - * util/mkisofs/tree.c: Likewise. - * util/mkisofs/write.c: Likewise. - - * util/mkisofs/eltorito.c (rcsid): Remove. - * util/mkisofs/hash.c: Likewise. - * util/mkisofs/joliet.c: Likewise. - * util/mkisofs/name.c: Likewise. - * util/mkisofs/rock.c: Likewise. - * util/mkisofs/tree.c: Likewise. - * util/mkisofs/write.c: Likewise. - -2009-11-18 Robert Millan - - * util/mkisofs/match.c: Rewrite from scratch, using a linked list - instead of static allocation. - * util/mkisofs/match.h: Likewise. - -2009-11-18 Robert Millan - - * po/POTFILES-shell: New file. List `util/grub.d/10_kfreebsd.in' - and `util/grub.d/10_linux.in'. - * Makefile.in (po/$(PACKAGE).pot): Process `po/POTFILES-shell' for - translatable Shell files. - -2009-11-18 Robert Millan - - * Makefile.in ($(srcdir)/aclocal.m4): New target. - -2009-11-17 Robert Millan - - * INSTALL: Document Automake is needed for bootstrap. - * po/ca.po: Fix PO-Revision-Date and Language-Team fields. - * util/grub.d/10_kfreebsd.in (bindir): New variable. - Add gettext initialization. - (kfreebsd_entry): Make menuentry output translatable. - -2009-11-17 Robert Millan - - * Makefile.in (XGETTEXT, MSGMERGE, MSGFMT): New variables. - (po/$(PACKAGE).pot): Replace `xgettext' with `$(XGETTEXT)'. - (po/*.po): Replace `msgmerge' with `$(MSGMERGE)'. - (po/%.mo): Replace `msgfmt' with `$(MSGFMT)'. - (LINGUAS): Auto-generate using `po/LINGUAS'. - * po/LINGUAS: New file. - -2009-11-17 Robert Millan - - * configure.ac: Call AM_GNU_GETTEXT() (defines localedir, among - other things). - * Makefile.in (CPPFLAGS): Add `-DLOCALEDIR=\"$(localedir)\"'. - * util/i386/pc/grub-mkimage.c (main): Issue setlocale() and - bindtextdomain() calls for gettext initialization. - -2009-11-17 Robert Millan - - * gnulib/progname.c: New file (imported from Gnulib). - * gnulib/progname.h: Likewise. - * conf/i386-pc.rmk (grub_mkimage_SOURCES): Add `gnulib/progname.c'. - * util/i386/pc/grub-mkimage.c: Include `"progname.h"'. - (usage): Replace `progname' with `program_name'. - (main): Use set_program_name() for program name initialization. - -2009-11-17 Robert Millan - - * conf/common.rmk (grub_mkisofs_CFLAGS): Move `-I$(srcdir)/gnulib' - from here ... - * Makefile.in (CPPFLAGS): ... to here. - -2009-11-16 Robert Millan - - * aclocal.m4: Move from here ... - * acinclude.m4: ... to here. - * autogen.sh: Add call to `aclocal'. - * configure.ac: Add AM_INIT_AUTOMAKE() after AC_INIT() call. - -2009-11-16 Robert Millan - - * Makefile.in (CLEANFILES): Add `po/*.mo'. - (LINGUAS): New variable. - (all-local): Add `$(foreach lang, $(LINGUAS), po/$(lang).mo)'. - (install-local): Install MO files. - (po/$(PACKAGE).pot, po/*.po, po/%.mo): New rules. - * include/grub/i18n.h: New file. - * po/POTFILES: New file. - * po/ca.po: New file. - * util/grub.d/10_linux.in (bindir): New variable. - Add gettext initialization. - (linux_entry): Make menuentry output translatable. - * util/i386/pc/grub-mkimage.c: Include `'. - (usage): Make --help output translatable. - (main): Initialize gettext. - -2009-11-17 Robert Millan - - * import_gcry.py: New file (written by Vladimir with minor - adjustments). - * autogen.sh: Use import_gcry.py to auto-generate GRUB-ified - ciphers. - * INSTALL: Document that Python is required for bootstrap. - -2009-11-17 Robert Millan - - Import ciphers from libgcrypt 1.4.4. - - * lib/libgcrypt/cipher/ChangeLog - * lib/libgcrypt/cipher/ac.c - * lib/libgcrypt/cipher/arcfour.c - * lib/libgcrypt/cipher/bithelp.h - * lib/libgcrypt/cipher/blowfish.c - * lib/libgcrypt/cipher/camellia-glue.c - * lib/libgcrypt/cipher/camellia.c - * lib/libgcrypt/cipher/camellia.h - * lib/libgcrypt/cipher/cast5.c - * lib/libgcrypt/cipher/cipher.c - * lib/libgcrypt/cipher/crc.c - * lib/libgcrypt/cipher/des.c - * lib/libgcrypt/cipher/dsa.c - * lib/libgcrypt/cipher/ecc.c - * lib/libgcrypt/cipher/elgamal.c - * lib/libgcrypt/cipher/hash-common.c - * lib/libgcrypt/cipher/hash-common.h - * lib/libgcrypt/cipher/hmac-tests.c - * lib/libgcrypt/cipher/md.c - * lib/libgcrypt/cipher/md4.c - * lib/libgcrypt/cipher/md5.c - * lib/libgcrypt/cipher/primegen.c - * lib/libgcrypt/cipher/pubkey.c - * lib/libgcrypt/cipher/rfc2268.c - * lib/libgcrypt/cipher/rijndael-tables.h - * lib/libgcrypt/cipher/rijndael.c - * lib/libgcrypt/cipher/rmd.h - * lib/libgcrypt/cipher/rmd160.c - * lib/libgcrypt/cipher/rsa.c - * lib/libgcrypt/cipher/seed.c - * lib/libgcrypt/cipher/serpent.c - * lib/libgcrypt/cipher/sha1.c - * lib/libgcrypt/cipher/sha256.c - * lib/libgcrypt/cipher/sha512.c - * lib/libgcrypt/cipher/tiger.c - * lib/libgcrypt/cipher/twofish.c - * lib/libgcrypt/cipher/whirlpool.c - -2009-11-16 Robert Millan - - Fix build for systems without error(). - - * gnulib/error.c: New file (imported from Gnulib). - * gnulib/error.h: Likewise. - * conf/common.rmk (grub_mkisofs_SOURCES): Add `gnulib/error.c'. - * util/mkisofs/mkisofs.c (program_name): Remove `static' qualifier - (this variable is now used by error()). - -2009-11-16 Felix Zielcke - - * util/mkisofs/name.c (iso9660_file_length): Use isascii macro - instead of relying that char is signed. - -2009-11-16 Vladimir Serbinenko - - * fs/i386/pc/pxe.c (grub_pxefs_open): Correctly handle PXE choosing - blocksize different from specified. - (grub_pxefs_read): Likewise. - -2009-11-16 Felix Zielcke - - Enable ata.mod on x86_64-efi, i386-efi and i386-ieee1275. - - * disk/ata.c (grub_ata_dumpinfo): Add a cast. - (grub_ata_readwrite): Likewise. Update 2 format strings. - (grub_atapi_read): Likewise. - - * conf/i386-coreboot.rmk (pkglib_MODULES): Move `ata.mod' from here ... - * conf/i386.rmk (pkglib_MODULES): ... to here ... - * conf/x86_64-efi.rmk (pkglib_MODULES): ... and here. - * conf/i386-coreboot.rmk (ata_mod_SOURCES, ata_mod_CFLAGS) - (ata_mod_LDFLAGS): Move from here ... - * conf/i386.rmk: ... to here ... - * conf/x86_64-efi.rmk: ... and here. - * conf/i386-pc.rmk (pkglib_MODULES): Remove `ata.mod' - (ata_mod_SOURCES, ata_mod_CFLAGS, ata_mod_LDFLAGS): Remove. - -2009-11-16 Robert Millan - - Relicense multiboot.h, with RMS' blessing. - - * include/multiboot.h: Change to X11 license. - -2009-11-15 Robert Millan - - Support --version in grub-mkisofs. - - * util/mkisofs/mkisofs.c (rcsid): Remove variable. - (OPTION_VERSION): New macro. - (ld_options): Recognize --version. - (usage): Move `program_name' from here ... - (program_name): ... to here. Add `static' qualifier. - (main): Recognize `OPTION_VERSION'. - -2009-11-15 Felix Zielcke - - * Makefile.in (TARGET_CPPFLAGS): Replace `-isystem=$(srcdir)/include' - with `-nostdinc -isystem $(shell $(TARGET_CC) -print-file-name=include)'. - -2009-11-14 Robert Millan - - Fix help2man generation for mkisofs. - - * util/mkisofs/mkisofs.c (ld_options): Recognize --help. - (usage): Send output to stdout (rather than stderr). - -2009-11-14 Robert Millan - - * conf/i386-coreboot.rmk (grub_mkrescue_SOURCES): Replace - `util/i386/coreboot/grub-mkrescue.in' with `util/grub-mkrescue.in'. - * conf/i386-pc.rmk (grub_mkrescue_SOURCES): Replace - `util/i386/pc/grub-mkrescue.in' with `util/grub-mkrescue.in'. - (bin_SCRIPTS): Add `grub-mkfloppy'. - (grub_mkfloppy_SOURCES): New variable. - - * util/grub-mkrescue.in: New file. - * util/i386/pc/grub-mkfloppy.in: New file. - - * util/i386/coreboot/grub-mkrescue.in: Remove. - * util/i386/pc/grub-mkrescue.in: Remove. - -2009-11-13 Robert Millan - - * include/grub/multiboot.h (struct grub_multiboot_header): Move - from here ... - * include/multiboot.h (struct multiboot_header): ... to here. Update - all users. - * include/grub/multiboot.h (struct grub_multiboot_info): Move - from here ... - * include/multiboot.h (struct multiboot_info): ... to here. Update - all users. - * include/grub/multiboot.h (struct grub_multiboot_mmap_entry): Move - from here ... - * include/multiboot.h (struct multiboot_mmap_entry): ... to here. - Update all users. - * include/grub/multiboot.h (struct grub_mod_list): Move - from here ... - * include/multiboot.h (struct multiboot_mod_list): ... to here. - Update all users. - -2009-11-13 Robert Millan - - * include/multiboot2.h (multiboot_word): Rename from this ... - (multiboot2_word): ... to this. Update all users. - (multiboot_header): Rename from this ... - (multiboot2_header): ... to this. Update all users. - (multiboot_tag_header): Rename from this ... - (multiboot2_tag_header): ... to this. Update all users. - (multiboot_tag_start): Rename from this ... - (multiboot2_tag_start): ... to this. Update all users. - (multiboot_tag_name): Rename from this ... - (multiboot2_tag_name): ... to this. Update all users. - (multiboot_tag_module): Rename from this ... - (multiboot2_tag_module): ... to this. Update all users. - (multiboot_tag_memory): Rename from this ... - (multiboot2_tag_memory): ... to this. Update all users. - (multiboot_tag_unused): Rename from this ... - (multiboot2_tag_unused): ... to this. Update all users. - (multiboot_tag_end): Rename from this ... - (multiboot2_tag_end): ... to this. Update all users. - -2009-11-13 Robert Millan - - Disable Multiboot2 in i386-ieee1275. It didn't actually work, and on - this platform we should support Multiboot1 first. - - * conf/i386-ieee1275.rmk (pkglib_MODULES): Remove `multiboot.mod'. - (multiboot_mod_SOURCES, multiboot_mod_CFLAGS) - (multiboot_mod_LDFLAGS, multiboot_mod_ASFLAGS): Remove. - -2009-11-12 Robert Millan - - * util/mkisofs/eltorito.c (init_boot_catalog): Handle return code - of write calls (converting them to fwrite() if they aren't already). - (get_torito_desc): Likewise. - * util/mkisofs/rock.c (generate_rock_ridge_attributes): Likewise. - -2009-11-12 Robert Millan - - * util/i386/pc/grub-install.in: Move from here ... - * util/grub-install.in: ... to here. Update all users. - -2009-11-11 Colin Watson - - * util/powerpc/ieee1275/grub-mkrescue.in: Fix --version output. - -2009-11-11 Robert Millan - - Support for El Torito without floppy emulation. - - * util/mkisofs/eltorito.c: Include `'. - (init_boot_catalog): Improve error handling. - (get_torito_desc): Don't use floppy emulation unless requested by - user. Patch boot information table when requested via - `-boot-info-table'. - * util/mkisofs/iso9660.h (struct eltorito_boot_info): New struct. - * util/mkisofs/mkisofs.c (use_eltorito_emul_floppy) - (use_boot_info_table): New variables. - (OPTION_BOOT_INFO_TABLE, OPTION_NO_EMUL_BOOT) - (OPTION_ELTORITO_EMUL_FLOPPY): New macros. - (ld_options): Handle `-boot-info-table', `-no-emul-boot' and - `--eltorito-emul-floppy'. - (main): Handle `OPTION_BOOT_INFO_TABLE', `OPTION_NO_EMUL_BOOT' - and `OPTION_ELTORITO_EMUL_FLOPPY'. - * util/mkisofs/mkisofs.h (use_eltorito_emul_floppy) - (use_boot_info_table, get_731): New prototypes. - * util/mkisofs/write.c (get_731): New function. - -2009-11-11 Felix Zielcke - - Fix the generation of the man page. - - * util/pc/i386/grub-install.in: Source - `${libdir}/grub/grub-mkconfig_lib' after options have been parsed. - -2009-11-11 Robert Millan - - Large file support for grub-mkisofs. - - * conf/common.rmk (grub_mkisofs_CFLAGS): Add `-D_FILE_OFFSET_BITS=64'. - * util/mkisofs/mkisofs.c (next_extent, last_extent) - (session_start): Upgrade type to `uint64_t'. Update all users. - * util/mkisofs/mkisofs.h: Include `'. - (struct directory_entry): Upgrade type of `starting_block' and - `size' to `uint64_t'. Update all users. - (struct deferred): Remove unused structure. - (xfwrite): Upgrade type of `count' and `size' to `uint64_t'. - Update all users. - * util/mkisofs/tree.c (stat_filter, lstat_filter): Return -1 when - file is larger than `UINT32_MAX'. - * util/mkisofs/write.c (xfwrite): Upgrade type of `count' and - `size' to `uint64_t'. Update all users. Fix handling of fwrite() - return value. - (struct deferred_write): Upgrade type of `extent' and `size' to - `uint64_t'. Update all users. - (last_extent_written): Upgrade type to `uint64_t'. Update all - users. - (write_one_file): Upgrade type of `count' and `size' to `uint64_t'. - Update all users. Upgrade type of `remain' to `int64_t' and - `use' to `size_t'. Use error() to handle fread() errors. - (write_files): Rely on write_one_file() rather than calling - xfwrite() directly. - -2009-11-09 Felix Zielcke - - * util/mkisofs/mkisofs.c (ld_options): Fix a spelling mistake. - -2009-11-09 Robert Millan - - * util/mkisofs/fnmatch.c: Remove. - * util/mkisofs/getopt1.c: Likewise. - * util/mkisofs/getopt.c: Likewise. - * conf/common.rmk (grub_mkisofs_SOURCES): Replace - `util/mkisofs/fnmatch.c', `util/mkisofs/getopt1.c' and - `util/mkisofs/getopt.c' with `gnulib/fnmatch.c', - `gnulib/getopt1.c' and `gnulib/getopt.c'. - (grub_mkisofs_CFLAGS): Add `-I$(srcdir)/gnulib'. - - * configure.ac: Detect `mingw32msvc' host_os. - Check for lstat(), getuid() and getgid(). - - * util/mkisofs/joliet.c: Include `'. Replace all - instances of `u_char' with `uint8_t'. - - * util/mkisofs/mkisofs.h: Include `'. - [!HAVE_GETUID] (getuid): New function (stub). - [!HAVE_GETGID] (getgid): Likewise. - [!HAVE_LSTAT] (lstat): Likewise. - [!S_IROTH] (S_IROTH): New macro (dummy). - [!S_IRGRP] (S_IRGRP): Likewise. - -2009-11-09 Robert Millan - - * gnulib/fnmatch_loop.c (EXT): Fix warning (signed and unsigned type in - conditional expression). - -2009-11-09 Robert Millan - - Import from Gnulib. - - * gnulib/fnmatch.c: New file. - * gnulib/fnmatch.h: Likewise. - * gnulib/fnmatch_loop.c: Likewise. - * gnulib/getopt.c: Likewise. - * gnulib/getopt.h: Likewise. - * gnulib/getopt1.c: Likewise. - * gnulib/getopt_int.h: Likewise. - * gnulib/gettext.h: Likewise. - -2009-11-09 Robert Millan - - * normal/dyncmd.c (read_command_list): Replace `0' with `NULL'. - * normal/handler.c (read_handler_list): Likewise. - -2009-11-09 Robert Millan - - Misc cleanup. - - * kern/command.c (grub_register_command_prio): Use - grub_zalloc() instead of explicitly zeroing data. - * kern/list.c: Include `'. - (grub_named_list_find): Replace `0' with `NULL'. - * normal/autofs.c (struct grub_fs_module_list): Remove ad-hoc type. - (fs_module_list): Change type to `grub_named_list_t'. Update all - users. - * normal/dyncmd.c (read_command_list): Add space between function - call and parenthesis. - * normal/handler.c (read_handler_list): Likewise. - -2009-11-09 Robert Millan - - * normal/auth.c (punishment_delay): Moved from here ... - (grub_auth_strcmp): ... to here (inside function). - -2009-11-09 Robert Millan - - * include/grub/list.h (struct grub_named_list): Remove `const' - qualifier from `name'. - (struct grub_prio_list): Likewise. - -2009-11-09 Robert Millan - - * normal/auth.c: Include `'. - (grub_auth_strcmp): Replace `strcmp' with `grub_strcmp'. - -2009-11-09 Robert Millan - - * normal/auth.c (punishment_delay): New variable. - (grub_auth_strcmp): Rewrite using grub_get_time_ms (). - (grub_auth_check_authentication): Punish failed login attempts with - an incremental (2^N) delay. - -2009-11-09 Robert Millan - - * conf/common.rmk (grub_mkisofs_CFLAGS): Prefix include - path with $(srcdir). - -2009-11-09 Vladimir Serbinenko - - * normal/auth.c (grub_auth_strcmp): Fixed incorrect variable usage. - -2009-11-09 Robert Millan - - * util/i386/coreboot/grub-mkrescue.in: New file. - * conf/i386-coreboot.rmk (bin_SCRIPTS, grub_mkrescue_SOURCES): New - variables. - - * conf/common.rmk (bin_UTILITIES): Add `grub-mkisofs'. - (grub_mkisofs_SOURCES, grub_mkisofs_CFLAGS): New variables. - * configure.ac: Add header and function checks to satisfy grub-mkisofs - requirements. - * util/mkisofs/defaults.h: New file. - * util/mkisofs/eltorito.c: Likewise. - * util/mkisofs/exclude.h: Likewise. - * util/mkisofs/fnmatch.c: Likewise. - * util/mkisofs/getopt.c: Likewise. - * util/mkisofs/getopt1.c: Likewise. - * util/mkisofs/hash.c: Likewise. - * util/mkisofs/include/fctldefs.h: Likewise. - * util/mkisofs/include/mconfig.h: Likewise. - * util/mkisofs/include/prototyp.h: Likewise. - * util/mkisofs/include/statdefs.h: Likewise. - * util/mkisofs/iso9660.h: Likewise. - * util/mkisofs/joliet.c: Likewise. - * util/mkisofs/match.c: Likewise. - * util/mkisofs/match.h: Likewise. - * util/mkisofs/mkisofs.c: Likewise. - * util/mkisofs/mkisofs.h: Likewise. - * util/mkisofs/multi.c: Likewise. - * util/mkisofs/name.c: Likewise. - * util/mkisofs/rock.c: Likewise. - * util/mkisofs/tree.c: Likewise. - * util/mkisofs/write.c: Likewise. - -2009-11-09 Vladimir Serbinenko - - * normal/auth.c (grub_auth_strcmp): Fix bug which resulted in function - being insecure. - -2009-11-08 Robert Millan - - * util/i386/pc/grub-mkrescue.in: Fix miss-identification as - `grub-mkimage' (and use $0 when possible). - -2009-11-08 Robert Millan - - * kern/i386/multiboot_mmap.c (grub_machine_mmap_init): Improve - error message for excessively large memory map. - -2009-11-08 Robert Millan - - * autogen.sh: Use `sh gendistlist.sh' to avoid reliing on - executable bit. - -2009-11-08 Robert Millan - - * kern/i386/multiboot_mmap.c (grub_machine_mmap_init): Improve error - message for coreboot users. - -2009-11-07 Robert Millan - - Fix build with GNU gold. - - * conf/i386-pc.rmk (boot_img_LDFLAGS, pxeboot_img_LDFLAGS) - (diskboot_img_LDFLAGS, lnxboot_img_LDFLAGS) - (cdboot_img_LDFLAGS): Prepend `0x' qualifier to hexadecimal - link addresses. - * aclocal.m4: Likewise. - -2009-11-04 Felix Zielcke - - * configure.ac (AC_PREREQ): Bump to 2.59d. - * INSTALL: Make it more clear when Autoconf and Ruby are - needed and when to run `./autogen.sh'. - -2009-11-03 Samuel Thibault - - * util/grub.d/30_os-prober.in: Restore default behavior for unsupported - OSes. - -2009-11-02 Samuel Thibault - - * util/grub.d/30_os-prober.in: Add GNU/Hurd support - -2009-11-02 Samuel Thibault - - * util/grub.d/10_hurd.in: Drop /dev/ prefix from root device path before - giving it to GNU Mach. - -2009-11-02 Samuel Thibault - - * util/hostdisk.c (grub_util_biosdisk_get_grub_dev): Subtract 1 from - GNU partition number to get internal GRUB partition number. - -2009-11-02 Samuel Thibault - - * util/grub.d/10_hurd.in: Call prepare_grub_to_access_device - ${GRUB_DEVICE_BOOT} before loading /boot kernel. - -2009-11-01 Robert Millan - - Based on patch from BVK Chaitanya - * kern/misc.c (grub_strchr, grub_strrchr): Fix to handle c == '\0' - case. - -2009-11-01 Felix Zielcke - - * Makefile.in (TARGET_CPPFLAGS): Add `-I$(srcdir)/include'. - -2009-10-30 Robert Millan - - Fix build problem. - - * Makefile.in (TARGET_CPPFLAGS): Replace `-nostdinc' with - `-isystem=$(srcdir)/include'. - -2009-10-30 Robert Millan - - * util/i386/pc/grub-install.in: Remove hint that device.map should be - checked (grub-install doesn't currently rely on it). - -2009-10-29 Robert Millan - - Revert SVN r2660. - - * conf/common.rmk (script/sh/lexer.c_DEPENDENCIES): Moved from here ... - * conf/i386-coreboot.rmk (script/sh/lexer.c_DEPENDENCIES): ... to here. - * conf/i386-efi.rmk (script/sh/lexer.c_DEPENDENCIES): ... and here. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - -2009-10-28 Robert Millan - - * Makefile.in (TARGET_CPPFLAGS): Add `-nostdinc'. - -2009-10-28 Robert Millan - - * include/grub/misc.h: Stop checking for APPLE_CC. - -2009-10-28 Robert Millan - - * kern/i386/coreboot/init.c (grub_exit): Reimplement in a way that - doesn't cause an infinite call loop. - -2009-10-28 Felix Zielcke - - * commands/acpi.c (grub_cmd_acpi): Fix the out of memory error - strings. - -2009-10-26 Robert Millan - - * autogen.sh: Support addition of external modules via `GRUB_CONTRIB' - variable. - * Makefile.in: Likewise. - -2009-10-26 Robert Millan - - * gendistlist.sh: Simplify .svn check. Skip .bzr as well. - -2009-10-26 Robert Millan - - * Makefile.in (RMKFILES): Rewrite using $(wildcard). - -2009-10-26 Robert Millan - - * disk/scsi.c: Remove `' (not needed). - -2009-10-26 Robert Millan - - * gensymlist.sh.in (COMPILE_TIME_ASSERT): Copy macro declaration - from here ... - * include/grub/misc.h (COMPILE_TIME_ASSERT): ... to here. - -2009-10-26 Robert Millan - - * Makefile.in (docs/grub.info): Use make syntax to ignore errors - in $(MAKEINFO) invocation. This makes it clear in output that - errors are being ignored. - -2009-10-26 Robert Millan - - * conf/i386-coreboot.rmk (script/sh/lexer.c_DEPENDENCIES): Moved - from here ... - * conf/common.rmk (script/sh/lexer.c_DEPENDENCIES): ... to here. - * conf/i386-efi.rmk (script/sh/lexer.c_DEPENDENCIES): Remove. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - -2009-10-26 Colin Watson - - * util/grub-editenv.c (main): If only a command is given, use - DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG as a default file name. - (usage): FILENAME is now optional and has a default. - -2009-10-26 Colin Watson - - Improve grub-mkconfig performance when there are several menu - entries on a single filesystem. - - * util/grub.d/10_linux.in (linux_entry): Cache the output of - prepare_grub_to_access_device. - * util/grub.d/10_kfreebsd.in (kfreebsd_entry): Likewise. - * util/grub.d/30_os-prober.in: Likewise. - -2009-10-26 Robert Millan - - * util/grub.d/10_freebsd.in: Remove. - * util/grub.d/10_kfreebsd.in: New file (based on 10_linux.in). - * configure.ac: Set host_kernel=kfreebsd for FreeBSD and GNU/kFreeBSD. - -2009-10-26 Robert Millan - - * docs/grub.cfg: Fix example usage of *BSD loaders. - -2009-10-25 Robert Millan - - * util/i386/pc/grub-setup.c (setup): Add missing parameter to - grub_util_error() call. - -2009-10-25 Robert Millan - - * include/grub/fs.h [GRUB_UTIL] (struct grub_fs): Add - `reserved_first_sector' member. - * fs/ext2.c [GRUB_UTIL] (grub_ext2_fs): Initialize - `reserved_first_sector' to 1. - * fs/fat.c [GRUB_UTIL] (grub_fat_fs): Likewise. - * fs/ntfs.c [GRUB_UTIL] (grub_ntfs_fs): Likewise. - * fs/hfsplus.c [GRUB_UTIL] (grub_hfsplus_fs): Likewise. - * util/i386/pc/grub-setup.c (setup): Add safety check that probes for - filesystems which begin at first sector. - (options): New option --skip-fs-probe. - (main): Handle --skip-fs-probe and pass it to setup(). - -2009-10-25 Robert Millan - - * include/grub/misc.h: Fix wrong evaluation of APPLE_CC. - (memset): Fix function prototype. - -2009-10-25 Robert Millan -2009-10-25 Vasily Averin - - * fs/ext2.c (grub_ext2_iterate_dir): Avoid infinite loop when - `dirent.direntlen == 0'. - -2009-10-25 Robert Millan - - * fs/cpio.c [MODE_USTAR]: Initialize `tar' module instead of - `cpio'. - [! MODE_USTAR]: Initialize `cpio' module instead of `tar'. - -2009-10-25 Robert Millan - - * configure.ac: Check for `__ashldi3', `__ashrdi3', `__lshrdi3', - `__trampoline_setup' and `__ucmpdi2'. - * include/grub/powerpc/libgcc.h: Only export symbols for functions - that libgcc provides. - -2009-10-25 Robert Millan - - * include/grub/powerpc/libgcc.h (memset): Remove function prototype. - * include/grub/sparc64/libgcc.h (memset): Likewise. - * include/grub/misc.h (memset, memcmp): New function prototypes. - -2009-10-25 Robert Millan - - * fs/cpio.c [MODE_USTAR]: Finish `tar' module instead of - `cpio'. - [! MODE_USTAR]: Finish `cpio' module instead of `tar'. - -2009-10-25 Robert Millan - - Patch from Samuel Thibault - * docs/grub.cfg: Compensate for recent change in multiboot - loader (since 2009-08-14 it won't pass filename to payload). - * util/grub.d/10_hurd.in: Likewise. - -2009-10-21 Felix Zielcke - - * config.guess: Update to latest version from config git - repository. - * config.sub: Likewise. - -2009-10-20 Robert Millan - - Fix build on sparc64. - - * configure.ac: Perform checks for libgcc symbols before - adding `-nostdlib' to LDFLAGS. - -2009-10-16 Vladimir Serbinenko - - Let user specify OpenBSD root device. - - * loader/i386/bsd.c (openbsd_root): New variable. - (openbsd_opts): New option 'root'. - (OPENBSD_ROOT_ARG): New macro. - (grub_openbsd_boot): Use 'openbsd_root'. - (grub_cmd_openbsd): Fill 'openbsd_root'. - -2009-10-16 Robert Millan - - * NEWS: Misc adjustments. - -2009-10-16 Vladimir Serbinenko - - * NEWS: Mentioned XNU, ACPI, gptsync, password and parttool. - -2009-10-16 Robert Millan - - * configure.ac: Bump version to 1.97. - -2009-10-16 Colin Watson - - * configure.ac (TARGET_CFLAGS): Add -mno-mmx -mno-sse -mno-sse2 - -mno-3dnow on x86 architectures. Some toolchains enable these - features by default, but they rely on registers that aren't enabled - in GRUB. Thanks to Vladimir Serbinenko for the suggestion. - -2009-10-15 Robert Millan - - Make entry text a bit more readable. - - * util/grub.d/10_linux.in: Add `with' before `Linux'. - -2009-10-15 Vladimir Serbinenko - - * loader/i386/pc/xnu.c (grub_xnu_set_video): Fix loading splash image. - -2009-10-15 Vladimir Serbinenko - - * commands/xnu_uuid.c (grub_cmd_xnu_uuid): Remove duplicated bitwise - operations. - -2009-10-15 Vladimir Serbinenko - - * configure.ac: Add missing dollar. - -2009-10-15 Vladimir Serbinenko - - Revert 2009-06-10 Pavel Roskin - - * configure.ac: Put checks for __bswapsi2 and __bswapdi2. - * include/grub/powerpc/libgcc.h: Don't use weak attribute for all - exports. - * include/grub/sparc64/libgcc.h: Likewise. Use - preprocessor conditionals. - -2009-10-14 Robert Millan - - * conf/common.rmk (grub-dumpbios): Remove rule. - (sbin_SCRIPTS, CLEANFILES): Remove `grub-dumpbios'. - * util/grub-dumpbios.in: Remove file. - -2009-10-14 Robert Millan - - Refer to kernel of FreeBSD "kFreeBSD" to avoid confusion between - the Operating System (FreeBSD) and its kernel (kernel of FreeBSD). - - * loader/i386/bsd.c (grub_freebsd_boot): Read kernel environment - from "kFreeBSD" namespace (rather than "FreeBSD"). Update all - users. - - (GRUB_MOD_INIT (bsd)): Rename "freebsd" command to "kfreebsd", - "openbsd" to "kopenbsd", "netbsd" to "knetbsd", "freebsd_loadenv" - to "kfreebsd_loadenv", "freebsd_module" to "kfreebsd_module", - and "freebsd_module_elf" to "kfreebsd_module_elf". Update all - users. - -2009-10-12 Robert Millan - - * term/tparm.c: Switch to GPLv3. - -2009-10-09 Robert Millan - - * include/grub/i386/cpuid.h: Add header protection. - -2009-10-09 Robert Millan - - Fail gracefuly when attempting to load 64-bit kFreeBSD on IA32 CPU. - - * include/grub/i386/cpuid.h: New file. - * commands/i386/cpuid.c: Include `'. - (has_longmode): Rename to ... - (grub_cpuid_has_longmode): ... this. Update all users. Remove - `static' attribute. - * loader/i386/bsd.c: Include `'. - (grub_bsd_load_elf): Fail if load of 64-bit kernel was requested - on a CPU that doesn't implement AMD64 instruction set. - -2009-10-06 Colin Watson - - * Makefile.in (docs/stamp-vti): Depend on configure.ac as well, so - that version.texi is rebuilt on version number changes. - -2009-10-06 Colin Watson - - * Makefile.in: Don't set info_INFOS unless makeinfo was found. - Fixes bug #27602. - -2009-10-06 Colin Watson - - * util/i386/pc/grub-install.in: Source - ${libdir}/grub/grub-mkconfig_lib before option processing, in order - that the --grub-probe option will work. - * util/sparc64/ieee1275/grub-install.in: Likewise. - -2009-10-05 Robert Millan - - * configure.ac: Bump version to 1.97~beta4. - -2009-10-03 Robert Millan - - Resync grub-mkdevicemap in x86_64-efi. - - * conf/x86_64-efi.rmk (sbin_UTILITIES): Enable `grub-mkdevicemap'. - (grub_mkdevicemap_SOURCES): Add missing `util/deviceiter.c' and - `util/devicemap.c'. - -2009-10-01 Colin Watson - - * util/grub-editenv.c (create_envblk_file): Write new block with a - .new suffix and then rename it into place, to ensure atomic - creation. - -2009-09-28 Robert Millan - - Do not automatically install headers. - - * Makefile.in (include_DATA): Remove. Update all users. - -2009-09-26 Robert Millan - - * conf/common.rmk (pkglib_MODULES): Remove `lua.mod'. - (lua_mod_SOURCES, lua_mod_CFLAGS, lua_mod_LDFLAGS): Remove. - - * util/osdetect.lua: Remove. - * script/lua/lauxlib.c: Likewise. - * script/lua/ldebug.c: Likewise. - * script/lua/grub_main.c: Likewise. - * script/lua/lauxlib.h: Likewise. - * script/lua/ldebug.h: Likewise. - * script/lua/ltablib.c: Likewise. - * script/lua/liolib.c: Likewise. - * script/lua/lstrlib.c: Likewise. - * script/lua/lualib.h: Likewise. - * script/lua/ldo.c: Likewise. - * script/lua/ldump.c: Likewise. - * script/lua/ldo.h: Likewise. - * script/lua/loslib.c: Likewise. - * script/lua/lundump.c: Likewise. - * script/lua/grub_lib.c: Likewise. - * script/lua/ldblib.c: Likewise. - * script/lua/lundump.h: Likewise. - * script/lua/lmem.c: Likewise. - * script/lua/grub_lib.h: Likewise. - * script/lua/lmathlib.c: Likewise. - * script/lua/lstate.c: Likewise. - * script/lua/ltm.c: Likewise. - * script/lua/lvm.c: Likewise. - * script/lua/lmem.h: Likewise. - * script/lua/lstate.h: Likewise. - * script/lua/ltm.h: Likewise. - * script/lua/ltable.c: Likewise. - * script/lua/lvm.h: Likewise. - * script/lua/llex.c: Likewise. - * script/lua/lgc.c: Likewise. - * script/lua/grub_lua.h: Likewise. - * script/lua/loadlib.c: Likewise. - * script/lua/lfunc.c: Likewise. - * script/lua/lopcodes.c: Likewise. - * script/lua/lparser.c: Likewise. - * script/lua/ltable.h: Likewise. - * script/lua/llex.h: Likewise. - * script/lua/lgc.h: Likewise. - * script/lua/lfunc.h: Likewise. - * script/lua/lbaselib.c: Likewise. - * script/lua/lopcodes.h: Likewise. - * script/lua/lparser.h: Likewise. - * script/lua/lzio.c: Likewise. - * script/lua/linit.c: Likewise. - * script/lua/lobject.c: Likewise. - * script/lua/llimits.h: Likewise. - * script/lua/lstring.c: Likewise. - * script/lua/lzio.h: Likewise. - * script/lua/lapi.c: Likewise. - * script/lua/lcode.c: Likewise. - * script/lua/lua.h: Likewise. - * script/lua/lobject.h: Likewise. - * script/lua/lstring.h: Likewise. - * script/lua/lapi.h: Likewise. - * script/lua/lcode.h: Likewise. - * script/lua/luaconf.h: Likewise. - -2009-09-26 Colin Watson - - * docs/grub.texi (Command-line and menu entry commands): Document - date and echo commands. - -2009-09-24 Pavel Roskin - - * include/grub/kernel.h (struct grub_module_header): Remove - `grub_module_header_types'. Make `type' unsigned. Make `size' - 32-bit on all platforms. - * util/elf/grub-mkimage.c (load_modules): Treat `type' as an - 8-bit field. Use grub_host_to_target32() for `size'. - * util/i386/efi/grub-mkimage.c (make_mods_section): Likewise. - * util/i386/pc/grub-mkimage.c (generate_image): Likewise. - * util/sparc64/ieee1275/grub-mkimage.c (generate_image): Likewise. - -2009-09-24 Robert Millan - - Fix "lost keypress" bug in at_keyboard. - - * term/i386/pc/at_keyboard.c (grub_at_keyboard_checkkey): New function. - Checks for readyness of input buffer (without flushing it). - (grub_at_keyboard_term): Use grub_at_keyboard_checkkey() rather - than grub_at_keyboard_getkey_noblock() for `checkkey' struct member. - -2009-09-24 Robert Millan - - * util/i386/pc/grub-mkimage.c (generate_image): Enclose BIOS-specific - size check within GRUB_MACHINE_PCBIOS section. - -2009-09-24 Robert Millan - - * include/grub/i386/at_keyboard.h (KEYBOARD_ISREADY): Negate - return value. - * term/i386/pc/at_keyboard.c (grub_keyboard_getkey): Negate - KEYBOARD_ISREADY check. - (grub_at_keyboard_checkkey): Rename to ... - (grub_at_keyboard_getkey_noblock): ... this. Update all users. - Remove gratuitous cast. - -2009-09-23 Colin Watson - - * configure.ac: Call AC_PROG_MKDIR_P. - * Makefile.in (docs/stamp-vti): Create docs directory. Create - version.texi in $(builddir) rather than $(srcdir). - (docs/grub.info): Create docs directory. Prepend $(builddir)/docs - to makeinfo's @include search path. - -2009-09-23 Felix Zielcke - - * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Cope with `*.dpkg-*' - -2009-09-23 Felix Zielcke - - * util/grub-mkconfig_lib.in (grub_file_is_not_garbage): Add support - for `*.dpkg-new'. - -2009-09-21 Colin Watson - - Build info documentation. Some code borrowed from Automake. - - * configure.ac: Check for makeinfo. - * Makefile.in (MAKEINFO, INFOS, info_INFOS): New variables. - (MAINTAINER_CLEANFILES): Add $(INFOS), docs/stamp-vti, and - docs/version.texi. - (MOSTLYCLEANFILES): Add vti.tmp. - (docs/version.texi, docs/stamp-vti): Update automatically. - (docs/grub.info): Build info documentation. Use --force and ignore - errors for now. - (all-local): Add $(INFOS). - (install-local): Install info files. - (uninstall): Uninstall info files. - * docs/version.texi: Remove from revision control. This file is - automatically generated on build now. - * gendistlist.sh: Add `*.info'. - -2009-09-21 Felix Zielcke - - * kern/term.c: Fix indentation. - -2009-09-21 Felix Zielcke - - * util/hostdisk.c: Fix a comment. - -2009-09-20 Robert Millan - - Fix regression introduced in r2539. - - * term/usb_keyboard.c (USB_HID_DEVICE_TO_HOST): Change from 0x61 - to 0xA1. - -2009-09-19 Colin Watson - - * util/grub.d/30_os-prober.in: Don't throw away stderr from - os-prober. Under normal operation, it does not print anything to - stderr; if it does, we need to debug it, and throwing away stderr - makes that excessively difficult. - -2009-09-16 Vladimir Serbinenko - - * mmap/mmap.c (grub_cmd_badram): Fix off-by-one error. - -2009-09-16 Robert Millan - - * aclocal.m4 (AC_LANG_PROGRAM): New macro. Overrides stock - AC_LANG_PROGRAM from autoconf. - (grub_ASM_USCORE, grub_PROG_OBJCOPY_ABSOLUTE): Add missing - prototypes (fixes warning). - - * configure.ac: Add `-Werror' to TARGET_CFLAGS unless - `--disable-werror' was used. - -2009-09-16 Robert Millan - - * partmap/msdos.c (pc_partition_map_iterate): Fix possible use of - uninitialized `lastaddr'. - -2009-09-15 Vladimir Serbinenko - - * partmap/msdos.c (pc_partition_map_iterate): Detect and break loops. - -2009-09-14 Colin Watson - - * commands/test.c (get_fileinfo): Return immediately if - grub_fs_probe fails. - -2009-09-14 JosĂ© MartĂ­nez - - * commands/acpi.c (grub_cmd_acpi): Fix loading ACPI tables from file. - -2009-09-14 Colin Watson - - * util/grub.d/30_os-prober.in: Cope with Windows 7 in os-prober - output. - -2009-09-13 Robert Millan - - * configure.ac: Remove --enable-grub-pe2elf. Only build - grub-pe2elf when needed by the build system itself. - * conf/common.rmk: Remove $(enable_grub_pe2elf) check. - -2009-09-12 Robert Millan - - * configure.ac: Bump version to 1.97~beta3. - * docs/version.texi: Likewise. - -2009-09-12 Robert Millan - - * video/i386/pc/vbe.c (grub_vbe_get_video_mode_info): Move packed - mode special handling (grub_vbe_bios_set_dac_palette_width() call) - from here ... - * loader/i386/linux.c [GRUB_MACHINE_PCBIOS] - (grub_linux_setup_video): ... to here (with some adjustments). - -2009-09-12 Robert Millan - - Fix memory corruption issue (spotted by Colin Watson). - - * kern/i386/pc/startup.S (grub_vbe_bios_getset_dac_palette): Fix bug - causing returned size to be stored in an incorrect memory location. - Fix use of uninitialized value when storing the returned size. - -2009-09-12 Yves Blusseau - - Change clean rules to properly remove files - - * genmk.rb: add new clean rules - * Makefile.in (clean): add the new targets - (mostlyclean): likewise - -2009-09-11 Colin Watson - - * include/grub/ntfs.h (struct grub_fshelp_node): Change `size' - to grub_uint64_t. - * fs/ntfs.c (init_file): Understand 64-bit sizes for - non-resident files. - -2009-09-11 Colin Watson - - * configure.ac: Don't look for help2man when cross-compiling. Fixes - part of bug #27349. - -2009-09-10 Felix Zielcke - - * util/grub-mkconfig.in: Make the created config mode 400 and - print a warning if it fails. - -2009-09-10 Robert Millan - - * util/grub.d/40_custom.in: Ask user to type custom entries below - comment, rather than below 'exec tail' line. - -2009-09-10 Colin Watson - - * util/grub.d/40_custom.in: Make sure that the explanatory text is - visible in grub.cfg. - -2009-09-10 Colin Watson - - * util/grub.d/40_custom.in: Make it a little clearer how to use this - file. - -2009-09-10 Felix Zielcke - - * docs/grub.cfg: Add an example menu entry for memtest86+. - -2009-09-09 Felix Zielcke - - * config.guess: Update to latest version from config git. - * config.sub: Likewise. - -2009-09-08 Colin Watson - - * script/sh/execute.c (grub_script_execute_cmdline): Set "?" in - unknown-command case. Fixes bug #27320. - -2009-09-08 Felix Zielcke - - * kern/rescue_parser.c (grub_rescue_parse_line): Only suggest to try - `help' if the command exists. - -2009-09-06 Robert Millan - - * INSTALL: Require GCC 4.1.3 or later. - -2009-09-06 Yves Blusseau - - * Makefile.in (RMKFILES): add i386-qemu.rmk - (MAINTAINER_CLEANFILES): add $(srcdir)/DISTLIST $(srcdir)/config.h.in - $(srcdir)/stamp-h.in - -2009-09-05 Robert Millan - - * util/grub-probe.c (probe): Comment out buggy codepath, which - was unexpectedly enabled by Colin Watson's 2009-09-02 fix. This - should be re-enabled after 1.97. - -2009-09-05 Felix Zielcke - - * gendistlist.sh: Add `grub-dumpdevtree' and `*.lua' to the list - find searches for. - -2009-09-04 Vladimir Serbinenko - - * loader/i386/xnu.c (grub_cpu_xnu_fill_devicetree): Remove - unnecessary calls to grub_error. - -2009-09-04 Colin Watson - - * NEWS: Mention `keystatus' and Unicode fonts. - -2009-09-04 Robert Millan - - * configure.ac: Bump version to 1.97~beta2. - * docs/version.texi: Likewise. - -2009-09-03 Colin Watson - - * configure.ac: By default, GCC 4.4 generates .eh_frame sections - containing unwind information in some cases where it previously did - not. Use -fno-dwarf2-cfi-asm if available to restore the old - behaviour. See http://patchwork.kernel.org/patch/8555/ for related - discussion. - -2009-09-02 Yves BLUSSEAU - - Embedding loadenv module into grub-emu - - * conf/i386-pc.rmk (grub_emu_SOURCES): add lib/envblk.c and - commands/loadenv.c - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Likewise - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise - -2009-09-03 Magnus Granberg - - * aclocal.m4: Add grub_CHECK_PIE. It check if the compiler - include -fPIE in the default specs. - * configure.ac: Check if pie_possible is yes and add -fno-PIE - to TARGET_CFLAGS. - -2009-09-03 Felix Zielcke - - * INSTALL: Note that GNU Bison 2.3 or later is required. - -2009-09-03 Colin Watson - - * kern/i386/pc/startup.S: Fix typo. - -2009-09-02 Vladimir Serbinenko - - * efiemu/loadcore.c (SUFFIX (grub_efiemu_loadcore_load)): Fix style - according to GCS. - -2009-09-02 Colin Watson - - * docs/grub.texi (Naming convention): Describe one-based partition - numbering. - (Device syntax): Likewise. - (File name syntax): Likewise. - (Block list syntax): Likewise. - (Making a GRUB bootable CD-ROM): Talk about grub.cfg rather than - menu.lst. - (File name syntax): Likewise. - (Command-line and menu entry commands): Document acpi, blocklist, - crc, export, insmod, keystatus, ls, set, and unset commands. - -2009-09-02 Colin Watson - - * commands/keystatus.c (GRUB_MOD_INIT (keystatus)): Adjust summary - to avoid implying that only one of --shift, --ctrl, or --alt may be - used. - -2009-09-02 Colin Watson - - * util/grub-probe.c (probe): Test st.st_mode using S_ISREG macro - rather than comparing against S_IFREG, which will almost never work. - -2009-09-01 Vladimir Serbinenko - - * commands/loadenv.c (check_blocklists): Fix off-by-one error. - (write_blocklists): Likewise. - -2009-09-01 Colin Watson - - * script/lua/grub_lua.h (fputs): Supply a format string as the first - argument to grub_printf. - -2009-09-01 Felix Zielcke - - * genmk.rb: Add quotes around $(TARGET_OBJ2ELF) to cope with - non GNU test. - -2009-08-30 Vladimir Serbinenko - - * kern/file.c (grub_file_read): Spelling fix - -2009-08-30 Vladimir Serbinenko - - * loader/i386/bsdXX.c (SUFFIX (grub_freebsd_load_elfmodule)): Fix - loading of headers in some cases. - -2009-08-30 Robert Millan - - * configure.ac: Bump version to 1.97~beta1. - * docs/version.texi: Likewise. - -2009-08-29 Vladimir Serbinenko - - * include/grub/i386/xnu.h: Add license header. - include grub/err.h explicitly. - -2009-08-29 Robert Millan - - * util/grub.d/10_freebsd.in: Detect `ufs1' and `ufs2' and map them - to `ufs' in the vfs.root.mountfrom kernel parameter. - -2009-08-29 Robert Millan - - * term/i386/pc/serial.c: Include `'. - - [GRUB_MACHINE_PCBIOS] (serial_hw_io_addr): Macroify initialization - value (0x0400 -> GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR). - - [! GRUB_MACHINE_PCBIOS] (GRUB_SERIAL_PORT_NUM): Calculate using - `ARRAY_SIZE' macro. - -2009-08-28 Vladimir Serbinenko - - * kern/file.c (grub_file_read): Check offset. - * fs/hfs.c (grub_hfs_read_file): Remove unnecessary offset check. - * fs/jfs.c (grub_jfs_read_file): Likewise. - * fs/ntfs.c (grub_ntfs_read): Likewise. - * fs/reiserfs.c (grub_reiserfs_read): Likewise. - * fs/minix.c (grub_minix_read_file): Correct offset check. - * fs/ufs.c (grub_ufs_read_file): Likewise. - -2009-08-28 Colin Watson - - * term/i386/pc/console.c (bios_data_area): Cast - GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR explicitly. - -2009-08-28 Vladimir Serbinenko - - 1-bit optimised blitters. - - * include/grub/fbblit.h (grub_video_fbblit_replace_32bit_1bit): New - prototype. - (grub_video_fbblit_replace_24bit_1bit): Likewise. - (grub_video_fbblit_replace_16bit_1bit): Likewise. - (grub_video_fbblit_replace_8bit_1bit): Likewise. - (grub_video_fbblit_blend_XXXA8888_1bit): Likewise. - (grub_video_fbblit_blend_XXX888_1bit): Likewise. - (grub_video_fbblit_blend_XXX565_1bit): Likewise. - * video/fb/fbblit.c (grub_video_fbblit_replace_32bit_1bit): New - function. - (grub_video_fbblit_replace_24bit_1bit): Likewise. - (grub_video_fbblit_replace_16bit_1bit): Likewise. - (grub_video_fbblit_replace_8bit_1bit): Likewise. - (grub_video_fbblit_blend_XXXA8888_1bit): Likewise. - (grub_video_fbblit_blend_XXX888_1bit): Likewise. - (grub_video_fbblit_blend_XXX565_1bit): Likewise. - * video/fb/video_fb.c (common_blitter): Use 1-bit optimised blitters - when possible. - * video/video.c (grub_video_get_blit_format): Return - GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED if bpp = 1. - -2009-08-28 Colin Watson - - * normal/cmdline.c (grub_cmdline_get): Supply a format string as - the first argument to grub_printf. - -2009-08-28 Colin Watson -2009-08-28 Robert Millan - - Add `getkeystatus' terminal method. Add a new `keystatus' command - to query it. - - * include/grub/term.h (GRUB_TERM_STATUS_SHIFT, - GRUB_TERM_STATUS_CTRL, GRUB_TERM_STATUS_ALT): Definitions for - modifier key bitmasks. - (struct grub_term_input): Add `getkeystatus' member. - (grub_getkeystatus): Add prototype. - * kern/term.c (grub_getkeystatus): New function. - - * include/grub/i386/pc/memory.h - (GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR): New macro. - (struct grub_machine_bios_data_area): Define necessary parts of BIOS - Data Area layout. - * term/i386/pc/console.c (grub_console_getkeystatus): New function. - (grub_console_term_input): Set `getkeystatus' member. - * term/usb_keyboard.c (grub_usb_hid): Macroify HID protocol - constants. - (grub_usb_keyboard_getreport): Likewise. - (grub_usb_keyboard_checkkey): Likewise. - (grub_usb_keyboard_getkeystatus): New function. - (grub_usb_keyboard_term): Set `getkeystatus' member. - - * commands/keystatus.c: New file. - * conf/common.rmk (pkglib_MODULES): Add keystatus.mod. - (keystatus_mod_SOURCES): New variable. - (keystatus_mod_CFLAGS): Likewise. - (keystatus_mod_LDFLAGS): Likewise. - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add - commands/keystatus.c. - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise. - -2009-08-28 Vladimir Serbinenko - - Split befs.mod and afs.mod into *_be.mod and *.mod - - * conf/common.rmk (grub_probe_SOURCES): Add afs_be.c and befs_be.c. - (grub_fstest_SOURCES): Likewise. - (pkglib_MODULES): Add afs_be.mod and befs_be.mod. - (afs_be_mod_SOURCES): New variable. - (afs_be_mod_CFLAGS): Likewise. - (afs_be_mod_LDFLAGS): Likewise. - (befs_be_mod_SOURCES): Likewise. - (befs_be_mod_CFLAGS): Likewise. - (befs_be_mod_LDFLAGS): Likewise. - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add afs_be.c and befs_be.c. - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-pc.rmk (grub_setup_SOURCES): Likewise. - (grub_emu_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise. - * fs/afs_be.c: New file. - * fs/befs_be.c: New file. - * fs/afs.c (GRUB_AFS_FSNAME_SUFFIX): New definition. - (GRUB_AFS_FSNAME): Use GRUB_AFS_FSNAME_SUFFIX. - (U16): Replaced with ... - (grub_afs_to_cpu16): ...this. All users updated. - (U32): Replaced with ... - (grub_afs_to_cpu32): ...this. All users updated. - (U64): Replaced with ... - (grub_afs_to_cpu64): ...this. All users updated. - (GRUB_AFS_BO_LITTLE_ENDIAN): Remove. - (GRUB_AFS_BO_BIG_ENDIAN): Likewise. - (grub_afs_validate_sblock): Check only one endianness. - (GRUB_MOD_INIT (befs)) [MODE_BIGENDIAN && MODE_BFS]: Rename to .. - (GRUB_MOD_INIT (befs_be)) [MODE_BIGENDIAN && MODE_BFS]: ... this. - (GRUB_MOD_INIT (afs)) [MODE_BIGENDIAN && !MODE_BFS]: Rename to .. - (GRUB_MOD_INIT (afs_be)) [MODE_BIGENDIAN && !MODE_BFS]: ... this. - (GRUB_MOD_FINI (befs)) [MODE_BIGENDIAN && MODE_BFS]: Rename to .. - (GRUB_MOD_FINI (befs_be)) [MODE_BIGENDIAN && MODE_BFS]: ... this. - (GRUB_MOD_FINI (afs)) [MODE_BIGENDIAN && !MODE_BFS]: Rename to .. - (GRUB_MOD_FINI (afs_be)) [MODE_BIGENDIAN && !MODE_BFS]: ... this. - -2009-08-26 Bean - - * fs/xfs.c (GRUB_XFS_INO_INOINAG): Replace 1L with 1LL to support - 64-bit number. - (GRUB_XFS_FSB_TO_BLOCK): Likewise. - (grub_xfs_inode_block): Change return type to grub_uint64_t. - (grub_xfs_read_inode): Change type of block to grub_uint64_t. - -2009-08-25 Vladimir Serbinenko - - NetBSD memory map support. - - * include/grub/i386/bsd.h (NETBSD_BTINFO_MEMMAP): New definition. - (grub_netbsd_btinfo_mmap_header): New structure. - (grub_netbsd_btinfo_mmap_entry): Likewise. - * loader/i386/bsd.c (grub_netbsd_boot): Pass memory map. - -2009-08-25 Vladimir Serbinenko - - Enable bsd.mod on coreboot. - - * conf/i386-coreboot.rmk (pkglib_MODULES): Add bsd.mod. - (bsd_mod_SOURCES): New variable. - (bsd_mod_CFLAGS): Likewise. - (bsd_mod_LDFLAGS): Likewise. - (bsd_mod_ASFLAGS): Likewise. - * loader/i386/bsd.c [!GRUB_MACHINE_PCBIOS]: Fix includes. - (grub_bsd_get_device) [!GRUB_MACHINE_PCBIOS]: Set *biosdev to 0xff. - -2009-08-25 Vladimir Serbinenko - - Cleanup NetBSD root support. - - * loader/i386/bsd.c (grub_netbsd_boot): Remove call to - grub_bsd_get_device. - Fix typo. - -2009-08-25 Felix Zielcke - - * util/grub.d/00_header.in: Move check for the video backend of - gfxterm from here ... - * util/grub-mkconfig.in: ... to here. Enable gfxterm if there's - a suitable video backend. - -2009-08-25 Vladimir Serbinenko - - Fix breakage in grub-setup. - - * util/i386/pc/grub-setup.c (setup): Use "part_msdos" instead of - "msdos_partition_map". - -2009-08-25 Vladimir Serbinenko - - Fix breakage in normal/auth.c. - - * normal/auth.c (grub_iswordseparator): New function. - -2009-08-25 Vladimir Serbinenko - - Authentication support. - - * commands/password.c: New file. - * conf/common.rmk (pkglib_MODULES): Add password.mod. - (password_mod_SOURCES): New variable. - (password_mod_CFLAGS): Likewise. - (password_mod_LDFLAGS): Likewise. - (normal_mod_SOURCES): Add normal/auth.c. - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add commands/password.c and - normal/auth.c. - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise. - * include/grub/auth.h: New file. - * include/grub/err.h (grub_err_t): New enum value - GRUB_ERR_ACCESS_DENIED. - * include/grub/menu.h (grub_menu_entry): New fields 'restricted' and - 'users'. - * include/grub/normal.h (grub_cmdline_get): New argument 'history'. - * normal/cmdline.c (grub_cmdline_get): New argument 'history'. All - users updated. - * normal/auth.c: New file. - * normal/main.c (grub_normal_add_menu_entry): Handle --users option. - (grub_cmdline_run): Don't allow to go to command line without - authentication. - * normal/menu.c (grub_menu_execute_entry): Handle restricted entries. - * normal/menu_entry.c (grub_menu_entry_run): Don't allow editing - menuentry without superuser rights. - * normal/menu_viewer.c (grub_menu_viewer_show_menu): Don't exit if - user isn't a superuser. - -2009-08-24 Vladimir Serbinenko - - Save space by inlining misc.c functions. - - * kern/misc.c (grub_iswordseparator): Made static. - * kern/misc.c (grub_strcat): Moved from here ... - * include/grub/misc.h (grub_strcat): ... here. Inlined. - * kern/misc.c (grub_strncat): Moved from here ... - * include/grub/misc.h (grub_strncat): ... here. Inlined. - * kern/misc.c (grub_strcasecmp): Moved from here ... - * include/grub/misc.h (grub_strcasecmp): ... here. Inlined. - * kern/misc.c (grub_strncasecmp): Moved from here ... - * include/grub/misc.h (grub_strncasecmp): ... here. Inlined. - * kern/misc.c (grub_isalpha): Moved from here ... - * include/grub/misc.h (grub_isalpha): ... here. Inlined. - * kern/misc.c (grub_isdigit): Moved from here ... - * include/grub/misc.h (grub_isdigit): ... here. Inlined. - * kern/misc.c (grub_isgraph): Moved from here ... - * include/grub/misc.h (grub_isgraph): ... here. Inlined. - * kern/misc.c (grub_tolower): Moved from here ... - * include/grub/misc.h (grub_tolower): ... here. Inlined. - -2009-08-24 Vladimir Serbinenko - - * script/sh/function.c (grub_script_function_find): Cut error message - not to flood terminal. - * script/sh/lexer.c (grub_script_yylex): Remove command line length - limit. - * script/sh/script.c (grub_script_arg_add): Duplicate string. - -2009-08-24 Colin Watson - - * term/usb_keyboard.c (grub_usb_keyboard_getreport): Make - `report' grub_uint8_t *. - (grub_usb_keyboard_checkkey): Make `data' elements grub_uint8_t. - Use a 50-millisecond timeout rather than just repeating - grub_usb_keyboard_getreport 50 times. - (grub_usb_keyboard_getkey): Make `data' elements grub_uint8_t. - -2009-08-24 Vladimir Serbinenko - - Rename *_partition_map to part_* - - * partmap/acorn.c (grub_acorn_partition_map): Set name to 'part_acorn'. - * partmap/amiga.c (grub_amiga_partition_map): Set name to 'part_amiga'. - * partmap/apple.c (grub_apple_partition_map): Set name to 'part_apple'. - * partmap/gpt.c (grub_gpt_partition_map): Set name to 'part_gpt'. - All users updated. - * partmap/msdos.c (grub_msdos_partition_map): Set name to 'part_msdos'. - All users updated. - * partmap/sun.c (grub_sun_partition_map): Set name to 'part_sun'. - * util/grub-probe.c (probe_partmap): Don't transform partition name - to get module name. - -2009-08-24 Vladimir Serbinenko - - Fix OpenBSD and NetBSD support. - - * include/grub/i386/bsd.h (GRUB_BSD_TEMP_BUFFER): Change to resolve - memory address conflict. - (OPENBSD_MMAP_ACPI): New definition. - (OPENBSD_MMAP_NVS): Likewise. - * loader/i386/bsd.c (grub_openbsd_boot): Support OPENBSD_MMAP_ACPI - and OPENBSD_MMAP_NVS. - Add memory map terminator - Explicit cast when calling grub_unix_real_boot. - (grub_netbsd_boot): Explicit cast when calling grub_unix_real_boot. - -2009-08-24 Vladimir Serbinenko - - Let user specify NetBSD root device. - - * loader/i386/bsd.c (netbsd_root): New variable. - (netbsd_opts): New option 'root'. - (NETBSD_ROOT_ARG): New macro. - (grub_netbsd_boot): Use 'netbsd_root'. - (grub_bsd_unload): Free 'netbsd_root'. - (grub_cmd_netbsd): Fill 'netbsd_root'. - -2009-08-24 Vladimir Serbinenko - - Support for 64-bit NetBSD. - - * loader/i386/bsd.c (grub_bsd_load_elf): Apply correct mask to entry - point when booting non-FreeBSD. - -2009-08-24 Vladimir Serbinenko - - Support --no-smp and --no-acpi for NetBSD. - - * include/grub/i386/bsd.h (NETBSD_AB_NOSMP): New definition. - (NETBSD_AB_NOACPI): Likewise. - * loader/i386/bsd.c (netbsd_opts): New entries no-smp and no-acpi. - (netbsd_flags): Add NETBSD_AB_NOSMP, NETBSD_AB_NOACPI. - -2009-08-23 Vladimir Serbinenko - - * fs/hfsplus.c (grub_hfsplus_mount): Don't ignore grub_hfsplus_read_file - errors. - (grub_hfsplus_btree_iterate_node): Don't ignore grub_hfsplus_read_file - errors. Call grub_error when needed. - -2009-08-23 Vladimir Serbinenko - - * commands/search.c (search_fs): Try searching without autoload first. - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Load - filesystem module explicitly for faster booting. - -2009-08-23 Colin Watson - - * util/grub-mkconfig.in: Export GRUB_DISABLE_OS_PROBER. - -2009-08-23 Colin Watson - - * util/grub.d/30_os-prober.in: Disable os-prober if - `GRUB_DISABLE_OS_PROBER' was set to true. - -2009-08-23 Robert Millan - - * partmap/pc.c: Rename to ... - * partmap/msdos.c: ... this. Update all users. - (grub_pc_partition_map): Rename to ... - (grub_msdos_partition_map): ... this. Update all users. - - * parttool/pcpart.c: Rename to ... - * parttool/msdospart.c: ... this. Update all users. - - * include/grub/pc_partition.h: Rename to ... - * include/grub/msdos_partition.h: ... this. Update all users. - (grub_pc_partition_bsd_entry): Rename to ... - (grub_msdos_partition_bsd_entry): ... this. Update all users. - (grub_pc_partition_disk_label): Rename to ... - (grub_msdos_partition_disk_label): ... this. Update all users. - (grub_pc_partition_entry): Rename to ... - (grub_msdos_partition_entry): ... this. Update all users. - (grub_pc_partition_mbr): Rename to ... - (grub_msdos_partition_mbr): ... this. Update all users. - (grub_pc_partition): Rename to ... - (grub_msdos_partition): ... this. Update all users. - (grub_pc_partition_is_empty): Rename to ... - (grub_msdos_partition_is_empty): ... this. Update all users. - (grub_pc_partition_is_extended): Rename to ... - (grub_msdos_partition_is_extended): ... this. Update all users. - (grub_pc_partition_is_bsd): Rename to ... - (grub_msdos_partition_is_bsd): ... this. Update all users. - - * conf/common.rmk (amiga_mod_SOURCES, amiga_mod_CFLAGS) - (amiga_mod_LDFLAGS, apple_mod_SOURCES, apple_mod_CFLAGS) - (apple_mod_LDFLAGS, msdos_mod_SOURCES, msdos_mod_CFLAGS) - (msdos_mod_LDFLAGS, sun_mod_SOURCES, sun_mod_CFLAGS) - (sun_mod_LDFLAGS, acorn_mod_SOURCES, acorn_mod_CFLAGS) - (acorn_mod_LDFLAGS, gpt_mod_SOURCES, gpt_mod_CFLAGS) - (gpt_mod_LDFLAGS): Rename to ... - (part_amiga_mod_SOURCES, part_amiga_mod_CFLAGS, part_amiga_mod_LDFLAGS) - (part_apple_mod_SOURCES, part_apple_mod_CFLAGS, part_apple_mod_LDFLAGS) - (part_msdos_mod_SOURCES, part_msdos_mod_CFLAGS, part_msdos_mod_LDFLAGS) - (part_sun_mod_SOURCES, part_sun_mod_CFLAGS, part_sun_mod_LDFLAGS) - (part_acorn_mod_SOURCES, part_acorn_mod_CFLAGS, part_acorn_mod_LDFLAGS) - (part_gpt_mod_SOURCES, part_gpt_mod_CFLAGS) - (part_gpt_mod_LDFLAGS): ... this. - (pkglib_MODULES): Prefix partition modules with `part_'. Rename - `pcpart.mod' to `msdospart.mod'. - (pcpart_mod_SOURCES, pcpart_mod_CFLAGS, pcpart_mod_LDFLAGS): Rename - to ... - (msdospart_mod_SOURCES, msdospart_mod_CFLAGS) - (msdospart_mod_LDFLAGS): ... this. - -2009-08-23 Vladimir Serbinenko - - * loader/i386/bsd.c (freebsd_opts): Rewritten to use extcmd. - (openbsd_opts): Likewise. - (netbsd_opts): Likewise. - (freebsd_flags): Added 0 terminator. - (openbsd_flags): Likewise. - (netbsd_flags): Likewise. - (grub_bsd_parse_flags): Rewritten to use extcmd. All users updated. - (grub_cmd_freebsd): Transformed into extended command. - (grub_cmd_openbsd): Likewise. - (grub_cmd_netbsd): Likewise. - (cmd_freebsd): Changed type to grub_extcmd_t. - (cmd_openbsd): Likewise. - (cmd_netbsd): Likewise. - (GRUB_MOD_INIT (bsd)): Register grub_cmd_freebsd, grub_cmd_netbsd and - grub_cmd_openbsd as extended commands. - (GRUB_MOD_FINI (bsd)): Use grub_unregister_extcmd for cmd_freebsd, - cmd_netbsd and cmd_openbsd - -2009-08-22 Vladimir Serbinenko - - * commands/xnu_uuid.c (transform): Use grub_memcpy instead of memcpy. - -2009-08-21 Pavel Roskin - - * Makefile.in (install-local): When checking if a file is in the - build directory, use "test -e" to detect symlinks. - - * Makefile.in (install-local): Remove all files in - $(DESTDIR)$(pkglibdir) before installing new files there. - -2009-08-18 Felix Zielcke - - * util/powerpc/ieee1275/grub-mkrescue.in (grub_mkimage): Use - grub-mkelfimage. - -2009-08-18 Felix Zielcke - - * util/grub-mkconfig.in: Don't use gfxterm by default if not - explicitly specified by the user. - -2009-08-18 Pavel Roskin - - * include/grub/fbfill.h (struct grub_video_fbrender_target): Use - grub_uint8_t pointer for data. - * include/grub/fbutil.h (struct grub_video_fbblit_info): - Likewise. - * video/fb/fbutil.c: Remove unnecessary casts. - -2009-08-17 Michal Suchanek - - VBE cleanup. - - * video/i386/pc/vbe.c (vbe_mode_in_use): Removed (duplicate). - (grub_vbe_set_video_mode): Save active mode info - only after setting the mode. - (grub_video_vbe_setup): Call 'grub_vbe_set_video_mode' with NULL as - second argument. - -2009-08-17 Michal Suchanek - - Rename variables for clarity. - - * video/i386/pc/vbe.c (active_mode_info): Renamed to ... - (active_vbe_mode_info): ... this. All users updated. - (framebuffer): Rename 'active_mode' to 'active_vbe_mode'. - All users updated. - (initial_mode): Rename to ... - (initial_vbe_mode): ... this. All users updated. - (mode_in_use): Rename to .. - (vbe_mode_in_use): ... this. All users updated. - (mode_list): Rename to .. - (vbe_mode_list): ... this. All users updated. - (grub_vbe_set_video_mode): Rename 'mode' to 'vbe_mode', 'mode_info' to - 'vbe_mode_info' and 'old_mode' to 'old_vbe_mode'. - (grub_video_vbe_init): Rename 'rm_mode_list' to 'rm_vbe_mode_list' and - 'mode_list_size' to 'vbe_mode_list_size'. - (grub_video_vbe_setup): Rename 'mode_info' to 'vbe_mode_info', - 'best_mode_info' to 'best_vbe_mode_info' and - 'best_mode' to 'best_vbe_mode' - -2009-08-17 Michal Suchanek - - Remove duplicate grub_video_fb_get_video_ptr. - - * include/grub/fbutil.h (get_data_ptr): Rename to ... - (grub_video_fb_get_video_ptr): ... this. - * include/grub/video_fb.h (grub_video_fb_get_video_ptr): Removed. - * video/fb/fbutil.c: Add comment about addressing. - (get_data_ptr): Rename to ... - (grub_video_fb_get_video_ptr): ... this. All users updated. - * video/fb/video_fb.c (grub_video_fb_get_video_ptr): Remove. - -2009-08-17 Robert Millan - - * fs/fat.c (grub_fat_read_data): Remove `#if 0' braces around the - grub_dprintf() that was just added. - -2009-08-17 Robert Millan - - * loader/i386/linux.c (GRUB_ASSUME_LINUX_HAS_FB_SUPPORT) - (DEFAULT_VIDEO_MODE): Remove macros. - (grub_linux_boot): Remove assumption that Linux has FB support, - and use "text" as default video mode. - -2009-08-15 Vladimir Serbinenko - - * fs/affs.c (grub_affs_read_symlink): Change leftover grub_printf into - grub_dprintf. - * fs/fat.c (grub_fat_read_data): Likewise. - -2009-08-14 Vladimir Serbinenko - - * loader/i386/multiboot.c (grub_multiboot): Don't pass filename to - payload. - (grub_module): Likewise. - -2009-08-14 Vladimir Serbinenko - - * loader/i386/multiboot.c (grub_multiboot_unload): Don't free mbi and - mbi->cmdline but free playground. - -2009-08-14 Vladimir Serbinenko - - Handle group offset on UFS1. - - * fs/ufs.c (grub_ufs_sblock): New field 'cylg_mask'. - (grub_ufs_read_inode) [!MODE_UFS2]: handle cylg_offset and cylg_mask. - -2009-08-14 Vladimir Serbinenko - - Split ufs.mod into ufs1.mod and ufs2.mod. - - * conf/common.rmk (grub_probe_SOURCES): Add fs/ufs2.c. - (grub_fstest_SOURCES): Likewise. - (pkglib_MODULES): Remove ufs.mod. Add ufs1.mod and ufs2.mod. - (ufs_mod_SOURCES): Remove. - (ufs_mod_CFLAGS): Likewise. - (ufs_mod_LDFLAGS): Likewise. - (ufs1_mod_SOURCES): New variable. - (ufs1_mod_CFLAGS): Likewise. - (ufs1_mod_LDFLAGS): Likewise. - (ufs2_mod_SOURCES): New variable. - (ufs2_mod_CFLAGS): Likewise. - (ufs2_mod_LDFLAGS): Likewise. - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add fs/ufs2.c. - * conf/i386-efi.rmk (util/i386/efi/grub-mkimage.c_DEPENDENCIES): - Likewise. - (grub_emu_SOURCES): Likewise. - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise. - (grub_setup_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/sparc64.rmk (grub_emu_SOURCES): Likewise. - (grub_setup_SOURCES): Likewise. - * conf/x86_64-efi.rmk (util/i386/efi/grub-mkimage.c_DEPENDENCIES): - Likewise. - * fs/ufs2.c: New file. - * fs/ufs.c: Separate UFS1 from UFS2 by using preprocessor. - -2009-08-14 Vladimir Serbinenko - - Framebuffer split. - - * commands/i386/pc/vbetest.c (grub_cmd_vbetest): Restore video - subsystem at the end. - * conf/common.rmk (pkglib_MODULES): Add video_fb.mod. - (video_fb_mod_SOURCES): New variable. - (video_fb_mod_CFLAGS): Likewise. - (video_fb_mod_LDFLAGS): Likewise. - * conf/i386-pc.rmk (vbe_mod_SOURCES): Remove video/i386/pc/vbeblit.c, - video/i386/pc/vbefill.c and video/i386/pc/vbeutil.c. - * video/i386/pc/vbeblit.c: Moved from here ... - * video/fb/fbblit.c: ..here. Replaced 'vbe' with 'fb'. - * video/i386/pc/vbefill.c: Moved from here ... - * video/fb/fbfill.c: ..here. Replaced 'vbe' with 'fb'. - * video/i386/pc/vbeutil.c: Moved from here ... - * video/fb/fbutil.c: ..here. Replaced 'vbe' with 'fb'. - * include/grub/i386/pc/vbeblit.h: Moved from here ... - * include/grub/fbblit.h: ... here. Replaced 'vbe' with 'fb'. - * include/grub/i386/pc/vbefill.h: Moved from here ... - * include/grub/fbfill.h: ... here. Replaced 'vbe' with 'fb'. - * include/grub/i386/pc/vbeutil.h: Moved from here ... - * include/grub/fbutil.h: ... here. Replaced 'vbe' with 'fb'. - * include/grub/i386/pc/vbe.h: Moved framebuffer part ... - * include/grub/video_fb.h: ... here. Replaced 'vbe' with 'fb'. - * include/grub/video.h (GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER): Removed. - (GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER): Likewise. - (grub_video_adapter): Added 'get_info_and_fini'. - (grub_video_get_info_and_fini): New prototype. - (grub_video_set_mode): make modestring const char *. - * loader/i386/linux.c (grub_linux_setup_video): Use - grub_video_get_info_and_fini. - (grub_linux_boot): Move modesetting just before booting. - * loader/i386/pc/xnu.c (grub_xnu_set_video): Use - grub_video_get_info_and_fini. - * video/i386/pc/vbe.c: Moved framebuffer part ... - * video/fb/video_fb.c: ... here. Replaced 'vbe' with 'fb'. - * video/i386/pc/vbe.c (grub_vbe_set_video_mode): Use - grub_video_fbstd_colors and grub_video_fb_set_palette. - (grub_video_vbe_init): Clear 'framebuffer' variable and use - grub_video_fb_init. - (grub_video_vbe_fini): Use grub_video_fb_fini. - (grub_video_vbe_setup): Use framebuffer.render_target instead of - render_target and use grub_video_fb_set_active_render_target and - grub_video_fb_set_palette. - (grub_video_vbe_set_palette): Use grub_video_fb_set_palette. - (grub_video_vbe_set_viewport): Use grub_video_fb_set_viewport. - (grub_video_vbe_adapter): Use framebuffer. - * video/video.c (grub_video_get_info_and_fini): New function. - (grub_video_set_mode): Make modestring const char *. - (GRUB_MOD_INIT(video_video)): Don't set variables to 0 since these - values are already initialised. - -2009-08-14 Pavel Roskin - - * boot/i386/pc/cdboot.S: Use LOCAL for local labels. Eliminate - ABS and APPLE_CC. - * boot/i386/pc/diskboot.S: Likewise. - * boot/i386/pc/lnxboot.S: Likewise. Hardcode the number of code - sectors allow compilation on MacOSX. - * conf/i386-pc.rmk: Enable unconditional compilation of - lnxboot.img. - -2009-08-13 Colin Watson - - * util/grub-mkconfig.in: Export GRUB_HIDDEN_TIMEOUT. - * util/grub.d/00_header.in: Enter interruptible sleep if - GRUB_HIDDEN_TIMEOUT is set. - -2009-08-13 Yves Blusseau - - * include/grub/symbol.h: Add the LOCAL macro. - * boot/i386/pc/boot.S: Use the LOCAL macro for all labels - starting with "L_". - -2009-08-13 Pavel Roskin - - * boot/i386/pc/boot.S: Remove ABS macro, it's not required by - any modern compilers we support. - - * boot/i386/pc/boot.S: Remove all code dependent on APPLE_CC. - Use local labels starting with "L_" so that Apple assembler - knows they are local. - -2009-08-10 Robert Millan - - * include/grub/i386/bsd.h (KERNEL_TYPE_NONE, KERNEL_TYPE_FREEBSD) - (KERNEL_TYPE_OPENBSD, KERNEL_TYPE_NETBSD): Convert to ... - (bsd_kernel_types): ... this enum. - - * loader/i386/bsd.c (grub_cmd_freebsd_loadenv, grub_cmd_freebsd_module) - (grub_cmd_freebsd_module_elf): Abort with "You need to load the - kernel first." when `kernel_type' is set to KERNEL_TYPE_NONE. - - (grub_bsd_load_aout, grub_bsd_load, grub_cmd_freebsd_loadenv) - (grub_cmd_freebsd_module, grub_cmd_freebsd_module_elf) - (GRUB_MOD_INIT (bsd)): Fix capitalization in a few error - messages. - -2009-08-08 Robert Millan - - * util/grub-dumpdevtree: Moved from here ... - * util/i386/efi/grub-dumpdevtree: ... to here. - (hexify): New function. Converts a string to its hex version. - Generate hex versions of "efi" and "device-properties" by calling - hexify() on the ASCII strings rather than by hardcoding numbers. - -2009-08-08 Robert Millan - - * fs/jfs.c: Update copyright year. - -2009-08-08 Felix Zielcke - - * util/grub.d/00_header.in: Fix a comment. - * util/grub.d/10_linux.in: Likewise. - * util/grub.d/10_windows.in: Likewise. - * util/grub.d/10_hurd.in: Likewise. - -2009-08-08 Felix Zielcke - - * util/grub-mkconfig.in: Allow the user to specify the used font - with GRUB_FONT. - -2009-08-08 Pavel Roskin - - * include/grub/powerpc/libgcc.h: Export __ashrdi3() if - available, xfs.mod needs it now. - - * util/grub-mkconfig_lib.in (version_test_numeric): Don't use - the "g" modifier in sed when the intention is to strip something - once. This fixes comparison of kernels with multiple dashes. - - * util/grub-mkconfig.in: Define datarootdir, datadir may depend - on it. Add missing space before closing bracket. Fix - misleading formatting. - -2009-08-07 Robert Millan - - * docs/grub.texi: Major overhaul. Remove all sections that are - specific to GRUB Legacy, or mostly composed of Legacy-specific - information. - -2009-08-07 Robert Millan - - * docs/version.texi: New file. Provides version information for - grub.texi. - -2009-08-07 Robert Millan - - * docs/grub.texi: Update CVS information to SVN. - Replace outdated "GRUB 2 will include" phrase with "GRUB 2 includes". - -2009-08-07 Felix Zielcke - - * util/grub-mkconfig.in: Remove a wrong `fi'. - -2009-08-07 Felix Zielcke - - * fs/uuid.c (grub_jfs_superblock): New fields unused2 and uuid. - (grub_jfs_uuid): New function. - (grub_jfs_fs): Set uuid field to grub_jfs_uuid. - -2009-08-07 Felix Zielcke - - * util/grub-mkconfig_lib.in (font_path): Move the functionality - of it to ... - * util/grub-mkconfig.in: ... here. Prefer unicode.pf2 and - unifont.pf2 over ascii.pf2. Export LANG=C in case ascii.pf2 gets used. - -2009-08-07 Robert Millan - - * util/grub.d/10_linux.in (test_numeric): Moved from here ... - * util/grub-mkconfig_lib.in (version_test_numeric): ... to here. - Update all users. - - * util/grub.d/10_linux.in (test_gt): Strip any basename prefix, - not just "vmlinu[zx]". - Moved from here ... - * util/grub-mkconfig_lib.in (version_test_gt): ... to here. Update - all users. - - * util/grub.d/10_linux.in (find_latest): Moved from here ... - * util/grub-mkconfig_lib.in (version_find_latest): ... to here. Update - all users. - -2009-08-07 Robert Millan - - * util/grub.d/10_freebsd.in: Use an absolute device path for - `vfs.root.mountfrom'. Set `vfs.root.mountfrom.options=rw'. - -2009-08-06 Felix Zielcke - - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Fix - handling of multiple abstraction modules. - -2009-08-04 Robert Millan - - Fix a bug resulting in black screen when loading Linux using a - packed video mode. - - * kern/i386/pc/startup.S (grub_vbe_bios_getset_dac_palette_width): New - function. - - * include/grub/i386/pc/vbe.h (GRUB_VBE_CAPABILITY_DACWIDTH): New macro. - (grub_vbe_bios_getset_dac_palette_width): New function. - (grub_vbe_bios_get_dac_palette_width) - (grub_vbe_bios_set_dac_palette_width): New macros (act as wrappers for - grub_vbe_bios_getset_dac_palette_width()). - - * video/i386/pc/vbe.c (grub_vbe_probe): Use `GRUB_VBE_STATUS_OK' to - check for return status. - (grub_vbe_get_video_mode_info): When getting information for a packed - mode (<= 8 bpp), obtain DAC palette width using - grub_vbe_bios_getset_dac_palette_width(), and use that for initializing - {red,green,blue}_mark_size. - -2009-08-04 Felix Zielcke - - * commands/search.c (options): Fix help output to match actual code. - -2009-08-02 Vladimir Serbinenko - - * commands/hexdump.c (grub_cmd_hexdump): Use grub_disk_read instead - of homegrown code. - -2009-08-01 Vladimir Serbinenko - - * util/hostfs.c (grub_hostfs_dir): Don't use DT_DIR: It doesn't work - on XFS or ReiserFS. - -2009-08-01 Vladimir Serbinenko - - Support Apple partition map with sector size different from 512 bytes. - - * partmap/apple.c (grub_apple_header): New field 'blocksize'. - (apple_partition_map_iterate): Respect 'aheader.blocksize' - and 'apart.partmap_size'. - -2009-08-01 Vladimir Serbinenko -2009-08-01 Robert Millan - - Fix cpuid command. - - * commands/i386/cpuid.c (options): New variable. - (grub_cmd_cpuid): Return real error. - (GRUB_MOD_INIT(cpuid)): Declare options. - -2009-07-31 Vladimir Serbinenko - - * partmap/pc.c (pc_partition_map_iterate): Check that boot flags are - valid. - -2009-07-31 Bean - - * fs/xfs.c (grub_xfs_sblock): Change unused5 field to log2_sect and - log2_inode. - (grub_fshelp_node): Move inode field to the end. - (grub_xfs_data): Remove inode field. - (grub_xfs_inode_block): Calculate inode size using sblock. - (grub_xfs_inode_offset): Likewise. - (grub_xfs_read_inode): Calculate inode size using sblock. - (grub_xfs_read_block): Replace XFS_INODE_EXTENTS with nrec. - (grub_xfs_iterate_dir): Calculate inode size using sblock. - (grub_xfs_mount): Use grub_zalloc instead of grub_malloc. Realloc data - to match inode size. - (grub_xfs_dir): goto mount_fail when mount fails, as data->diropen is - not accessible when data is null. - (grub_xfs_open): Likewise. - -2009-07-31 Bean - - * disk/lvm.c (grub_lvm_scan_device): Ignore extra copy of metadata. - Don't change pv->disk if it's already set. - - * disk/raid.c (grub_raid_scan_device): Merge this function into ... - (grub_raid_register): ... here. - (grub_raid_rescan): Removed. - - * include/grub/raid.h (grub_raid_rescan): Removed. - - * util/grub-fstest.c: Remove include file . - (fstest): Replace grub_raid_rescan with module fini function followed - by init function. - - * util/grub-probe.c: Add include file . - (probe_raid_level): New function. - (probe): Detect abstraction by walking the disk device, support two - level of abstraction (LVM on RAID) when detecting partition map. - -2009-07-31 Pavel Roskin - - * disk/raid5_recover.c (grub_raid5_recover): Revert conversion - to grub_zalloc(), it was erroneous. - Reported by Bean - -2009-07-30 Vladimir Serbinenko - - * util/i386/pc/grub-setup.c (setup): Check that no partition is in - embedding zone, not only the first one. - -2009-07-29 Joe Auricchio - - * term/gfxterm.c (clear_char): New function. - (grub_virtual_screen_setup): Use clear_char. - (scroll_up): Likewise. - (grub_virtual_screen_cls): Likewise. - -2009-07-29 Felix Zielcke - - * util/deviceiter.c (get_acceleraid_disk_name): New static - function. - (grub_util_iterate_devices): Handle Accelraid devices. - * util/hostdisk.c (convert_system_partition_to_system_disk): Likewise. - -2009-07-28 Robert Millan - - * loader/i386/linux.c (grub_cmd_linux): Use ',' rather than ';' as - separator for the suggested gfxpayload string (';' collides with the - parser and needs escaping). - -2009-07-28 Vladimir Serbinenko - - * loader/i386/multiboot_helper.S (grub_multiboot_backward_relocator): - Clear direction flag before jumping to OS. - (grub_multiboot2_real_boot): Likewise. - -2009-07-28 Felix Zielcke - - * util/i386/pc/grub-install: Fix parsing of --disk-module - option. - -2009-07-28 Felix Zielcke - - * util/i386/pc/grub-setup.c (setup): Fix 2 incorrect checks - when embedding. - -2009-07-26 Felix Zielcke - - * util/grub-mkconfig.in (package_version): New variable. - Use it do display the version. - -2009-07-25 Felix Zielcke - - * kern/file.c (grub_file_open): Revert to previous check with - grub_errno. - -2009-07-25 Vladimir Serbinenko - - * commands/probe.c (GRUB_MOD_INIT (probe)): Remove "[--target=target]" - from help line. It's out of sync with code. - -2009-07-25 Vladimir Serbinenko - - * kern/parser.c (grub_parser_execute): Fix a bug causing truncated - entries on failed boot. - -2009-07-25 Felix Zielcke - - * kern/file.c (grub_file_open): Fix an error check. - -2009-07-24 Vladimir Serbinenko - - * util/i386/pc/grub-setup.c (setup): Fix segmentation fault when - partition map couldn't be identified. - -2009-07-23 Pavel Roskin - - * commands/xnu_uuid.c (transform): Use GRUB_CPU_WORDS_BIGENDIAN - instead of WORDS_BIGENDIAN. Use grub_le_to_cpu32(), so that the - case of little endian words becomes just an optimization. - Respect const modifier. - (md5_final): Use code that doesn't depend on endianness. - - * include/grub/misc.h (ALIGN_UP): Cast align to the type of addr - to avoid loss of upper bits if align is unsigned and shorter - than addr. - -2009-07-21 Vladimir Serbinenko - - UUID support for UFS - - * fs/ufs.c (grub_ufs_sblock): Add uuidhi and uuidlow. - (grub_ufs_uuid): New function. - (grub_ufs_fs): add .uuid - -2009-07-21 Pavel Roskin - - * kern/dl.c (grub_dl_check_header): Make static. - -2009-07-21 Felix Zielcke - - * util/grub.d/30_os-prober.in: Remove unused CHAINROOT. Don't - add drivemap for Vista. It breaks Windows 7. - -2009-07-21 Vladimir Serbinenko - - * fs/ufs.c (grub_ufs_sblock): Fix offset of mtime2 which was off by - 128 bytes - -2009-07-20 Vladimir Serbinenko - - Add BFS support - - * conf/common.rmk (grub_probe_SOURCES): Add fs/befs.c. - (grub_fstest_SOURCES): Likewise. - (pkglib_MODULES): Add befs.mod. - (befs_mod_SOURCES): New variable. - (befs_mod_CFLAGS): Likewise. - (befs_mod_LDFLAGS): Likewise. - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise. - (grub_setup_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise. - (grub_setup_SOURCES): Likewise. - * fs/befs.c: New file. - * fs/afs.c (GRUB_AFS_FSNAME): New declaration. - (GRUB_AFS_SBLOCK_SECTOR): Likewise. - (GRUB_AFS_SBLOCK_MAGIC1) [MODE_BFS]: New conditional declaration. - (GRUB_AFS_BTREE_MAGIC) [MODE_BFS]: Likewise - (B_KEY_INDEX_ALIGN): New declaration. - (B_KEY_INDEX_OFFSET): Use B_KEY_INDEX_ALIGN. - (grub_afs_bnode) [MODE_BFS]: Make key_count and key_size 16-bit - (grub_afs_btree) [MODE_BFS]: New conditional declaration. - (grub_afs_sblock) [MODE_BFS]: Remove link_count. - (grub_afs_validate_sblock) [MODE_BFS]: Support BFS - (grub_afs_mount) [MODE_BFS]: Likewise. - (grub_afs_dir) [MODE_BFS]: Divide mtime by 65536 and not 1000000. - (grub_afs_fs): Use GRUB_AFS_FSNAME - (GRUB_MOD_INIT (afs)) [MODE_BFS]: Rename to ... - (GRUB_MOD_INIT (befs)) [MODE_BFS]: ... this - (GRUB_MOD_FINI (afs)) [MODE_BFS]: Rename to ... - (GRUB_MOD_FINI (befs)) [MODE_BFS]: ... this - -2009-07-19 Yves BLUSSEAU - - * util/getroot.c (find_root_device): Add support for MacOSX. - * util/hostdisk.c: Likewise. - -2009-07-20 Vladimir Serbinenko - - * font/font.c (find_glyph): Check whether a font is present to avoid - segmentation fault. - -2009-07-20 Joe Auricchio - - * term/gfxterm.c (grub_virtual_screen_setup): Clear virtual_screen. - -2009-07-20 Pavel Roskin - - * configure.ac: Trim excessively wordy excuses. - -2009-07-20 Vladimir Serbinenko - - Add symlink, mtime and label support to AtheFS. - - * fs/afs.c (grub_afs_sblock): Declare `name' as char. - (grub_afs_iterate_dir): Handle symlinks. - (grub_afs_open): Use grub_afs_read_symlink. - (grub_afs_dir): Likewise. - Pass mtime. - (grub_afs_label): New function. - (grub_afs_fs): Add grub_afs_label. - (grub_afs_read_symlink): New function. - -2009-07-20 Vladimir Serbinenko - - Fix AtheFS support. - - * fs/afs.c: Fix comments style. - (grub_afs_blockrun): Declare as packed. - (grub_afs_datastream): Likewise. - (grub_afs_bnode): Likewise. - (grub_afs_btree): Likewise. - (grub_afs_sblock): Likewise. - Declare `name' as char. - (grub_afs_inode): Declare as packed. - Change void *vnode to grub_uint32_t unused. - (grub_afs_iterate_dir): Check that key_size is positive. - (grub_afs_mount): Don't read superblock twice. - (grub_afs_dir): Don't free node in case of error, - grub_fshelp_find_file already handles this. - (grub_afs_open): Likewise. - -2009-07-19 Pavel Roskin - - * Makefile.in: Remove LIBLZO and enable_lzo. - * conf/i386-pc.rmk: Remove lzo support. - * configure.ac: Remove checks for lzo, don't define ENABLE_LZMA. - * include/grub/i386/pc/kernel.h: Define ENABLE_LZMA. Remove lzo - support. - * kern/i386/pc/lzo1x.S: Remove. - * kern/i386/pc/startup.S: Remove lzo support. - * util/i386/pc/grub-mkimage.c: Likewise. - -2009-07-19 Vladimir Serbinenko - - * disk/usbms.c (grub_usbms_transfer): Fix double semicolon. - * fs/xfs.c (grub_xfs_dir): Likewise. - * fs/afs.c (grub_afs_dir): Likewise. - * fs/iso9660.c (grub_iso9660_iterate_dir): Likewise. - (grub_iso9660_open): Likewise. - * fs/jfs.c (grub_jfs_open): Likewise. - * fs/ext2.c (grub_ext2_dir): Likewise. - * include/grub/macho.h (grub_macho_fat_arch): Likewise. - * script/sh/lexer.c (grub_script_yylex): Likewise. - -2009-07-16 Pavel Roskin - - * configure.ac: Never add "-c" to CFLAGS. - - * configure.ac: Fix incorrect comparison for grub_cv_cc_efiemu. - - * configure.ac: Fix wrong use of grub_cv_cc_no_red_zone where - grub_cv_cc_efiemu should be used. - - * configure.ac: Typo fixes. - - * kern/mm.c (grub_zalloc): New function. - (grub_debug_zalloc): Likewise. - * include/grub/mm.h: Declare grub_zalloc() and - grub_debug_zalloc(). - * util/misc.c (grub_zalloc): New function. - * bus/usb/uhci.c (grub_uhci_pci_iter): Use grub_zalloc() - instead of grub_malloc(), remove unneeded initializations. - * bus/usb/usbhub.c (grub_usb_hub_add_dev): Likewise. - * commands/extcmd.c (grub_extcmd_dispatcher): Likewise. - * commands/parttool.c (grub_cmd_parttool): Likewise. - * disk/i386/pc/biosdisk.c (grub_biosdisk_open): Likewise. - * disk/raid5_recover.c (grub_raid5_recover): Likewise. - * disk/raid6_recover.c (grub_raid6_recover): Likewise. - * disk/usbms.c (grub_usbms_finddevs): Likewise. - * efiemu/mm.c (grub_efiemu_request_memalign): Likewise. - * efiemu/pnvram.c (grub_efiemu_pnvram): Likewise. - (grub_cmd_efiemu_pnvram): Likewise. - * fs/i386/pc/pxe.c (grub_pxefs_open): Likewise. - * fs/iso9660.c (grub_iso9660_mount): Likewise. - (grub_iso9660_iterate_dir): Likewise. - * fs/jfs.c (grub_jfs_opendir): Likewise. - * fs/ntfs.c (list_file): Likewise. - (grub_ntfs_mount): Likewise. - * kern/disk.c (grub_disk_open): Likewise. - * kern/dl.c (grub_dl_load_core): Likewise. - * kern/elf.c (grub_elf_file): Likewise. - * kern/env.c (grub_env_context_open): Likewise. - (grub_env_set): Likewise. - (grub_env_set_data_slot): Likewise. - * kern/file.c (grub_file_open): Likewise. - * kern/fs.c (grub_fs_blocklist_open): Likewise. - * loader/i386/multiboot.c (grub_module): Likewise. - * loader/xnu.c (grub_xnu_create_key): Likewise. - (grub_xnu_create_value): Likewise. - * normal/main.c (grub_normal_add_menu_entry): Likewise. - (read_config_file): Likewise. - * normal/menu_entry.c (make_screen): Likewise. - * partmap/sun.c (sun_partition_map_iterate): Likewise. - * script/sh/lexer.c (grub_script_lexer_init): Likewise. - * script/sh/script.c (grub_script_parse): Likewise. - * video/bitmap.c (grub_video_bitmap_create): Likewise. - * video/readers/jpeg.c (grub_video_reader_jpeg): Likewise. - * video/readers/png.c (grub_png_output_byte): Likewise. - (grub_video_reader_png): Likewise. - -2009-07-16 Vladimir Serbinenko - - Enable all targets that can be built by default - - * configure.ac: enable efiemu runtime, grub-emu, grub-emu-usb, - grub-mkfont and grub-fstest if they can be built - -2009-07-16 Vladimir Serbinenko - - Fix hang and segmentation fault in grub-emu-usb - - * disk/scsi.c (grub_scsi_open): return err and not grub_errno - * util/usb.c (grub_libusb_devices): likewise - (grub_libusb_init): rename to ... - (GRUB_MOD_INIT (libusb)):...this - (grub_libusb_fini): rename to .. - (GRUB_MOD_FINI (libusb)):...this - * disk/usbms.c (grub_usbms_transfer): fix retry logic - * include/grub/disk.h (grub_raid_init): removed, it's useless - (grub_raid_fini): likewise - (grub_lvm_init): likewise - (grub_lvm_fini): likewise - * util/grub-emu.c (main): don't call grub_libusb_init, it's done - by grub_init_all - -2009-07-16 Vladimir Serbinenko - - Fix libusb - - * Makefile.in (LIBUSB): new macro - * genmk.rb (Utility/print_tail): new method - (Utility/rule): use intermediary variable #{prefix}_OBJECTS - (top level): call util.print_tail at the end. - -2009-07-16 Vladimir Serbinenko - - Make FreeBSD accept zpool.cache - - * loader/i386/bsd.c (grub_freebsd_add_meta_module): spoof filename if - type is /boot/zfs/zpool.cache - -2009-07-16 Vladimir Serbinenko - - Fix 64-bit efiemu - - * include/grub/efiemu/efiemu.h (grub_efiemu_configuration_table64_t): - correct wrong typedef - * efiemu/prepare.c (SUFFIX (grub_efiemu_prepare)): minor style fixes - -2009-07-15 Pavel Roskin - - * include/grub/disk.h (struct grub_disk_dev): Use enum for id. - * kern/disk.c (struct grub_disk_cache): Likewise. - - * commands/probe.c (options): Typo fix. - - * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_BPB_END): - Increase to 0x5a to accommodate FAT32. Adjust other offsets - accordingly. - Original patch by Yves Blusseau - - * boot/i386/pc/boot.S (general_error_string): Add DOS newline at - the end of "Error" to make the message more readable. - - * boot/i386/pc/boot.S (kernel_segment): Remove. - (copy_buffer): Use GRUB_BOOT_MACHINE_KERNEL_ADDR in segment 0 - for destination. - - * boot/i386/pc/boot.S (boot_version): Remove. - * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_VER_MAJ): - Remove. - - * include/grub/i386/pc/boot.h: Sort all offsets. - (GRUB_BOOT_MACHINE_KERNEL_ADDRESS): Remove, it's unused. - (GRUB_BOOT_MACHINE_KERNEL_SEGMENT): Likewise. - * boot/i386/pc/boot.S: Assert location of every offset listed in - include/grub/i386/pc/boot.h. - -2009-07-13 Pavel Roskin - - * include/grub/i386/coreboot/machine.h: Rename - GRUB_MACHINE_LINUXBIOS to GRUB_MACHINE_COREBOOT. - * loader/multiboot_loader.c (grub_cmd_multiboot_loader): Allow - multiboot 1 for GRUB_MACHINE_COREBOOT and GRUB_MACHINE_QEMU. - - * kern/dl.c: Force native word size to suppress warnings when - compiling grub-emu. - - * kern/device.c (grub_device_iterate): Change struct part_ent to - hold the name, not a pointer to it. Use one grub_malloc() per - partition, not two. Free partition_name if grub_malloc() fails. - Set ents to NULL only before grub_partition_iterate() is called. - -2009-07-11 Bean - - * kern/ieee1275/openfw.c (grub_children_iterate): Fix size of - childname. - -2009-07-10 Bean -2009-07-10 Robert Millan - - * kern/ieee1275/openfw.c (grub_children_iterate) - (grub_devalias_iterate): Fix size evaluation for property or path - strings, which was broken since r2132. - -2009-07-07 Pavel Roskin - - * commands/search.c (search_file): Merge into ... - (search_fs): ... this. Accept search type as argument. - (grub_cmd_search): Pass search type to search_fs(). - - * include/grub/util/console.h: New file. - * util/console.c: Use it instead of grub/machine/console.h. - * util/grub-emu.c: Likewise. - - * lib/arg.c (find_long_option): Remove. - (find_long): Add `len' argument, make `s' const char *. - (grub_arg_parse): Parse long options in place, not in a - temporary buffer. - -2009-07-06 Pavel Roskin - - * commands/search.c (search_fs): Fix potential NULL pointer - dereference. - - * commands/search.c (search_fs): Replace QUID macro with quid_fn - function pointer. - -2009-07-06 Daniel Mierswa - - * commands/search.c (search_fs): Use grub_strcasecmp() for UUID - comparison. - -2009-07-05 Pavel Roskin - - * include/grub/i386/linux.h (struct linux_kernel_params): - Restore padding3, it's still needed. - - * util/grub.d/10_freebsd.in: Fix spelling of `device.hints' on - FreeBSD. - * util/osdetect.lua: Likewise. - -2009-07-05 Bean - - * conf/common.rmk (lua_mode_SOURCES): Add script/lua/lstrlib.c. - - * script/lua/grub_lib.c (grub_lua_run): Check input parameter. - (grub_lua_getenv): Likewise. - (grub_lua_setenv): Likewise. - (save_errno): New function. - (push_result): Likewise. - (grub_lua_enum_device): Likewise. - (grub_lua_enum_file): Likewise. - (grub_lua_file_open): Likewise. - (grub_lua_file_close): Likewise. - (grub_lua_file_seek): Likewise. - (grub_lua_file_read): Likewise. - (grub_lua_file_getline): Likewise. - (grub_lua_file_getsize): Likewise. - (grub_lua_file_getpos): Likewise. - (grub_lua_file_eof): Likewise. - (grub_lua_file_exist): Likewise. - (grub_lua_add_menu): Likewise. - - * script/lua/grub_lua.h (isupper): New inline function. - (islower): Likewise. - (ispunct): Likewise. - (isxdigit): Likewise. - (strcspn): Change to normal function. - (strpbkr): New function declaration. - (memchr): Likewise. - - * script/lua/grub_main.c (scan_str): New function. - (strcspn): Likewise. - (strpbrk): Likewise. - (memchr): Likewise. - - * script/lua/linit.c (lualibs): Enable the string library. - - * util/osdetect.lua: New file. - -2009-07-04 Robert Millan - - * include/grub/i386/linux.h (struct linux_kernel_params): Add - `capabilities' member. - -2009-07-02 Pavel Roskin - - * genparttoollist.sh: Add missing newline at the end. - -2009-07-01 Pavel Roskin - - * kern/x86_64/efi/callwrap.S: Add missing newline at the end. - - * util/hostdisk.c (open_device): Remove `const' from - `sysctl_size', as sysctlbyname() can change it (in this case it - doesn't actually happen). - - * include/grub/types.h: Define GRUB_LONG_MAX and GRUB_LONG_MIN - using signed long int constants. - - * util/hostdisk.c (grub_util_biosdisk_get_grub_dev): Make `p' - constant to avoid a warning on FreeBSD. - - * util/hostdisk.c (device_is_wholedisk): Compile only on systems - where it's needed. - - * Makefile.in: Install include/grub/machine symlink. - - * Makefile.in: When installing symlinks, use "cp -fR", which - works on FreeBSD and MacOSX. - From Yves Blusseau - - * kern/dl.c (grub_dl_resolve_symbol): Make static. - * include/grub/dl.h: Remove grub_dl_resolve_symbol(). - - * util/misc.c: Move grub_reboot() and grub_halt() ... - * util/grub-emu.c: ... here. Make main_env static. - * include/grub/util/misc.h: Remove main_env. - - * kern/mm.c: Use correct format to print size_t. - - * include/grub/elf.h: Define Elf_Sword and Elf_Xword. - * kern/i386/dl.c: Use ELF symbols without "32" or "64". - * kern/powerpc/dl.c: Likewise. - * kern/sparc64/dl.c: Likewise. - * kern/x86_64/dl.c: Likewise. - -2009-07-01 Robert Millan - - Fix grub-emu build on sparc64-ieee1275. - - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Synchronize with ... - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): ... this. - -2009-07-01 Robert Millan - - * util/misc.c: Include `' and `'. - (grub_reboot, grub_halt): New functions. - - * util/i386/pc/misc.c: Delete. Update all users. - * util/sparc64/ieee1275/misc.c: Likewise. - * util/powerpc/ieee1275/misc.c: Likewise. - -2009-07-01 Robert Millan - - * conf/i386.rmk (setjmp_mod_SOURCES) - (setjmp_mod_ASFLAGS, setjmp_mod_LDFLAGS): Move to ... - * conf/common.rmk (setjmp_mod_SOURCES) - (setjmp_mod_ASFLAGS, setjmp_mod_LDFLAGS): ... here, and modify - to use $(target_cpu). - * conf/x86_64-efi.rmk (setjmp_mod_SOURCES) - (setjmp_mod_ASFLAGS, setjmp_mod_LDFLAGS): Remove. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - - * conf/i386-pc.rmk (kernel_img_SOURCES): Use - $(target_cpu) for kern/$(target_cpu)/dl.c. - * conf/i386-efi.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - * conf/i386-coreboot.rmk: Likewise. - * conf/powerpc-ieee1275.rmk (kernel_img_SOURCES): Use - $(target_cpu) for kern/$(target_cpu)/dl.c and for - kern/$(target_cpu)/cache.S. - * conf/sparc64-ieee1275.rmk: Likewise. - -2009-07-01 Robert Millan - - * include/grub/i386/linux.h (linux_kernel_params): Change `mmap_size' - type to `grub_uint8_t', and adjust `padding9' accordingly. - -2009-06-29 Robert Millan - - * include/grub/i386/linux.h (GRUB_VIDEO_TYPE_TEXT): New macro. - - * loader/i386/linux.c [__i386__] (grub_linux_boot): Simplify inline - assembly in final jump, using register constraints. - - (grub_linux_boot): For text mode, initialize `have_vga' using - GRUB_VIDEO_TYPE_TEXT rather than 0 (this changes its value to 1). - - Initialize `video_cursor_x' and `video_cursor_y' as late as possible, - right before the final jump. - - Set `video_mode' to 0x3. - - Document initialization of `video_page', `video_mode' and - `video_ega_bx'. - -2009-06-29 Robert Millan - - * include/grub/i386/linux.h (GRUB_LINUX_FLAG_QUIET): New macro. - * loader/i386/linux.c (grub_cmd_linux): Recognize "quiet" option, - and set GRUB_LINUX_FLAG_QUIET appropriately. - -2009-06-29 Robert Millan - - Fix build on Debian / sparc. - - * configure.ac: Recognize `sparc' target_cpu (as sparc64). - -2009-06-28 Pavel Roskin - - * kern/i386/qemu/mmap.c (grub_machine_mmap_iterate): Use cast to - fix a warning. - - * util/grub.d/10_linux.in: Match SUSE style initrd names. - -2009-06-27 Robert Millan - - * loader/i386/linux.c (grub_linux_boot): Fix uninitialized use of - `err'. - -2009-06-27 Robert Millan - - Revert r2338. - - * loader/i386/linux.c (grub_cmd_linux): Don't call grub_error when - file can't be opened. grub_file_open() is already supposed to set - grub_errno / grub_errmsg appropriately. - * loader/i386/pc/linux.c (grub_cmd_linux): Likewise. - -2009-06-27 Pavel Roskin -2009-06-27 Robert Millan - - * include/grub/dl.h: Include grub/elf.h. - (struct grub_dl): Add symtab field. - * kern/dl.c [GRUB_MACHINE_QEMU]: Define - GRUB_MODULES_MACHINE_READONLY. - (grub_dl_resolve_symbols): Populate mod->symtab, making a copy - of the header for read-only modules. - (grub_dl_unload): Free mod->symtab for read-only modules. - * kern/i386/dl.c: Use mod->symtab. - * kern/powerpc/dl.c: Likewise. - * kern/sparc64/dl.c: Likewise. - * kern/x86_64/dl.c: Likewise. - - * conf/i386-qemu.rmk: New file. - * kern/i386/qemu/startup.S: Likewise. - * kern/i386/qemu/mmap.c: Likewise. - * boot/i386/qemu/boot.S: Likewise. - * include/grub/i386/qemu/time.h: Likewise. - * include/grub/i386/qemu/serial.h: Likewise. - * include/grub/i386/qemu/kernel.h: Likewise. - * include/grub/i386/qemu/console.h: Likewise. - * include/grub/i386/qemu/boot.h: Likewise. - * include/grub/i386/qemu/init.h: Likewise. - * include/grub/i386/qemu/machine.h: Likewise. - * include/grub/i386/qemu/loader.h: Likewise. - * include/grub/i386/qemu/memory.h: Likewise. - - * conf/i386-coreboot.rmk (GRUB_BOOT_MACHINE_LINK_ADDR) - (GRUB_KERNEL_MACHINE_LINK_ADDR): New variables. - [qemu] (pkglib_IMAGES): Add `boot.img'. - [qemu] (boot_img_SOURCES, boot_img_ASFLAGS, boot_img_LDFLAGS) - [qemu] (boot_img_FORMAT): New variables. - [qemu] (bin_UTILITIES): Add `grub-mkimage'. - [qemu] (grub_mkimage_SOURCES, grub_mkimage_CFLAGS): New variables. - [qemu] (kernel_img_SOURCES, kernel_img_HEADERS, kernel_img_CFLAGS) - [qemu] (kernel_img_ASFLAGS, kernel_img_LDFLAGS) - [qemu] (kernel_img_FORMAT): New variables. - - * configure.ac: Recognise `i386-qemu'. - - * util/i386/pc/grub-mkimage.c (compress_kernel): Add dummy variant - (for no compression). - [GRUB_MACHINE_QEMU] (generate_image): Misc adjustments to produce - a valid i386 ROM image. Make `GRUB_KERNEL_MACHINE_COMPRESSED_SIZE', - `GRUB_KERNEL_MACHINE_INSTALL_DOS_PART' and - `GRUB_KERNEL_MACHINE_INSTALL_BSD_PART' optional features (with - ifdefs). - -2009-06-27 Pavel Roskin - - * efiemu/prepare.c: Eliminate TYPE macro, it makes code hard to - read. - * efiemu/prepare32.c: Likewise. - * efiemu/prepare64.c: Likewise. - -2009-06-26 Pavel Roskin - - * include/grub/types.h: Define GRUB_TARGET_WORDSIZE. - * include/grub/elf.h: Define symbols without "32" or "64" based - on GRUB_TARGET_WORDSIZE. - * include/grub/multiboot2.h: Use GRUB_TARGET_WORDSIZE. - * efiemu/loadcore32.c: Redefine GRUB_TARGET_WORDSIZE, remove own - ELF definitions. - * efiemu/loadcore64.c: Likewise. - * loader/i386/bsd32.c: Likewise. - * loader/i386/bsd64.c: Likewise. - * kern/dl.c: Remove own ELF definitions. - * util/i386/efi/grub-mkimage.c: Likewise. - -2009-06-23 Robert Millan - - * kern/i386/pc/startup.S (real_to_prot): Access `gdtdesc' using - segment 0x0 unconditionally, because the reference generated by - GAS is an absolute address. - -2009-06-22 Robert Millan - - * include/grub/i386/kernel.h: Include `'. - [! GRUB_MACHINE_IEEE1275]: Set `GRUB_MOD_ALIGN' to 0x1. - -2009-06-22 Robert Millan - - * commands/search.c (grub_cmd_search): Macroify hardcoded args[] - indexes. Check for -f explicitly. - (search_file): Improve error message. - (GRUB_MOD_INIT(search)): Add missing `-n' to help output. - -2009-06-22 Robert Millan - - * conf/i386-pc.rmk (GRUB_MEMORY_MACHINE_LINK_ADDR): Rename to ... - (GRUB_KERNEL_MACHINE_LINK_ADDR): ... this. Update all users. - -2009-06-22 Robert Millan - - * conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/misc.S'. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-coreboot.rmk: Likewise. - - * kern/i386/pc/startup.S (grub_stop): Remove function. - * kern/i386/ieee1275/startup.S: Likewise. - * kern/i386/coreboot/startup.S: Likewise. - * kern/i386/misc.S (grub_stop): New function. - -2009-06-22 Robert Millan - - * kern/i386/pc/startup.S (real_to_prot): Move from here ... - * kern/i386/realmode.S (real_to_prot): ... to here. - -2009-06-22 Robert Millan - - * conf/i386-ieee1275.rmk (pkglib_PROGRAMS): Replace `kernel.elf' - with `kernel.img'. - (kernel_elf_SOURCES): Rename to ... - (kernel_img_SOURCES): ... this. - (kernel_elf_HEADERS): Rename to ... - (kernel_img_HEADERS): ... this. Update all users. - (kernel_elf_ASFLAGS): Rename to ... - (kernel_img_ASFLAGS): ... this. - (kernel_elf_CFLAGS): Rename to ... - (kernel_img_CFLAGS): ... this. - (kernel_elf_LDFLAGS): Rename to ... - (kernel_img_LDFLAGS): ... this. - * conf/i386-coreboot.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - - * util/elf/grub-mkimage.c (add_segments): Replace "kernel.elf" - with "kernel.img". - -2009-06-21 Pavel Roskin - - * loader/powerpc/ieee1275/linux.c (offset_phdr): Fix prototypes - to match nested functions. - * loader/sparc64/ieee1275/linux.c: Likewise. - - * conf/i386-ieee1275.rmk: Define kernel_elf_ASFLAGS. - -2009-06-21 Robert Millan - - * configure.ac: Enable `END_SYMBOL' / `BSS_START_SYMBOL' test on - all i386 platforms. - -2009-06-21 Robert Millan - - Fix asm file handling on ELF, and remove workarounds. - - * genmk.rb (class Programs): Detect assembly files, and set ASFLAGS - and -DASM_FILE=1 appropriately (copied from `class Images' stanza). - * kern/i386/ieee1275/startup.S (ASM_FILE): Remove macro. - * kern/i386/coreboot/startup.S (ASM_FILE): Likewise. - -2009-06-21 Vladimir Serbinenko - - Load BSD ELF modules - - * conf/i386-pc.rmk (bsd_mod_SOURCES): Add loader/i386/bsd32.c - and loader/i386/bsd64.c - * include/grub/i386/bsd.h (FREEBSD_MODTYPE_MODULE): Remove - (FREEBSD_MODTYPE_ELF_MODULE): New definition - (FREEBSD_MODTYPE_ELF_MODULE_OBJ): Likewise - (grub_freebsd_load_elfmodule32): New declaration - (grub_freebsd_load_elfmoduleobj64): Likewise - (grub_freebsd_load_elf_meta32): Likewise - (grub_freebsd_load_elf_meta64): Likewise - (grub_freebsd_add_meta): Likewise - (grub_freebsd_add_meta_module): Likewise - * loader/i386/bsd.c (grub_freebsd_add_meta): Make global - (grub_freebsd_add_meta_module): Likewise and move module-specific - parts to grub_cmd_freebsd and grub_cmd_freebsd_module - (grub_cmd_freebsd): Add elf-kernel specific parts - based on grub_freebsd_add_meta_module - (grub_cmd_freebsd_module): Add type parsing moved from - grub_freebsd_add_meta_module - (grub_cmd_freebsd_module_elf): New function - (cmd_freebsd_module_elf): New variable - (GRUB_MOD_INIT): Register freebsd_module_elf - * loader/i386/bsd32.c: New file - * loader/i386/bsd64.c: Likewise - * loader/i386/bsdXX.c: Likewise - * kern/elf.c (grub_elf32_load): Let hook decide which pheaders to load - (grub_elf64_load): Likewise - * include/grub/elfload.h (grub_elf32_load_hook_t): New parameter do_load - All users updated - (grub_elf64_load_hook_t): Likewise - -2009-06-21 Colin Watson - - * util/grub-mkconfig.in (GRUB_DISABLE_LINUX_RECOVERY): Export - variable. - * util/grub.d/10_linux.in: If GRUB_DISABLE_LINUX_RECOVERY is true, - don't write a menu entry for recovery mode. - -2009-06-20 Robert Millan - - * util/i386/pc/grub-mkimage.c (main): Oops, free `output' only - after it's no longer needed. - -2009-06-20 Robert Millan - - * include/grub/i386/loader.h (grub_linux_prot_size) - (grub_linux_tmp_addr, grub_linux_real_addr) - (grub_linux_is_bzimage, grub_linux16_boot): Declare only on - GRUB_MACHINE_PCBIOS. - * util/i386/pc/grub-mkimage.c (compress_kernel): Move - common grub_util_info() call to ... - (generate_image): ... here. - Fix use of uninitialized memory, comparison of signed with - unsigned integers and memory leak. - Remove bogus module address message. - -2009-06-20 Vladimir Serbinenko - - * disk/mdraid_linux.c (GRUB_MOD_FINI): use grub_raid_unregister and not - grub_raid_register - * disk/dmraid_nvidia.c (GRUB_MOD_FINI): likewise - -2009-06-19 Pavel Roskin - - * configure.ac: Remove stray AC_MSG_CHECKING. - -2009-06-19 Vladimir Serbinenko - - * disk/scsi.c (grub_scsi_open): use continue instead of big if - -2009-06-18 Pavel Roskin - - * conf/common.rmk: Add fs_file.mod. - * disk/fs_file.c: New file. - * include/grub/disk.h (enum grub_disk_dev_id): Add - GRUB_DISK_DEVICE_FILE_ID. - -2009-06-18 Vladimir Serbinenko - - Fix build with Apple's toolchain. Part 2 - - * aclocal.m4 (grub_PROG_TARGET_CC): add missing prototype for main and - a fake start - -2009-06-18 Vladimir Serbinenko - - Fix build with Apple's toolchain. Part 1 - - * commands/i386/pc/drivemap_int13h.S: use assembly-time constants - for long calls - * configure.ac: remove a leftover AC_MSG_RESULT - (CFLAGS): don't add -Wl,--defsym,___main=0x8100 when building with - Apple's toolchain - -2009-06-18 Vladimir Serbinenko - - Fix warnings - - * fs/ntfscomp.c (decomp_get16): initialize c1 and c2 - (decomp_block): initialize ch - use grub_memcpy instead of memcpy - -2009-06-17 Pavel Roskin - - * include/grub/i386/coreboot/console.h: Don't use the i386-pc - version, use declarations needed to use vga_text as the startup - console. - - * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Remove - term/i386/pc/at_keyboard.c, it doesn't need to be compiled into - the kernel. - * kern/i386/coreboot/init.c: Don't call grub_at_keyboard_init() - and grub_at_keyboard_fini(), it's done on module load and - unload. - -2009-06-17 Felix Zielcke - - * loader/i386/linux.c (grub_cmd_linux): Set grub_error if the - file can't be found. - * loader/i386/pc/linux.c (grub_cmd_linux): Likewise. - -2009-06-17 Vladimir Serbinenko - - Fix newline handling - - * include/grub/script_sh.h (grub_lexer_param): new field was_newline - * script/sh/lexer.c (grub_script_lexer_init): initialize was_newline - (grub_script_yylex): don't segfault on unterminated script - newline terminates command and variable - -2009-06-17 Vladimir Serbinenko - - avoid double grub_adjust_range call. Bug reported by David Simner - - * kern/disk.c (grub_disk_write): change to raw disk access before - calling disk_read - -2009-06-17 Colin Watson - - * util/elf/grub-mkimage.c (usage): Prefix each option line with two - spaces, for the benefit of help2man. - * util/i386/efi/grub-mkimage.c (usage): Likewise. - -2009-06-16 Pavel Roskin - - * kern/i386/halt.c: Include grub/machine/init.h. - * kern/i386/reboot.c: Include grub/cpu/reboot.h. - -2009-06-16 Felix Zielcke - - * util/grub.d/30_os-prober.in: Use ${root} in the generated - drivemap menuentry. - -2009-06-16 James Jarvis - - * commands/help.c GRUB_MOD_INIT(echo): Fix the help output of - `echo' command. - -2009-06-16 Pavel Roskin - - * boot/i386/pc/boot.S: Remove root_drive. Assert offset of - boot_drive_check by using GRUB_BOOT_MACHINE_DRIVE_CHECK. Don't - save %dx, we only need %dl and we never change it. - * boot/i386/pc/cdboot.S: Don't set the root drive. - * boot/i386/pc/pxeboot.S: Likewise. - * include/grub/i386/pc/boot.h: Remove - GRUB_BOOT_MACHINE_ROOT_DRIVE, adjust - GRUB_BOOT_MACHINE_DRIVE_CHECK. - * include/grub/i386/pc/kernel.h: Remove grub_root_drive. - * kern/i386/pc/init.c (make_install_device): Remove references - to grub_root_drive. - * kern/i386/pc/startup.S: Likewise. - * util/i386/pc/grub-setup.c (setup): Don't set root_drive. - -2009-06-16 Vladimir Serbinenko - - xnu_uuid command - - * commands/xnu_uuid.c: new file - * conf/common.rmk (pkglib_MODULES): add xnu_uuid.mod - (xnu_uuid_mod_SOURCES): new variable - (xnu_uuid_mod_CFLAGS): likewise - (xnu_uuid_mod_LDFLAGS): likewise - * conf/i386-coreboot.rmk (grub_emu_SOURCES): add commands/probe.c - * conf/i386-ieee1275.rmk: likewise - * conf/i386-pc.rmk: likewise - * conf/powerpc-ieee1275.rmk: likewise - * conf/sparc64-ieee1275.rmk: likewise - * util/grub.d/30_os-prober.in: use UUID for Mac OS X/Darwin - -2009-06-16 Pavel Roskin - - * configure.ac: Avoid '==' in test command, it's not portable. - -2009-06-16 Vladimir Serbinenko - - Probe command - - * commands/probe.c: new file - * conf/common.rmk (pkglib_MODULES): add probe.mod - (probe_mod_SOURCES): new variable - (probe_mod_CFLAGS): likewise - (probe_mod_LDFLAGS): likewise - * conf/i386-coreboot.rmk (grub_emu_SOURCES): add commands/probe.c - * conf/i386-ieee1275.rmk: likewise - * conf/i386-pc.rmk: likewise - * conf/powerpc-ieee1275.rmk: likewise - * conf/sparc64-ieee1275.rmk: likewise - -2009-06-15 Vladimir Serbinenko - - Fix handling of string like \"hello\" and "a - b" - - * script/sh/lexer.c (check_textstate): accept GRUB_PARSER_STATE_ESC - (grub_script_yylex): fix parsing of quoting, escaping and newline - -2009-06-13 Vladimir Serbinenko - - * loader/i386/multiboot.c (grub_multiboot_get_bootdev): fix partition - handling - -2009-06-13 Jun Inoue - - * util/grub-mkconfig.in: Fix parsing of --output option. - -2009-06-12 Pavel Roskin - - * Makefile.in (pkgdata_SRCDIR): Remove. genmodsrc.sh and - genmk.rb don't need to be generated or installed. - -2009-06-12 Vladimir Serbinenko - - * commands/i386/pc/drivemap_int13h.S: add more comments - -2009-06-11 Pavel Roskin - - * Makefile.in (uninstall): Uninstall manuals. - - * Makefile.in: Rename lib_DATA to lib_SCRIPTS, move it from - PKGLIB to SCRIPTS. This fixes installation of grub-mkconfig_lib - and update-grub_lib in two places. - * conf/common.rmk: Rename lib_DATA to lib_SCRIPTS. - - * disk/usbms.c (grub_usbms_transfer): Initialize `err' to fix - a compiler warning. - - * loader/i386/bsd.c (grub_freebsd_boot): Rename `entry' to - `entry_lo' to fix variable shadowing. - -2009-06-11 Christian Franke - - * kern/misc.c (__enable_execute_stack): Add missing return type - to prevent gcc warning. - -2009-06-11 Felix Zielcke - - * conf/i386-ieee1275.rmk (COMMON_LDFLAGS): Remove `-static -lgcc'. - -2009-06-11 Pavel Roskin - - * Makefile.in: Don't rely on any scripts being executable. - Always use $(SHELL) to run shell scripts. - - * configure.ac: Always define ___main if using -nostdlib. This - fixes tests on Cygwin. - -2009-06-11 Giuseppe Caizzone - - UDF fix - - * fs/udf.c (grub_udf_read_block): handle the fact that ad->length - is in bytes and not in blocks - -2009-06-11 Pavel Roskin - - * kern/i386/halt.c (grub_halt): Make `i' unsigned to fix a - warning. - -2009-06-11 Felix Zielcke - - * util/grub.d/30_os-prober.in: Fix a comment. Source - ${libdir}/grub/grub-mkconfig_lib. Use prepare_grub_to_access_device - to set the root device. Place drivemap command in the generated - chain entry. - -2009-06-11 Pavel Roskin - - * configure.ac: Remove host_m32. Issues with 64-bit utilities - have long been resolved. - -2009-06-11 Colin Watson - - * util/grub.d/10_linux.in: Capitalise "Linux". - - * util/grub-pe2elf.c (usage): Fix references to grub-editenv. - -2009-06-11 Pavel Roskin - - * kern/efi/efi.c (grub_exit): Add infinite loop at the end to - fix a gcc warning and ensure that the function won't ever exit. - - * kern/i386/ieee1275/init.c: Add missing prototype for - grub_stop_floppy(). - - * loader/ieee1275/multiboot2.c [__i386__]: Include - grub/cpu/multiboot.h. - - * term/i386/pc/serial.c (serial_translate_key_sequence): Avoid - casts to short - they are not portable and cause warnings. Fix - use of uninitialized values in input_buf. Use ARRAY_SIZE. - -2009-06-11 Vladimir Serbinenko - - Drivemap fixes - - * commands/i386/pc/drivemap.c (grub_get_root_biosnumber_drivemap): - new function - (grub_get_root_biosnumber_saved): new variable - (GRUB_MOD_INIT): register grub_get_root_biosnumber_drivemap - (GRUB_MOD_FINI): unregister grub_get_root_biosnumber_drivemap - * commands/i386/pc/drivemap_int13h.S (grub_drivemap_handler): restore - %dx after the call if necessary - * conf/common.rmk (pkglib_MODULES): remove boot.mod - (boot_mod_SOURCES): remove - (boot_mod_CFLAGS): remove - (boot_mod_LDFLAGS): remove - * conf/i386-coreboot.rmk (pkglib_MODULES): add boot.mod - (boot_mod_SOURCES): new variable - (boot_mod_CFLAGS): likewise - (boot_mod_LDFLAGS): likewise - * conf/i386-efi.rmk: likewise - * conf/i386-ieee1275.rmk: likewise - * conf/i386-pc.rmk: likewise - * conf/powerpc-ieee1275.rmk: likewise - * conf/sparc64-ieee1275.rmk: likewise - * conf/x86_64-efi.rmk: likewise - * include/grub/i386/pc/biosnum.h: new file - * lib/i386/pc/biosnum.c: likewise - * loader/i386/bsd.c (grub_bsd_get_device): use grub_get_root_biosnumber - * loader/i386/multiboot.c (grub_multiboot_get_bootdev): likewise - * loader/i386/pc/chainloader.c (grub_chainloader_cmd): likewise - -2009-06-10 Pavel Roskin - - * io/gzio.c (test_header): Don't reuse one buffer for all data. - Use separate variables. Read only the file size at the end, but - not the checksum that we don't use. - - * kern/file.c (grub_file_read): Use void pointer for the buffer. - Adjust all callers. - - * kern/ieee1275/openfw.c: Remove libc includes. - * kern/ieee1275/cmain.c: Likewise. - * include/grub/ieee1275/ieee1275.h: Likewise. - - * kern/i386/coreboot/init.c: Include grub/cpu/tsc.h to fix - compiler warnings. - -2009-06-10 Felix Zielcke - - * Makefile.in: Remove all trailing whitespace. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * docs/grub.texi: Likewise. - * docs/texinfo.tex: Likewise. - * disk/fs_uuid.c: Likewise. - * disk/lvm.c: Likewise. - * disk/scsi.c: Likewise. - * disk/ata.c: Likewise. - * disk/ieee1275/ofdisk.c: Likewise. - * disk/i386/pc/biosdisk.c: Likewise. - * disk/host.c: Likewise. - * disk/raid.c: Likewise. - * disk/efi/efidisk.c: Likewise. - * disk/usbms.c: Likewise. - * disk/memdisk.c: Likewise. - * disk/loopback.c: Likewise. - * kern/powerpc/dl.c: Likewise. - * kern/device.c: Likewise. - * kern/dl.c: Likewise. - * kern/sparc64/dl.c: Likewise. - * kern/ieee1275/ieee1275.c: Likewise. - * kern/term.c: Likewise. - * kern/fs.c: Likewise. - * kern/i386/dl.c: Likewise. - * kern/i386/pc/startup.S: Likewise. - * kern/i386/pc/init.c: Likewise. - * kern/i386/pc/mmap.c: Likewise. - * kern/i386/pc/lzo1x.S: Likewise. - * kern/i386/ieee1275/init.c: Likewise. - * kern/i386/realmode.S: Likewise. - * kern/i386/tsc.c: Likewise. - * kern/partition.c: Likewise. - * kern/corecmd.c: Likewise. - * kern/file.c: Likewise. - * kern/efi/efi.c: Likewise. - * kern/efi/init.c: Likewise. - * kern/efi/mm.c: Likewise. - * kern/main.c: Likewise. - * kern/err.c: Likewise. - * kern/env.c: Likewise. - * kern/disk.c: Likewise. - * kern/generic/millisleep.c: Likewise. - * kern/generic/rtc_get_time_ms.c: Likewise. - * kern/misc.c: Likewise. - * kern/parser.c: Likewise. - * genmk.rb: Likewise. - * configure.ac: Likewise. - * boot/i386/pc/diskboot.S: Likewise. - * boot/i386/pc/pxeboot.S: Likewise. - * boot/i386/pc/boot.S: Likewise. - * boot/i386/pc/lnxboot.S: Likewise. - * boot/i386/pc/cdboot.S: Likewise. - * parttool/pcpart.c: Likewise. - * video/readers/tga.c: Likewise. - * video/video.c: Likewise. - * video/bitmap.c: Likewise. - * lib/envblk.c: Likewise. - * lib/i386/setjmp.S: Likewise. - * fs/xfs.c: Likewise. - * fs/afs.c: Likewise. - * fs/fat.c: Likewise. - * fs/ntfs.c: Likewise. - * fs/udf.c: Likewise. - * fs/affs.c: Likewise. - * fs/iso9660.c: Likewise. - * fs/hfs.c: Likewise. - * fs/fshelp.c: Likewise. - * fs/ext2.c: Likewise. - * fs/jfs.c: Likewise. - * fs/reiserfs.c: Likewise. - * fs/hfsplus.c: Likewise. - * fs/minix.c: Likewise. - * fs/cpio.c: Likewise. - * fs/sfs.c: Likewise. - * fs/ufs.c: Likewise. - * efiemu/prepare.c: Likewise. - * efiemu/loadcore_common.c: Likewise. - * efiemu/runtime/efiemu.sh: Likewise. - * efiemu/runtime/efiemu.S: Likewise. - * efiemu/runtime/efiemu.c: Likewise. - * efiemu/pnvram.c: Likewise. - * efiemu/main.c: Likewise. - * efiemu/i386/pc/cfgtables.c: Likewise. - * efiemu/i386/loadcore64.c: Likewise. - * efiemu/i386/loadcore32.c: Likewise. - * efiemu/loadcore.c: Likewise. - * efiemu/symbols.c: Likewise. - * efiemu/mm.c: Likewise. - * include/grub/autoefi.h: Likewise. - * include/grub/datetime.h: Likewise. - * include/grub/term.h: Likewise. - * include/grub/hfs.h: Likewise. - * include/grub/lvm.h: Likewise. - * include/grub/i386/tsc.h: Likewise. - * include/grub/i386/linux.h: Likewise. - * include/grub/i386/xnu.h: Likewise. - * include/grub/i386/efiemu.h: Likewise. - * include/grub/i386/pc/biosdisk.h: Likewise. - * include/grub/i386/pc/memory.h: Likewise. - * include/grub/i386/pc/vbe.h: Likewise. - * include/grub/parttool.h: Likewise. - * include/grub/video.h: Likewise. - * include/grub/memory.h: Likewise. - * include/grub/fs.h: Likewise. - * include/grub/partition.h: Likewise. - * include/grub/xnu.h: Likewise. - * include/grub/efi/api.h: Likewise. - * include/grub/efi/pe32.h: Likewise. - * include/grub/efi/memory.h: Likewise. - * include/grub/multiboot.h: Likewise. - * include/grub/usbdesc.h: Likewise. - * include/grub/multiboot2.h: Likewise. - * include/grub/acpi.h: Likewise. - * include/grub/efiemu/efiemu.h: Likewise. - * include/grub/disk.h: Likewise. - * include/grub/ieee1275/ieee1275.h: Likewise. - * include/grub/net.h: Likewise. - * include/grub/machoload.h: Likewise. - * include/grub/macho.h: Likewise. - * include/multiboot.h: Likewise. - * genmoddep.awk: Likewise. - * normal/main.c: Likewise. - * normal/menu_entry.c: Likewise. - * normal/menu_viewer.c: Likewise. - * normal/completion.c: Likewise. - * normal/cmdline.c: Likewise. - * normal/misc.c: Likewise. - * normal/datetime.c: Likewise. - * bus/usb/usbtrans.c: Likewise. - * bus/usb/ohci.c: Likewise. - * bus/usb/uhci.c: Likewise. - * bus/usb/usb.c: Likewise. - * mmap/efi/mmap.c: Likewise. - * mmap/i386/pc/mmap_helper.S: Likewise. - * mmap/i386/pc/mmap.c: Likewise. - * mmap/i386/mmap.c: Likewise. - * mmap/i386/uppermem.c: Likewise. - * mmap/mmap.c: Likewise. - * commands/acpi.c: Likewise. - * commands/echo.c: Likewise. - * commands/blocklist.c: Likewise. - * commands/loadenv.c: Likewise. - * commands/usbtest.c: Likewise. - * commands/boot.c: Likewise. - * commands/parttool.c: Likewise. - * commands/search.c: Likewise. - * commands/cat.c: Likewise. - * commands/i386/pc/play.c: Likewise. - * commands/i386/pc/drivemap.c: Likewise. - * commands/i386/pc/vbeinfo.c: Likewise. - * commands/i386/pc/acpi.c: Likewise. - * commands/i386/pc/vbetest.c: Likewise. - * commands/ls.c: Likewise. - * commands/cmp.c: Likewise. - * commands/test.c: Likewise. - * commands/efi/acpi.c: Likewise. - * commands/gptsync.c: Likewise. - * commands/help.c: Likewise. - * partmap/amiga.c: Likewise. - * partmap/apple.c: Likewise. - * partmap/acorn.c: Likewise. - * partmap/pc.c: Likewise. - * partmap/sun.c: Likewise. - * partmap/gpt.c: Likewise. - * script/sh/lexer.c: Likewise. - * script/sh/function.c: Likewise. - * font/font.c: Likewise. - * font/font_cmd.c: Likewise. - * loader/powerpc/ieee1275/linux.c: Likewise. - * loader/efi/chainloader.c: Likewise. - * loader/multiboot_loader.c: Likewise. - * loader/macho.c: Likewise. - * loader/i386/multiboot.c: Likewise. - * loader/i386/linux.c: Likewise. - * loader/i386/pc/linux.c: Likewise. - * loader/i386/pc/multiboot2.c: Likewise. - * loader/i386/pc/chainloader.c: Likewise. - * loader/i386/pc/xnu.c: Likewise. - * loader/i386/bsd_trampoline.S: Likewise. - * loader/i386/efi/linux.c: Likewise. - * loader/i386/multiboot_elfxx.c: Likewise. - * loader/i386/bsd_helper.S: Likewise. - * loader/i386/bsd.c: Likewise. - * loader/i386/linux_trampoline.S: Likewise. - * loader/i386/xnu_helper.S: Likewise. - * loader/i386/xnu.c: Likewise. - * loader/i386/bsd_pagetable.c: Likewise. - * loader/i386/multiboot_helper.S: Likewise. - * loader/xnu.c: Likewise. - * loader/xnu_resume.c: Likewise. - * io/gzio.c: Likewise. - * term/efi/console.c: Likewise. - * term/terminfo.c: Likewise. - * term/ieee1275/ofconsole.c: Likewise. - * term/i386/pc/serial.c: Likewise. - * term/i386/pc/vesafb.c: Likewise. - * term/i386/pc/vga.c: Likewise. - * term/usb_keyboard.c: Likewise. - * term/gfxterm.c: Likewise. - * aclocal.m4: Likewise. - * util/lvm.c: Likewise. - * util/grub.d/30_os-prober.in: Likewise. - * util/grub.d/10_hurd.in: Likewise. - * util/console.c: Likewise. - * util/grub-macho2img.c: Likewise. - * util/grub-probe.c: Likewise. - * util/hostfs.c: Likewise. - * util/i386/pc/grub-mkimage.c: Likewise. - * util/i386/pc/grub-setup.c: Likewise. - * util/i386/efi/grub-mkimage.c: Likewise. - * util/grub-mkconfig.in: Likewise. - * util/raid.c: Likewise. - * util/resolve.c: Likewise. - * util/grub-mkdevicemap.c: Likewise. - * util/grub-emu.c: Likewise. - * util/getroot.c: Likewise. - * util/hostdisk.c: Likewise. - * util/usb.c: Likewise. - * util/grub-editenv.c: Likewise. - * util/misc.c: Likewise. - -2009-06-10 Felix Zielcke - - * gendistlist.sh (EXTRA_DISTFILES): Add `genhandlerlist.sh' and - `genparttoollist.sh'. - (DISTDIRS): Add `efiemu', `mmap', `parttool' and `script'. - Add `*.sh' to the list find searches for and change `mdate.sh' - to `mdate-sh'. - -2009-06-10 Pavel Roskin - - * include/grub/multiboot2.h: Provide compatibility defines for - multiboot2.h. - * include/multiboot2.h: Include stdint.h only if needed, using - angle brackets. - * loader/i386/pc/multiboot2.c: Include multiboot2.h after - grub/multiboot2.h. - * loader/ieee1275/multiboot2.c: Likewise. - * loader/multiboot2.c: Likewise. - * loader/multiboot_loader.c: Likewise. - - * configure.ac: Use -nostdlib when probing for the target. It - should not be required to have libc for the target. - - * configure.ac: Remove checks for __bswapsi2 and __bswapdi2, - they fail without libc headers for the target. - * include/grub/powerpc/libgcc.h: Use weak attribute for all - exports. - * include/grub/sparc64/libgcc.h: Likewise. Don't use - preprocessor conditionals. - - * conf/common.rmk: Compile tar.mod from tar.c, not cpio.c. The - build system doesn't need to be aware of the tar.c internals. - -2009-06-09 Michel Hermier - - * fs/i386/pc/pxe.c (grub_pxefs_read): Fix returned values. - -2009-06-09 Robert Millan - - * util/deviceiter.c (grub_util_iterate_devices): Increase number of - disk limit to 26 for IDE, Virtio, Xen and SCSI. - -2009-06-09 Felix Zielcke - - * util/i386/pc/grub-install.in: Change the error message if UUIDs - aren't available if ata.mod gets used. - -2009-06-09 Oliver Henshaw - - * bus/usb/ohci.c (grub_ohci_pci_iter): Link struct only after - initialising controller. - * bus/usb/uhci.c (grub_uhci_pci_iter): Likewise. - -2009-06-08 Felix Zielcke - - * util/i386/pc/grub-install.in: Add a parameter --disk-module - to choose between ata and biosdisk module on i386-pc. - -2009-06-08 Oliver Henshaw - - * bus/usb/ohci.c (grub_ohci_pci_iter): Define the Class, - Subclass and Programming Interface fields in terms of the 3 byte - Class Code register. - * bus/usb/uhci.c (grub_uhci_pci_iter): Likewise. - - * bus/usb/ohci.c (grub_ohci_pci_iter): Check that programming - interface is OHCI. Add grub_dprintf for symmetry with - bus/usb/uhci.c. - * bus/usb/uhci.c (grub_uhci_pci_iter): Check that programming - interface is UHCI. Add interf variable for programming - interface. Print interface with class/subclass. - - * bus/usb/ohci.c: Set interf with correct field. - - * bus/usb/uhci.c: Remove unneeded doubled lines. - * bus/usb/ohci.c: Likewise. Change interf to grub_uint32_t. - Remove whitespace inside comment. - -2009-06-08 Robert Millan - - * loader/i386/linux.c (grub_cmd_linux): When processing `vga=', use - as fallback an equivalent option without depth. - -2009-06-08 Vladimir Serbinenko - - Not fail if unable to retrieve C/H/S on LBA disks - - * disk/i386/pc/biosdisk.c (grub_biosdisk_open): behave gracefully - if unable to retrieve C/H/S on LBA disks - -2009-06-08 Pavel Roskin - - * fs/hfs.c (grub_hfs_find_dir): Use union to avoid a warning - about aliasing. - -2009-06-08 Felix Zielcke - - * Makefile.in (uninstall): Remove all $lib_DATA files. - -2009-06-08 Vladimir Serbinenko - - Bugfix: install on partitionless device - - * util/hostdisk.c (grub_util_biosdisk_get_grub_dev): check if os_dev - is a whole disk - -2009-06-08 Felix Zielcke - - * Makefile.in (uninstall): Remove all $include_DATA files. - -2009-06-08 Felix Zielcke - - * commands/true.c: New file. Implement the true and false commands. - * conf/common.rmk.c (pkglib_MODULES): Add `true.mod'. - (true_mod_SOURCES): New variable. - (true_mod_CFLAGS): Likewise. - (true_mod_LDFLAGS): Likewise. - -2009-06-05 Colin D Bennett - - Optimized font character lookup using binary search instead of linear - search. Fonts now are required to have the character index ordered by - code point. - - * font/font.c (load_font_index): Verify that fonts have ordered - character indices. - (find_glyph): Use binary search instead of linear search to find a - character in a font. - -2009-06-05 Michael Scherer - - * fs/hfsplus.c (grub_hfsplus_mount): Determine if the filesystem - uses case sensitive btree. - (grub_hfsplus_iterate_dir): Use GRUB_FSHELP_CASE_INSENSITIVE - only for case insensitive filesystems. - -2009-06-05 Vladimir Serbinenko - - * conf/i386-pc.rmk (efiemu_mod_CFLAGS): remove -Werror -Wall - * conf/common.rmk (search_mod_CFLAGS): likewise - -2009-06-04 Vladimir Serbinenko - - * kern/i386/pc/startup.S [APPLE_CC]: block of nops to - compensate a compiler bug - -2009-06-04 Vladimir Serbinenko - - * include/grub/term.h (GRUB_TERM_BACKSPACE): explicitly define as 8 - instead of '\b' - -2009-06-04 Vladimir Serbinenko - - Definitions for creating asm symbols with Apple's CC - - * include/grub/symbol.h [APPLE_CC] (FUNCTION): new macro - [APPLE_CC] (VARIABLE): likewise - -2009-06-04 Vladimir Serbinenko - - Disable lnxboot.img when compiled - with Apple's CC - - * conf/i386-pc.rmk (pkglib_IMAGES): remove lnxboot.img - pkglib_IMAGES [! TARGET_APPLE_CC] (pkglib_IMAGES): add lnxboot.img - * boot/i386/pc/lnxboot.S [APPLE_CC]: define an #error - [! APPLE_CC] (CODE_LENG): skip - [! APPLE_CC] (setup_sects): likewise - [! APPLE_CC]: skip filling - -2009-06-04 Vladimir Serbinenko - - Address in trampolines based on 32-bit registers when compiled - with Apple's CC - - * loader/i386/xnu_helper.S [APPLE_CC]: use 32-bit registers - for addresses - * loader/i386/linux_trampoline.S [APPLE_CC]: likewise - -2009-06-04 Vladimir Serbinenko - - Avoid aliases when compiling with Apple's CC for PCBIOS machine - - * kern/misc.c [APPLE_CC] (memcpy): new function - [APPLE_CC] (memmove): likewise - [APPLE_CC && !GRUB_UTIL] (grub_err_printf): likewise - (memcpy): define alias conditionally on !APPLE_CC - (memset): likewise - (abort): likewise - * include/grub/misc.h (memove): don't define when both GRUB_UTIL and - APPLE_CC are defined - * include/grub/list.h [APPLE_CC] (grub_assert_fail): new function - (grub_assert_fail): make prototype conditional - -2009-06-04 Vladimir Serbinenko - - Use grub-macho2img when compiling with Apple's CC for PCBIOS machine - - * conf/common.rmk (bin_UTILITIES): add (on false on condition) - grub-macho2img - (CLEANFILES): add grub-macho2img - (grub_macho2img_SOURCES): new variable - * kern/i386/pc/startup.S (bss_start): new variable - (bss_end): likewise - * genmk.rb: use grub-macho2img for *.img when compiled with Apple's CC - * util/grub-macho2img.c: new file - -2009-06-04 Vladimir Serbinenko - - Use objconv when compiling with Apple's CC - - * conf/i386-pc.rmk (efiemu32.o): use OBJCONV if defined - (efiemu64.o): likewise - (efiemu64_c.o): omit -mcmodel=large and add -DAPPLE_CC=1 - when compiling with Apple's CC - (efiemu64_s.o): likewise - * configure.ac: check for objconv when compiling with Apple's CC - * genmk.rb: use objconv for modules when compiled with Apple's CC - -2009-06-04 Vladimir Serbinenko - - Define segment as well as section when compiling with - Apple's CC - - * efiemu/runtime/efiemu.c (PHYSICAL_ATTRIBUTE): new definition - (efiemu_set_virtual_address_map): declare with PHYSICAL_ATTRIBUTE - (efiemu_convert_pointer): likewise - (efiemu_set_virtual_address_map): likewise - (efiemu_convert_pointer): likewise - (efiemu_getcrc32): likewise - (init_crc32_table): likewise - (reflect): likewise - * include/grub/dl.h (GRUB_MOD_NAME): define segment with Apple's CC - (GRUB_MOD_DEP): likewise - -2009-06-04 Vladimir Serbinenko - - Allow a compilation without -mcmodel=large - - * kern/efi/mm.c (grub_efi_allocate_pages): don't allocate >4GiB - when compiled without -mcmodel=large - (filter_memory_map): remove memory post 4 GiB when compiled - without -mcmodel=large - * configure.ac: fail gracefully and add -DMCMODEL_SMALL=1 to - TARGET_CFLAGS when -mcmodel=large isn't supported - -2009-06-04 Vladimir Serbinenko - - Remove nested functions in efiemu core - - * efiemu/runtime/efiemu.c (reflect): make static instead of nested - -2009-06-04 Vladimir Serbinenko - - Avoid clobbering %ebx/%rbx in inline assembly with Apple's CC - - * efiemu/runtime/efiemu.c (write_cmos): use %cl instead of %bl as - temporary storage - * include/grub/i386/tsc.h (grub_get_tsc): restore %rbx/%ebx when - using Apple's CC - (grub_cpu_is_tsc_supported): likewise - * loader/i386/xnu.c (guessfsb): restore %rbx/%ebx in inline assembly - -2009-06-04 Vladimir Serbinenko - - Absolute addressing through constant with Apple's cc - - * kern/i386/pc/startup.S: Define necessary constants - and address through it when using ABS with Apple's CC - * boot/i386/pc/diskboot.S: likewise - * boot/i386/pc/boot.S: likewise - * boot/i386/pc/lnxboot.S: likewise - * boot/i386/pc/cdboot.S: likewise - * mmap/i386/pc/mmap_helper.S: likewise - * commands/i386/pc/drivemap_int13h.S: likewise - -2009-06-04 Vladimir Serbinenko - - Check if compiler is apple cc - - * Makefile.in (ASFLAGS): new variable - (TARGET_ASFLAGS): likewise - (TARGET_MODULE_FORMAT): likewise - (TARGET_APPLE_CC): likewise - (OBJCONV): likewise - (TARGET_IMG_CFLAGS): likewise - (TARGET_CPPFLAGS): add includedir - * configure.ac: call grub_apple_cc and grub_apple_target_cc - (TARGET_IMG_LDFLAGS): Add -Wl,-Ttext,. All users updated - Check for linker script only if compiler isn't Apple's CC - (TARGET_MODULE_FORMAT): set - (TARGET_APPLE_CC): likewise - (TARGET_ASFLAGS): likewise - (ASFLAGS): likewise - Check for objcopy only if compiler isn't Apple's CC - Check for BSS symbol only if compiler isn't Apple's CC - * genmk.rb: adapt nm options if we use Apple's utils - * aclocal.m4 (grub_apple_cc): new test - (grub_apple_target_cc): likewise - -2009-06-04 Vladimir Serbinenko - - Simplify sed expressions and improve awk - - * Makefile.in (install-local): simplify sed expression - * gencmdlist.sh: likewise - * genmoddep.awk: avoid adding module as a dependency of itself - -2009-06-04 Vladimir Serbinenko - - Add missing start symbols - - * boot/i386/pc/boot.S: add start - * boot/i386/pc/pxeboot.S: likewise - -2009-06-04 Vladimir Serbinenko - - Fix wrong assumptions with grub-mkimage on EFI - - * i386/efi/grub-mkimage.c (read_kernel_module): don't write prefix here - (relocate_addresses): consider both r_addend and value at offset - (make_mods_section): zerofill modinfo and header - (convert_elf): write prefix here - -2009-06-04 Vladimir Serbinenko - - Use .asciz instead of .string - - * i386/pc/diskboot.S: use .asciz instead of .string - * i386/pc/boot.S: likewise - * include/grub/dl.h (GRUB_MOD_DEP): likewise - (GRUB_MOD_NAME): likewise - -2009-06-04 Vladimir Serbinenko - - gfxpayload support - - * commands/videotest.c (grub_cmd_videotest): use grub_video_set_mode - * include/grub/video.h (GRUB_VIDEO_MODE_TYPE_PURE_TEXT): new definition - (grub_video_setup): remove - (grub_video_set_mode): new prototype - * loader/i386/linux.c (DEFAULT_VIDEO_MODE): new definition - (vid_mode): remove - (linux_vesafb_res): compile only on PCBIOS - (grub_linux_boot): support gfxpayload - * loader/i386/pc/xnu.c (video_hook): new function - (grub_xnu_set_video): support gfxpayload - * term/gfxterm.c (DEFAULT_VIDEO_WIDTH): removed - (DEFAULT_VIDEO_HEIGHT): likewise - (DEFAULT_VIDEO_FLAGS): likewise - (DEFAULT_VIDEO_MODE): new definition - (video_hook): new function - (grub_gfxterm_init): use grub_video_set_mode - * util/grub.d/30_os-prober.in: remove explicit modesetting before - loading xnu - * video/video.c (grub_video_setup): removed - (grub_video_set_mode): new function based on grub_gfxterm_init and - grub_video_setup - -2009-06-04 Vladimir Serbinenko - - Avoid calling biosdisk in drivemap - - * commands/i386/pc/drivemap.c (parse_biosdisk): remove - (revparse_biosdisk): likewise - (list_mappings): derive name from id directly - (grub_cmd_drivemap): use tryparse_diskstring - -2009-06-04 Vladimir Serbinenko - - Script fixes - - * include/grub/script_sh.h (grub_script_cmdline): remove cmdline - (grub_lexer_param): add tokenonhold - (grub_script_create_cmdline): remove cmdline. All callers updated - (grub_script_function_create): make functionname - grub_script_arg. All callers updated - (grub_script_execute_argument_to_string): new prototype - * kern/parser.c (state_transitions): reorder - (grub_parser_cmdline_state): fix a bug and make more compact - * script/sh/execute.c (grub_script_execute_argument_to_string): - make global - (grub_script_execute_cmdline): use new format - * script/sh/function.c (grub_script_function_create): make functionname - grub_script_arg. All callers updated - * script/sh/lexer.c (grub_script_lexer_init): initialize tokenonhold - (grub_script_yylex): remove - (grub_script_yylex2): renamed to ... - (grub_script_yylex): ...renamed - parse the expressions like a${b}c - * script/sh/parser.y (GRUB_PARSER_TOKEN_ARG): new typed terminal - (GRUB_PARSER_TOKEN_VAR): remove - (GRUB_PARSER_TOKEN_NAME): likewise - ("if"): declare as typeless - ("while"): likewise - ("function"): likewise - ("else"): likewise - ("then"): likewise - ("fi"): likewise - (text): remove - (argument): likewise - (script): accept empty scripts and make exit on error - (arguments): use GRUB_PARSER_TOKEN_ARG - (function): likewise - (command): move error handling to script - (menuentry): move grub_script_lexer_ref before - * script/sh/script.c (grub_script_create_cmdline): remove cmdline - argument. All callers updated - -2009-06-04 Robert Millan - - Prevent GRUB from probing floppies during boot. - - * conf/common.rmk (search_mod_CFLAGS): Use `-Werror -Wall'. - * commands/search.c (options): Add --no-floppy. - (search_fs, search_file, grub_cmd_search): Support --no-floppy. - * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Use - --no-floppy when searching for UUIDs. - -2009-06-04 Robert Millan - - Simplify the code duplication in commands/search.c. - - * commands/search.c (search_label, search_fs_uuid): Merge into ... - (search_fs): ... this. Update all users. - -2009-06-03 Felix Zielcke - - * util/grub-mkconfig.in (update_grub_dir): Rename to grub_mkconfig_dir. - -2009-05-28 Pavel Roskin - - * Makefile.in: Don't use "cp -d", it doesn't work on FreeBSD. - Remove the original symlink explicitly. - - * fs/hfs.c (grub_hfs_find_dir): Skip sequences of slashes, not - just one slash. That's how grub_fshelp_find_file() does it. - -2009-05-26 Pavel Roskin - - * genmk.rb: Avoid shadowing variable `s', rename the outer `s' - to `str'. - - * util/getroot.c (grub_util_get_dev_abstraction): Mark os_dev as - possibly unused. - -2009-05-25 Christian Franke - - * disk/ata.c (grub_ata_wait_not_busy): Add debug output of status - register. - (grub_atapi_identify): Add wait after drive select. - (grub_ata_identify): Do more strict status register check before - calling grub_atapi_identify (). Suppress error message if status - register is 0x00 after command failure. Add status register - check after PIO read to avoid bogus identify due to stuck DRQ. - Thanks to Pavel Roskin for testing. - (grub_device_initialize): Remove unsafe status register check. - Thanks to 'phcoder' for problem report and patch. - Prevent sign extension in debug message. - -2009-05-23 Colin D Bennett - - Cleaned up `include/grub/normal.h'. Grouped prototypes by - definition file, and functions defined in `normal/menu.c' have had - their prototypes moved to `include/grub/menu.h' for consistency. - - * include/grub/menu.h (grub_menu_execute_callback): Added; moved - from normal.h. - (grub_menu_get_entry): Likewise. - (grub_menu_get_timeout): Likewise. - (grub_menu_set_timeout): Likewise. - (grub_menu_execute_entry): Likewise. - (grub_menu_execute_with_fallback): Likewise. - (grub_menu_entry_run): Likewise. - - * include/grub/normal.h: Re-ordered and grouped function - prototypes by file that the function is defined in. - (grub_menu_execute_callback): Removed; moved to menu.h. - (grub_menu_get_entry): Likewise. - (grub_menu_get_timeout): Likewise. - (grub_menu_set_timeout): Likewise. - (grub_menu_execute_entry): Likewise. - (grub_menu_execute_with_fallback): Likewise. - (grub_menu_entry_run): Likewise. - (grub_menu_addentry): Renamed from this ... - (grub_normal_add_menu_entry): ... to this. - - * normal/main.c (grub_menu_addentry): Renamed from this ... - (grub_normal_add_menu_entry): ... to this. - - * script/sh/execute.c (grub_script_execute_menuentry): Update - reference to renamed grub_menu_addentry function. - -2009-05-23 Felix Zielcke - - * commands/i386/pc/drivemap.c (MODNAME): Remove. Update all users. - -2009-05-22 Pavel Roskin - - * aclocal.m4 (grub_I386_CHECK_REGPARM_BUG): Remove. - * configure.ac: Don't call grub_I386_CHECK_REGPARM_BUG. Define - NESTED_FUNC_ATTR using AH_BOTTOM. Use regparm(1) only when - compiling for the i386 targets, but not for the utilities. - - * include/grub/i386/pc/kernel.h (grub_boot_drive): Change type - to grub_uint8_t. - (grub_root_drive): Likewise. - * kern/i386/pc/startup.S (grub_boot_drive): Change size to byte, - remove alignment. - (grub_root_drive): Change size to byte. - (grub_start_addr): Remove. - (grub_end_addr): Likewise. - (grub_apm_bios_info): Likewise. - -2009-05-21 Felix Zielcke - - * normal/i386: Remove. - * normal/powerpc: Likewise. - * normal/sparc64: Likewise. - * normal/x86_64: Likewise. - -2009-05-19 Vladimir Serbinenko - - * conf/x86_64-efi.rmk (linux_mod_ASFLAGS): Add missing variable - * loader/i386/linux_trampoline.S: Fix indentation - * loader/i386/xnu_helper.S: Likewise - -2009-05-18 Colin D Bennett - - Display error messages when parsing a Lua statement fails. - Previously, executing a syntactically invalid statement like - ")foo" or "bar;" would silently fail. - - * script/lua/grub_main.c (handle_lua_error): New function. - (grub_lua_parse_line): Improved reporting of Lua parser and - execution errors. - -2009-05-17 Vladimir Serbinenko - - Remove -Werror which causes build to fail on some systems - - * conf/i386-pc.rmk (xnu_mod_CFLAGS): Remove -Werror -Wall - * conf/i386-efi.rmk (xnu_mod_CFLAGS): Likewise - * conf/x86_64-efi.rmk (xnu_mod_CFLAGS): Likewise - -2009-05-17 Vladimir Serbinenko - - trampoline for linux on 64-bit platform - - * conf/x86_64-efi.rmk (linux_mod_SOURCES): added - loader/i386/efi/linux_trampoline.S - * include/grub/x86_64/efi/loader.h (grub_linux_real_boot): removed - declaration - * kern/x86_64/efi/startup.S (grub_linux_real_boot): moved from - here - * loader/i386/linux_trampoline.S: moved here - * loader/i386/efi/linux.c (allocate_pages): reserve space for - trampoline - (jumpvector): removed - (grub_linux_trampoline_start): new declaration - (grub_linux_trampoline_end): likewise - (grub_linux_boot): use trampoline when on 64-bit platform - * loader/i386/linux.c: likewise - -2009-05-16 Pavel Roskin - - * script/lua/grub_lib.c (grub_lua_getenv): Make name and value - const to avoid a warning. - (grub_lua_setenv): Likewise. - * script/lua/grub_main.c (grub_lua_parse_line): Use size_t for - lmsg to fix a warning. - -2009-05-16 Felix Zielcke - - * conf/i386.rmk (setjmp_mod_CFLAGS): Rename to ... - (setjmp_mod_ASFLAGS): ... this. Set to $(COMMON_ASFLAGS). - * conf/x86_64-efi.rmk (setjmp_mod_CFLAGS): Rename to ... - (setjmp_mod_ASFLAGS): ... this. Set to $(COMMON_ASFLAGS). - * conf/powerpc-ieee1275.rmk (setjmp_mod_CFLAGS): Rename to ... - (setjmp_mod_ASFLAGS): ... this. Set to $(COMMON_ASFLAGS). - * conf/sparc64-ieee1275.rmk (setjmp_mod_CFLAGS): Rename to ... - (setjmp_mod_ASFLAGS): ... this. Set to $(COMMON_ASFLAGS). - -2009-05-16 Felix Zielcke - - * util/grub-mkconfig.in: Export GRUB_TERMINAL_INPUT. - -2009-05-16 Bean - - * conf/common.rmk (pkglib_MODULES): Add lua.mod. - (lua_mod_SOURCES): New variable. - (lua_mod_CFLAGS): Likewise. - (lua_mod_LDFLAGS): Likewise. - - * conf/i386.rmk (pkglib_MODULES): Add setjmp.mod. - (setjmp_mod_SOURCES): New variable. - (setjmp_mod_CFLAGS): Likewise. - (setjmp_LDFLAGS): Likewise. - - * conf/x86_64-efi.rmk (pkglib_MODULES): Add setjmp.mod. - (setjmp_mod_SOURCES): New variable. - (setjmp_mod_CFLAGS): Likewise. - (setjmp_LDFLAGS): Likewise. - - * conf/powerpc-ieee1275.rmk (pkglib_MODULES): Add setjmp.mod. - (setjmp_mod_SOURCES): New variable. - (setjmp_mod_CFLAGS): Likewise. - (setjmp_LDFLAGS): Likewise. - - * conf/sparc64-ieee1275.rmk (pkglib_MODULES): Add setjmp.mod. - (setjmp_mod_SOURCES): New variable. - (setjmp_mod_CFLAGS): Likewise. - (setjmp_LDFLAGS): Likewise. - - * normal/i386/setjmp.S: Moved from here ... - * lib/i386/setjmp.S: ... Moved here - * normal/x86_64/setjmp.S: Moved from here ... - * lib/x86_64/setjmp.S: ... Moved here - * normal/powerpc/setjmp.S: Moved from here ... - * lib/powerpc/setjmp.S: ... Moved here - * normal/sparc64/setjmp.S: Moved from here ... - * lib/sparc64/setjmp.S: ... Moved here - - * include/grub/i386/setjmp.h (grub_setjmp): Don't use attribute - returns_twice in mingw. - - * script/lua/grub_lib.c: New file. - * script/lua/grub_lib.h: Likewise. - * script/lua/grub_lua.h: Likewise. - * script/lua/grub_main.c: Likewise. - * script/lua/lapi.c: Likewise. - * script/lua/lapi.h: Likewise. - * script/lua/lauxlib.c: Likewise. - * script/lua/lauxlib.h: Likewise. - * script/lua/lbaselib.c: Likewise. - * script/lua/lcode.c: Likewise. - * script/lua/lcode.h: Likewise. - * script/lua/ldblib.c: Likewise. - * script/lua/ldebug.c: Likewise. - * script/lua/ldebug.h: Likewise. - * script/lua/ldo.c: Likewise. - * script/lua/ldo.h: Likewise. - * script/lua/ldump.c: Likewise. - * script/lua/lfunc.c: Likewise. - * script/lua/lfunc.h: Likewise. - * script/lua/lgc.c: Likewise. - * script/lua/lgc.h: Likewise. - * script/lua/linit.c: Likewise. - * script/lua/liolib.c: Likewise. - * script/lua/llex.c: Likewise. - * script/lua/llex.h: Likewise. - * script/lua/llimits.h: Likewise. - * script/lua/lmathlib.c: Likewise. - * script/lua/lmem.c: Likewise. - * script/lua/lmem.h: Likewise. - * script/lua/loadlib.c: Likewise. - * script/lua/lobject.c: Likewise. - * script/lua/lobject.h: Likewise. - * script/lua/lopcodes.c: Likewise. - * script/lua/lopcodes.h: Likewise. - * script/lua/loslib.c: Likewise. - * script/lua/lparser.c: Likewise. - * script/lua/lparser.h: Likewise. - * script/lua/lstate.c: Likewise. - * script/lua/lstate.h: Likewise. - * script/lua/lstring.c: Likewise. - * script/lua/lstring.h: Likewise. - * script/lua/lstrlib.c: Likewise. - * script/lua/ltable.c: Likewise. - * script/lua/ltable.h: Likewise. - * script/lua/ltablib.c: Likewise. - * script/lua/ltm.c: Likewise. - * script/lua/ltm.h: Likewise. - * script/lua/lua.h: Likewise. - * script/lua/luaconf.h: Likewise. - * script/lua/lualib.h: Likewise. - * script/lua/lundump.c: Likewise. - * script/lua/lundump.h: Likewise. - * script/lua/lvm.c: Likewise. - * script/lua/lvm.h: Likewise. - * script/lua/lzio.c: Likewise. - * script/lua/lzio.h: Likewise. - -2009-05-16 Bean - - * include/grub/kernel.h (grub_module_header_types): Add type - OBJ_TYPE_CONFIG. - - * kern/main.c (grub_load_config): New function. - (grub_main): Call grub_load_config to read boot config. - - * grub-mkimage (generate_image): New parameter config_path. - (options): New option --config. - (main): Parse --config option, and pass it to generate_image. - -2009-05-14 Christian Franke - - * commands/i386/pc/drivemap_int13h.S: Add missing EXT_C for symbols. - This fixes build on Cygwin. - -2009-05-14 Pavel Roskin - - * commands/i386/pc/drivemap_int13h.S: Eliminate unconditional - jump. This saves two bytes, so the typical case of 2 swapped - drives would fit 32 bytes. - -2009-05-13 Pavel Roskin - - * loader/i386/multiboot.c (grub_multiboot): Cast mmap_addr to - grub_uint32_t to avoid a warning. - - * loader/i386/linux.c (allocate_pages): When assigning - real_mode_mem, cast through grub_size_t to fix a warning. The - code already makes sure that the value would fit a pointer. - (grub_linux_setup_video): Cast render_target->data to - grub_size_t to fix a warning. - -2009-05-13 Javier Martín - - * commands/i386/pc/drivemap.c: New file - implement drivemap - command. - * commands/i386/pc/drivemap_int13h.S: New file - int13 handler. - * conf/i386-pc.rmk: Add drivemap.c and drivemap_int13h.S. - -2009-05-13 Pavel Roskin - - * util/i386/pc/grub-setup.c (setup): Remove unused variable - embedding_area_exists. - -2009-05-13 Robert Millan - - * util/i386/pc/grub-setup.c (setup): Restructure code flow to make - it easier to understand / work with. - Improve warning messages for cases where there's no embedding area, - or when it is too small (or core.img too large). - -2009-05-13 Pavel Roskin - - * loader/i386/pc/multiboot2.c: Add necessary includes for - grub_multiboot2_real_boot(). - - * fs/iso9660.c (grub_iso9660_iterate_dir): The file mode in the - PX record is always little-endian. We only need the lower 2 - bytes of the mode. - - * fs/cpio.c: Use the same name "struct head" for tar and cpio to - facilitate code reuse. - (grub_cpio_mount): Use "struct head", not a char buffer. This - fixes a warning reported by gcc 4.4. - - * kernel/disk.c (grub_disk_read): Use void pointer for the - buffer. - (grub_disk_write): Use const void pointer for the buffer. - Adjust all callers. Remove unnecessary casts. - -2009-05-10 Robert Millan - - * util/i386/pc/grub-install.in: Update copyright year. - -2009-05-09 Vladimir Serbinenko - - gptsync - - * commands/gptsync.c: new file - * conf/common.rmk (pkglib_MODULES): add gptsync.mod - (gptsync_mod_SOURCES): new variable - (gptsync_mod_CFLAGS): likewise - (gptsync_mod_LDFLAGS): likewise - * include/grub/pc_partition.h (GRUB_PC_PARTITION_TYPE_NTFS): - new definition - (GRUB_PC_PARTITION_TYPE_HFS): likewise - * conf/i386-coreboot.rmk (grub_emu_SOURCES): add commands/gptsync.c - * conf/i386-ieee1275.rmk: likewise - * conf/i386-pc.rmk: likewise - * conf/powerpc-ieee1275.rmk: likewise - -2009-05-09 Vladimir Serbinenko - - Fixed grub-emu - - * kern/dl.c (grub_dl_ref): omit when compiling grub-emu - (grub_dl_ref): likewise - -2009-05-08 Robert Millan - - * util/i386/pc/grub-setup.c (setup): Factorize find_usable_region(), - split in two functions (one for msdos and one for gpt). - -2009-05-08 Pavel Roskin - - * disk/raid.c (grub_raid_block_xor): Make buf2 constant, it's - not modified. - - * disk/raid6_recover.c (grub_raid6_recover): Fix warnings about - uninitialized err[0] and err[1]. Rename them to bad1 and bad2. - Initialize them with -1. Add sanity check for bad1. Eliminate - nerr variable. - -2009-05-08 David S. Miller - - * util/sparc64/ieee1275/grub-ofpathname.c (main): Set progname. - -2009-05-06 Robert Millan - - * util/i386/pc/grub-setup.c (setup): Fix check for embed region - existence. - -2009-05-05 Felix Zielcke - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add - `kern/rescue_reader.c', `kern/rescue_parser.c' and `normal/autofs.c'. - -2009-05-05 David S. Miller - - * util/sparc64/ieee1275/grub-install.in: Fix sed arg quoting. - -2009-05-05 Pavel Roskin - - * include/grub/dl.h [GRUB_UTIL]: Provide inline implementations - of grub_dl_ref() and grub_dl_unref(). - * commands/parttool.c: Remove preprocessor conditionals around - grub_dl_ref() and grub_dl_unref(). - * fs/affs.c: Likewise. - * fs/afs.c: Likewise. - * fs/cpio.c: Likewise. - * fs/ext2.c: Likewise. - * fs/fat.c: Likewise. - * fs/hfs.c: Likewise. - * fs/hfsplus.c: Likewise. - * fs/iso9660.c: Likewise. - * fs/jfs.c: Likewise. - * fs/minix.c: Likewise. - * fs/ntfs.c: Likewise. - * fs/reiserfs.c: Likewise. - * fs/sfs.c: Likewise. - * fs/udf.c: Likewise. - * fs/ufs.c: Likewise. - * fs/xfs.c: Likewise. - * include/grub/dl.h: Likewise. - * loader/xnu.c: Likewise. - -2009-05-04 Pavel Roskin - - * commands/acpi.c: Remove unused variable my_mod. - * partmap/amiga.c: Likewise. - * partmap/apple.c: Likewise. - * partmap/gpt.c: Likewise. - * partmap/pc.c: Likewise. - * partmap/sun.c: Likewise. - * term/gfxterm.c: Likewise. - * term/i386/pc/vesafb.c: Likewise. - * term/i386/pc/vga.c: Likewise. - -2009-05-04 David S. Miller - - * kern/ieee1275/openfw.c (grub_children_iterate): Fix string - pointer args to grub_ieee1275_get_property(). - - * conf/sparc64-ieee1275.rmk: Fix build due to missing '\'. - - * disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): Bypass cdrom - devices, and do not traverse down under controller nodes. - - * disk/ieee1275/ofdisk.c (compute_dev_path): New. - (grub_ofdisk_open): Use it to un-escape "," characters. - * kern/disk.c (find_part_sep): New. - (grub_disk_open): Use it to find the first non-escaped ',' - character in the disk name. - * util/ieee1275/devicemap.c (escape_of_path): New. - (grub_util_emit_devicemap_entry): Use it. - * util/sparc64/ieee1275/grub-install.in: Update script to - strip partition specifiers properly by not triggering on - '\' escaped ',' characters. - -2009-05-04 Robert Millan - - * include/grub/i386/linux.h (GRUB_LINUX_VID_MODE_VESA_START): Set - to 0x300. - * loader/i386/linux.c (vga_modes, linux_vesafb_res): Add a few - resolutions. - (linux_vesafb_modes): Add a lot of additional modes to the list (based - on documentation from Wikipedia). - -2009-05-04 Pavel Roskin - - * disk/ata.c: Spelling fixes. - * disk/raid.c: Likewise. - * disk/usbms.c: Likewise. - * disk/dmraid_nvidia.c: Likewise. - * kern/ieee1275/openfw.c: Likewise. - * kern/ieee1275/init.c: Likewise. - * kern/ieee1275/cmain.c: Likewise. - * boot/i386/pc/cdboot.S: Likewise. - * video/readers/png.c: Likewise. - * video/i386/pc/vbe.c: Likewise. - * fs/udf.c: Likewise. - * fs/hfs.c: Likewise. - * fs/reiserfs.c: Likewise. - * efiemu/runtime/efiemu.c: Likewise. - * efiemu/main.c: Likewise. - * efiemu/mm.c: Likewise. - * include/grub/elf.h: Likewise. - * include/grub/xnu.h: Likewise. - * include/grub/usbdesc.h: Likewise. - * include/grub/usb.h: Likewise. - * include/grub/script_sh.h: Likewise. - * include/grub/lib/LzmaEnc.h: Likewise. - * include/grub/efiemu/efiemu.h: Likewise. - * include/grub/command.h: Likewise. - * normal/menu.c: Likewise. - * normal/main.c: Likewise. - * normal/datetime.c: Likewise. - * bus/usb/uhci.c: Likewise. - * mmap/i386/uppermem.c: Likewise. - * mmap/mmap.c: Likewise. - * commands/acpi.c: Likewise. - * commands/test.c: Likewise. - * partmap/apple.c: Likewise. - * font/font.c: Likewise. - * loader/sparc64/ieee1275/linux.c: Likewise. - * loader/macho.c: Likewise. - * loader/i386/bsd_trampoline.S: Likewise. - * loader/i386/bsd.c: Likewise. - * loader/xnu.c: Likewise. - * term/i386/pc/vesafb.c: Likewise. - * term/usb_keyboard.c: Likewise. - * util/resolve.c: Likewise. - * util/getroot.c: Likewise. - -2009-05-04 Felix Zielcke - - * conf/i386-pc.rmk (libpkg_DATA): Rename to pkglib_DATA. - -2009-05-04 Robert Millan - - * loader/i386/linux.c [GRUB_MACHINE_PCBIOS] (grub_cmd_linux): Fix - build error. - -2009-05-04 Robert Millan - - * loader/i386/linux.c (grub_cmd_linux): Make "vga=" compatibility - parameter only available on BIOS. - -2009-05-04 Vladimir Serbinenko - - Removed wrong semicolon in declaration - - * grub/misc.h (grub_dprintf): remove semicolon - -2009-05-04 Robert Millan - - * loader/i386/linux.c (GRUB_ASSUME_LINUX_HAS_FB_SUPPORT): New macro. - (grub_linux_boot): Don't check for `linux_vesafb_modes' bounds (this - is done by grub_cmd_linux() now). - [! GRUB_ASSUME_LINUX_HAS_FB_SUPPORT]: If "vga=" parameter wasn't set, - restore video to text mode. - (grub_cmd_linux): Default `vid_mode' initialization to 0, which - indicates lack of "vga=" parameter. "vga=0" is mapped to - `GRUB_LINUX_VID_MODE_NORMAL'. - -2009-05-04 Felix Zielcke - - * conf/i386-efi.rmk (grub_emu_SOURCES): Remove `normal/execute.c', - `normal/lexer.c', `kern/rescue.c', `normal/function.c', `normal/misc.c' - and `normal/script.c'. Add `kern/rescue_reader.c', - `kern/rescue_parser.c', `script/sh/main.c', `script/sh/execute.c', - `script/sh/function.c', `script/sh/lexer.c', `script/sh/script.c' and - `grub_script.tab.c'. - - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise. - - * Makefile.in: Remove duplicated 2008 in Copyright line. - -2009-05-04 Robert Millan - - * util/misc.c (grub_util_warn): New function. Emits a warning - unconditionally. - * include/grub/util/misc.h (grub_util_warn): New declaration. - - * util/i386/pc/grub-install.in: Understand --force and pass it down - to grub-setup. - - * util/i386/pc/grub-setup.c (main): Understand --force and pass it - down to setup(). - (setup): Improve error messages and add warnings when requested to - install in odd layouts. Refuse to install using blocklists unless - --force was set. - -2009-05-04 martin f. krafft - - * disk/raid.c (grub_raid_scan_device): Improve debug message. - -2009-05-04 Vladimir Serbinenko - - Updated copyright year - - * fs/hfsplus.c: updated copyright year - -2009-05-04 Vladimir Serbinenko - - HFS+ UUID - - * fs/hfsplus.c (grub_hfsplus_volheader): added num_serial field - in the space previously used by unused3 - (grub_hfsplus_uuid): new function - (grub_hfsplus_fs): added uuid field - -2009-05-03 Pavel Roskin - - * disk/ata.c: Don't cast mod to void in GRUB_MOD_INIT to - suppress warnings. It's no longer needed. - * disk/host.c: Likewise. - * disk/ata_pthru.c: Likewise. - * disk/loopback.c: Likewise. - * hook/datehook.c: Likewise. - * parttool/pcpart.c: Likewise. - * fs/i386/pc/pxe.c: Likewise. - * fs/ntfscomp.c: Likewise. - * efiemu/main.c: Likewise. - * mmap/mmap.c: Likewise. - * commands/crc.c: Likewise. - * commands/hexdump.c: Likewise. - * commands/hdparm.c: Likewise. - * commands/acpi.c: Likewise. - * commands/echo.c: Likewise. - * commands/minicmd.c: Likewise. - * commands/blocklist.c: Likewise. - * commands/memrw.c: Likewise. - * commands/loadenv.c: Likewise. - * commands/usbtest.c: Likewise. - * commands/lsmmap.c: Likewise. - * commands/boot.c: Likewise. - * commands/parttool.c: Likewise. - * commands/configfile.c: Likewise. - * commands/search.c: Likewise. - * commands/ieee1275/suspend.c: Likewise. - * commands/cat.c: Likewise. - * commands/i386/pc/pxecmd.c: Likewise. - * commands/i386/pc/play.c: Likewise. - * commands/i386/pc/halt.c: Likewise. - * commands/i386/pc/vbeinfo.c: Likewise. - * commands/i386/pc/vbetest.c: Likewise. - * commands/lspci.c: Likewise. - * commands/date.c: Likewise. - * commands/handler.c: Likewise. - * commands/ls.c: Likewise. - * commands/test.c: Likewise. - * commands/cmp.c: Likewise. - * commands/efi/loadbios.c: Likewise. - * commands/efi/fixvideo.c: Likewise. - * commands/halt.c: Likewise. - * commands/help.c: Likewise. - * commands/reboot.c: Likewise. - * hello/hello.c: Likewise. - * script/sh/main.c: Likewise. - * loader/xnu.c: Likewise. - * term/terminfo.c: Likewise. - * term/i386/pc/serial.c: Likewise. - * term/usb_keyboard.c: Likewise. - -2009-05-03 David S. Miller - - * normal/menu.c: Include grub/parser.h - -2009-05-03 Pavel Roskin - - * mmap/efi/mmap.c (grub_mmap_malign_and_register): Return void*, - not char*. - * mmap/i386/mmap.c (grub_mmap_malign_and_register): Likewise. - Suggested by Javier Martín - - * util/i386/pc/grub-mkrescue.in: Allow for the case when - efiemu??.o doesn't exist. - * util/i386/pc/grub-install.in: Likewise. Use "cp -f" for - copying. - -2009-05-03 Bean Vladimir Serbinenko - - FreeBSD 64-bit support - - * conf/i386-pc.rmk (bsd_mod_SOURCES): add loader/i386/bsd_helper.S - and loader/i386/bsd_trampoline.S - (bsd_mod_ASFLAGS): new variable - * include/grub/i386/bsd.h (FREEBSD_MODINFOMD_SMAP): new definition - (FREEBSD_MODTYPE_KERNEL64): likewise - (grub_bsd64_trampoline_start): likewise - (grub_bsd64_trampoline_end): likewise - (grub_bsd64_trampoline_selfjump): likewise - (grub_bsd64_trampoline_gdt): likewise - * include/grub/i386/loader.h (grub_unix_real_boot): moved from here ... - * include/grub/i386/bsd.h (grub_unix_real_boot): ... moved here - * kern/i386/loader.S (grub_unix_real_boot): moved from here ... - * loader/i386/bsd_helper.S (grub_unix_real_boot): moved here - * include/grub/gpt_partition.h (grub_gpt_partentry): Corrected the type - of "attrib" member - * loader/i386/bsd_pagetable.c: new file - * loader/i386/bsd_trampoline.S: likewise - * loader/i386/bsd.c (ALIGN_QWORD): new macro - (ALIGN_VAR): likewise - (entry_hi): new variable - (kern_end_mdofs): likewise - (is_64bit): likewise - (grub_freebsd_add_meta): use ALIGN_VAR - (grub_e820_mmap): new declaration - (grub_freebsd_add_mmap): new function - (grub_freebsd_add_meta_module): support 64 bit kernels - (grub_freebsd_list_modules): use ALIGN_VAR - (gdt_descriptor): new declaration - (grub_freebsd_boot): support 64 bit kernels - (grub_bsd_elf64_hook): new function - (grub_bsd_load_elf): support elf64 - -2009-05-03 Bean - - * script/sh/execute.c (grub_script_execute_cmdif): Reset grub_errno - after we get the result of if statement. - -2009-05-03 Bean - - * Makefile.in (enable_efiemu): New variable. - - * conf/i386-pc.rmk: Only compile efiemu runtimes when enable_efiemu is - set. - (efiemu32.o): Use macro $< for source file, add $(srcdir) to include - path. - (efi64_c.o): Use macro $< for source file, add $(srcdir) to include - path, add -mno-red-zone option. - (efiemu64_s.o): Likewise. - (efiemu64.o): Use macro $^ for source file. - - * configure.ac (--enable-efiemu): New option. - -2009-05-03 Vladimir Serbinenko - - xnu support - - * conf/i386-efi.rmk (kernel_mod_HEADERS): added i386/pit.h - (pkglib_MODULES): add xnu.mod - (xnu_mod_SOURCES): new variable - (xnu_mod_CFLAGS): likewise - (xnu_mod_LDFLAGS): likewise - (xnu_mod_ASFLAGS): likewise - * conf/i386-pc.rmk: likewise - * conf/x86_64-efi.rmk: likewise - * include/grub/efi/efi.h (grub_efi_finish_boot_services): - new declaration - * include/grub/i386/macho.h: new file - * include/grub/i386/xnu.h: likewise - * include/grub/macho.h: likewise - * include/grub/machoload.h: likewise - * include/grub/x86_64/macho.h: likewise - * include/grub/x86_64/xnu.h: likewise - * include/grub/xnu.h: likewise - * kern/efi/efi.c (grub_efi_finish_boot_services): new function - * kern/efi/mm.c (MAX_HEAP_SIZE): increase - * loader/i386/efi/xnu.c: new file - * loader/i386/pc/xnu.c: likewise - * loader/i386/xnu.c: likewise - * loader/i386/xnu_helper.S: likewise - * loader/macho.c: likewise - * loader/xnu.c: likewise - * loader/xnu_resume.c: likewise - * util/grub-dumpdevtree: likewise - * include/grub/i386/pit.h: include grub/err.h - (grub_pit_wait): export - * util/grub.d/30_os-prober.in: support Darwin/Mac OS X - -2009-05-02 Vladimir Serbinenko - - Efiemu - - * conf/i386-pc.rmk: new modules efiemu, efiemu_acpi, efiemu_pnvram, - _linux_efi, linux_efi. - new files in grub-emu - new targets efiemu32.o and efiemu64.o - * loader/linux_normal_efiemu.c: likewise - * loader/i386/efi/linux.c: added preliminary efiemu support - * util/i386/pc/grub-install.in: add efiemu??.o to the list of - files to copy - * include/grub/autoefi.h: new file - * include/grub/i386/efiemu.h: likewise - * include/grub/i386/pc/efiemu.h: likewise - * include/grub/efi/api.h: add LL suffix when necessary - new definitions relating to tables - * include/grub/efiemu/efiemu.h: new file - * include/grub/efiemu/runtime.h: likewise - * efiemu/prepare.c: likewise - * efiemu/loadcore_common.c: likewise - * efiemu/loadcore64.c: likewise - * efiemu/runtime/efiemu.sh: likewise - * efiemu/runtime/efiemu.S: likewise - * efiemu/runtime/efiemu.c: likewise - * efiemu/runtime/config.h: likewise - * efiemu/prepare32.c: likewise - * efiemu/main.c: likewise - * efiemu/modules/pnvram.c: likewise - * efiemu/modules/i386: likewise - * efiemu/modules/i386/pc: likewise - * efiemu/modules/acpi.c: likewise - * efiemu/i386/pc/cfgtables.c: likewise - * efiemu/i386/loadcore64.c: likewise - * efiemu/i386/loadcore32.c: likewise - * efiemu/prepare64.c: likewise - * efiemu/loadcore.c: likewise - * efiemu/symbols.c: likewise - * efiemu/mm.c: likewise - * efiemu/loadcore32.c: likewise - -2009-05-02 Vladimir Serbinenko - - ACPI spoofing - - * commands/acpi.c: new file - * commands/i386/pc/acpi.c: likewise - * commands/efi/acpi.c: likewise - * include/grub/acpi.h: likewise - * conf/i386-pc.rmk (pkglib_MODULES): added acpi.mod - (acpi_mod_SOURCES): new variable - (acpi_mod_CFLAGS): likewise - (acpi_mod_LDFLAGS): likewise - * conf/i386-efi.rmk: likewise - * conf/x86_64-efi.rmk: likewise - -2009-05-02 Vladimir Serbinenko - - Missing part from mmap patch - - * mmap/efi/mmap.c (grub_machine_mmap_unregister): renamed to - (grub_mmap_unregister) - (grub_mmap_free_and_unregister): use grub_mmap_register - -2009-05-02 Vladimir Serbinenko - - Mmap services - - * loader/i386/efi/linux.c (grub_linux_boot): use grub_mmap_iterate - * loader/i386/linux.c (find_mmap_size): likewise - (allocate_pages): likewise - * loader/i386/multiboot.c (grub_get_multiboot_mmap_len): likewise - (grub_fill_multiboot_mmap): likewise - (grub_multiboot): use grub_mmap_get_lower and grub_mmap_get_upper - * loader/i386/pc/linux.c (grub_cmd_linux): use grub_mmap_get_lower - * include/grub/i386/bsd.h (OPENBSD_MMAP_AVAILABLE): new definition - (OPENBSD_MMAP_RESERVED): likewise - * include/grub/i386/pc/memory.h: include grub/memory.h - (grub_lower_mem): removed - (grub_upper_mem): likewise - (GRUB_MACHINE_MEMORY_ACPI): new definition - (GRUB_MACHINE_MEMORY_NVS): likewise - (GRUB_MACHINE_MEMORY_MAX_TYPE): likewise - (GRUB_MACHINE_MEMORY_HOLE): likewise - (grub_machine_mmap_register): likewise - (grub_machine_mmap_unregister): likewise - (grub_machine_get_upper): likewise - (grub_machine_get_lower): likewise - (grub_machine_get_post64): likewise - * include/grub/i386/efi/memory.h: new file - * include/grub/x86_64/efi/memory.h: likewise - * include/grub/efi/memory.h: likewise - * conf/i386-pc.rmk (pkglib_MODULES): added mmap.mod - (mmap_mod_SOURCES): new variable - (mmap_mod_LDFLAGS): likewise - (mmap_mod_ASFLAGS): likewise - * conf/i386-coreboot.rmk: likewise - * conf/i386-ieee1275.rmk: likewise - * conf/i386-efi.rmk: likewise - * conf/x86_64-efi.rmk: likewise - * include/grub/types.h (UINT_TO_PTR): new macro - (PTR_TO_UINT32): likewise - (PTR_TO_UINT64): likewise - * include/grub/memory.h: new file - * mmap/i386/pc/mmap.c: likewise - * mmap/i386/pc/mmap_helper.S: likewise - * mmap/i386/uppermem.c: likewise - * mmap/mmap.c: likewise - * mmap/efi/mmap.c: likewise - * kern/i386/coreboot/init.c (grub_machine_init): don't use - grub_upper_mem - * kern/i386/pc/init.c (grub_lower_mem): removed variable - (grub_upper_mem): likewise - (grub_machine_init): don't use grub_upper_mem, - make grub_lower_mem local - * loader/i386/bsd.c (grub_openbsd_boot): use grub_mmap_get_lower, - grub_mmap_iterate and grub_mmap_get_upper - (grub_netbsd_boot): use grub_mmap_get_lower and grub_mmap_get_upper - -2009-05-02 Bean - - * conf/common.rmk (grub_script.tab.c): Change normal/parser.y to - script/sh/parser.y. - (pkglib_MODULES): Add normal.mod and sh.mod. - (normal_SOURCES): New variable. - (normal_mod_CFLAGS): Likewise. - (normal_mod_LDFLAGS): Likewise. - (sh_mod_SOURCES): Likewise. - (sh_mod_CFLAGS): Likewise. - (sh_mod_LDFLAGS): Likewise. - - * conf/i386-pc.rmk (normal/lexer.c_DEPENDENCIES): Changed to - script/sh/lexer.c_DEPENDENCIES. - (kernel_img_SOURCES): Remove kern/rescue.c, and kern/reader.c, - kern/rescue_reader.c and kern/rescue_parser.c. - (kernel_img_HEADERS): Remove rescue.h, add reader.h. - (grub_emu_SOURCES): Change source files. - (pkglib_MODULES): Remove normal.mod. - (normal_SOURCES): Removed. - (normal_mod_CFLAGS): Likewise. - (normal_mod_LDFLAGS): Likewise. - * conf/i386-coreboot.rmk: Likewise. - * conf/i386-efi.rmk: Likewise. - * conf/i386-ieee1276.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - - * include/grub/command.h (grub_command_execute): New inline function. - - * include/grub/menu.h (grub_menu_entry): Removed commands field. - - * include/grub/normal.h: Remove . - (grub_fs_module_list): Moved to normal/autofs.c. - (grub_exit_env): Removed. - (grub_command_execute): Likewise. - (grub_normal_menu_addentry): Renamed to grub_menu_addentry, removed - parameter script. - (read_command_list): New function declaration. - (read_fs_list): Likewise. - - * include/parser.h: Include . - (grub_parser_split_cmdline): Change type of getline parameter. - (grub_parser): New structure. - (grub_parser_class): New variable. - (grub_parser_execute): New function declaration. - (grub_register_rescue_parser): Likewise. - (grub_parser_register): New inline function. - (grub_parser_unregister): Likewise. - (grub_parser_get_current): Likewise. - (grub_parser_set_current): Likewise. - - * include/grub/reader.h: New file. - * kern/reader.c: Likewise. - * kern/rescue_parser.c: Likewise. - * kern/rescue_reader.c: Likewise. - * normal/autofs.c: Likewise. - * normal/dyncmd.c: Likewise. - - * include/grub/rescue.h: Removed. - * normal/command.h: Likewise. - - * include/grub/script.h: Moved to ... - * include/grub/script_sh.h: ... Moved here. - * normal/execute.c: Moved to ... - * script/sh/execute.c: ... Moved here. - * normal/function.c: Moved to ... - * script/sh/function.c: ... Moved here. - * normal/lexer.c: Moved to ... - * script/sh/lexer.c: ... Moved here. - * normal/parser.y: Moved to ... - * script/sh/parser.y: ... Moved here. - * normal/script.c: Moved to ... - * script/sh/script.c: ... Moved here. - - * normal/main.c: Remove and , include - . - (grub_exit_env): Removed. - (fs_module_list): Moved to normal/autofs.c. - (grub_file_getline): Don't handle comment here. - (free_menu): Skip removed field entry->commands. - (grub_normal_menu_addentry): Removed as grub_menu_entry, removed - script parameter. - (read_config_file): Removed nested parameter, change getline function. - (grub_enter_normal_mode): Removed. - (grub_dyncmd_dispatcher): Moved to normal/dyncmd.c. - (read_command_list): Likewise. - (autoload_fs_module): Moved to normal/autofs.c. - (read_fs_list): Likewise. - (reader_nested): New variable. - (grub_normal_execute): Run parser.sh to switch to sh parser. - (grub_cmd_rescue): Removed. - (cmd_normal): Removed. - (grub_cmd_normal): Unregister itself at the beginning. Don't register - rescue command. - (grub_cmdline_run): New function. - (grub_normal_reader_init): Likewise. - (grub_normal_read_line): Likewise. - (grub_env_write_pager): Likewise. - (cmdline): New variable. - (grub_normal_reader): Likewise. - (GRUB_MOD_INIT): Register normal reader and set as current, register - pager hook, register normal command with grub_register_command_prio, - so that it won't show up in command.lst. - (GRUB_MOD_FINI): Unregister normal reader, unhook pager, clear - grub_fs_autoload_hook. - - * normal/menu.c: Remove , add . - (grub_menu_execute_entry): Replace grub_script_execute with - grub_parser_execute, change parameter to grub_command_execute. - - * normal/menu_text.c: Remove . - - * normal/menu_entry.c: Remove , add - and . - (run): Change editor_getline to use new parser interface. Change - parameter to grub_command_execute. - - * kern/main.c: Remove , include , - and . - (grub_load_normal_mode): Execute normal command. - (grub_main): Call grub_register_core_commands, - grub_register_rescue_parser and grub_register_rescue_reader, use - grub_reader_loop to enter input loop. - - * kern/parser.c (grub_parser_split_cmdline): Change type of - getline parameter. - (grub_parser_class): New variable. - (grub_parser_execute): New function. - - * loader/i386/multiboot.c: Remove . - * loader/multiboot2.c: Likewise. - * loader/sparc64/ieee1275/linux.c: Likewise. - - * util/grub-emu.c (read_command_list): New dummy function. - -2009-05-02 Robert Millan - - * util/deviceiter.c (grub_util_iterate_devices): Increase max drive - count to 16 for CCISS and IDA. - -2009-05-02 Robert Millan - - * normal/menu_text.c (grub_wait_after_message): Print a newline - after waiting for user input. - - * loader/i386/linux.c: Include `'. - (grub_cmd_linux): Improve the error message about `ask' mode, by - waiting for user input so it's not missed (we can do this, since - user requested interaction). - -2009-05-02 Vladimir Serbinenko - - Added missing lst to grub-mkrescue - - * util/i386/pc/grub-mkrescue.in: added ${input_dir}/handler.lst - and ${input_dir}/parttool.lst - -2009-04-30 David S. Miller - - * util/hostdisk.c (device_is_wholedisk): New function. - (grub_util_biosdisk_get_grub_dev): Shortcut when hdg.start is - zero only if device_is_wholedisk() returns true. - - * util/hostdisk.c (convert_system_partition_to_system_disk): - Handle virtual disk devices named /dev/vdiskX as found on sparc - and powerpc. - - * kern/sparc64/ieee1275/init.c (grub_machine_set_prefix): If - lettered partition specifier is found, convert to numbered. - -2009-04-29 David S. Miller - - * include/grub/powerpc/ieee1275/memory.h: Include ieee1275.h. - * include/grub/sparc64/ieee1275/memory.h: Likewise. - - * normal/command.c: Add missing newline at end of file. - - * commands/lsmmap.c (grub_cmd_lsmmap): Add casts to avoid printf - warnings. - * kern/ieee1275/openfw.c (grub_claimmap): Likewise. - * disk/ieee1275/ofdisk.c (grub_ofdisk_open, grub_ofdisk_close, - grub_ofdisk_read): Likewise, and deal similarly with the fact that - ihandles have a 32-bit type but need to be stored in a "void *". - -2009-04-28 Pavel Roskin - - * disk/fs_uuid.c (grub_fs_uuid_open): Use parent->data for dev, - not disk. Adjust all dependencies. - (grub_fs_uuid_close): Use grub_device_close(), not - grub_disk_close(). - - * disk/fs_uuid.c (grub_fs_uuid_open): Allocate memory to copy - parent's partition, don't copy it by reference, as it gets freed - on close. - -2009-04-27 Vladimir Serbinenko - - Preboot hooks support - - * commands/boot.c (struct grub_preboot_t): new declaration - (preboots_head): new variable - (preboots_tail): likewise - (grub_loader_register_preboot_hook): new function - (grub_loader_unregister_preboot_hook): likewise - (grub_loader_set): launch preboot hooks - * include/grub/loader.h (grub_loader_preboot_hook_prio_t): new type - (grub_loader_register_preboot_hook): new declaration - (grub_loader_unregister_preboot_hook): likewise - -2009-04-27 Vladimir Serbinenko - - Warning fix - - * disk/scsi.c (grub_scsi_open): added missing cast when - calling grub_dprintf - -2009-04-26 Vladimir Serbinenko - - Bug and warning fixes - - * include/grub/i386/pc/init.h (grub_stop_floppy): added missing - declaration - * commands/test.c (test_parse): fixed bug with file tests and corrected - declaration of find_file - -2009-04-26 Pavel Roskin - - * Makefile.in: Don't install empty manual pages if help2man is - missing. Use help2man option for output, not shell redirection. - -2009-04-26 David S. Miller - - * util/grub-mkdevicemap.c (make_device_map): Add missing - NESTED_FUNC_ATTR to process_device(). - -2009-04-25 Vladimir Serbinenko - - Test command - - * commands/test.c: rewritten to use bash-like test - -2009-04-25 Vladimir Serbinenko - - Parttool autoloading and improvements - - * Makefile.in (pkglib_DATA): add parttool.lst - (parttool.lst): new target - * genmk.rb: generate parttool-* - (CLEANFILES): add #{parttool} - (PARTTOOLFILES): new variable - * genparttoollist.sh: new file - * parttool/pcpart.c (grub_pcpart_boot): more feedback - (grub_pcpart_type): likewise - * commands/parttool.c (helpmsg): new variable - (grub_cmd_parttool): output help if not enough arguments are supplied - autoload modules - (GRUB_MOD_INIT(parttool)): use helpmsg - -2009-04-24 David S. Miller - - Avoiding opening same device multiple times in device iterator. - - * kern/device.c: (grub_device_iterate): Define struct part_ent, - and use it to build a list of partitions in iterate_disk() and - iterate_partition(). - - * disk/fs_uuid.c (grub_fs_uuid_close): Call grub_disk_close() - on disk->data. - - * disk/ieee1275/nand.c (grub_nand_iterate): Return - grub_devalias_iterate() result instead of unconditional 0. - * disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): Likewise. - Also, capture hook return value, either directly or via - grub_children_iterate(), and propagate to caller. - * include/grub/ieee1275/ieee1275.h (grub_devalias_iterate, - grub_children_iterate): Return value is now 'int' instead of - 'grub_err_t'. - * kern/ieee1275/openfw.c (grub_children_iterate): Fix to behave - like a proper iterator, stopping when hooks return non-zero. - (grub_devalias_iterate): Likewise. - -2009-04-23 David S. Miller - - * kern/sparc64/ieee1275/openfw.c: Unused, delete. - -2009-04-22 David S. Miller - - * kern/ieee1275/mmap.c (grub_machine_mmap_iterate): If size_cells - is larger than address_cells, use that value for address_cells too. - - * include/grub/ieee1275/ieee1275.h (IEEE1275_MAX_PROP_LEN, - IEEE1275_MAX_PATH_LEN): Define. - * kern/ieee1275/openfw.c (grub_children_iterate): Dynamically - allocate 'childtype', 'childpath', 'childname', and 'fullname'. - (grub_devalias_iterate): Dynamically allocate 'aliasname' and - 'devtype'. Explicitly NULL terminate devalias expansion. - - * util/sparc64/ieee1275/misc.c: New file. - * util/sparc64/ieee1275/grub-setup.c: New file. - * util/sparc64/ieee1275/grub-ofpathname.c: New file. - * util/sparc64/ieee1275/grub-mkimage.c: New file. - * util/sparc64/ieee1275/grub-install.in: New file. - * util/ieee1275/ofpath.c: New file. - * util/ieee1275/devicemap.c: New file. - * util/devicemap.c: New file. - * util/deviceiter.c: New file. - * kern/sparc64/ieee1275/init.c: New file. - * include/grub/util/ofpath.h: New file. - * include/grub/util/deviceiter.h: New file. - * util/grub-mkdevicemap.c: Include deviceiter.h. - Implement using grub_util_emit_devicemap_entry and - grub_util_iterate_devices. - * conf/i386-corebook.rmk: Build util/deviceiter.c and - util/devicemap.c into grub-mkdevicemap - * conf/i386-efi.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Add rules to build boot block - images and installation utilities. Build kernel as image - instead of as elf binary. Use common rules as much as possible. - -2009-04-19 Vladimir Serbinenko - - Correct GPT definition - - * include/grub/gpt_partition.h (grub_gpt_partentry): Corrected the type - of "attrib" member - -2009-04-19 Felix Zielcke - - * INSTALL: Replace `autogen.sh' with `./autogen.sh'. - -2009-04-19 David S. Miller - - * loader/sparc64/ieee1275/linux.c: Include grub/command.h - (grub_rescue_cmd_linux): Rename to... - (grub_cmd_linux): and fix prototype. - (grub_rescue_cmd_initrd): Rename to... - (grub_cmd_initrd): and fix prototype. - (cmd_linux, cmd_initrd): New. - (GRUB_MOD_INIT(linux)): Use grub_register_command(). - (GRUB_MOD_FINI(linux): Use grub_unregister_command(). - -2009-04-17 Pavel Roskin - - * bus/usb/ohci.c (grub_ohci_transaction): Fix incorrect printf - format. - (grub_ohci_transfer): Likewise. - - * bus/usb/usbtrans.c (grub_usb_control_msg): Warning fix. - - * loader/multiboot_loader.c (grub_cmd_multiboot_loader): Fix - return without a value. Fix inconsistent indentation. - - * fs/i386/pc/pxe.c (grub_pxefs_dir): Fix function prototype to - match struct grub_fs. - - * disk/ata.c (grub_ata_pciinit): Use NESTED_FUNC_ATTR. - * bus/usb/ohci.c (grub_ohci_pci_iter): Likewise. - * bus/usb/uhci.c (grub_uhci_pci_iter): Likewise. - * commands/lspci.c (grub_lspci_iter): Likewise. - -2009-04-16 Bean - - * commands/efi/loadbios.c (grub_cmd_fakebios): Add missing return - value. - -2009-04-15 Pavel Roskin - - * include/grub/types.h: Rename ULONG_MAX to GRUB_ULONG_MAX and - LONG_MAX to GRUB_LONG_MAX. Introduce GRUB_LONG_MIN. Update all - users of ULONG_MAX, LONG_MAX and LONG_MIN to use the new - definitions. - -2009-04-15 Felix Zielcke - - * disk/lvm.c (grub_lvm_scan_device): Add `LVM' to the error messages, - that no multiple data or metadata areas are supported and `Unknown - metadata header'. - -2009-04-15 Vladimir Serbinenko - - Move loader out of the kernel - - * kern/loader.c: moved to ... - * commands/boot.c: ... moved here - * commands/minicmd.c (grub_mini_cmd_boot): moved to ... - * commands/boot.c (grub_cmd_boot): moved here. All users updated - * include/grub/kernel.h (grub_machine_fini): export - * include/grub/loader.h (grub_loader_is_loaded): update declaration - (grub_loader_set): likewise - (grub_loader_unset): likewise - (grub_loader_boot): likewise - * conf/common.rmk: new module boot.mod - (pkglib_MODULES): add boot.mod - * conf/i386-coreboot.rmk (kernel_elf_SOURCES): remove kern/loader.c - (grub_emu_SOURCES): likewise - * conf/i386-efi.rmk (kernel_elf_SOURCES): likewise - (grub_emu_SOURCES): likewise - * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): likewise - (grub_emu_SOURCES): likewise - * conf/i386-pc.rmk (kernel_elf_SOURCES): likewise - (grub_emu_SOURCES): likewise - * conf/powerpc-ieee1275.rmk (kernel_elf_SOURCES): likewise - (grub_emu_SOURCES): likewise - * conf/sparc64-ieee1275.rmk (kernel_elf_SOURCES): likewise - (grub_emu_SOURCES): likewise - * conf/x86_64-efi.rmk (kernel_elf_SOURCES): likewise - (grub_emu_SOURCES): likewise - -2009-04-15 Vladimir Serbinenko - - use grub_lltoa instead of grub_itoa and grub_ltoa for all purposes - - * kern/misc.c (grub_itoa): Removed function - (grub_ltoa): likewise - (grub_vsprintf): use grub_lltoa - -2009-04-15 Vladimir Serbinenko - - Restore grub-emu - - * conf/i386-pc.rmk (grub_emu_SOURCES): add normal/handler.c - * conf/i386-coreboot.rmk: likewise - * conf/i386-ieee1275.rmk: likewise - * conf/powerpc-ieee1275.rmk: likewise - -2009-04-15 Felix Zielcke - - * INSTALL: Add that `./autogen.sh' needs to be run before - `./configure.'. - -2009-04-14 Bean - - * Makefile.in (pkglib_DATA): Add handler.lst. - (handler.lst): New rule. - - * conf/i386-pc.rmk (normal_mod_SOURCES): Add normal/handler.c. - * conf/i386-coreboot.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-efi.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - - * genhandlerlist.sh: New file. - - * genmk.rb: Add rules to generate handler.lst. - - * include/grub/normal.h (grub_file_getline): New function definition. - (read_handler_list): Likewise. - (free_handler_list): Likewise. - - * include/grub/term.h (grub_term_register_input): Add name parameter - for auto generation of handler.lst. - (grub_term_register_output): Likewise. - - * normal/handler.c: New file. - - * normal/main.c (get_line): Renamed to grub_file_getline. - (read_config_file): Use the newly renamed grub_file_getline. - (read_command_list): Likewise. - (read_fs_list): Likewise. - (grub_normal_execute): Call read_handler_list to parse handler.lst. - (GRUB_MOD_FINI): Call free_handler_list to free handler list. - - * term/efi/console.c (grub_console_init): Add name parameter for auto - generation of handler.lst. - * term/gfxterm.c: Likewise. - * term/i386/pc/at_keyboard.c: Likewise. - * term/i386/pc/console.c: Likewise. - * term/i386/pc/serial.c: Likewise. - * term/i386/pc/vesafb.c: Likewise. - * term/i386/pc/vga.c: Likewise. - * term/i386/pc/vga_text.c: Likewise. - * term/ieee1275/ofconsole.c: Likewise. - * term/usb_keyboard.c: Likewise. - -2009-04-14 Bean - - * util/grub-pe2elf.c (write_symbol_table): Terminate short name symbol - properly with null character. - -2009-04-14 Felix Zielcke - - * configure: Remove. - * config.h.in: Likewise. - * stamp-h.in: Likewise. - * DISTLIST: Likewise. - * conf/common.mk: Likewise. - * conf/i386-coreboot.mk: Likewise. - * conf/i386-efi.mk: Likewise. - * conf/i386-ieee1275.mk: Likewise. - * conf/i386.mk: Likewise. - * conf/i386-pc.mk: Likewise. - * conf/powerpc-ieee1275.mk: Likewise. - * conf/sparc64-ieee1275.mk: Likewise. - * conf/x86_64-efi.mk: Likewise. - - * INSTALL: Remove the sentence that Ruby and autoconf are only required if you - develop on GRUB. - -2009-04-14 John Stanley - David S. Miller - - * util/hostdisk.c (make_device_name): Fix buffer length - calculations. - -2009-04-14 Felix Zielcke - - * util/hostdisk.c [__FreeBSD__ || __FreeBSD_kernel__]: Include - and . - (open_device) [__FreeBSD__ || __FreeBSD_kernel_]: Use sysctlgetbyname() - to add 0x10 to `kern.geom.debugflags' if it's not already set, before - opening the device and reset them afterwards. - -2009-04-13 Pavel Roskin - - * conf/common.rmk (grub_fstest_SOURCES): Add normal/datetime.c. - Reported by John Stanley - -2009-04-13 Robert Millan - - * util/grub.d/10_freebsd.in: Detect Debian GNU/kFreeBSD and use - that name for menuentries when appropriate. - -2009-04-13 Felix Zielcke - - * util/grub.d/10_freebsd.in: Add a missing `fi'. - -2009-04-13 Robert Millan - - * loader/i386/linux.c (grub_cmd_linux): Don't pass `vga=ask' parameter - to Linux, simply abort telling the user it's no longer supported. - -2009-04-13 Felix Zielcke - - * util/grub.d/10_freebsd.in: Don't exit if /boot/devices.hints - doesn't exist. Check also for /boot/kernel/kernel.gz. Print - `freebsd_loadenv' only when devices.hints exist. - -2009-04-13 Pavel Roskin - - * term/usb_keyboard.c (grub_usb_keyboard_getkey): Warning fixes. - -2009-04-13 Felix Zielcke - - * util/i386/pc/grub-install.in (install_drive): Remove the BSD - partition number. - (grub_drive): Likewise. - -2009-04-13 David S. Miller - - * kern/sparc64/ieee1275/ieee1275.c: New file. - * include/grub/sparc64/ieee1275/ieee1275.h (IEEE1275_MAP_WRITE, - IEEE1275_MAP_READ, IEEE1275_MAP_EXEC, IEEE1275_MAP_LOCKED, - IEEE1275_MAP_CACHED, IEEE1275_MAP_SE, IEEE1275_MAP_GLOBAL, - IEEE1275_MAP_IE, IEEE1275_MAP_DEFAULT): Define. - (grub_ieee1275_map_physical, grub_ieee1275_claim_vaddr, - grub_ieee1275_alloc_physmem): Declare new exported functions. - - * include/grub/sparc64/ieee1275/loader.h: New file. - * include/grub/sparc64/ieee1275/memory.h: Likewise. - * include/grub/sparc64/kernel.h: Likewise. - * loader/sparc64/ieee1275/linux.c: Likewise. - - * conf/common.rmk (grub_probe_SOURCES): Add Sun partition module. - (grub_fstest_SOURCES): Likewise. - - * util/hostdisk.c (make_device_name): Do not make any assumptions - about the length of drive names. - - * kern/dl.c (grub_dl_load_file): Close file immediately when - we are done using it. - -2009-04-12 David S. Miller - - * kern/misc.c (grub_ltoa): Fix cast when handling negative - values. Noticed by Pavel Roskin. - - * configure.ac: Check for __bswapsi2 and__bswapdi2 using - target compiler. - - * genmk.rb: Add more flexible image type specification, also - pass --strip-unneeded to objcopy. - * conf/i386-pc.rmk: Use *_FORMAT. - * conf/i386-pc.mk: Rebuilt. - - * disk/ieee1275/ofdisk.c (struct ofdisk_hash_ent): New struct. - (OFDISK_HASH_SZ): Define. - (ofdisk_hash): New hash table. - (ofdisk_hash_fn, ofdisk_hash_find, ofdisk_hash_add): New functions. - (grub_ofdisk_open): Use ofdisk_hash_ent address as disk->id - instead of device phandle which is not unique. - - * kern/sparc64/ieee1275/init.c: Delete, replace with... - * kern/sparc64/ieee1275/crt0.S: assembler implementation. - * include/grub/sparc64/ieee1275/kernel.h: Declare grub_prefix[]. - (GRUB_MOD_ALIGN, GRUB_MOD_GAP, GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE, - GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE, - GRUB_KERNEL_MACHINE_COMPRESSED_SIZE, GRUB_KERNEL_MACHINE_PREFIX, - GRUB_KERNEL_MACHINE_DATA_END): Define. - (grub_kernel_image_size, grub_total_module_size): Declare. - -2009-04-12 Pavel Roskin - - * configure.ac: Change the logic when we check for target tools. - Do it when the target is specified and it's different from the - specified value of the host. - -2009-04-11 Felix Zielcke - - * util/hostdisk.c [__FreeBSD_kernel__]: Include sys/disk.h. - (grub_util_biosdisk_open) [__FreeBSD_kernel__]: Add support for - GNU/kFreeBSD. Check if a device is a character device. Use - DIOCGMEDIASIZE to get the size. - (convert_system_partition_to_system_disk) [__FreeBSD_kernel__]: Add - support for GNU/kFreeBSD. - (grub_util_biosdisk_get_grub_dev) [__FreeBSD_kernel__]: Check if OS_DEV - is a character device instead of a block device. Add support for - FreeBSD device names. - - * util/getroot.c (find_root_device) [__FreeBSD_kernel__]: Check if ENT - is a character device instead of a block device. - - * util/grub-probe.c (probe) [__FreeBSD_kernel__]: Check if DEVICE_NAME - is a character device instead of a block device. - -2009-04-11 Andrey Shuvikov - - * util/hostdisk.c [__FreeBSD__]: Include sys/disk.h. - (grub_util_biosdisk_open) [__FreeBSD__]: Add support for - FreeBSD. Check if a device is a character device. Use - DIOCGMEDIASIZE to get the size. - (convert_system_partition_to_system_disk) [__FreeBSD__]: Add - support for FreeBSD. - (grub_util_biosdisk_get_grub_dev) [__FreeBSD__]: Check if OS_DEV - is a character device instead of a block device. Add support for - FreeBSD device names. - - * util/getroot.c (find_root_device) [__FreeBSD__]: Check if ENT is - a character device instead of a block device. - (grub_util_check_char_device): New function. - - * util/grub-probe.c (probe) [__FreeBSD__]: Check if DEVICE_NAME is - a character device instead of a block device. - - * include/grub/util/getroot.h (grub_util_check_char_device): New - prototype. - -2009-04-11 David S. Miller - - * conf/sparc64-ieee1275.rmk (kernel_img_LDFLAGS): Link with - static libgcc. - * configure.ac: Check for __bswapsi2 and __bswapdi2 presence. - * include/grub/sparc64/libgcc.h (__bswapsi2): Export libgcc - function, if present. - (__bswapdi2): Likewise. - - * include/grub/sparc64/ieee1275/boot.h: New file. - * boot/sparc64/ieee1275/boot.S: Likewise. - * boot/sparc64/ieee1275/diskboot.S: Likewise. - - * kern/misc.c (grub_ltoa): New function. - (grub_vsprintf): Use it to format 'long' integers. - -2009-04-10 David S. Miller - - * disk/ieee1275/nand.c (grub_nand_open): All ieee1275 call arg - slots are of type grub_ieee1275_cell_t. - (grub_nand_read): Likewise. - * kern/ieee1275/ieee1275.c (IEEE1275_PHANDLE_INVALID, - IEEE1275_IHANDLE_INVALID): Use grub_ieee1275_cell_t since these - macros are used to compare values in arg/ret block of the call. - (grub_ieee1275_finddevice, grub_ieee1275_get_property, - grub_ieee1275_next_property, grub_ieee1275_get_property_length, - grub_ieee1275_instance_to_package, grub_ieee1275_package_to_path, - grub_ieee1275_instance_to_path, grub_ieee1275_write, - grub_ieee1275_read, grub_ieee1275_seek, grub_ieee1275_peer, - grub_ieee1275_child, grub_ieee1275_parent, grub_ieee1275_open, - grub_ieee1275_close, grub_ieee1275_set_property, - grub_ieee1275_set_color): All ieee1275 call arg slots are of type - grub_ieee1275_cell_t. - * kern/ieee1275/openfw.c (grub_map): Likewise. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_ihandle_t, - grub_ieee1275_phandle_t): Define as grub_unit32_t type. - - * kern/ieee1275/init.c (grub_machine_init): Make 'actual' grub_ssize_t. - * kern/ieee1275/openfw.c (grub_children_iterate): Likewise. - (grub_devalias_iterate): Likewise. - -2009-04-10 Vladimir Serbinenko - - UFS improvements - - * fs/ufs.c (INODE_NBLOCKS): new definition - (struct grub_ufs_dirent): added fields for non-BSD dirents - (grub_ufs_get_file_block): fixed double indirect handling - (grub_ufs_lookup_symlink): use more robust way to determine whether - symlink is inline - (grub_ufs_find_file): support for non-BSD dirents - (grub_ufs_dir): support for non-BSD dirents - -2009-04-10 Bean - - * include/grub/efi/api.h (grub_efi_configuration_table): Add packed - attribute, otherwise the size would be wrong for i386 platform. - - * include/grub/pci.h (grub_pci_read_word): New inline function. - (grub_pci_read_byte): Likewise. - (grub_pci_write): Likewise. - (grub_pci_write_word): Likewise. - (grub_pci_write_byte): Likewise. - - * include/grub/pci.h (grub_pci_iteratefunc_t): Add NESTED_FUNC_ATTR. - - * loader/i386/efi/linux.c (fake_bios_data): Moved to loadbios module. - (find_framebuf): Scan pci to locate the frame buffer address. - - * commands/efi/fixvideo.c: New file. - - * commands/efi/loadbios.c: Likewise. - - * commands/memrw.c: Likewise. - - * util/grub-dumpbios.in: Likewise. - - * conf/common.rmk (grub-dumpbios): New utility. - (pkglib_MODULES): New module memrw.mod. - (memrw_mod_SOURCE): New macro. - (memrw_mod_CFLAGS): Likewise. - (memrw_mod_LDFLAGS): Likewise. - - * conf/i386-efi.rmk (pkglib_MODULES): New module loadbios.mod and - fixvideo.mod. - (loadbios_mod_SOURCE): New macro. - (loadbios_mod_CFLAGS): Likewise. - (loadbios_mod_LDFLAGS): Likewise. - (fixvideo_mod_SOURCE): Likewise. - (fixvideo_mod_CFLAGS): Likewise. - (fixvideo_mod_LDFLAGS): Likewise. - - * conf/x86_64.rmk (pkglib_MODULES): New module loadbios.mod and - fixvideo.mod. - (loadbios_mod_SOURCE): New macro. - (loadbios_mod_CFLAGS): Likewise. - (loadbios_mod_LDFLAGS): Likewise. - (fixvideo_mod_SOURCE): Likewise. - (fixvideo_mod_CFLAGS): Likewise. - (fixvideo_mod_LDFLAGS): Likewise. - -2009-04-08 Felix Zielcke - - * disk/lvm.c (grub_lvm_scan_device): Add a missing NULL check. - -2009-04-07 David S. Miller - - * kern/sparc64/dl.c (grub_arch_dl_relocate_symbols): Add - support for R_SPARC_OLO10 relocations. Fix compile warning for - R_SPARC_WDISP30 case. - * kern/sparc64/cache.S: Fix grub_arch_sync_caches implementation. - -2009-04-06 Pavel Roskin - - * include/grub/misc.h (ARRAY_SIZE): New macro. - * include/grub/i386/linux.h (GRUB_LINUX_VID_MODE_VESA_START): - New macro. - * loader/i386/linux.c (allocate_pages): Use free_pages(). - (grub_linux_unload): Don't use free_pages(). - (grub_linux_boot): Prevent accessing linux_vesafb_modes with a - wrong index. Treat all other modes as text modes. - (grub_cmd_linux): Initialize vid_mode unconditionally to - GRUB_LINUX_VID_MODE_NORMAL. Recognize and support "vga=ask". - - * commands/help.c (print_command_help): Use cmd->prio, not - cmd->flags to check for GRUB_PRIO_LIST_FLAG_ACTIVE. - -2009-04-06 Vladimir Serbinenko - - Parttool - - * parttool/pcpart.c: new file - * commands/parttool.c: likewise - * conf/common.rmk (pkglib_MODULES): Added parttool.mod and pcpart.mod - (parttool_mod_SOURCES): new variable - (parttool_mod_CFLAGS): likewise - (parttool_mod_LDFLAGS): likewise - (pcpart_mod_SOURCES): likewise - (pcpart_mod_CFLAGS): likewise - (pcpart_mod_LDFLAGS): likewise - * conf/i386-coreboot.rmk (grub_emu_SOURCES): added commands/parttool.c - and parttool/pcpart.c - * conf/i386-efi.rmk: likewise - * conf/i386-ieee1275.rmk: likewise - * conf/i386-pc.rmk: likewise - * conf/powerpc-ieee1275.rmk: likewise - * conf/sparc64-ieee1275.rmk: likewise - * conf/x86_64-ieee1275.rmk: likewise - -2009-04-05 Vladimir Serbinenko - - Support for mtime and further expandability of dir command - - * include/grub/lib/datetime.h: moved to ... - * include/grub/datetime.h: ... moved here and added - declaration of grub_unixtime2datetime. All users updated - * include/grub/fs.h: new syntax for dir and mtime functions in - struct grub_fs - * include/grub/fshelp.h: new declarations of GRUB_FSHELP_TYPE_MASK - and GRUB_FSHELP_FLAGS_MASK - * commands/ls.c (grub_ls_list_files): Write mtime in long format - * fs/ext2.c (grub_ext2_dir): use new dir syntax and supply mtime - (grub_ext2_mtime): new function - * fs/hfsplus.c (grub_hfsplus_dir): use new dir syntax and supply mtime - (grub_hfsplus_mtime): new function - * fs/ufs.c (GRUB_UFS_ATTR_TYPE): new definition - (GRUB_UFS_ATTR_FILE): likewise - (GRUB_UFS_ATTR_LNK): likewise - (struct grub_ufs_sblock): new fields mtime - (grub_ufs_read_inode): new parameter to read inode to a separate buffer - all users updated - (grub_ufs_dir): mtime support - (grub_ufs_mtime): new function - * fs/affs.c (grub_affs_dir): use new dir syntax - * fs/afs.c (grub_afs_dir): likewise - * fs/cpio.c (grub_cpio_dir): likewise - * fs/fat.c (grub_fat_find_dir): likewise - * fs/hfs.c (grub_hfs_dir): likewise - * fs/iso9660.c (grub_iso9660_dir): likewise - * fs/jfs.c (grub_jfs_dir): likewise - * fs/minix.c (grub_minix_dir): likewise - * fs/ntfs.c (grub_ntfs_dir): likewise - * fs/reiserfs.c (grub_reiserfs_dir): likewise - * fs/sfs.c (grub_sfs_dir): likewise - * fs/xfs.c (grub_xfs_dir): likewise - * util/hostfs.c (grub_hostfs_dir): likewise - * lib/datetime.c: moved to ... - * normal/datetime.c: ... moved here - (grub_unixtime2datetime): new function - * kern/rescue.c (grub_rescue_print_files): use new dir syntax - * normal/completion.c (iterate_dir): use new dir syntax - * normal/misc.c (grub_normal_print_device_info): tell the - last modification time of a volume - * kern/fs.c (grub_fs_probe): updated dummy function to use new syntax - * conf/common.rmk: added lib/datetime.c to ls.mod - * conf/i386-coreboot.rmk (grub_emu_SOURCES): add normal/datetime.c - (normal_mod_SOURCES): likewise - (datetime_mod_SOURCES): Removed lib/datetime.c - * conf/i386-efi.rmk: likewise - * conf/i386-ieee1275.rmk: likewise - * conf/i386-pc.rmk: likewise - * conf/powerpc-ieee1275.rmk: likewise - * conf/sparc64-ieee1275.rmk: likewise - * conf/x86_64-efi.rmk: likewise - -2009-04-05 Vladimir Serbinenko - - Trim trailing spaces in FAT label and support mtools-like labels - - * fs/fat.c (grub_fat_iterate_dir): New function based - on grub_fat_find_dir - (grub_fat_find_dir): use grub_fat_iterate_dir - (grub_fat_label): likewise - -2009-04-04 Vladimir Serbinenko - - * conf/powerpc-ieee1275.rmk (kernel_elf_HEADERS): add list.h - and command.h - remove extraneous kernel_elf_HEADERS - -2009-04-04 Bean - - * include/grub/util/misc.h: Add dummy function fsync for mingw. - - * util/misc.c: Likewise. - -2009-04-04 Yoshinori K. Okuji - - * loader/i386/efi/linux.c (fake_bios_data): Use grub_dprintf - instead of grub_printf. - -2009-04-03 Robert Millan - - * loader/i386/linux.c (grub_linux_setup_video): Fill - `params->{red,green,blue,reserved}_{mask_size,field_pos}' with - values from `mode info' structure instead of hardcoded - values. - -2009-04-01 Pavel Roskin - - * Makefile.in: Remove all references to MODULE_LDFLAGS, it's - unused now. - * genmk.rb: Likewise. - * configure.ac: Likewise. - -2009-04-01 Manoel Abranches - - * aclocal.m4: Move --build-id=none from MODULE_LDFLAGS to - TARGET_LDFLAGS. This corrects a problem with grub-mkelfimage. - -2009-04-01 David S. Miller - - * normal/sparc64/setjmp.S: Fix setjmp implementation. - * include/grub/sparc64/setjmp.h (grub_jmp_buf): Update. - (grub_setjmp): Mark with 'returns_twice' attribute. - * include/grub/i386/setjmp.h (grub_setjmp): Likewise - * include/grub/powerpc/setjmp.h (grub_setjmp): Likewise. - * include/grub/x86_64/setjmp.h (grub_setjmp): Likewise. - -2009-04-01 Robert Millan - - Reapply fix from 2008-07-28 which was accidentally reverted; also - perform the same fix to a similar check in same function. - - * disk/raid.c (grub_raid_scan_device): Do not abort when two disks - with the same number are found, just use issue a warning with - grub_dprintf(), as this error has been reported to be non-fatal. - -2009-03-31 Pavel Roskin - - * aclocal.m4 (grub_I386_CHECK_REGPARM_BUG): Provide safe default - for cross-compilation. - -2009-03-30 Robert Millan - - Fix i386-ieee1275 build. - - * include/grub/i386/ieee1275/loader.h (grub_multiboot2_real_boot): - Remove declaration. - -2009-03-30 Pavel Roskin - - * fs/hfs.c (grub_hfs_strncasecmp): Integrate into ... - (grub_hfs_cmp_catkeys): ... this. Don't assume strings to be - zero-terminated, rely only on the strlen value. Fix comparison - of strings differing in length. - -2009-03-30 Robert Millan - - * loader/i386/linux.c (grub_cmd_linux): Check for zImage before - checking for abi version. Improve error messages on BIOS to notify - user about `linux16' command. - -2009-03-29 Vladimir Serbinenko - - Leak fixes - - * kern/disk.c (grub_disk_cache_store): Invalidate previous cache - in case of collision - * disk/scsi.c (grub_scsi_open): free scsi in case of error - -2009-03-29 Robert Millan - - * loader/i386/linux.c (grub_cmd_linux): Parse "vga=" parameter and - set `vid_mode' accordingly. - (grub_linux_boot): Process `vid_mode' and set video mode. - -2009-03-29 Robert Millan - - * util/grub.d/10_linux.in (linux_entry): New function. - Factorize generation of Linux boot entries. - -2009-03-29 Yoshinori K. Okuji - - Make the format of Environment Block plain text. The boot loader - part is not tested well yet. - - * util/grub-editenv.c (DEFAULT_ENVBLK_SIZE): New macro. - (buffer): Removed. - (envblk): Likewise. - (usage): Remove "info" and "clear". Add "unset". Update the - description of "set", as this does not delete variables any - longer. - (create_envblk_file): Complete rewrite. - (open_envblk_file): Likewise. - (cmd_info): Removed. - (cmd_list): Likewise. - (cmd_set): Likewise. - (cmd_clear): Likewise. - (list_variables): New function. - (write_envblk): Likewise. - (set_variables): Likewise. - (unset_variables): Likewise. - (main): Complete rewrite. - - * commands/loadenv.c (buffer): Removed. - (envblk): Likewise. - (open_envblk_file): New function. - (read_envblk_file): Complete rewrite. - (grub_cmd_load_env): Likewise. - (grub_cmd_list_env): Likewise. - (struct blocklist): New struct. - (free_blocklists): New function. - (check_blocklists): Likewise. - (write_blocklists): Likewise. - (grub_cmd_save_env): Complete rewrite. - - * include/grub/lib/envblk.h (GRUB_ENVBLK_SIGNATURE): Replaced with - a plain text signature. - (GRUB_ENVBLK_MAXLEN): Removed. - (struct grub_envblk): Complete rewrite. - (grub_envblk_find): Removed. - (grub_envblk_insert): Likewise. - (grub_envblk_open): New prototype. - (grub_envblk_set): Likewise. - (grub_envblk_delete): Put const to VALUE. - (grub_envblk_iterate): Put const to NAME and VALUE. - (grub_envblk_close): New prototype. - (grub_envblk_buffer): New inline function. - (grub_envblk_size): Likewise. - - * lib/envblk.c: Include grub/mm.h. - (grub_env_find): Removed. - (grub_envblk_open): New function. - (grub_envblk_close): Likewise. - (escaped_value_len): Likewise. - (find_next_line): Likewise. - (grub_envblk_insert): Removed. - (grub_envblk_set): New function. - (grub_envblk_delete): Complete rewrite. - (grub_envblk_iterate): Likewise. - -2009-03-28 Robert Millan - - * conf/i386-pc.rmk (pkglib_MODULES): Add `linux16.mod'. - (linux16_mod_SOURCES, linux16_mod_CFLAGS, linux16_mod_LDFLAGS): New - variables. Use 16-bit loader. - (linux_mod_SOURCES, linux_mod_CFLAGS, linux_mod_LDFLAGS): Use 32-bit - loader. - * kern/i386/loader.S (grub_linux_boot): Rename to ... - (grub_linux16_boot): ... this. Update all users. - * loader/i386/linux.c (grub_linux32_boot): Rename to ... - (grub_linux_boot): ... this. Update all users. - - * loader/i386/pc/linux.c (GRUB_MOD_INIT(linux)): Rename to ... - (GRUB_MOD_INIT(linux16)): ... this. Rename `linux' and `initrd' - commands to `linux16' and `initrd16'. - (GRUB_MOD_FINI(linux)): Rename to ... - (GRUB_MOD_FINI(linux16)): ... this. - -2009-03-24 Pavel Roskin - - * genmk.rb: Define ASM_FILE for *.S files for *.lst generation, - not just for compilation. - -2009-03-22 Vladimir Serbinenko - - Move multiboot helper out of kernel - - * conf/i386-pc.rmk (multiboot_mod_SOURCES): Add - `loader/i386/multiboot_helper.S'. - * conf/i386-coreboot.rmk: Likewise - * conf/i386-ieee1275.rmk: Likewise - - * kern/i386/loader.S: Move multiboot helpers from here... - * loader/i386/multiboot_helper.S: ...moved here - * include/grub/i386/loader.h: Move declarations of multiboot - helpers from here... - * include/grub/i386/multiboot.h: ...moved here - * loader/i386/multiboot.c: Added include of grub/cpu/multiboot.h - -2009-03-22 Yoshinori K. Okuji - - * kern/env.c (grub_env_context_open): Added an argument to specify - whether a new context inherits exported variables from current - one. This is useful when making a sandbox to interpret a config - file. - All callers updated. - - * include/grub/env.h (grub_env_context_open): Updated the prototype. - -2009-03-22 Yoshinori K. Okuji - - * kern/env.c (grub_env_context_close): Fix memory leaks. - -2009-03-22 Yoshinori K. Okuji - - * normal/main.c (grub_normal_execute): Added an argument - BATCH to specify if an interactive interface should be provided - after reading a config file. - All callers updated. - (read_command_list): Prevent being executed twice. - (read_fs_list): Likewise. - - * include/grub/normal.h (grub_normal_execute): Updated the - prototype. - -2009-03-22 Pavel Roskin - - * kern/powerpc/ieee1275/startup.S: Replace EXT_C(start) with - _start. - * kern/i386/pc/startup.S: Likewise. - * kern/i386/efi/startup.S: Likewise. - * kern/i386/ieee1275/startup.S: Likewise. - * kern/i386/coreboot/startup.S: Likewise. - * kern/x86_64/efi/startup.S: Likewise. - - * aclocal.m4 (grub_CHECK_START_SYMBOL): Remove. - * configure.ac: Don't call grub_CHECK_START_SYMBOL. - * kern/i386/pc/startup.S: Use _start instead of START_SYMBOL. - -2009-03-21 Vladimir Serbinenko - - Bugfixes in multiboot for bugs uncovered by solaris kernel. - - * loader/i386/multiboot_elfxx.c (grub_multiboot_load_elf): Corrected - limit detection. - Use vaddr of correct segment for entry_point. - -2009-03-21 Bean - - * commands/blocklist.c: Add include file , remove - and . - (grub_cmd_blocklist): Use the new command interface. - (GRUB_MOD_INIT): Likewise. - (GRUB_MOD_FINI): Likewise. - * commands/boot.c: Likewise. - * commands/cat.c: Likewise. - * commands/cmp.c: Likewise. - * commands/configfile.c: Likewise. - * commands/crc.c: Likewise. - * commands/echo.c: Likewise. - * commands/halt.c: Likewise. - * commands/handler.c: Likewise. - * commands/hdparm.c: Likewise. - * commands/help.c: Likewise. - * commands/hexdump.c: Likewise. - * commands/loadenv.c: Likewise. - * commands/ls.c: Likewise. - * commands/lsmmap.c: Likewise. - * commands/lspci.c: Likewise. - * commands/loadenv.c: Likewise. - * commands/read.c: Likewise. - * commands/reboot.c: Likewise. - * commands/search.c: Likewise. - * commands/sleep.c: Likewise. - * commands/test.c: Likewise. - * commands/usbtest.c: Likewise. - * commands/videotest.c: Likewise. - * commands/i386/cpuid.c: Likewise. - * commands/i386/pc/halt.c: Likewise. - * commands/i386/pc/play.c: Likewise. - * commands/i386/pc/pxecmd.c: Likewise. - * commands/i386/pc/vbeinfo.c: Likewise. - * commands/i386/pc/vbetest.c: Likewise. - * commands/ieee1275/suspend.c: Likewise. - * disk/loopback.c: Likewise. - * font/font_cmd.c: Likewise. - * hello/hello.c: Likewise. - * loader/efi/appleloader.c: Likewise. - * loader/efi/chainloader.c: Likewise. - * loader/i386/bsd.c: Likewise. - * loader/i386/efi/linux.c: Likewise. - * loader/i386/ieee1275/linux.c: Likewise. - * loader/i386/linux.c: Likewise. - * loader/i386/pc/chainloader.c: Likewise. - * loader/i386/pc/linux.c: Likewise. - * loader/powerpc/ieee1275/linux.c: Likewise. - * loader/multiboot_loader.c: Likewise. - * term/gfxterm.c: Likewise. - * term/i386/pc/serial.c: Likewise. - * term/terminfo.c: Likewise. - - * term/i386/pc/vesafb.c: Removed . - * term/i386/pc/vga.c: Likewise. - * video/readers/jpeg.c: Likewise. - * video/readers/png.c: Likewise. - * video/readers/tga.c: Likewise. - - * util/grub-fstest (cmd_loopback): Removed. - (cmd_blocklist): Likewise. - (cmd_ls): Likewise. - (grub_register_command): Likewise. - (grub_unregister_command): Likewise. - (execute_command): Use grub_command_find to locate command and execute - it. - - * include/grub/efi/chainloader.h: Removed. - * loader/efi/chainloader_normal.c: Likewise. - * loader/i386/bsd_normal.c: Likewise. - * loader/i386/pc/chainloader_normal.c: Likewise. - * loader/i386/pc/multiboot_normal.c: Likewise. - * loader/linux_normal.c: Likewise. - * loader/multiboot_loader_normal.c: Likewise. - * loader/powerpc/ieee1275/linux_normal.c: Likewise. - - * gencmdlist.sh: Scan new registration command grub_register_extcmd - and grub_register_command_p1. - - * conf/common.rmk (grub_fstest_SOURCES): Add kern/list.c, - kern/command.c, lib/arg.c and commands/extcmd.c. - (pkglib_MODULES): Remove boot.mod, and minicmd.mod and extcmd.mod. - (minicmd_mod_SOURCES): New variable. - (minicmd_mod_CFLAGS): Likewise. - (minicmd_mod_LDFLAGS): Likewise. - (extcmd_mod_SOURCES): Likewise. - (extcmd_mod_CFLAGS): Likewise. - (extcmd_mod_LDFLAGS): Likewise. - (boot_mod_SOURCES): Removed. - (boot_mod_CFLAGS): Likewise. - (boot_mod_LDFLAGS): Likewise. - - * conf/i386-pc.rmk (kernel_img_SOURCES): Add kern/command.c and - kern/corecmd.c. - (kernel_img_HEADERS): Add command.h. - (grub_emu_SOURCES): Remove commands/boot.c and normal/arg.c, add - commands/minicmd.c, kern/command.c, kern/corecmd.c, commands/extcmd.c - and lib/arg.c. - (pkglib_MODULES): Change _linux.mod, _chain.mod, _bsd.mod and - _multiboot.mod as linux.mod, chain.mod, bsd.mod and multiboot.mod, - remove the corresponding normal mode command. - (normal_mod_SOURCES): Remove normal/arg.c. - * conf/i386-coreboot.rmk: Likewise. - * conf/i386-efi.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - - * include/grub/arg.h: Move from here ... - * include/grub/lib/arg.h: ... to here. - - * normal/arg.c: Move from here ... - * lib/arg.c: ... to here. - - * commands/extcmd.c: New file. - * commands/minicmd.c: Likewise. - * include/grub/command.h: Likewise. - * include/grub/extcmd.h: Likewise. - * kern/command.c: Likewise. - * kern/corecmd.c: Likewise. - - * kern/list.c (grub_list_iterate): Return int instead of void. - (grub_list_insert): New function. - (grub_prio_list_insert): Likewise. - - * kern/rescue.c (grub_rescue_command): Removed. - (grub_rescue_command_list): Likewise. - (grub_rescue_register_command): Likewise. - (grub_rescue_unregister_command): Likewise. - (grub_rescue_cmd_boot): Move to minicmd.c - (grub_rescue_cmd_help): Likewise. - (grub_rescue_cmd_info): Likewise. - (grub_rescue_cmd_boot): Likewise. - (grub_rescue_cmd_testload): Likewise. - (grub_rescue_cmd_dump): Likewise. - (grub_rescue_cmd_rmmod): Likewise. - (grub_rescue_cmd_lsmod): Likewise. - (grub_rescue_cmd_exit): Likewise. - (grub_rescue_print_devices): Moved to corecmd.c. - (grub_rescue_print_files): Likewise. - (grub_rescue_cmd_ls): Likewise. - (grub_rescue_cmd_insmod): Likewise. - (grub_rescue_cmd_set): Likewise. - (grub_rescue_cmd_unset): Likewise. - (attempt_normal_mode): Use grub_command_find to get normal module. - (grub_enter_rescue_mode): Use grub_register_core_commands to register - commands, remove grub_rescue_register_command calls. - - * normal/command.c (grub_register_command): Removed. - (grub_unregister_command): Likewise. - (grub_command_find): Likewise. - (grub_iterate_commands): Likewise. - (rescue_command): Likewise. - (export_command): Moved to corecmd.c. - (set_command): Removed. - (unset_command): Likewise. - (insmod_command): Likewise. - (rmmod_command): Likewise. - (lsmod_command): Likewise. - (grub_command_init): Likewise. - - * normal/completion.c (iterate_command): Use cmd->prio to check for - active command. - (complete_arguments): Use grub_extcmd_t structure to find options. - (grub_normal_do_completion): Change function grub_iterate_commands to - grub_command_iterate. - - * normal/execute.c (grub_script_execute_cmd): No need to parse - argument here. - - * normal/main.c (grub_dyncmd_dispatcher): New function. - (read_command_list): Register unload commands as dyncmd. - (grub_cmd_normal): Use new command interface, register rescue, - unregister normal at entry, register normal, unregister rescue at exit. - - * include/grub/list.h (grub_list_test_t): New type. - (grub_list_iterate): Return int instead of void. - (grub_list_insert): New function. - (GRUB_AS_NAMED_LIST_P): New macro. - (GRUB_AS_PRIO_LIST): Likewise. - (GRUB_AS_PRIO_LIST_P): Likewise. - (GRUB_PRIO_LIST_PRIO_MASK): New constant. - (GRUB_PRIO_LIST_FLAG_ACTIVE): Likewise. - (grub_prio_list): New structure. - (grub_prio_list_insert): New function. - (grub_prio_list_remove): New inline function. - - * include/grub/normal.h: Remove , add . - (GRUB_COMMAND_FLAG_CMDLINE): Moved to command.h. - (GRUB_COMMAND_FLAG_MENU): Likewise. - (GRUB_COMMAND_FLAG_BOTH): Likewise. - (GRUB_COMMAND_FLAG_TITLE): Likewise. - (GRUB_COMMAND_FLAG_NO_ECHO): Likewise. - (GRUB_COMMAND_FLAG_NO_ARG_PARSE): Removed. - (GRUB_COMMAND_FLAG_NOT_LOADED): Likewise. - (grub_command): Likewise. - (grub_register_command): Likewise. - (grub_command_find): Likewise. - (grub_iterate_commands): Likewise. - (grub_command_init): Likewise. - (grub_arg_parse): Likewise. - (grub_arg_show_help): Likewise. - - * include/grub/rescue.h (grub_rescue_register_command): Removed. - (grub_rescue_unregister_command): Likewise. - - * include/grub/i386/bsd.h: Remove grub_rescue_cmd_freebsd, - grub_rescue_cmd_openbsd, grub_rescue_cmd_netbsd, - grub_rescue_cmd_freebsd_loadenv and grub_rescue_cmd_freebsd_module. - - * include/grub/i386/efi/loader.h: Remove grub_rescue_cmd_linux and - grub_rescue_cmd_initrd. - * include/grub/i386/loader.h: Likewise. - * include/grub/x86_64/loader.h: Likewise. - - * include/grub/i386/pc/chainloader.h: Remove grub_chainloader_cmd. - -2009-03-21 Bean - - * util/hostdisk.c (read_device_map): Use grub_util_get_disk_size - instead of stat in mingw environment. - - * util/misc.c (grub_millisleep): Use Sleep in mingw environment. - - * aclocal.m4 (grub_CHECK_LINK_DIR): New function. - - * configure.ac: Use grub_CHECK_LINK_DIR to determine whether to use - AC_CONFIG_LINKS. - -2009-03-21 Bean - - * fs/ext2.c (grub_ext2_mount): Change errno to GRUB_ERR_BAD_FS for - out of range error. - -2009-03-18 Michel Dänzer - - * fs/ext2.c (grub_ext2_read_block): Take endianness into account when - checking inode flags for EXT4_EXTENTS_FLAG. - -2009-03-18 Robert Millan - - * loader/i386/linux.c: Include `' and - `'.. - (grub_linux_setup_video): New function. Loosely based on the EFI one. - (grub_linux32_boot): Attempt to configure video settings with - grub_linux_setup_video(). - (grub_rescue_cmd_linux): Set noreturn=0 in grub_loader_set, in order - to avoid grub_console_fini() which would step out of graphical mode - unconditionally. - -2009-03-14 Robert Millan - - Fix build on powerpc. - * conf/powerpc-ieee1275.rmk (kernel_elf_HEADERS): Add `handler.h'. - -2009-03-12 Vladimir Serbinenko - - * term/gfxterm.c (GRUB_MOD_FINI(term_gfxterm)): Correct name of - background image command. - -2009-03-12 Colin D Bennett - - * term/gfxterm.c (draw_cursor): Ensure character is redrawn. - (grub_gfxterm_putchar): Extract pairs of identical calls to - draw_cursor out of conditional blocks. - -2009-03-11 Pavel Roskin - - * fs/hfs.c (grub_hfs_strncasecmp): New function. - (grub_hfs_cmp_catkeys): Use HFS specific string comparison. - -2009-03-11 Robert Millan - - * loader/i386/multiboot_elfxx.c - (CONCAT(grub_multiboot_load_elf, XX)): Do not reject ET_DYN files. - -2009-03-11 Felix Zielcke - - * conf/powerpc-ieee1275.rmk (kernel_elf_SOURCES): Add `kern/list.c' and - `kern/handler.c'. - -2009-03-11 Robert Millan - - * loader/i386/multiboot.c (code_size): New variable. - (grub_multiboot): Define offsets by adding to `code_size' rather - than subtracting from `grub_multiboot_payload_size'. Provide - 4-byte alignment to MBI and others by increasing - `boot_loader_name_length' appropriately. - - * loader/i386/multiboot_elfxx.c - (CONCAT(grub_multiboot_load_elf, XX)): Initialize `code_size'. - -2009-03-09 Felix Zielcke - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Remove duplicated - `fs/ext2.c'. - -2009-03-08 Robert Millan - - Make loader/i386/linux.c usable on i386-pc again. - - * kern/i386/pc/init.c (grub_machine_init): Disable addition of low - memory to heap. - * loader/i386/linux.c [GRUB_MACHINE_PCBIOS] (allocate_pages): Remove - `#error' stanza. - -2009-03-07 Bean - - * loader/i386/efi/linux.c (grub_rescue_cmd_initrd): Fix a bug in initrd - allocation. - -2009-03-06 Robert Millan - - Fix display issue on terminals with screen size other than 80x25 - (e.g. gfxterm with resolution higher than 640x480). - - * normal/main.c (grub_normal_init_page): Display title text in a - position relative to the center of the terminal instead of relying - on a hardcoded offset. - -2009-03-04 Robert Millan - - Filter /etc/grub.d/10_* so that only add-ons for native kernels are - installed. - - * Makefile.in (host_kernel): New variable. - * conf/common.rmk (grub-mkconfig_SCRIPTS): Conditionalize all 10_*.in - scripts instead of just the windows one. - * configure.ac: Initialize and AC_SUBST `host_kernel'. - -2009-03-04 Felix Zielcke - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `kern/list.c' and - `kern/handler.c'. - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - -2009-03-04 Felix Zielcke - - * partmap/pc.c (pc_partition_map_iterate): Skip over invalid BSD partitions - or if there's no space for the disk label and print the partition number on a - invalid magic. - -2009-03-04 Felix Zielcke - - * util/misc.c: Include . - (grub_millisleep): New function. - -2009-03-04 Bean - - * configure.ac: Only test -mcmodel=large option in x86_64-efi, also add - another option -mno-red-zone. - - * commands/handler.c: Change module description. - - * kern/handler.c: Add missing space at the end of description line. - - * kern/list.c: Likewise. - -2009-03-03 Robert Millan - - Move more components to the relocation area, and fix mbi pointer - handling to use the destination rather than the origin (thanks to - Vladimir Serbinenko for spotting). - - * loader/i386/multiboot.c (mbi_dest): New variable. - (grub_multiboot_boot): Use `mbi_dest' instead of `mbi'. - (grub_multiboot): Put cmdline, boot_loader_name and mbi in the - relocation area. - -2009-03-01 Bean - - * include/grub/efi/api.h (GRUB_EFI_MPS_TABLE_GUID): New constant. - (GRUB_EFI_ACPI_TABLE_GUID): Likewise. - (GRUB_EFI_ACPI_20_TABLE_GUID): Likewise. - (GRUB_EFI_SMBIOS_TABLE_GUID): Likewise. - - * loader/i386/efi/linux.c (acpi_guid): New variable. - (acpi_guid): Likewise. - (EBDA_SEG_ADDR): New constant. - (LOW_MEM_ADDR): Likewise. - (FAKE_EBDA_SEG): Likewise. - (fake_bios_data): New function. - (grub_linux_boot): Call fake_bios_data. - -2009-03-01 Bean - - * commands/terminal.c: Removed. - - * commands/handler.c: New file. - - * include/grub/list.h: Likewise. - - * include/grub/handler.h: Likewise. - - * kern/list.c: Likewise. - - * kern/handler.c: Likewise. - - * kern/term.h: Include header file . - (grub_term_input): Move next field to the beginning. - (grub_term_output): Likewise. - (grub_term_input_class): New variable. - (grub_term_output_class): Likewise. - (grub_term_register_input): Changed to inline function. - (grub_term_register_output): Likewise. - (grub_term_unregister_input): Likewise. - (grub_term_unregister_output): Likewise. - (grub_term_set_current_input): Likewise. - (grub_term_set_current_output): Likewise. - (grub_term_get_current_input): Likewise. - (grub_term_get_current_output): Likewise. - (grub_term_iterate_input): Removed. - (grub_term_iterate_output): Likewise. - - * kern/term.c (grub_term_list_input): Removed. - (grub_term_list_output): Likewise. - (grub_term_input_class): New variable. - (grub_term_output_class): Likewise. - (grub_cur_term_input): Change variable as macro. - (grub_cur_term_output): Likewise. - (grub_term_register_input): Removed. - (grub_term_register_output): Likewise. - (grub_term_unregister_input): Likewise. - (grub_term_unregister_output): Likewise. - (grub_term_set_current_input): Likewise. - (grub_term_set_current_output): Likewise. - (grub_term_iterate_input): Likewise. - (grub_term_iterate_output): Likewise. - (grub_term_get_current_input): Likewise. - (grub_term_get_current_output): Likewise. - - * util/grub-editenv.c: Include header file . - (grub_term_get_current_input): Removed. - (grub_term_get_current_output): Likewise. - (grub_term_input_class): New variable. - (grub_term_output_class): Likewise. - - * util/grub-fstest.c (grub_term_get_current_input): Removed. - (grub_term_get_current_output): Likewise. - (grub_term_input_class): New variable. - (grub_term_output_class): Likewise. - - * util/grub-probe.c (grub_term_get_current_input): Removed. - (grub_term_get_current_output): Likewise. - (grub_term_input_class): New variable. - (grub_term_output_class): Likewise. - - * util/i386/pc/grub-setup.c (grub_term_get_current_input): Removed. - (grub_term_get_current_output): Likewise. - (grub_term_input_class): New variable. - (grub_term_output_class): Likewise. - - * conf/common.rmk (pkglib_MODULES): Replace terminal with handler. - (terminal_mod_SOURCES): Likewise. - (terminal_mod_CFLAGS): Likewise. - (terminal_mod_LDFLAGS): Likewise. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Replace terminal.c with - handler.c. - (kernel_img_SOURCES): Add list.c and handler.c. - (kernel_img_HEADERS): Add list.h and handler.h. - - * conf/i386-efi.rmk (grub_emu_SOURCES): Replace terminal.c with - handler.c. - (kernel_mod_SOURCES): Add list.c and handler.c. - (kernel_mod_HEADERS): Add list.h and handler.h. - - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Replace terminal.c with - handler.c. - (kernel_elf_SOURCES): Add list.c and handler.c. - (kernel_elf_HEADERS): Add list.h and handler.h. - - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Replace terminal.c with - handler.c. - (kernel_elf_SOURCES): Add list.c and handler.c. - (kernel_elf_HEADERS): Add list.h and handler.h. - - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Replace terminal.c with - handler.c. - (kernel_mod_SOURCES): Add list.c and handler.c. - (kernel_mod_HEADERS): Add list.h and handler.h. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Replace terminal.c with - handler.c. - (kernel_elf_SOURCES): Add list.c and handler.c. - (kernel_elf_HEADERS): Add list.h and handler.h. - -2009-02-27 Robert Millan - - Factorize elf32 / elf64 code in Multiboot loader. This will - prevent it from getting out of sync again. - - * loader/i386/multiboot.c (grub_multiboot_is_elf32, - grub_multiboot_load_elf32, grub_multiboot_is_elf64, - grub_multiboot_load_elf64): Move from here ... - * loader/i386/multiboot_elfxx.c (grub_multiboot_is_elf, - grub_multiboot_load_elf): ... to here (new file). - -2009-02-27 Robert Millan - - * util/grub.d/10_linux.in: Rename "single-user mode" to - "recovery mode". - -2009-02-27 Vladimir Serbinenko - - Don't leak in SCSI code. - * disk/scsi.c (grub_scsi_close): free `scsi'. - -2009-02-27 Robert Millan - - * loader/i386/pc/multiboot.c: Move from here ... - * loader/i386/multiboot.c: ... to here. Update all users. - -2009-02-27 Robert Millan - - Patch from Alexandre Bique - * util/i386/pc/grub-setup.c (setup): Fix directory path. - -2009-02-27 Krzysztof Smiechowicz - - * fs/sfs.c (grub_sfs_read_extent): Correction to traversing extent - b-tree. - -2009-02-27 Robert Millan - - * kern/misc.c (grub_strtoull): Fix bug (it mistakenly parsed the - `0x' qualifier as 0 when base is specified as parameter). - -2009-02-24 Bean - - * configure.ac: Check for -mcmodel=large in x86_64 target. - - * include/grub/efi/api.h (efi_call_10): New macro. - (efi_wrap_10): New function. - - * include/grub/efi/pe32.h (GRUB_PE32_REL_BASE_HIGH): New macro. - (GRUB_PE32_REL_BASED_HIGH): Likewise. - (GRUB_PE32_REL_BASED_LOW): Likewise. - (GRUB_PE32_REL_BASED_HIGHLOW): Likewise. - (GRUB_PE32_REL_BASED_HIGHADJ): Likewise. - (GRUB_PE32_REL_BASED_MIPS_JMPADDR): Likewise. - (GRUB_PE32_REL_BASED_SECTION): Likewise. - (GRUB_PE32_REL_BASED_REL): Likewise. - (GRUB_PE32_REL_BASED_IA64_IMM64): Likewise. - (GRUB_PE32_REL_BASED_DIR64): Likewise. - (GRUB_PE32_REL_BASED_HIGH3ADJ): Likewise. - - * kern/x86_64/dl.c (grub_arch_dl_relocate_symbols): Fixed relocation - issue. - - * kern/x86_64/efi/callwrap.S (efi_wrap_6): Bug fix. - (efi_wrap_10): New function. - - * kern/x86_64/efi/startup.S (codestart): Use relative addressing. - - * loader/efi/appleloader.c (devpath_5): Add support for late 2008 - MB/MBP model (NV chipset). - (devdata_devs): Add devpath_5 to the list. - - * load/i386/efi/linux.c (video_base): Remove variable. - (RGB_MASK): New macro. - (RGB_MAGIC): Likewise. - (LINE_MIN): Likewise. - (LINE_MAX): Likewise. - (FBTEST_STEP): Likewise. - (FBTEST_COUNT): Likewise. - (fb_list): New variable. - (grub_find_video_card): Remove function. - (find_framebuf): New function. - (grub_linux_setup_video): Use find_framebuf to get frame buffer and - line length. - - * util/i386/efi/grub-mkimage.c (grub_reloc_section): Fix relocation - problem for x86_64. - -2009-02-22 Vesa Jääskeläinen - - Patch #25624 by Kevin Lacquement . - - * util/grub-mkconfig.in: Use ${grub_mkdevicemap} instead of hard - coding tool name. - -2009-02-22 Robert Millan - - * include/multiboot.h (MULTIBOOT_INFO_ALIGN): New macro. - * loader/i386/pc/multiboot.c (grub_multiboot): Include the MBI - in our relocation, instead of using it directly from heap. Also - use `MULTIBOOT_INFO_ALIGN' to ensure it is aligned. - -2009-02-21 Robert Millan - - Implement USB keyboard support (based on patch by Marco Gerards) - - * conf/i386-pc.rmk (pkglib_MODULES): Add `usb_keyboard.mod'. - (usb_keyboard_mod_SOURCES, usb_keyboard_mod_CFLAGS) - (usb_keyboard_mod_LDFLAGS): New variables. - - * term/usb_keyboard.c: New file. - -2009-02-14 Vladimir Serbinenko - - Corrected wrong declaration - - * kern/disk.c: corrected declaration of grub_disk_ata_pass_through. - -2009-02-14 Christian Franke - - * commands/lspci.c (grub_pci_classes): Add `SATA Controller'. - (grub_lspci_iter): Print class code and programming interface byte. - -2009-02-14 Christian Franke - - * gendistlist.sh: Ignore `.svn' directories. - -2009-02-14 Felix Zielcke - - * fs/fat.c: Add 2009 to Copyright line. - -2009-02-14 Christian Franke - - * commands/hdparm.c: New file. Provides `hdparm' command - which sends ATA commands via grub_disk_ata_pass_through (). - - * conf/i386-pc.rmk: Add ata_pthru.mod and hdparm.mod. - - * disk/ata.c: Include . Move - and to include/grub/ata.h. - (enum grub_ata_addressing_t): Move to include/grub/ata.h. - (GRUB_CDROM_SECTOR_SIZE): Remove. - (GRUB_ATA_*): Move to include/grub/ata.h. - (GRUB_ATAPI_*): Likewise. - (enum grub_ata_commands): Likewise. - (enum grub_ata_timeout_milliseconds): Likewise. - (struct grub_ata_device): Likewise. - (grub_ata_regset): Likewise. - (grub_ata_regget): Likewise. - (grub_ata_regset2): Likewise. - (grub_ata_regget2): Likewise. - (grub_ata_check_ready): Likewise. - (grub_ata_wait_not_busy): Remove static, exported in - include/grub/ata.h. - (grub_ata_wait_drq): Likewise. - (grub_ata_pio_read): Likewise. - - * disk/ata_pthru.c: New file. Provides grub_ata_pass_through () - function for hdparm.mod. - - * include/grub/ata.h: New file, contains declarations from - disk/ata.c. - (enum grub_ata_commands): Add new commands for commands/hdparm.c. - - * include/grub/disk.h (grub_disk_ata_pass_through_parms): New struct. - (grub_disk_ata_pass_through): New exported variable. - - * kern/disk.c (grub_disk_ata_pass_through): New variable. - -2009-02-13 Colin D Bennett - - Support multiple fallback entries, and provide an API to support - executing default+fallback menu entries. Renamed the `terminal' menu - viewer to `text'. - - * include/grub/normal.h (grub_normal_text_menu_viewer): New global - variable declaration. - (grub_menu_execute_callback): New structure declaration. - (grub_menu_execute_callback_t): New typedef. - (grub_menu_execute_with_fallback): New function declaration. - (grub_menu_get_entry): Likewise. - (grub_menu_get_timeout): Likewise. - (grub_menu_set_timeout): Likewise. - - * normal/main.c (GRUB_MOD_INIT(normal)): Refer to new variable name. - - * normal/menu.c (grub_wait_after_message): Moved to - `normal/menu_text.c'. - (draw_border): Likewise. - (print_message): Likewise. - (print_entry): Likewise. - (print_entries): Likewise. - (grub_menu_init_page): Likewise. - (get_entry_number): Likewise. - (print_timeout): Likewise. - (run_menu): Likewise. - (grub_menu_execute_entry): Likewise. - (show_text_menu): Likewise. - (get_and_remove_first_entry_number): New function. - (grub_menu_execute_with_fallback): Likewise. - (get_entry): Renamed to ... - (grub_menu_get_entry): .. this and made it global. - (get_timeout): Renamed to ... - (grub_menu_get_timeout): ... this and made it global. - (set_timeout): Renamed to ... - (grub_menu_set_timeout): ... this and made it global. - (grub_normal_terminal_menu_viewer): Renamed to ... - (grub_normal_text_menu_viewer): ... this. - - * normal/menu_text.c: New file. Extracted text-menu-specific code - from normal/menu.c. - - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add `normal/menu_text.c'. - (normal_mod_SOURCES): Likewise. - - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - (normal_mod_SOURCES): Likewise. - - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - (normal_mod_SOURCES): Likewise. - - * conf/i386-pc.rmk, (grub_emu_SOURCES): Likewise. - (normal_mod_SOURCES): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - (normal_mod_SOURCES): Likewise. - - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise. - (normal_mod_SOURCES): Likewise. - - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise. - (normal_mod_SOURCES): Likewise. - -2009-02-11 Robert Millan - - * util/grub.d/00_header.in: Update old reference to `font' command. - -2009-02-10 Felix Zielcke - - * fs/fat.c (grub_fat_mount): Fix wrong comparison. - - Based on patch from Javier Martín. - -2009-02-09 Felix Zielcke - - * conf/common.rmk (grub_probe_SOURCES): Move fs/ext2.c before fs/fat.c - to avoid false positives with FAT. - (grub_fstest_SOURCES): Likewise. - * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise. - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - -2009-02-09 Felix Zielcke - - * fs/fat.c (grub_fat_mount): Try to avoid false positives by checking - bpb.version_specific.fat12_or_fat16.fstype and - bpb.version_specific.fat32.fstype. - -2009-02-08 Robert Millan - - * fs/tar.c: Replace "fs/cpio.c" with "cpio.c". - -2009-02-08 Robert Millan - - * Makefile.in (host_os, host_cpu): New variables. - (target_os): Remove. Update all users. - -2009-02-08 Marco Gerards - - * Makefile.in (enable_grub_emu_usb): New variable. - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `disk/scsi.c'. - (grub_emu_SOURCES) [grub_emu_SOURCES]: Add `disk/usbms.c', - `util/usb.c', `bus/usb/usb.c' and `commands/usbtest.c'. - (grub_emu_LDFLAGS): Add `$(LIBUSB)'. - (pkglib_MODULES): Add `usb.mod', `uhci.mod', `ohci.mod', - `usbtest.mod' and `usbms.mod'. - (usb_mod_SOURCES, usb_mod_CFLAGS, usb_mod_LDFLAGS) - (usbtest_mod_SOURCES, usbtest_mod_CFLAGS, usbtest_mod_LDFLAGS) - (uhci_mod_SOURCES, uhci_mod_CFLAGS, uhci_mod_LDFLAGS, - (ohci_mod_SOURCES, ohci_mod_CFLAGS, ohci_mod_LDFLAGS) - (usbms_mod_SOURCES, usbms_mod_CFLAGS, usbms_mod_LDFLAGS): New - variables. - - * disk/usbms.c: New file. - - * include/grub/usb.h: Likewise. - - * include/grub/usbtrans.h: Likewise. - - * include/grub/usbdesc.h: Likewise. - - * bus/usb/usbtrans.c: Likewise. - - * bus/usb/ohci.c: Likewise. - - * bus/usb/uhci.c: Likewise. - - * bus/usb/usbhub.c: Likewise. - - * bus/usb/usb.c: Likewise. - - * commands/usbtest.c: Likewise. - - * util/usb.c: Likewise. - - * include/grub/err.h (grub_err_t): Add `GRUB_ERR_IO'. - - * configure.ac: Test for libusb presence. - - * util/grub-emu.c (main) [HAVE_LIBUSB_H]: Call `grub_libusb_init'. - -2009-02-08 Vesa Jääskeläinen - - * kern/mm.c: Add more comments. - -2009-02-08 Robert Millan - - Patch from Javier Martín. - * fs/ext2.c (EXT2_DRIVER_SUPPORTED_INCOMPAT): Add - `EXT4_FEATURE_INCOMPAT_FLEX_BG'. - -2009-02-08 Robert Millan - - * fs/cpio.c: Split tar functionality to ... - * fs/tar.c: ... here (new file). Update all users. - -2009-02-07 Robert Millan - - * fs/ext2.c (grub_ext2_mount): Avoid mounting filesystems with - backward-incompatible features. - - Based on patch from Javier Martín, with some adjustments. - -2009-02-07 Michael Scherer - - * fs/hfs.c (grub_hfsplus_iterate_dir): Treat hfs+ as case insensitive. - -2009-02-07 Robert Millan - - * conf/common.rmk (grub_probe_SOURCES, grub_fstest_SOURCES): Move - position of `disk/lvm.c' to ensure grub_init_all() always picks it - after the RAID stuff. - -2009-02-05 Vesa Jääskeläinen - - Fixes problem when running vbetest command as reported by - Vladimir Serbinenko . - - * (grub_vbe_set_video_mode): Fixed problem with text modes. - -2009-02-04 Felix Zielcke - - util/getroot.c (grub_util_get_grub_dev): Add support for /dev/mdNpN and - /dev/md/NpN style mdraid devices. - -2009-02-03 Felix Zielcke - - * util/unifont2pff.rb: Remove. - -2009-02-03 Felix Zielcke - - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Add a missing trailing - `#'. - -2009-02-03 Felix Zielcke - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `normal/menu_viewer.c'. - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - -2009-02-02 Christian Franke - - * lib/hexdump.c (hexdump): Print at most 3 lines if data is identical. - -2009-02-01 Felix Zielcke - - * INSTALL: Note that we now require at least autoconf 2.59 and - that LZO is optional. - -2009-02-01 Vesa Jääskeläinen - - Base on patch on bug #24154 created by Tomas Tintera - . - - * video/i386/pc/vbe.c (grub_video_vbe_scroll): Fix downward scrolling. - -2009-02-01 Vesa Jääskeläinen - - Based on patch on bug #25318 created by Bernhard Rosenkraenzer - . - - * normal/parser.y (script_init): Add missing semicolon. - -2009-01-31 Colin D Bennett - - * normal/main.c: Add include to grub/menu_viewer.h. - (free_menu_entry_classes): Added. - (grub_normal_menu_addentry): Added class property handling. - (grub_normal_execute): Changed to use new menu viewer for menu viewing. - (GRUB_MOD_INIT(normal)): Added register for text based menu viewer. - - * normal/menu_viewer.c: New file. - - * normal/menu.c (run_menu_entry): Renamed to ... - (grub_menu_execute_entry): ... this and made it as global. - (grub_menu_run): Renamed to ... - (show_text_menu): ... this and made it local. - (show_text_menu): Adapt to new function names. - (grub_normal_terminal_menu_viewer): New global variable. - - * include/grub/menu.h: New file. - - * include/grub/menu_viewer.h: New file. - - * include/grub/normal.h: Added include to grub/menu.h. - (grub_menu_entry): Moved to include/grub/menu.h. - (grub_menu_entry_t): Likewise. - (grub_menu): Likewise. - (grub_menu_t): Likewise. - (grub_normal_terminal_menu_viewer): Added. - (grub_menu_execute_entry): Likewise. - (grub_menu_run): Removed. - - * DISTLIST: Added include/grub/menu.h. - Added include/grub/menu_viewer.h. - Added normal/menu_viewer.c. - -2009-01-31 Vesa Jääskeläinen - - * normal/execute.c (grub_script_execute_menuentry): Changed to use - arglist for menutitle arguments. - - * normal/main.c (grub_normal_menu_addentry): Likewise. - - * normal/parser.y (menuentry): Likewise. - - * normal/script.c (grub_script_create_cmdmenu): Likewise. - - * include/grub/script.h (grub_script_cmd_menuentry): Likewise. - (grub_script_create_cmdmenu): Likewise. - - * include/grub/normal.h (grub_normal_menu_addentry): Likewise. - - * conf/i386-pc.rmk (normal_mod_SOURCES): Adapt Colin D Bennett's - changes. - - * conf/x86_64-efi.rmk (normal_mod_SOURCES): Likewise. - - * conf/i386-coreboot.rmk (normal_mod_SOURCES): Likewise. - - * conf/i386-efi.rmk (normal_mod_SOURCES): Likewise. - - * conf/i386-ieee1275.rmk (normal_mod_SOURCES): Likewise. - - * conf/powerpc-ieee1275.rmk (normal_mod_SOURCES): Likewise. - - * conf/sparc64-ieee1275.rmk (normal_mod_SOURCES): Likewise. - -2009-01-30 Christian Franke - - * normal/arg.c (grub_arg_show_help): Add indentation if '\n' appears - in option help text. - -2009-01-27 Pavel Roskin - - * disk/fs_uuid.c (search_fs_uuid): Ignore case of the UUID. - -2009-01-27 Vesa Jääskeläinen - - * commands/lsmmap.c: Add include to grub/machine/memory.h. - - * fs/i386/pc/pxe.c (grub_pxefs_open): Fix sign problem. - - * term/i386/pc/at_keyboard.c (GRUB_MOD_FINI(at_keyboard)): Use proper - unregister function. - -2009-01-27 Vesa Jääskeläinen - - * disk/scsi.c (grub_scsi_read): Fix sign problem. - - * term/i386/pc/vga_text.c (grub_vga_text_init_fini). Fix declaration. - - * util/grub-mkfont.c (usage): Fix typo. - - * util/elf/grub-mkimage.c (load_modules): Fix warning. - -2009-01-26 Daniel Mierswa - - * fs/fat.c (grub_fat_uuid): Fix shift of the first two bytes. - - * commands/search.c (search_fs_uuid): Ignore case of the UUID. - - * kern/misc.c (grub_strcasecmp): New function. - (grub_strcasecmp): Use grub_size_t instead of int for length. - Fix return value. - * include/grub/misc.h: Update function prototypes. - -2009-01-26 Robert Millan - - * configure.ac: Fix cross-compilation check. - -2009-01-22 Christian Franke - - * kern/misc.c (grub_vsprintf): Fix size and termination of `format2' - (precision) digit string. Allow `.format2' without `format1' (width). - Limit input chars for `%s' output to `format2' if specified. This is - compatible with standard printf (). - -2009-01-22 Christian Franke - - * disk/ata.c (grub_ata_wait_status): Replace by ... - (grub_ata_wait_not_busy): ... this function. Checks only BSY bit, - other status bits may be invalid while BSY is asserted. - (grub_ata_check_ready): New function. - (grub_ata_cmd): Removed. - (grub_ata_wait_drq): New function. - (grub_ata_strncpy): Remove inline. - (grub_ata_pio_read): Reduce to actual block transfer. BSY wait - and error check now done by grub_ata_wait_drq (). - (grub_ata_pio_write): Likewise. - (grub_atapi_identify): Set DEV before check for !BSY. Use - grub_ata_wait_drq () to wait for data. - (grub_ata_device_initialize): Add status register check to - detect missing SATA slave devices. Add debug messages. - (grub_atapi_wait_drq): Use grub_ata_wait_not_busy (). - (grub_atapi_packet): Set DEV before check for !BSY. Replace - transfer loop by grub_ata_pio_write (). - (grub_ata_identify): Set DEV before check for !BSY. Use - grub_ata_wait_drq () to wait for data. - (grub_ata_setaddress): Set DEV before check for !BSY. - (grub_ata_readwrite): Remove duplicate code, handle batch/rest and - read/write in one loop. Fix invalid command on write. Fix incomplete - command on (size % batch) == 0. Add missing error check after write of - last block. Add debug messages. - (grub_atapi_read): Replace transfer loop by grub_ata_pio_read (). - -2009-01-19 Christian Franke - - * disk/ata.c (GRUB_ATAPI_REG_*): New defines. - (GRUB_ATAPI_IREASON_*): Likewise. - (grub_ata_pio_write): Fix timeout error return. - (grub_atapi_identify): Add grub_ata_wait () after cmd. - (grub_atapi_wait_drq): New function. - (grub_atapi_packet): New parameter `size'. - Use grub_atapi_wait_drq () and direct write instead of - grub_ata_pio_write (). - (grub_atapi_read): Replace grub_ata_pio_read () by a loop which - reads the number of bytes requested by the device for each DRQ - assertion. - (grub_atapi_write): Remove old implementation, return not - implemented instead. - -2009-01-19 Christian Franke - - * disk/scsi.c (grub_scsi_read10): Use scsi->blocksize instead - of 512 to calculate data size. - (grub_scsi_read12): Likewise. - (grub_scsi_write10): Likewise. - (grub_scsi_write12): Likewise. - (grub_scsi_read): Adjust size according to blocksize. - Add checks for invalid blocksize and unaligned transfer. - -2009-01-19 Vesa Jääskeläinen - - * font/font.c (grub_font_loader_init): Re-position unknown glyph. - - * term/gfxterm.c (write_char): Fix background rendering for wide - width glyphs. - -2009-01-19 Robert Millan - - * config.guess: Update to latest version from config git. - * config.sub: Likewise. - -2009-01-17 Felix Zielcke - - * Makefile.in: Change font compilation to use new grub-mkfont instead - of java version. - - * util/fonttool/src/org/gnu/grub/fonttool/BDFLoader.java: Remove. - * util/fonttool/src/org/gnu/grub/fonttool/CharDefs.java: Likewise. - * util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise. - * util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise. - * util/fonttool/src/org/gnu/grub/fonttool/Converter.java: Likewise. - * util/fonttool/src/org/gnu/grub/fonttool/Font.java: Likewise. - * util/fonttool/src/org/gnu/grub/fonttool/Glyph.java: Likewise. - * util/fonttool/src/org/gnu/grub/fonttool/PFF2Sections.java: Likewise. - * util/fonttool/src/org/gnu/grub/fonttool/PFF2Writer.java: Likewise. - -2009-01-16 Christian Franke - - * disk/ata.c (enum grub_ata_commands): Remove EXEC_DEV_DIAGNOSTICS. - (enum grub_ata_timeout_milliseconds): New enum. - (grub_ata_wait_status): Add parameter milliseconds. - (grub_ata_cmd): Remove variable `err'. Remove wait for !DRQ to allow - recovery from timed-out commands. - (grub_ata_pio_read): Add parameter milliseconds. Fix error return, - return grub_errno instead of REG_ERROR. - (grub_ata_pio_write): Add parameter milliseconds. - (grub_atapi_identify): Fix size of ATAPI IDENTIFY sector. - Pass milliseconds to grub_ata_wait_status () and - grub_ata_pio_read (). - (grub_atapi_packet): Pass milliseconds to grub_ata_pio_write (). - (grub_ata_identify): Remove variable `ataerr'. Pass milliseconds to - grub_ata_wait_status (). Fix IDENTIFY timeout check. - (grub_ata_device_initialize): Remove EXECUTE DEVICE DIAGNOSTICS. - It is not suitable for device detection, because DEV bit is ignored, - the command may run too long, and not all devices set the signature - properly. - (grub_ata_pciinit): Clear grub_errno before grub_ata_device_initialize (). - (grub_ata_setaddress): Pass milliseconds to grub_ata_wait_status (). - Fix device selection, DEV bit must be set first to address the registers - of the correct device. - (grub_ata_readwrite): Pass milliseconds to grub_ata_wait_status () and - grub_ata_pio_read/write (). - (grub_atapi_read): Pass milliseconds to grub_ata_pio_read (). - (grub_atapi_write): Pass milliseconds to grub_ata_pio_write (). - -2009-01-13 Carles Pina i Estany - - * util/grub-editenv.c (main): Use fseeko(), not fseek(). - -2009-01-13 Bean - - * util/grub-mkfont.c (write_font): forget to remove some debug code. - -2009-01-13 Bean - - * Makefile.in: (enable_grub_mkfont): New variable. - (freetype_cflags): Likewise. - (freetype_libs): Likewise. - - * common.rmk (bin_UTILITIES): Add `grub-mkfont' if requested. - (grub_mkfont_SOURCES): New variable. - (grub_mkfont_CFLAGS): Likewise. - (grub_mkfont_LDFLAGS): Likewise. - - * configure.ac (--enable-grub-mkfont): New option. Check for freetype2 - library if `--enable-grub-mkfont' is requested. - (enable_grub_mkfont): New variable. - (freetype_cflags): Likewise. - (freetype_libs): Likewise. - - * util/grub-mkfont.c: New file. - -2009-01-12 Christian Franke - - * disk/ata.c (grub_ata_pciinit): Fix bit numbers of compatibility - mode check. Fix setting of compat_use[]. - -2009-01-10 Robert Millan - - Update a few copyright years which we forgot to do in 2008 (only for - files whose changes made in 2008 were copyright-significant) - - * Makefile.in: Add 2008 to Copyright line. - * disk/ieee1275/ofdisk.c: Likewise. - * disk/efi/efidisk.c: Likewise. - * kern/dl.c: Likewise. - * kern/sparc64/ieee1275/init.c: Likewise. - * kern/mm.c: Likewise. - * kern/efi/mm.c: Likewise. - * boot/i386/pc/boot.S: Likewise. - * genfslist.sh: Likewise. - * fs/iso9660.c: Likewise. - * fs/hfs.c: Likewise. - * fs/jfs.c: Likewise. - * fs/minix.c: Likewise. - * fs/ufs.c: Likewise. - * gensymlist.sh.in: Likewise. - * genkernsyms.sh.in: Likewise. - * include/grub/misc.h: Likewise. - * include/grub/types.h: Likewise. - * include/grub/symbol.h: Likewise. - * include/grub/elf.h: Likewise. - * include/grub/kernel.h: Likewise. - * include/grub/disk.h: Likewise. - * include/grub/dl.h: Likewise. - * include/grub/i386/linux.h: Likewise. - * include/grub/i386/pc/biosdisk.h: Likewise. - * include/grub/efi/api.h: Likewise. - * include/grub/efi/pe32.h: Likewise. - * include/grub/util/misc.h: Likewise. - * normal/execute.c: Likewise. - * normal/arg.c: Likewise. - * normal/completion.c: Likewise. - * normal/lexer.c: Likewise. - * normal/parser.y: Likewise. - * normal/misc.c: Likewise. - * commands/i386/pc/vbeinfo.c: Likewise. - * commands/hexdump.c: Likewise. - * commands/terminal.c: Likewise. - * commands/ls.c: Likewise. - * commands/help.c: Likewise. - * partmap/pc.c: Likewise. - * loader/efi/chainloader.c: Likewise. - * loader/multiboot_loader.c: Likewise. - * loader/i386/pc/multiboot2.c: Likewise. - * term/efi/console.c: Likewise. - * term/i386/pc/serial.c: Likewise. - * util/lvm.c: Likewise. - * util/console.c: Likewise. - * util/i386/efi/grub-mkimage.c: Likewise. - * util/raid.c: Likewise. - -2009-01-06 Vesa Jääskeläinen - - * commands/videotest.c: Removed include to grub/machine/memory.h. - - * conf/i386-pc.rmk (pkglib_MODULES): Removed video.mod, gfxterm.mod, - videotest.mod, bitmap.mod, tga.mod, jpeg.mod, png.mod. - (video_mod_SOURCES): Removed. - (video_mod_CFLAGS): Likewise. - (video_mod_LDFLAGS): Likewise. - (gfxterm_mod_SOURCES): Likewise. - (gfxterm_mod_CFLAGS): Likewise. - (gfxterm_mod_LDFLAGS): Likewise. - (videotest_mod_SOURCES): Likewise. - (videotest_mod_CFLAGS): Likewise. - (videotest_mod_LDFLAGS): Likewise. - (bitmap_mod_SOURCES): Likewise. - (bitmap_mod_CFLAGS): Likewise. - (bitmap_mod_LDFLAGS): Likewise. - (tga_mod_SOURCES): Likewise. - (tga_mod_CFLAGS): Likewise. - (tga_mod_LDFLAGS): Likewise. - (jpeg_mod_SOURCES): Likewise. - (jpeg_mod_CFLAGS): Likewise. - (jpeg_mod_LDFLAGS): Likewise. - (png_mod_SOURCES): Likewise. - (png_mod_CFLAGS): Likewise. - (png_mod_LDFLAGS): Likewise. - - * conf/common.rmk (pkglib_MODULES): Added video.mod, videotest.mod, - bitmap.mod, tga.mod, jpeg.mod, png.mod, font.mod, gfxterm.mod - (video_mod_SOURCES): Added. - (video_mod_CFLAGS): Likewise. - (video_mod_LDFLAGS): Likewise. - (videotest_mod_SOURCES): Likewise. - (videotest_mod_CFLAGS): Likewise. - (videotest_mod_LDFLAGS): Likewise. - (bitmap_mod_SOURCES): Likewise. - (bitmap_mod_CFLAGS): Likewise. - (bitmap_mod_LDFLAGS): Likewise. - (tga_mod_SOURCES): Likewise. - (tga_mod_CFLAGS): Likewise. - (tga_mod_LDFLAGS): Likewise. - (jpeg_mod_SOURCES): Likewise. - (jpeg_mod_CFLAGS): Likewise. - (jpeg_mod_LDFLAGS): Likewise. - (png_mod_SOURCES): Likewise. - (png_mod_CFLAGS): Likewise. - (png_mod_LDFLAGS): Likewise. - (gfxterm_mod_SOURCES): Likewise. - (gfxterm_mod_CFLAGS): Likewise. - (gfxterm_mod_LDFLAGS): Likewise. - - * term/gfxterm.c: Removed include to grub/machine/memory.h, - grub/machine/console.h. - -2009-01-04 Jerone Young - - Make on screen instructions clearer - - Based on patch created by Jidanni - - * normal/menu.c: print clearer instructions on the screen - -2009-01-02 Colin D Bennett - - New font engine. - - Additional changes by Vesa Jääskeläinen to adapt to - build system and fixed gfxterm.c to work with different sized fonts. - - * configure.ac: Changed UNIFONT_HEX to UNIFONT_BDF. - - * configure: Re-generated. - - * DISTLIST: Removed font/manager.c. - Added font/font.c. - Added font/font_cmd.c. - - * Makefile.in: Changed UNIFONT_HEX to UNIFONT_BDF. Added Font tool - compilation. - - * include/grub/misc.h (grub_utf8_to_ucs4): Changed prototype. Changed users. - - * kern/misc.c (grub_utf8_to_ucs4): Changed prototype. - - * kern/term.c: Changed users of grub_utf8_to_ucs4. - - * normal/menu.c: Likewise. - - * conf/common.rmk (font_mod_SOURCES): Removed font/manager.c. - (font_mod_SOURCES): Added font/font_cmd.c, font/font.c. - - * include/grub/font.h: Replaced with new file. - - * include/grub/video.h (GRUB_VIDEO_MODE_TYPE_ALPHA): Changed value. - (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED): Likewise. - (GRUB_VIDEO_MODE_TYPE_COLOR_MASK): Likewise. - (GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP): Added. - (grub_video_blit_format): Added GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED. - (grub_video_mode_info): Added bg_red, bg_green, bg_blue, bg_alpha, - fg_red, fg_green, fg_blue, fg_alpha. - (grub_video_adapter): Removed blit_glyph. - (grub_video_blit_glyph): Removed. - - * font/manager.c: Removed file. - - * font/font.c: New file. - - * font/font_cmd.c: Likewise. - - * video/video.c (grub_video_blit_glyph): Removed. - - * video/i386/pc/vbe.c (grub_video_vbe_map_rgb): Added 1-bit support. - (grub_video_vbe_map_rgba): Likewise. - (grub_video_vbe_unmap_color_int): Likewise. - (grub_video_vbe_blit_glyph): Removed. - (grub_video_vbe_adapter): Removed blit_glyph. - - * video/i386/pc/vbeutil.c (get_data_ptr): Added 1-bit support. - (get_pixel): Likewise. - (set_pixel): Likewise. - - * commands/videotest.c (grub_cmd_videotest): Added more tests for fonts. - - * term/gfxterm.c: Adapted to new font engine. - - * term/i386/pc/vesafb.c: Marked as deprecated. Made it compile. - - * term/i386/pc/vga.c: Likewise. - - * util/fonttool/src/org/gnu/grub/fonttool/BDFLoader.java: New file. - - * util/fonttool/src/org/gnu/grub/fonttool/CharDefs.java: Likewise. - - * util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise. - - * util/fonttool/src/org/gnu/grub/fonttool/CharacterRange.java: Likewise. - - * util/fonttool/src/org/gnu/grub/fonttool/Converter.java: Likewise. - - * util/fonttool/src/org/gnu/grub/fonttool/Font.java: Likewise. - - * util/fonttool/src/org/gnu/grub/fonttool/Glyph.java: Likewise. - - * util/fonttool/src/org/gnu/grub/fonttool/PFF2Sections.java: Likewise. - - * util/fonttool/src/org/gnu/grub/fonttool/PFF2Writer.java: Likewise. - - * util/grub.d/00_header.in: Changed to use new loadfont command. - - * util/grub-mkconfig_lib.in: Changed font extension. - -2008-12-28 Felix Zielcke - - * util/getroot.c (grub_util_get_grub_dev): Add support for - /dev/md/dNNpNN style partitionable mdraid devices. - -2008-12-12 Alex Smith - - * fs/i386/pc/pxe.c (grub_pxefs_open): Handle the one open connection - at a time limit of the PXE TFTP API correctly. - (grub_pxefs_close): Likewise. - -2008-11-29 Robert Millan - - * disk/ata.c (grub_ata_pciinit): Handle errors raised by - grub_ata_device_initialize() calls. - -2008-11-28 Krzysztof Smiechowicz - - * fs/affs.c (grub_affs_iterate_dir): Return failure when directory - iteration failed. - * fs/sfs.c (grub_sfs_iterate_dir): Likewise. - -2008-11-28 Robert Millan - - Fix build on powerpc-ieee1275. Based on patch created by - Manoel Abranches . - * conf/powerpc-ieee1275.rmk (kernel_elf_SOURCES): Add - `kern/ieee1275/mmap.c'. - * include/grub/powerpc/ieee1275/memory.h: New file. - - Provide grub-install on coreboot. - * conf/i386-coreboot.rmk (sbin_SCRIPTS): Add `grub-install'. - (grub_install_SOURCES): New variable. - * util/i386/pc/grub-install.in: Add a few condition checks to make it - usable on coreboot. - -2008-11-25 Felix Zielcke - - * util/grub-fstest.c (grub_term_get_current_input): Change return type - to `grub_term_input_t'. - (grub_term_get_current_output): Change return type to - `grub_term_output_t'. - -2008-11-22 Robert Millan - - Fix breakage on coreboot due to declaration mismatch. - * term/i386/pc/vga_text.c (grub_vga_text_init_fini): New function. - (grub_vga_text_term): Use grub_vga_text_init_fini() instead of - grub_vga_text_cls(). - - * kern/i386/loader.S (grub_multiboot_backward_relocator): Improve - comments. Avoid copying one more byte than necessary (just in case). - - * conf/powerpc-ieee1275.rmk (kernel_elf_LDFLAGS): Change link address - to 0x200000 (avoids trouble with some OFW implementations, and matches - with the one in Yaboot). - Reported by Manoel Abranches - -2008-11-20 Robert Millan - - * kern/i386/coreboot/init.c (grub_time_tics): Remove variable. - (grub_get_rtc, grub_exit): Abort with grub_fatal() if called. - - * util/grub-mkconfig_lib.in (grub_warn): New function. - (convert_system_path_to_grub_path): Use grub_warn() when issuing - warnings, to obtain consistent formatting. - * util/grub.d/00_header.in: Likewise. - * util/update-grub_lib.in: Likewise. - - * loader/i386/linux.c (allocate_pages): Fix a warning. - Move comment text to `#error' stanza. - - Harmonize ieee1275's grub_available_iterate() with the generic - grub_machine_mmap_iterate() interface (fixes a recently-introduced - build problem on i386-ieee1275): - * kern/ieee1275/openfw.c (grub_available_iterate): Moved from here ... - * kern/ieee1275/mmap.c (grub_machine_mmap_iterate): ... here. Add third - parameter `type'. Update all users of this function. - * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Add - `kern/ieee1275/mmap.c'. - * kern/ieee1275/init.c - * include/grub/ieee1275/ieee1275.h (grub_available_iterate): Replace - with ... - (grub_machine_mmap_iterate): ... this. - * include/grub/i386/pc/memory.h (grub_machine_mmap_iterate): Change - return type to `grub_err_t'. Update all implementations of this - function prototype. - * include/grub/i386/coreboot/memory.h (grub_machine_mmap_iterate): - Likewise. - - Add `lsmmap' command (lists firmware-provided memory map): - * commands/lsmmap.c: New file. - * conf/i386-pc.rmk (pkglib_MODULES): Add `lsmmap.mod'. - (lsmmap_mod_SOURCES, lsmmap_mod_CFLAGS, lsmmap_mod_LDFLAGS): New - variables. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/i386-coreboot.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - -2008-11-19 Robert Millan - - * loader/i386/pc/linux.c (grub_rescue_cmd_initrd): Fix a typo. - * loader/i386/linux.c (grub_rescue_cmd_initrd): Implement a few needed - constraints to initrd allocation (based on code from - loader/i386/pc/linux.c). Without them, initrd was allocated too high - for Linux to find it. - -2008-11-14 Robert Millan - - * fs/cpio.c (grub_cpio_open): Compare `name' and `fn' by hand in - order to cope with duplicate slashes. - -2008-11-14 Robert Millan - - * include/grub/i386/coreboot/memory.h (GRUB_MEMORY_MACHINE_LOWER_SIZE): - Redefine to match with GRUB_MEMORY_MACHINE_UPPER_START (0x100000). We - don't want to mess with lower memory, because it is used in the Linux - loader. - - * loader/i386/linux.c (allocate_pages): Allocate `real_mode_mem' in - an appropriate place in lower memory, between 0x10000 and 0x90000, - like loader/i386/efi/linux.c does. Linux often panics if real_mode_mem - is in our heap (probably as a result of it being corrupted during - decompression). Add #error instance with comment to explain why this - loader isn't currently usable on PC/BIOS. - -2008-11-14 Robert Millan - - * term/i386/pc/serial.c [! GRUB_MACHINE_PCBIOS] - (GRUB_SERIAL_PORT_NUM): Fix miscalculation. - -2008-11-12 Robert Millan - - Make loader/i386/linux.c buildable on i386-pc (although disabled). - - * include/grub/i386/pc/init.h: Include `'. - (struct grub_machine_mmap_entry, grub_machine_mmap_iterate): Move - from here ... - * include/grub/i386/pc/memory.h: ... to here. - -2008-11-12 Robert Millan - - Fix build problems on i386-ieee1275 and *-efi (introduced by vga_text - split). - - * include/grub/i386/pc/console.h: Include `'. - (grub_console_cur_color, grub_console_real_putchar) - (grub_console_putchar, grub_console_getcharwidth, grub_console_getwh) - (grub_console_setcolorstate, grub_console_setcolor) - (grub_console_getcolor): Move from here ... - * include/grub/i386/vga_common.h: ... to here (new file). - - * term/i386/pc/vga_text.c: Replace `' with - `' and `' with - `'. - * term/i386/vga_common.c: Replace `' with - `'. - -2008-11-12 Robert Millan - - * conf/i386-pc.rmk (kernel_img_SOURCES): Add `term/i386/vga_common.c'. - * conf/i386.rmk (pkglib_MODULES): Add `vga_text.mod'. - (vga_text_mod_SOURCES, vga_text_mod_CFLAGS, vga_text_mod_LDFLAGS): New - variables. - * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Replace - `term/i386/pc/console.c' with `term/i386/vga_common.c'. - - * kern/i386/coreboot/init.c (grub_machine_init): Replace call to - grub_console_init() with call to grub_vga_text_init(). - (grub_machine_fini): Replace call to - grub_console_fini() with call to grub_vga_text_fini() and - grub_at_keyboard_fini(). - - * include/grub/i386/pc/console.h: Include `'. - (grub_console_putchar, grub_console_getcharwidth, grub_console_getwh) - (grub_console_setcolorstate, grub_console_setcolor) - (grub_console_getcolor): New function prototypes. - - * term/i386/pc/vga_text.c: Include `'. - (grub_vga_text_getxy, grub_vga_text_gotoxy, grub_vga_text_cls) - (grub_vga_text_setcursor): Static-ize. - (grub_vga_text_term): New structure. - (GRUB_MOD_INIT(vga_text), GRUB_MOD_FINI(vga_text)): New functions. - - * term/i386/pc/console.c: Remove `'. - (grub_console_cur_color, grub_console_standard_color) - (grub_console_normal_color, grub_console_highlight_color) - (map_char, grub_console_putchar, grub_console_getcharwidth) - (grub_console_getwh, grub_console_setcolorstate, grub_console_setcolor) - (grub_console_getcolor): Move from here ... - * term/i386/vga_common.c: ... to here (same function names). - -2008-11-12 Robert Millan - - Use newly-added Multiboot support in coreboot. - - * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Replace - `kern/i386/coreboot/mmap.c' with `kern/i386/multiboot_mmap.c'. - - * kern/i386/coreboot/startup.S: Enable Multiboot header, fix its - alignment, set `MULTIBOOT_MEMORY_INFO' flag. - (codestart): Store the MBI in `startup_multiboot_info' when we're - being loaded using Multiboot. - - * kern/i386/coreboot/init.c (grub_machine_init): Move - grub_at_keyboard_init() call to beginning of function (useful for - debugging). Call grub_machine_mmap_init() before attempting to use - grub_machine_mmap_iterate(). - (grub_lower_mem, grub_upper_mem): Move from here ... - * kern/i386/multiboot_mmap.c (grub_lower_mem, grub_upper_mem): ... to - here (new file). - - * include/grub/i386/coreboot/memory.h (grub_machine_mmap_init): New - function prototype. - -2008-11-12 Robert Millan - - Fix a regression introduced by the at_keyboard.mod split. Because - some terminals are default on some platforms and non-default on - others, the first terminal being registered determines which is - going to be default. - - * kern/term.c (grub_term_register_input): If this is the first - terminal being registered, set it as the current one. - (grub_term_register_output): Likewise. - - * term/efi/console.c (grub_console_init): Do not call - grub_term_set_current_output() or grub_term_set_current_input(). - * term/ieee1275/ofconsole.c (grub_console_init): Likewise. - * term/i386/pc/console.c (grub_console_init): Likewise. - (grub_console_fini): Do not call grub_term_set_current_input() - (but leave grub_term_set_current_output() to restore text mode). - -2008-11-10 Robert Millan - - * util/grub.d/00_header.in: Add backward compatibility check for - versions of terminal.mod that don't understand `terminal_input' or - `terminal_output'. - -2008-11-09 Robert Millan - - * commands/terminal.c (GRUB_MOD_FINI(terminal)): Unregister - `terminal_input' / `terminal_output', not `terminal'. - -2008-11-08 Robert Millan - - * Makefile.in (include_DATA): Fix srcdir=. assumption. - (DISTCLEANFILES): Add `build_env.mk'. - -2008-11-08 Robert Millan - - * term/i386/pc/vesafb.c (grub_vesafb_term): Change type to - `struct grub_term_output'. Remove `.checkkey' and `.getkey' - members. Update all users. - * util/console.c (grub_ncurses_term): Split in ... - (grub_ncurses_term_input): ... this, and ... - (grub_ncurses_term_output): ... this. Update all users. - * term/ieee1275/ofconsole.c: Remove stale `#endif'. - -2008-11-08 Robert Millan - - * Makefile.in (PKGLIB): Add $(pkglib_BUILDDIR). - (PKGDATA): Add $(pkgdata_SRCDIR). - (pkglib_BUILDDIR): New variable. - (pkgdata_SRCDIR): New variable. - (build_env.mk): New target. - (include_DATA): New variable. - (install-local): Install $(include_DATA) files in $(includedir). - -2008-11-07 Pavel Roskin - - * gendistlist.sh: Use C locale for sorting to ensure consistent - output on all systems. - - * util/grub.d/00_header.in: Remove incorrect space before - "serial". - -2008-11-07 Robert Millan - - * include/multiboot2.h (struct multiboot_header): Add `flags' member as - per specification. - * loader/multiboot2.c (grub_multiboot2): Fix Multiboot2 header check. - * loader/multiboot_loader.c (find_multi_boot2_header): New function - (based on find_multi_boot1_header). - (grub_rescue_cmd_multiboot_loader): Check for Multiboot2 header, - using find_multi_boot2_header(), and abort if neither Multiboot or - Multiboot headers were found. - -2008-11-07 Robert Millan - - Modularize at_keyboard.mod: - - * conf/i386.rmk (pkglib_MODULES): Add `at_keyboard.mod'. - (at_keyboard_mod_SOURCES, at_keyboard_mod_CFLAGS) - (at_keyboard_mod_LDFLAGS): New variables. - - Actual terminal split: - - * include/grub/term.h (struct grub_term): Split in ... - (struct grub_term_input): ... this, and ... - (struct grub_term_output): ... this. Update all users. - (grub_term_set_current): Split in ... - (grub_term_set_current_input): ... this, and ... - (grub_term_set_current_output): ... this. - (grub_term_get_current): Split in ... - (grub_term_get_current_input): ... this, and ... - (grub_term_get_current_output): ... this. - (grub_term_register): Split in ... - (grub_term_register_input): ... this, and ... - (grub_term_register_output): ... this. - (grub_term_unregister): Split in ... - (grub_term_unregister_input): ... this, and ... - (grub_term_unregister_output): ... this. - (grub_term_iterate): Split in ... - (grub_term_iterate_input): ... this, and ... - (grub_term_iterate_output): ... this. - - * kern/term.c (grub_term_list): Split in ... - (grub_term_list_input): ... this, and ... - (grub_term_list_output): ... this. Update all users. - (grub_cur_term): Split in ... - (grub_cur_term_input): ... this, and ... - (grub_cur_term_output): ... this. Update all users. - (grub_term_set_current): Split in ... - (grub_term_set_current_input): ... this, and ... - (grub_term_set_current_output): ... this. - (grub_term_get_current): Split in ... - (grub_term_get_current_input): ... this, and ... - (grub_term_get_current_output): ... this. - (grub_term_register): Split in ... - (grub_term_register_input): ... this, and ... - (grub_term_register_output): ... this. - (grub_term_unregister): Split in ... - (grub_term_unregister_input): ... this, and ... - (grub_term_unregister_output): ... this. - (grub_term_iterate): Split in ... - (grub_term_iterate_input): ... this, and ... - (grub_term_iterate_output): ... this. - - * kern/misc.c (grub_abort): Split use of grub_term_get_current() into - a check for input and one for output (and only attempt to get keys - from user when input works). - - * util/grub-probe.c (grub_term_get_current): Split in ... - (grub_term_get_current_input): ... this, and ... - (grub_term_get_current_output): ... this. - * util/grub-fstest.c: Likewise. - * util/i386/pc/grub-setup.c: Likewise. - * util/grub-editenv.c: Likewise. - - Portability adjustments: - - * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Remove - `term/i386/pc/at_keyboard.c'. - * kern/ieee1275/init.c [__i386__] (grub_machine_init): Remove call to - grub_keyboard_controller_init() (now handled by terminal .init). - * kern/i386/coreboot/init.c (grub_machine_init): Add call to - grub_at_keyboard_init(). - * include/grub/i386/ieee1275/console.h (grub_keyboard_controller_init) - (grub_console_checkkey, grub_console_getkey): Remove (now provided by - at_keyboard.mod via input terminal interface). - * include/grub/i386/coreboot/console.h: Convert into a stub for - `'. - - Migrate full terminals to new API: - - * term/efi/console.c (grub_console_term): Split into ... - (grub_console_term_input): ... this, and ... - (grub_console_term_output): ... this. Update all users. - * term/ieee1275/ofconsole.c: Remove __i386__ hack. - (grub_ofconsole_init): Split into ... - (grub_ofconsole_init_input): ... this, and ... - (grub_ofconsole_init_output): ... this. - (grub_ofconsole_term): Split into ... - (grub_ofconsole_term_input): ... this, and ... - (grub_ofconsole_term_output): ... this. Update all users. - * term/i386/pc/serial.c (grub_serial_term): Split into ... - (grub_serial_term_input): ... this, and ... - (grub_serial_term_output): ... this. Update all users. - * term/i386/pc/console.c (grub_console_term): Split into ... - (grub_console_term_input): ... this, and ... - (grub_console_term_output): ... this. Update all users. - (grub_console_term_input): Only enable it on PC/BIOS platform. - (grub_console_init): Remove grub_keyboard_controller_init() call. - - Migrate input terminals to new API: - - * term/i386/pc/at_keyboard.c: Replace `cpu' and `machine' with - `i386' and `i386/pc' to enable build on x86_64 (this driver is - i386-specific anyway). - (grub_console_checkkey): Rename to ... - (grub_at_keyboard_checkkey): ... this. Static-ize. Update all - users. - (grub_keyboard_controller_orig): New variable. - (grub_console_getkey): Rename to ... - (grub_at_keyboard_getkey): ... this. Static-ize. Update all - users. - (grub_keyboard_controller_init): Static-ize. Save original - controller value so that it can be restored ... - (grub_keyboard_controller_fini): ... here (new function). - (grub_at_keyboard_term): New structure. - (GRUB_MOD_INIT(at_keyboard), GRUB_MOD_FINI(at_keyboard)): New - functions. - - Migrate output terminals to new API: - - * term/i386/pc/vga.c (grub_vga_term): Change type to - `struct grub_term_output'. Remove `.checkkey' and `.getkey' - members. Update all users. - * term/gfxterm.c (grub_video_term): Change type to - `struct grub_term_output'. Remove `.checkkey' and `.getkey' - members. Update all users. - * include/grub/i386/pc/console.h (grub_console_checkkey) - (grub_console_getkey): Do not export (no longer needed by gfxterm, - etc). - - Migrate `terminal' command and userland tools to new API: - - * commands/terminal.c (grub_cmd_terminal): Split into ... - (grub_cmd_terminal_input): ... this, and ... - (grub_cmd_terminal_output): ... this. - (GRUB_MOD_INIT(terminal)): Split `terminal' command in two commands: - `terminal_input' and `terminal_output'. - * util/grub.d/00_header.in: Adjust `terminal' calls to new - `terminal_input' / `terminal_output' API. - * util/grub-mkconfig.in: Export ${GRUB_TERMINAL_INPUT} and - ${GRUB_TERMINAL_OUTPUT} instead of ${GRUB_TERMINAL} (and if user - provided ${GRUB_TERMINAL}, convert it). - -2008-11-04 Robert Millan - - * util/grub.d/10_freebsd.in: New file. Generate grub configuration - for FreeBSD. - * conf/common.rmk (grub-mkconfig_SCRIPTS): Add 10_freebsd. - -2008-11-03 Bean - - * kern/elf.c (grub_elf32_load): Revert to previous code. - (grub_elf64_load): Likewise. - - * loader/i386/bsd.c (grub_bsd_elf32_hook): Change return address. - -2008-11-01 Robert Millan - - * Makefile.in (CPPFLAGS): Fix builddir=. assumption. - (TARGET_CPPFLAGS): Likewise. - * genmk.rb (mod_src): Fix builddir=. and srcdir=. assumptions. - -2008-11-01 Carles Pina i Estany - - * normal/menu.c (run_menu): Add Previous and Next Page keys in menu. - -2008-10-29 Guillem Jover - - * disk/lvm.c (grub_lvm_scan_device): Fix error recovery by delaying the - addition of objects until the code is not going to be able to fail. - -2008-10-29 Guillem Jover - - * disk/lvm.c (grub_lvm_scan_device): Fix possible NULL value handling - (add a missing NULL check, and correct them by moving the pointer - operations after the actual check). - -2008-10-29 Robert Millan - - * util/i386/pc/grub-install.in: Handle empty string as output from - make_system_path_relative_to_its_root(). - -2008-10-05 Hans Lambermont - - * disk/lvm.c (grub_lvm_scan_device): Allocate buffer space for the - circular metadata worst case scenario. If the metadata is circular - then copy the wrap in place. - * include/grub/lvm.h: Add GRUB_LVM_MDA_HEADER_SIZE, from the LVM2 - project lib/format_text/layout.h - Circular metadata bug found and patch debugged by Jan Derk Gerlings. - -2008-10-03 Felix Zielcke - - * util/i386/pc/grub-install.in: Source grub-mkconfig_lib instead of update-grub_lib. - -2008-10-03 Felix Zielcke - - * util/update-grub_lib.in: Mention filename in warning message. - -2008-09-29 Felix Zielcke - - * NEWS: Update for rename of update-grub to grub-mkconfig. - -2008-09-29 Felix Zielcke - - * util/update-grub_lib.in: Copy to ... - * util/grub-mkconfig_lib.in: ... this. Update all users. - * util/update-grub_lib.in: Make it a stub to `grub-mkconfig_lib.in'. - * util/update-grub.in: Rename to ... - * util/grub-mkconfig.in: ... this. Update all users. Remove `-y' - option. Add `--output' option to allow users to specify the generated - configuration file. Default to stdout. - (update_grub_dir): Rename to ... - (grub_mkconfig_dir): ... this. - (grub_cfg): Default to an empty string. - * conf/common.rmk (update-grub): Rename to ... - (grub-mkconfig): ... this. - (update-grub_lib): Copy to ... - (grub-mkconfig_lib): ... this. - (update-grub_SCRIPTS): Copy to ... - (grub-mkconfig_SCRIPTS): ... this. Update all users. - (update-grub_DATA): Rename to ... - (grub-mkconfig_DATA): ... this. - -2008-09-28 Robert Millan - - * fs/iso9660.c (struct grub_iso9660_primary_voldesc): Rename `created' - to `modified'. Add the real `created' field. - (grub_iso9660_uuid): Use `modified' rather than `created' for - constructing the UUID. - -2008-09-28 Felix Zielcke - - fs/jfs.c (grub_jfs_find_file): Treat multiple slashes like one. - Based on code from Tomas Ebenlendr . - -2008-09-28 Bean - - * fs/ntfs.c (grub_ntfs_iterate_dir): Fix a bug in the previous patch. - Thanks to Christian Franke for finding this bug. - -2008-09-25 Robert Millan - - * util/grub-mkdevicemap.c (make_device_map): Actually replace all - instances of grub_util_get_disk_name() (see previous commit). - -2008-09-25 Robert Millan - - * conf/i386-pc.rmk (grub_mkdevicemap_SOURCES): Remove - `util/i386/get_disk_name.c'. - * conf/i386-efi.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - * conf/i386-coreboot.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/powerpc-ieee1275.rmk (grub_mkdevicemap_SOURCES): Remove - `util/ieee1275/get_disk_name.c'. - * include/grub/util/misc.h (grub_util_get_disk_name): Remove. - * util/ieee1275/get_disk_name.c: Remove file. - * util/i386/get_disk_name.c: Remove file. - * util/grub-mkdevicemap.c (make_device_map): Back to hardcoding - "hd%d" for device.map entries, rather than using - grub_util_get_disk_name(). - -2008-09-24 Carles Pina i Estany - - * disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Fix `unused parameter' - warning. - * commands/i386/pc/pxecmd.c (dmraid_nvidia): Likewise. - -2008-09-24 Carles Pina i Estany - - * include/grub/i386/pc/console.h (GRUB_TERM_NPAGE): - Changed to 0x5100. - (GRUB_TERM_PPAGE): Changed to 0x4900. - -2008-09-24 Robert Millan - - * include/grub/powerpc/ieee1275/console.h (GRUB_CONSOLE_KEY_*): Remove - macros (they were i386-pc specific). - * include/grub/sparc64/ieee1275/console.h: Likewise. - * include/grub/efi/console.h: Likewise. - -2008-09-22 Bean - - * fs/ntfs.c (grub_ntfs_iterate_dir): Fix a rare case where $BITMAP is - resident and in attribute list. - - * include/grub/ntfs.h (BMP_LEN): Removed. - -2008-09-22 Bean - - * disk/ata.c (grub_atapi_open): Initialize devfnd, no need to set - scsi->name and scsi->luns, as they will be set in grub_scsi_open. - - * disk/scsi.c (grub_scsi_open): Don't call p->close (scsi) here when - error occurs, as grub_disk_open will call grub_disk_close, which will - call p->close (scsi). - -2008-09-21 Felix Zielcke - - * configure.ac (AC_INIT): Quote `GRUB' string and version number. - (AC_PREREQ): Bumped to 2.59. - (AC_TRY_COMPILE): Replace obsolete macro with ... - (AC_COMPILE_IFELSE): ... this. - * aclocal.m4 (AC_TRY_LINK): Replace obsolete macro with ... - (AC_LINK_IFELSE): ... this. - -2008-09-21 Felix Zielcke - - * autogen.sh: Add a call to `gendistlist.sh'. - -2008-09-19 Christian Franke - - * aclocal.m4 (grub_CHECK_ENABLE_EXECUTE_STACK): New function. - * configure.ac: Call grub_CHECK_ENABLE_EXECUTE_STACK. - * include/grub/misc.h [NEED_ENABLE_EXECUTE_STACK]: - Export __enable_execute_stack() to modules. - * kern/misc.c [NEED_ENABLE_EXECUTE_STACK] (__enable_execute_stack): - New function. - -2008-09-09 Felix Zielcke - - * Makefile.in (RMKFILES): Add `i386.rmk' and `x86_64-efi.rmk'. - Sort the list. - -2008-09-09 Felix Zielcke - - * util/hostdisk.c: Replace #include with - #include . - -2008-09-08 Robert Millan - - * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Skip - segments when their filesz is zero (grub_file_read() interprets - zero-size as "read until EOF", which results in memory corruption). - Use `lowest_segment' rather than 0 for calculating the current - segment load address. - -2008-09-08 Robert Millan - - * util/hostdisk.c (open_device): Replace a grub_util_info() call - with grub_dprintf("hostdisk", ...), as it was so verbose that it - clobbered useful information. - -2008-09-08 Robert Millan - - * include/grub/util/biosdisk.h: Move to ... - * include/grub/util/hostdisk.h: ... here. Update all users. - * util/biosdisk.c: Move to ... - * util/hostdisk.c: ... here. Update all users. - -2008-09-07 Robert Millan - - * loader/i386/pc/multiboot.c (mmap_addr, mmap_length): Remove - variables. - (grub_multiboot): Move `mbi' allocation upwards, so that mmap address - and length can be stored directly in the `mbi->mmap_addr' and - `mbi->mmap_length' struct fields. - -2008-09-07 Robert Millan - - * conf/i386.rmk: New file. Provides declaration for building - `cpuid.mod'. - * conf/i386-pc.rmk (pkglib_MODULES): Remove `cpuid.mod'. - (cpuid_mod_SOURCES, cpuid_mod_CFLAGS, cpuid_mod_LDFLAGS): Remove - variables. - Include `conf/i386.mk'. - * conf/i386-efi.rmk: Likewise. - * conf/x86_64-efi.rmk: Likewise. - * conf/i386-coreboot.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - -2008-09-07 Vesa Jääskeläinen - - Based on patch created by Colin D Bennett . - Adds optimization support for BGR based modes. - - * include/grub/i386/pc/vbeblit.h (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8) Removed. - (grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8): Likewise. - (grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Likewise. - (grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Likewise. - (grub_video_i386_vbeblit_index_R8G8B8A8): Likewise. - (grub_video_i386_vbeblit_index_R8G8B8X8): Likewise. - (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8): Likewise. - (grub_video_i386_vbeblit_R8G8B8_R8G8B8): Likewise. - (grub_video_i386_vbeblit_index_R8G8B8): Likewise. - (grub_video_i386_vbeblit_index_index): Likewise. - (grub_video_i386_vbeblit_replace_directN): Added. - (grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888): Likewise. - (grub_video_i386_vbeblit_replace_BGRX8888_RGB888): Likewise. - (grub_video_i386_vbeblit_replace_BGR888_RGBX8888): Likewise. - (grub_video_i386_vbeblit_replace_BGR888_RGB888): Likewise. - (grub_video_i386_vbeblit_replace_RGBX8888_RGB888): Likewise. - (grub_video_i386_vbeblit_replace_RGB888_RGBX8888): Likewise. - (grub_video_i386_vbeblit_replace_index_RGBX8888): Likewise. - (grub_video_i386_vbeblit_replace_index_RGB888): Likewise. - (grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888): Likewise. - (grub_video_i386_vbeblit_blend_BGR888_RGBA8888): Likewise. - (grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888): Likewise. - (grub_video_i386_vbeblit_blend_RGB888_RGBA8888): Likewise. - (grub_video_i386_vbeblit_blend_index_RGBA8888): Likewise. - - * include/grub/i386/pc/vbefill.h (grub_video_i386_vbefill_R8G8B8A8) Removed. - (grub_video_i386_vbefill_R8G8B8): Likewise. - (grub_video_i386_vbefill_index): Likewise. - (grub_video_i386_vbefill_direct32): Added. - (grub_video_i386_vbefill_direct24): Likewise. - (grub_video_i386_vbefill_direct16): Likewise. - (grub_video_i386_vbefill_direct8): Likewise. - - * include/grub/video.h (grub_video_blit_format): Removed - GRUB_VIDEO_BLIT_FORMAT_R8G8B8A8, GRUB_VIDEO_BLIT_FORMAT_R8G8B8. - (grub_video_blit_format): Added GRUB_VIDEO_BLIT_FORMAT_RGBA_8888, - GRUB_VIDEO_BLIT_FORMAT_BGRA_8888, GRUB_VIDEO_BLIT_FORMAT_RGB_888, - GRUB_VIDEO_BLIT_FORMAT_BGR_888, GRUB_VIDEO_BLIT_FORMAT_RGB_565, - GRUB_VIDEO_BLIT_FORMAT_BGR_565. - - * video/video.c (grub_video_get_blit_format): Updated to use new - blit formats. Added handling for 16 bit color modes. - - * video/i386/pc/vbe.c (grub_video_vbe_fill_rect): Updated to use new - fillers. - (common_blitter): Updated to use new blitters. - - * video/i386/pc/vbeblit.c (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8): - Removed. - (grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8): Likewise. - (grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Likewise. - (grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Likewise. - (grub_video_i386_vbeblit_index_R8G8B8A8): Likewise. - (grub_video_i386_vbeblit_index_R8G8B8X8): Likewise. - (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8): Likewise. - (grub_video_i386_vbeblit_R8G8B8_R8G8B8): Likewise. - (grub_video_i386_vbeblit_index_R8G8B8): Likewise. - (grub_video_i386_vbeblit_index_index): Likewise. - (grub_video_i386_vbeblit_replace_directN): Added. - (grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888): Likewise. - (grub_video_i386_vbeblit_replace_BGRX8888_RGB888): Likewise. - (grub_video_i386_vbeblit_replace_BGR888_RGBX8888): Likewise. - (grub_video_i386_vbeblit_replace_BGR888_RGB888): Likewise. - (grub_video_i386_vbeblit_replace_RGBX8888_RGB888): Likewise. - (grub_video_i386_vbeblit_replace_RGB888_RGBX8888): Likewise. - (grub_video_i386_vbeblit_replace_index_RGBX8888): Likewise. - (grub_video_i386_vbeblit_replace_index_RGB888): Likewise. - (grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888): Likewise. - (grub_video_i386_vbeblit_blend_BGR888_RGBA8888): Likewise. - (grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888): Likewise. - (grub_video_i386_vbeblit_blend_RGB888_RGBA8888): Likewise. - (grub_video_i386_vbeblit_blend_index_RGBA8888): Likewise. - - * video/i386/pc/vbefill.c (grub_video_i386_vbefill_R8G8B8A8): Removed. - (grub_video_i386_vbefill_R8G8B8): Likewise. - (grub_video_i386_vbefill_index): Likewise. - (grub_video_i386_vbefill_direct32): Added. - (grub_video_i386_vbefill_direct24): Likewise. - (grub_video_i386_vbefill_direct16): Likewise. - (grub_video_i386_vbefill_direct8): Likewise. - - * video/readers/jpeg.c (grub_jpeg_decode_sos): Adapt to new blitter - types. - - * video/readers/tga.c (grub_video_reader_tga): Adapt to new blitter - types. - - * video/readers/png.c (grub_png_decode_image_header): Adapt to new - blitter types. - - * video/bitmap.c (grub_video_bitmap_create): Adapt to new blitter - types. - -2008-09-06 Felix Zielcke - - * disk/raid.c (insert_array): Set `array->chunk_size' to 64 for - RAID level 1. - -2008-09-06 Felix Zielcke - - * fs/iso9660.c (grub_iso9660_date): New structure. - (grub_iso9660_primary_voldesc): Add `grub_iso9660_date' member. - (grub_iso9660_uuid): New function. - -2008-09-05 Bean - - * fs/fshelp.c (grub_fshelp_find_file): Handle case insensitive names. - - * fs/ntfs.c (list_file): Ignore names in DOS namespace, set the case - insensitive bit for names in Win32 and Win32 & DOS namespace. - - * include/grub/fshelp.h (GRUB_FSHELP_CASE_INSENSITIVE): New macro. - - * include/grub/types.h (LONG_MAX): Likewise. - -2008-09-04 Felix Zielcke - - * util/getroot.c: Include . - (grub_util_get_grub_dev): Rewrite to use asprintf for mdraid devices, - add support for /dev/md/N devices and handle LVM double dash escaping. - -2008-09-04 Felix Zielcke - - * config.guess: Update to latest version from config git. - * config.sub: Likewise. - -2008-09-03 Robert Millan - - * disk/scsi.c (grub_scsi_open): Remove size limit when printing - `disk->total_sectors'. - -2008-09-01 Colin D Bennett - - * include/grub/normal.h: Fixed incorrect comment for - GRUB_COMMAND_FLAG_NO_ARG_PARSE. - -2008-09-01 Colin D Bennett - - * commands/i386/pc/vbeinfo.c (grub_cmd_vbeinfo): Replaced constant - values with defines. - - * include/grub/i386/pc/vbe.h (GRUB_VBE_MODEATTR_SUPPORTED): Added. - (GRUB_VBE_MODEATTR_RESERVED_1): Likewise. - (GRUB_VBE_MODEATTR_BIOS_TTY_OUTPUT_SUPPORT): Likewise. - (GRUB_VBE_MODEATTR_COLOR): Likewise. - (GRUB_VBE_MODEATTR_GRAPHICS): Likewise. - (GRUB_VBE_MODEATTR_VGA_COMPATIBLE): Likewise. - (GRUB_VBE_MODEATTR_VGA_WINDOWED_AVAIL): Likewise. - (GRUB_VBE_MODEATTR_LFB_AVAIL): Likewise. - (GRUB_VBE_MODEATTR_DOUBLE_SCAN_AVAIL): Likewise. - (GRUB_VBE_MODEATTR_INTERLACED_AVAIL): Likewise. - (GRUB_VBE_MODEATTR_TRIPLE_BUF_AVAIL): Likewise. - (GRUB_VBE_MODEATTR_STEREO_AVAIL): Likewise. - (GRUB_VBE_MODEATTR_DUAL_DISPLAY_START): Likewise. - (GRUB_VBE_MEMORY_MODEL_TEXT): Likewise. - (GRUB_VBE_MEMORY_MODEL_CGA): Likewise. - (GRUB_VBE_MEMORY_MODEL_HERCULES): Likewise. - (GRUB_VBE_MEMORY_MODEL_PLANAR): Likewise. - (GRUB_VBE_MEMORY_MODEL_NONCHAIN4_256): Likewise. - (GRUB_VBE_MEMORY_MODEL_YUV): Likewise. - -2008-08-31 Robert Millan - - * loader/i386/pc/multiboot.c (grub_get_multiboot_mmap_len): Fix - declaration. - (grub_multiboot): Fix a few warnings. - -2008-08-31 Robert Millan - - * loader/i386/pc/multiboot.c: Update comment not to say that - boot_device support is unimplemented. - -2008-08-31 Robert Millan - - * loader/i386/pc/multiboot.c: Update comment not to say that a.out - or memory map support are unimplemented. - -2008-08-31 Colin D Bennett - - * util/i386/pc/grub-mkrescue.in: Support multiple overlay directories. - -2008-08-31 Colin D Bennett - - * commands/i386/pc/vbeinfo.c (grub_cmd_vbeinfo): Show VBE version and - total video memory in 'vbeinfo' output; show color format details for - each video mode. - -2008-08-30 Pavel Roskin - - * util/genmoddep.c: Remove for real this time. - * DISTLIST: Remove util/genmoddep.c. - -2008-08-30 Robert Millan - - * kern/i386/pc/startup.S (multiboot_header): Force 4-byte alignment - as required by Multiboot spec (it was already 4-byte aligned, but - only by chance). - -2008-08-29 Pavel Roskin - - * kern/powerpc/ieee1275/crt0.S: Rename to ... - * kern/powerpc/ieee1275/startup.S: ... this. - * conf/powerpc-ieee1275.rmk: Adjust for the above. - * DISTLIST: Likewise. - - * kern/powerpc/ieee1275/crt0.S: Include grub/symbol.h and - grub/cpu/kernel.h. Add start label for consistency with other - platforms. Add grub_prefix immediately after start. Add jump - to the code after grub_prefix. - * include/grub/powerpc/kernel.h: Provide valid values for - GRUB_KERNEL_CPU_PREFIX and GRUB_KERNEL_CPU_DATA_END. - -2008-08-29 Bean - - * configure.ac: Change host_os to cygwin for mingw. - (asprintf): New check for function. - - * include/grub/symbol.h: Replace #ifndef __CYGWIN__ with - #if ! defined (__CYGWIN__) && ! defined (__MINGW32__). - - * include/grub/util/misc.h: #include and , - declare asprintf if HAVE_ASPRINTF is not set, declare fseeko, ftello, - sync, sleep and grub_util_get_disk_size for mingw. - - * util/biosdisk.c (grub_util_biosdisk_open): Use grub_util_get_disk_size - to get size in mingw. - (open_device): Use flag O_BINARY if it's defined. - (find_root_device): Add dummy code for mingw. - - * util/grub-mkdevicemap.c (get_floppy_disk_name): Return 0 for mingw. - (get_ide_disk_name): Return //./PHYSICALDRIVE%d for mingw. - (get_scsi_disk_name): Return 0 for mingw. - - * util/hostfs.c: #include . - (grub_hostfs_open): Use "rb" flag to open file, use - grub_util_get_disk_size to get disk size for mingw. - - * util/misc.c: #include and in mingw. - (asprintf): New function if HAVE_ASPRINTF is not set. - (sync): New function for mingw. - (sleep): Likewise. - (grub_util_get_disk_size): Likewise. - -2008-08-28 Pavel Roskin - - * conf/powerpc-ieee1275.rmk (kernel_elf_SOURCES): Add - kern/time.c. - -2008-08-28 Robert Millan - - * util/biosdisk.c (find_grub_drive): Declare missing `i' variable. - -2008-08-28 Robert Millan - - Change find_grub_drive() syntax so it doesn't prevent it from - detecting NULL names as errors. - - * util/biosdisk.c (find_grub_drive): Move free slot search code - from here ... - (find_free_slot): ... to here. - (read_device_map): Use find_free_slot() to search for free slots. - -2008-08-27 Marco Gerards - - * conf/common.rmk (pkglib_MODULES): Add scsi.mod. - (scsi_mod_SOURCES): New variable. - (scsi_mod_CFLAGS): Likewise - (scsi_mod_LDFLAGS): Likewise. - - * disk/scsi.c: New file. - - * include/grub/scsi.h: Likewise. - - * include/grub/scsicmd.h: Likewise. - - * disk/ata.c: Include . - (grub_atapi_packet): Do not use grub_ata_cmd, use registers - instead. - (grub_ata_iterate): Skip ATAPI devices. - (grub_ata_open): Only handle ATAPI devices. - (struct grub_atapi_read): Removed. - (grub_atapi_readsector): Likewise. - (grub_ata_read): No longer handle ATAPI devices. - (grub_ata_write): Likewise. - (grub_atapi_iterate): New function. - (grub_atapi_read): Likewise. - (grub_atapi_write): Likewise. - (grub_atapi_open): Likewise. - (grub_atapi_close): Likewise. - (grub_atapi_dev): New variable. - (GRUB_MOD_INIT(ata)): Register ATAPI as SCSI device. - (GRUB_MOD_FINI(ata)): Unregister ATAPI. - - * include/grub/disk.h (enum grub_disk_dev_id): Add - `GRUB_DISK_DEVICE_SCSI_ID'. - -2008-08-26 Robert Millan - - * util/biosdisk.c (grub_util_biosdisk_open, open_device) - (grub_util_biosdisk_get_grub_dev): Make error messages a bit more - descriptive. - -2008-08-23 Bean - - * conf/common.rmk (grub_probe_SOURCES): Add disk/mdraid_linux.c. - (grub_fstest_SOURCES): Add disk/raid5_recover.c, disk/raid6_recover.c, - disk/mdraid_linux.c and disk/dmraid_nvidia.c and lib/crc.c. - (pkglib_MODULES): Add raid5rec.mod, raid6rec.mod, mdraid.mod and - dm_nv.mod. - (raid5rec_mod_SOURCES): New macro. - (raid5rec_mod_CFLAGS): Likewise. - (raid5rec_mod_LDFLAGS): Likewise. - (raid6rec_mod_SOURCES): Likewise. - (raid6rec_mod_CFLAGS): Likewise. - (raid6rec_mod_LDFLAGS): Likewise. - (mdraid_mod_SOURCES): Likewise. - (mdraid_mod_CFLAGS): Likewise. - (mdraid_mod_LDFLAGS): Likewise. - (dm_nv_mod_SOURCES): Likewise. - (dm_nv_mod_CFLAGS): Likewise. - (dm_nv_mod_LDFLAGS): Likewise. - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add disk/mdraid_linux.c. - (grub_emu_SOURCES): Add disk/raid5_recover.c, disk/raid6_recover.c, - disk/mdraid_linux.c and disk/dmraid_nvidia.c. - - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add disk/raid5_recover.c, - disk/raid6_recover.c, disk/mdraid_linux.c and disk/dmraid_nvidia.c. - - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise. - - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - - * disk/raid5_recover.c: New file. - - * disk/raid6_recover.c: Likewise. - - * disk/mdraid_linux.c: Likewise. - - * disk/dmraid_nvidia.c: Likewise. - - * disk/i386/pc/biosdisk.c: Set total_sectors of cdrom device to - ULONG_MAX. - - * disk/raid.c (grub_raid_open): Use the size of the smallest disk to - calculate the size of raid device. - (grub_raid_read): Simplify raid0 code. Support raid4, raid6 and four - different layout of raid5. - (grub_raid_scan_device): Remove code specific to mdraid. - (grub_raid_list): New variable. - (free_array): New function. - (grub_raid_register): Likewise. - (grub_raid_unregister): Likewise. - (grub_raid_rescan): Likewise. - (GRUB_MOD_INIT): Don't iterate device here. - (GRUB_MOD_FINI): Use free_array to release resource. - - * include/grub/raid.h: Remove macro and structure specific to mdraid. - (grub_raid5_recover_func_t): New function variable type. - (grub_raid6_recover_func_t): Likewise. - (grub_raid5_recover_func): New variable. - (grub_raid6_recover_func): Likewise. - (grub_raid_register): New function. - (grub_raid_unregister): Likewise. - (grub_raid_rescan): Likewise. - (grub_raid_block_xor): Likewise. - - * util/grub-fstest.c: Add #include and . - (CMD_CRC): New macro. - (part): Removed. - (read_file): Handle device as well as file. - (cmd_crc): New function. - (fstest): Handle multiple disks. - (options): Remove part, raw and long, add root and diskcount. - (usage): Add crc, remove -p, -r, -l, add -r and -c. - (main): Find the first non option entry and ignore subsequent options, - add handling for the new options, support multiple disks. - - * util/grub-probe.c (probe): Add mdraid to abstraction_name. - -2008-08-23 Bean - - * normal/x86_64/setjmp.S (grub_longjmp): Return 1 when val = 0. - - * genfslist.sh: Ignore kernel.mod. - - * genpartmaplist.sh: Likewise. - -2008-08-23 Robert Millan - - * util/getroot.c (find_root_device): Skip anything that starts with - a dot, not just directories. This avoids things like /dev/.tmp.md0. - -2008-08-22 Felix Zielcke - - * util/update-grub.in (GRUB_GFXMODE): Export variable. - * util/grub.d/00_header.in: Allow the administrator to change default - gfxmode via ${GRUB_GFXMODE}. - -2008-08-21 Felix Zielcke - - * fs/ntfs.c (grub_ntfs_mount): Fix a memory leak. - -2008-08-21 Robert Millan - - * loader/i386/linux.c: New file. Implements generic 32-bit Linux - loader. - * conf/i386-coreboot.rmk (_linux_mod_SOURCES): Replace - `loader/i386/pc/linux.c' with `loader/i386/linux.c'. - -2008-08-20 Carles Pina i Estany - - * menu/normal.c (run_menu): Replace hardcoded numbers with macros - (16 for GRUB_TERM_UP and 14 for GRUB_TERM_DOWN) - -2008-08-19 Robert Millan - - * term/gfxterm.c (DEFAULT_CURSOR_COLOR): Remove. - (struct grub_virtual_screen): Remove `cursor_color'. - (grub_virtual_screen_setup): Remove `virtual_screen.cursor_color' - initialization. - (write_cursor): Use `virtual_screen.fg_color' to draw cursor. - -2008-08-18 Robert Millan - - Unify (identical) linux_normal.c files. - * loader/i386/efi/linux_normal.c: Move from here ... - * loader/linux_normal.c: ... to here. Update all users. - * loader/i386/pc/linux_normal.c: Delete. Update all users. - * loader/i386/ieee1275/linux_normal.c: Likewise. - -2008-08-18 Robert Millan - - * include/grub/i386/linux.h (LINUX_LOADER_ID_LILO) - (LINUX_LOADER_ID_LOADLIN, LINUX_LOADER_ID_BOOTSECT) - (LINUX_LOADER_ID_SYSLINUX, LINUX_LOADER_ID_ETHERBOOT) - (LINUX_LOADER_ID_ELILO, LINUX_LOADER_ID_GRUB, LINUX_LOADER_ID_UBOOT) - (LINUX_LOADER_ID_XEN, LINUX_LOADER_ID_GUJIN, LINUX_LOADER_ID_QEMU): - New macros. - (GRUB_LINUX_CL_OFFSET, GRUB_LINUX_CL_END_OFFSET): Move from here ... - * loader/i386/pc/linux.c (GRUB_LINUX_CL_OFFSET) - (GRUB_LINUX_CL_END_OFFSET): ... to here. - * loader/i386/efi/linux.c (GRUB_EFI_CL_OFFSET): Rename to ... - (GRUB_LINUX_CL_OFFSET): ... this. Update all users. - (GRUB_EFI_CL_END_OFFSET): Rename to ... - (GRUB_LINUX_CL_END_OFFSET): ... this. Update all users. - (grub_rescue_cmd_linux): Macroify `type_of_loader' initialization. - Initialize `params->video_cursor_x' and `params->video_cursor_y' - portably using grub_getxy(). - Replace `-EFI' with `-bzImage' in boot message. - -2008-08-17 Robert Millan - - * include/grub/x86_64/kernel.h: New file ( stub). - -2008-08-17 Robert Millan - - * conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pc/mmap.c'. - - * include/grub/i386/pc/init.h (GRUB_MACHINE_MEMORY_AVAILABLE) - (GRUB_MACHINE_MEMORY_RESERVED): New macros. - (grub_machine_mmap_iterate): New function declaration. - * include/grub/multiboot.h (struct grub_multiboot_mmap_entry): New - structure. - (GRUB_MMAP_MEMORY_AVAILABLE, GRUB_MMAP_MEMORY_RESERVED): New - macros. - - * kern/i386/pc/init.c (grub_machine_init): Replace hardcoded region - type check value with `GRUB_MACHINE_MEMORY_AVAILABLE'. - Move e820 parsing from here ... - * kern/i386/pc/mmap.c: New file. - (grub_machine_mmap_iterate): ... to here. - - * include/grub/i386/coreboot/memory.h: Remove `'. - (GRUB_LINUXBIOS_MEMORY_AVAILABLE): Rename (for consistency) to ... - (GRUB_MACHINE_MEMORY_AVAILABLE): ... this. Update all users. - (grub_available_iterate): Redeclare to return `void', and redeclare - its hook to use grub_uint64_t as addr and size parameters, and rename - to ... - (grub_machine_mmap_iterate): ... this. Update all users. - - * kern/i386/coreboot/mmap.c (grub_mmap_iterate): Simplify parser loop - to make it more readable. Rename to ... - (grub_machine_mmap_iterate): ... this. - - * loader/i386/pc/multiboot.c (mmap_addr, mmap_length): New variables. - (grub_get_multiboot_mmap_len, grub_fill_multiboot_mmap): New functions. - (grub_multiboot): Allocate an extra region after the payload, and fill - it with a Multiboot memory map. Adjust a.out loader to calculate size - with the extra space. - (grub_multiboot_load_elf32): Adjust elf32 loader to calculate size - with the extra space. - -2008-08-17 Carles Pina i Estany - - * menu/normal.c (run_menu): Add Home and End keys in grub-menu. - -2008-08-17 Felix Zielcke - - * gendistlist.sh: Add *.y, *.tex, *.texi, grub.cfg, README, *.sc, - mdate-sh to the list `find' searches for. - * DISTLIST: Regenerated. - -2008-08-16 Felix Zielcke - - * gendistlist.sh (EXTRA_DISTFILES): Remove gensymlist.sh, - genkernsyms.sh. Add geninit.sh, geninitheader.sh, genkernsyms.sh.in, - genmoddep.awk, gensymlist.sh.in. - (DISTDIRS): Add bus, docs, hook, lib. - * DISTLIST: Regenerated. - * NEWS: Add cygwin support and change the `os-prober' entry a bit. - -2008-08-16 Robert Millan - - * disk/raid.c (grub_raid_init): Handle/report errors set by - grub_device_iterate(). - * disk/lvm.c (grub_lvm_init): Likewise. - -2008-08-15 Bean - - * conf/i386-pc.rmk (pkglib_MODULES): Add datetime.mod, date.mod - and datehook.mod. - (datetime_mod_SOURCES): New macro. - (datetime_mod_CFLAGS): Likewise. - (datetime_mod_LDFLAGS): Likewise. - (date_mod_SOURCES): Likewise. - (date_mod_CFLAGS): Likewise. - (date_mod_LDFLAGS): Likewise. - (datehook_mod_SOURCES): Likewise. - (datehook_mod_CFLAGS): Likewise. - (datehook_mod_LDFLAGS): Likewise. - - * conf/i386-coreboot.rmk (pkglib_MODULES): Add datetime.mod, date.mod - and datehook.mod. - (datetime_mod_SOURCES): New macro. - (datetime_mod_CFLAGS): Likewise. - (datetime_mod_LDFLAGS): Likewise. - (date_mod_SOURCES): Likewise. - (date_mod_CFLAGS): Likewise. - (date_mod_LDFLAGS): Likewise. - (datehook_mod_SOURCES): Likewise. - (datehook_mod_CFLAGS): Likewise. - (datehook_mod_LDFLAGS): Likewise. - - * conf/i386-ieee1275.rmk (pkglib_MODULES): Add datetime.mod, date.mod - and datehook.mod. - (datetime_mod_SOURCES): New macro. - (datetime_mod_CFLAGS): Likewise. - (datetime_mod_LDFLAGS): Likewise. - (date_mod_SOURCES): Likewise. - (date_mod_CFLAGS): Likewise. - (date_mod_LDFLAGS): Likewise. - (datehook_mod_SOURCES): Likewise. - (datehook_mod_CFLAGS): Likewise. - (datehook_mod_LDFLAGS): Likewise. - - * conf/i386-efi.rmk (pkglib_MODULES): Add datetime.mod, date.mod - and datehook.mod. - (datetime_mod_SOURCES): New macro. - (datetime_mod_CFLAGS): Likewise. - (datetime_mod_LDFLAGS): Likewise. - (date_mod_SOURCES): Likewise. - (date_mod_CFLAGS): Likewise. - (date_mod_LDFLAGS): Likewise. - (datehook_mod_SOURCES): Likewise. - (datehook_mod_CFLAGS): Likewise. - (datehook_mod_LDFLAGS): Likewise. - - * conf/x86_64-efi.rmk (pkglib_MODULES): Add datetime.mod, date.mod - and datehook.mod. - (datetime_mod_SOURCES): New macro. - (datetime_mod_CFLAGS): Likewise. - (datetime_mod_LDFLAGS): Likewise. - (date_mod_SOURCES): Likewise. - (date_mod_CFLAGS): Likewise. - (date_mod_LDFLAGS): Likewise. - (datehook_mod_SOURCES): Likewise. - (datehook_mod_CFLAGS): Likewise. - (datehook_mod_LDFLAGS): Likewise. - - * kern/env.c (grub_env_insert): Fix a bug in prevp pointer. - - * commands/date.c: New file. - - * hook/datehook.c: Likewise. - - * include/grub/lib/datetime.h: Likewise. - - * include/grub/i386/cmos.h: Likewise. - - * lib/datetime.c: Likewise. - - * lib/i386/datetime.c: Likewise. - - * lib/efi/datetime.c: Likewise. - -2008-08-14 Robert Millan - - * conf/common.rmk (bin_UTILITIES): Add `grub-mkelfimage'. - (grub_mkelfimage_SOURCES): New variable. - (util/elf/grub-mkimage.c_DEPENDENCIES): Likewise. - - * conf/i386-coreboot.rmk (bin_UTILITIES, grub_mkimage_SOURCES) - (grub_mkimage_LDFLAGS, util/elf/grub-mkimage.c_DEPENDENCIES): Remove. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - - * kern/ieee1275/init.c: Include `'. - * kern/i386/coreboot/init.c: Likewise. - - * kern/i386/ieee1275/startup.S: Replace `' - with `'. - (GRUB_KERNEL_MACHINE_PREFIX, GRUB_KERNEL_MACHINE_DATA_END): Renamed - to ... - (GRUB_KERNEL_CPU_PREFIX, GRUB_KERNEL_CPU_DATA_END): ... this. - * kern/i386/coreboot/startup.S: Likewise. - - * include/grub/powerpc/ieee1275/kernel.h (GRUB_MOD_ALIGN) - (GRUB_MOD_GAP): Remove. - * include/grub/powerpc/kernel.h: New file. - * include/grub/i386/ieee1275/kernel.h (GRUB_KERNEL_MACHINE_PREFIX) - (GRUB_KERNEL_MACHINE_DATA_END): Remove. - * include/grub/i386/kernel.h: New file. - * include/grub/i386/coreboot/kernel.h (GRUB_MOD_ALIGN) - (GRUB_MOD_GAP, GRUB_KERNEL_MACHINE_PREFIX) - (GRUB_KERNEL_MACHINE_DATA_END): Remove. - - * util/ieee1275/grub-install.in (grub_mkimage): Initialize to use - `grub-mkelfimage'. - Use --directory when invoking grub_mkimage. - - * util/elf/grub-mkimage.c: Include `'. - (add_segments): Replace GRUB_KERNEL_MACHINE_DATA_END and - GRUB_KERNEL_MACHINE_PREFIX with GRUB_KERNEL_CPU_DATA_END - and GRUB_KERNEL_CPU_PREFIX. - -2008-08-14 Felix Zielcke - - * include/grub/err.h (grub_err_printf): New function prototype. - * util/misc.c (grub_err_printf): New function. - * kern/misc.c [! GRUB_UTIL] (grub_err_printf): New alias for - grub_printf. - * kern/err.c (grub_print_error): Use grub_err_printf. - -2008-08-13 Robert Millan - - * docs/grub.cfg: Remove `/dev/' prefix in GNU/Hurd boot entry. - -2008-08-13 Robert Millan - - * docs/grub.cfg: Use the native device name for the example GNU/Hurd - boot entry. - -2008-08-12 Robert Millan - - * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Move part - of the relocation code from here ... - (grub_multiboot): ... to here. - (forward_relocator, backward_relocator): Move from here ... - * kern/i386/loader.S (grub_multiboot_forward_relocator) - (grub_multiboot_backward_relocator): ... to here. - (grub_multiboot_real_boot): Use %edx for entry offset. Put Multiboot - magic in %eax. Use %ebp for jumping (so %edx is not trashed). - * include/grub/i386/loader.h (grub_multiboot_forward_relocator) - (grub_multiboot_forward_relocator_end) - (grub_multiboot_backward_relocator) - (grub_multiboot_backward_relocator_end): New variables. - -2008-08-12 Bean - - * disk/raid.c (grub_raid_read): Fix a bug in raid0 code. - -2008-08-11 Robert Millan - - * kern/i386/linuxbios/startup.S: Move from here ... - * kern/i386/coreboot/startup.S: ... to here. - - * kern/i386/linuxbios/init.c: Move from here ... - * kern/i386/coreboot/init.c: ... to here. - - * kern/i386/linuxbios/table.c: Move from here ... - * kern/i386/coreboot/mmap.c: ... to here. - - * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Update moved files. - -2008-08-11 Robert Millan - - * kern/device.c (grub_device_open): Do not handle grub_disk_open() - errors. Leave it to the upper layer to handle them. - -2008-08-09 Christian Franke - - * Makefile.in: Add `target_os' and `enable_grub_pe2elf'. - * conf/common.rmk: Install `grub-pe2elf' only if requested. - Install `grub.d/10_windows' only on Cygwin. - * configure.ac: Add subst of `target_os'. - Check `target_os' also before setting TARGET_OBJ2ELF. - Add `--enable-grub-pe2elf'. - -2008-08-08 Robert Millan - - * kern/disk.c: Replace `' with `'. - (grub_last_time): Change type to grub_uint64_t. - (grub_disk_open): Migrate code from to using grub_get_time_ms(). - (grub_disk_close): Likewise. - - * normal/menu.c: Replace `' with `'. - (run_menu): Migrate code from to using grub_get_time_ms(). - - * util/misc.c (grub_get_time_ms): New function. - -2008-08-08 Marco Gerards - - * disk/ata.c (grub_ata_regget): Change return type to - `grub_uint8_t'. - (grub_ata_regget2): Likewise. - (grub_ata_wait_status): New function. - (grub_ata_wait_busy): Removed function, updated all users to use - `grub_ata_wait_status'. - (grub_ata_wait_drq): Likewise. - (grub_ata_cmd): New function. - (grub_ata_pio_read): Change return type to `grub_uint8_t'. Add - error handling. - (grub_ata_pio_write): Add error handling. - (grub_atapi_identify): Likewise. - (grub_atapi_packet): Use `grub_ata_cmd' and improve error - handling. - (grub_ata_identify): Use `grub_ata_cmd' and improve error - handling. Actually use the detected registers. Reorder the - detection logic such that it is easier to read. - (grub_ata_pciinit): Do not assign the same ID to each controller. - (grub_ata_setaddress): Use `grub_ata_cmd' and improve error - handling. - (grub_atapi_readsector): Check the result of `grub_ata_pio_read'. - - * include/grub/err.h (grub_err_t): Add `GRUB_ERR_TIMEOUT'. - -2008-08-08 Marco Gerards - - * NEWS: Update. - -2008-08-07 Bean - - * include/grub/x86_64/pci.h: New file. - -2008-08-07 Christian Franke - - * kern/i386/pit.c (TIMER2_SPEAKER): New define. - (TIMER2_GATE): Likewise. - (grub_pit_wait): Add enable/disable of the timer2 gate - bit of port 0x61. This fixes a possible infinite loop. - -2008-08-07 Bean - - * conf/x86_64-efi.rmk (kernel_mod_SOURCES): Add kern/time.c, - kern/i386/tsc.c and kern/i386/pit.c. - - * include/grub/i386/tsc.h (grub_cpu_is_cpuid_supported): Handle - x86_64 platform. - - * kern/i386/efi/init.c: Replace with - . - - * kern/i386/pit.c: Replace with . - -2008-08-07 Bean - - * conf/i386-efi.rmk (kernel_mod_SOURCES): Add kern/time.c. - - * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Add kern/time.c, - - * include/grub/i386/pit.h: Use macro KERNEL_CPU_PIT_HEADER to avoid - multiple inclusion. Add #include . - -2008-08-06 Christian Franke - - * conf/common.rmk: Build and install `10_windows'. - * util/grub.d/10_windows.in: New script. - -2008-08-06 Pavel Roskin - - * kern/i386/pit.c: Include `'. - -2008-08-06 Robert Millan - - * conf/i386-coreboot.rmk (kernel_elf_ASFLAGS): New variable. - * kern/i386/tsc.c: Include `'. - -2008-08-06 Bean - - * fs/i386/pc/pxe.c (grub_pxe_data): New member block_size. - (grub_pxefs_fs_int): Remove dummy definition. - (grub_pxefs_open): Use data->block_size to store the current block - size setting. - (grub_pxefs_read): Use block size stored in data->block_size. As the - value of grub_pxe_blksize can be changed after the file is opened. - -2008-08-06 Bean - - * fs/i386/pc/pxe.c (curr_file): new variable. - (grub_pxefs_open): Simply the handling of pxe file system. Don't - require the dummy internal file system anymore. - (grub_pxefs_read): Removed. - (grub_pxefs_close): Likewise. - (grub_pxefs_fs_int): Likewise. - (grub_pxefs_read_int): Renamed to grub_pxefs_read. Reinitialize tftp - connection when we switch file. - (grub_pxefs_close_int): Renamed to grub_pxefs_close. - -2008-08-06 Robert Millan - - * conf/i386-coreboot.rmk (pkglib_MODULES): Add `reboot.mod' and - `halt.mod'. - (reboot_mod_SOURCES, reboot_mod_CFLAGS, reboot_mod_LDFLAGS) - (halt_mod_SOURCES, halt_mod_CFLAGS, halt_mod_LDFLAGS): New variables. - - * kern/i386/halt.c: New file. - * kern/i386/reboot.c: Likewise. - * include/grub/i386/reboot.h: Likewise. - * include/grub/i386/halt.h: Likewise. - - * commands/halt.c [! GRUB_MACHINE_IEEE1275 ! GRUB_MACHINE_EFI]: - Include `'. - * commands/reboot.c [! GRUB_MACHINE_IEEE1275 ! GRUB_MACHINE_EFI] - [! GRUB_MACHINE_PCBIOS]: Include `'. - - * term/i386/pc/at_keyboard.c: Include `'. - (SHIFT_L, SHIFT_R, CTRL, ALT, CAPS_LOCK, KEYBOARD_REG_DATA) - (KEYBOARD_REG_STATUS, KEYBOARD_COMMAND_ISREADY, KEYBOARD_COMMAND_READ) - (KEYBOARD_COMMAND_WRITE, KEYBOARD_COMMAND_REBOOT) - (KEYBOARD_SCANCODE_SET1, KEYBOARD_ISMAKE, KEYBOARD_ISREADY) - (KEYBOARD_SCANCODE, OLPC_UP, OLPC_DOWN, OLPC_LEFT, OLPC_RIGHT): Move - from here ... - * include/grub/i386/at_keyboard.h: ... to here. - -2008-08-05 Robert Millan - - * conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/i386/pit.c'. - * conf/i386-efi.rmk (kernel_mod_SOURCES): Likewise. - * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Likewise. Also add - `kern/i386/tsc.c', `kern/generic/rtc_get_time_ms.c' and - `kern/generic/millisleep.c'. - - * kern/i386/tsc.c (calibrate_tsc): Rewrite using grub_pit_wait() - instead of grub_get_rtc(). - (grub_tsc_init): Initialize `tsc_boot_time'. - - * kern/i386/linuxbios/init.c (grub_millisleep): Remove stub. - (grub_machine_init): Use grub_tsc_init() rather than - installing an RTC-based handler via grub_install_get_time_ms(). - - * kern/i386/pit.c: New file. - * include/grub/i386/pit.h: Likewise. - -2008-08-05 Bean - - * boot/i386/pc/pxeboot.S (_start): Use drive number 0x7F for pxe. - - * conf/i386-pc.rmk (kernel_img_HEADERS): Add machine/pxe.h. - (pkglib_MODULES): Add pxe.mod and pxecmd.mod. - (pxe_mod_SOURCES): New macro. - (pxe_mod_CFLAGS): Likewise. - (pxe_mod_LDFLAGS): Likewise. - (pxecmd_mod_SOURCES): Likewise. - (pxecmd_mod_CFLAGS): Likewise. - (pxecmd_mod_LDFLAGS): Likewise. - - * kern/i386/pc/startup.S (grub_pxe_scan): New function. - (grub_pxe_call): Likewise. - - * include/grub/disk.h (grub_disk_dev_id): Add GRUB_DISK_DEVICE_PXE_ID. - - * commands/i386/pc/pxecmd.c: New file. - - * fs/i386/pc/pxe.c: Likewise. - - * include/grub/i386/pc/pxe.h: Likewise. - -2008-08-05 Bean - - * util/console.c (grub_console_cur_color): New variable. - (grub_console_standard_color): Likewise. - (grub_console_normal_color): Likewise. - (grub_console_highlight_color): Likewise. - (color_map): Likewise. - (use_color): Likewise. - (NUM_COLORS): New macro. - (grub_ncurses_setcolorstate): Handle color properly. - (grub_ncurses_setcolor): Don't change color here, just remember the - settings, color will be set in grub_ncurses_setcolorstate. - (grub_ncurses_getcolor): New function. - (grub_ncurses_init): Initialize color pairs. - (grub_ncurses_term): New member grub_ncurses_getcolor. - -2008-08-05 Colin D Bennett - - High resolution timer support. Implemented for x86 CPUs using TSC. - Extracted generic grub_millisleep() so it's linked in only as needed. - This requires a Pentium compatible CPU; if the RDTSC instruction is - not supported, then it falls back on the generic grub_get_time_ms() - implementation that uses the machine's RTC. - - * conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/time.c', - `kern/i386/tsc.c', `kern/generic/rtc_get_time_ms.c' and - `kern/generic/millisleep.c'. - - * conf/i386-efi.rmk (kernel_mod_SOURCES): Add `kern/i386/tsc.c', - `kern/generic/rtc_get_time_ms.c' and `kern/generic/millisleep.c'. - - * conf/x86_64-efi.rml (kernel_mod_SOURCES): Add - `kern/generic/millisleep.c' and `kern/generic/rtc_get_time_ms.c'. - - * conf/sparc64-ieee1275.rmk (kernel_elf_SOURCES): Likewise. - - * conf/powerpc-ieee1275.rmk (kernel_elf_SOURCES): Add - `kern/generic/millisleep.c'. - - * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Likewise. - - * conf/i386-coreboot.rmk (kernel_elf_SOURCES): Add `kern/time.c'. - - * kern/generic/rtc_get_time_ms.c: New file. - - * kern/generic/millisleep.c: New file. - - * kern/misc.c: Don't include - anymore. - (grub_millisleep_generic): Removed. - - * commands/sleep.c (grub_interruptible_millisleep): Uses - grub_get_time_ms() instead of grub_get_rtc(). - - * include/grub/i386/tsc.h (grub_get_tsc): New file. New inline - function. - (grub_cpu_is_cpuid_supported): New inline function. - (grub_cpu_is_tsc_supported): New inline function. - (grub_tsc_init): New function prototype. - (grub_tsc_get_time_ms): New function prototype. - - * kern/i386/tsc.c (grub_get_time_ms): New file. - - * include/grub/time.h: Include . Don't include - anymore. - (grub_millisleep): Removed. - (grub_machine_init): Call grub_tsc_init. - - * kern/i386/linuxbios/init.c (grub_machine_init): Install the RTC - get_time_ms() implementation. - - * kern/sparc64/ieee1275/init.c (grub_millisleep): Removed. - (ieee1275_get_time_ms): New function. - (grub_machine_init): Install get_time_ms() implementation. - - * kern/i386/pc/init.c: Include . - (grub_machine_init): Call grub_tsc_init(). - (grub_millisleep): Removed. - - * kern/ieee1275/init.c (grub_millisleep): Removed. - (grub_machine_init): Install ieee1275_get_time_ms() - implementation. - (ieee1275_get_time_ms): New function. - (grub_get_rtc): Now calls ieee1275_get_time_ms(), which does the - real work. - -2008-08-05 Marco Gerards - - * disk/ata.c: Include . - (enum grub_ata_commands): Add `GRUB_ATA_CMD_EXEC_DEV_DIAGNOSTICS'. - (grub_ata_initialize): Rewritten. - (grub_ata_device_initialize): New function. - -2008-08-04 Pavel Roskin - - * kern/main.c: Include grub/mm.h. - -2008-08-04 Robert Millan - - * conf/i386-coreboot.rmk (COMMON_ASFLAGS, COMMON_CFLAGS) - (COMMON_LDFLAGS): Harmonize with i386-pc version (fixes a code - corruption problem). - -2008-08-04 Robert Millan - - * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Fix misc - warnings introduced in my last commit. - -2008-08-03 Robert Millan - - Make PCI available on all i386 architectures. - - * include/grub/i386/pc/pci.h: Move from here ... - * include/grub/i386/pci.h: ... to here. - - * include/grub/i386/pc/pci.h: Remove. - * include/grub/i386/efi/pci.h: Remove. - * include/grub/x86_64/efi/pci.h: Remove. - - * include/grub/pci.h: Replace `' with - `'. - - * conf/i386-coreboot.rmk (pkglib_MODULES): Add `pci' and `lspci'. - (pci_mod_SOURCES, pci_mod_CFLAGS, pci_mod_LDFLAGS, lspci_mod_SOURCES) - (lspci_mod_CFLAGS, lspci_mod_LDFLAGS): New variables. - - * conf/i386-ieee1275.rmk: Likewise. - -2008-08-03 Robert Millan - - * term/i386/pc/vga_text.c (CRTC_CURSOR_DISABLE): New macro. - (grub_console_setcursor): Make it possible to set cursor off. - -2008-08-03 Robert Millan - - * util/grub.d/00_header.in: Be platform-agnostic. Probe for existence - of modules instead of assuming which platform provides what. - * util/update-grub.in: Likewise. - -2008-08-03 Robert Millan - - * kern/i386/pc/init.c (make_install_device): Check for `grub_prefix' - instead of `grub_install_dos_part' to determine whether a drive needs - to be prepended to prefix (`grub_install_dos_part' is not reliable, - because it can be overridden when loading GRUB via Multiboot). - -2008-08-02 Robert Millan - - * util/i386/pc/grub-install.in: Remove trailing slash from prefix. - -2008-08-02 Robert Millan - - * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Add a pair - of informational grub_dprintf() calls. - -2008-08-02 Robert Millan - - * disk/memdisk.c (memdisk_size): Don't initialize. - (GRUB_MOD_INIT(memdisk)): Find memdisk using grub_module_iterate(). - - * include/grub/i386/pc/kernel.h - (GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE): Remove macro. - (GRUB_KERNEL_MACHINE_PREFIX, GRUB_KERNEL_MACHINE_DATA_END): Shift. - (grub_memdisk_image_size, grub_arch_memdisk_addr) - (grub_arch_memdisk_size): Remove. - - * include/grub/kernel.h (struct grub_module_header): Remove `offset' - field (was only used to transfer a constant). Add `type' field to - support multiple module types. - (grub_module_iterate): New function. - - * kern/device.c (grub_device_open): Do not hide error messages - when grub_disk_open() fails. Use grub_print_error() instead. - - * kern/i386/pc/init.c (grub_arch_modules_addr) - (grub_arch_memdisk_size): Remove functions. - (grub_arch_modules_addr): Return the module address in high memory - (now that it isn't copied anymore). - - * kern/i386/pc/startup.S (grub_memdisk_image_size): Remove variable. - (codestart): Don't add grub_memdisk_image_size to %ecx in LZMA - decompression routine (grub_total_module_size already includes that - now). Don't copy modules back to low memory. - - * kern/main.c: Include `'. - (grub_load_modules): Split out (and use) ... - (grub_module_iterate): ... this function, which iterates through - module objects and runs a hook. - Comment out grub_mm_init_region() call, as it would cause non-ELF - modules to be overwritten. - - * util/i386/pc/grub-mkimage.c (generate_image): Instead of appending - the memdisk image in its own region, make it part of the module list. - * util/elf/grub-mkimage.c (options): Add "memdisk"|'m' option. - (main): Parse --memdisk|-m option, and pass user-provided path as - parameter to generate_image(). - (add_segments): Pass `memdisk_path' down to load_modules(). - (load_modules): Embed memdisk image in module section when requested. - * util/i386/efi/grub-mkimage.c (make_mods_section): Initialize - `header.type' instead of `header.offset'. - - * conf/powerpc-ieee1275.rmk (pkglib_MODULES): Add `memdisk.mod'. - (memdisk_mod_SOURCES, memdisk_mod_CFLAGS) - (memdisk_mod_LDFLAGS): New variables. - * conf/i386-coreboot.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - -2008-08-02 Robert Millan - - * loader/i386/pc/multiboot.c (playground, forward_relocator) - (backward_relocator): New variables. Used to allocate and relocate - the payload, respectively. - (grub_multiboot_load_elf32): Load into heap instead of requested - address, install the appropriate relocator code in each bound of - the payload, and set the entry point such that - grub_multiboot_real_boot() will jump to one of them. - - * kern/i386/loader.S (grub_multiboot_payload_size) - (grub_multiboot_payload_orig, grub_multiboot_payload_dest) - (grub_multiboot_payload_entry_offset): New variables. - (grub_multiboot_real_boot): Set cpu context to what the relocator - expects, and jump to the relocator instead of the payload. - - * include/grub/i386/loader.h (grub_multiboot_payload_size) - (grub_multiboot_payload_orig, grub_multiboot_payload_dest) - (grub_multiboot_payload_entry_offset): Export. - -2008-08-01 Bean - - * normal/menu_entry.c (editor_getline): Don't return the original - string as result, as it will be released by lexer once it has done - using it. - -2008-08-01 Robert Millan - - * util/grub.d/10_linux.in: Use prepare_grub_to_access_device() from - within menuentries, not before them. - util/grub.d/10_hurd.in: Likewise. - -2008-08-01 Bean - - * conf/common.rmk (pkglib_MODULES): Add bufio.mod. - (bufio_mod_SOURCES): New macro. - (bufio_mod_CFLAGS): Likewise. - (bufio_mod_LDFLAGS): Likewise. - - * include/grub/bufio.h: New file. - - * io/bufio.c: Likewise. - - * video/png.c: Replace with . - (grub_video_reader_png): Use grub_buffile_open to open file. - - * video/jpeg.c: Replace with . - (grub_video_reader_jpeg): Use grub_buffile_open to open file. - - * video/tga.c: Replace with . - (grub_video_reader_tga): Use grub_buffile_open to open file. - - * font/manager.c: Include . - (add_font): Use grub_buffile_open to open file. - -2008-07-31 Robert Millan - - * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): When loading - ELF segments, use a macro for arbitrarily accessing any of them instead - of preparing a pointer that allows access to one at a time. - (grub_multiboot_load_elf64): Likewise. - -2008-07-31 Bean - - * boot/i386/pc/lnxboot.S (real_code_2): Replace 0x50 with - GRUB_KERNEL_MACHINE_DATA_END. - -2008-07-30 Robert Millan - - * include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_DATA_END): - Increase from 0x50 to 0x60. - * util/i386/pc/grub-install.in: Detect cross-disk installs, and - use UUIDs to identify the root drive for them. If that's not - possible, abort. - * util/i386/pc/grub-setup.c (setup): Do not special-case, or even - check, for cross-disk installs. - -2008-07-30 Robert Millan - - * kern/ieee1275/init.c (grub_machine_set_prefix): If `grub_prefix' - is non-empty, use it to set the `prefix' environment variable instead - of the usual approach. - * kern/i386/linuxbios/init.c (make_install_device): Remove function. - (grub_machine_set_prefix): Use `grub_prefix' to set the `prefix' - environment variable instead of dummy make_install_device(). - - * kern/i386/ieee1275/startup.S: Include `'. - (start): Insert a data section, with `grub_prefix' variable. - * kern/i386/linuxbios/startup.S: Likewise. - - * include/grub/powerpc/ieee1275/kernel.h [!ASM_FILE] (grub_prefix): - New variable reference. - * include/grub/i386/ieee1275/kernel.h (GRUB_KERNEL_MACHINE_PREFIX): - New macro. Defines offset of `grub_prefix' within startup.S (relative - to `start'). - (GRUB_KERNEL_MACHINE_DATA_END): New macro. Defines the end of data - section within startup.S (relative to `start'). - * include/grub/i386/coreboot/kernel.h: Likewise. - - * util/elf/grub-mkimage.c (add_segments): Receive `prefix' parameter. - Overwrite grub_prefix with its contents, at the beginning of the - first segment. - (main): Understand -p|--prefix. - -2008-07-30 Robert Millan - - * util/grub.d/10_hurd.in: Source ${libdir}/grub/update-grub_lib. - -2008-07-30 Robert Millan - - * term/i386/pc/vga_text.c (grub_console_cls): Use - grub_console_gotoxy() to go back to beginning of the screen. - Found by Patrick Georgi - -2008-07-29 Christian Franke - - * util/update-grub_lib.in (make_system_path_relative_to_its_root): - Add conversion of emulated mount points on Cygwin. - -2008-07-29 Christian Franke - - * util/update-grub.in: Add a check for admin - group on Cygwin. - Remove old `grub.cfg.new' before creation. - Add `-f' to `mv' to handle the different filesystem - semantics of Windows. - -2008-07-29 Bean - - * normal/main.c (get_line): Fix buffer overflow bug. - -2008-07-28 Robert Millan - - * partmap/apple.c (GRUB_APPLE_HEADER_MAGIC): New macro. - (struct grub_apple_header): New struct. Describes the layout of - the partmap header. - (apple_partition_map_iterate): Check the header magic as well as the - partition magic (which was already being checked). - -2008-07-28 Pavel Roskin - - * genmk.rb: Add a warning to the beginning of the output that - it's a generated file and should not be edited. - -2008-07-28 Robert Millan - - * disk/raid.c (grub_raid_scan_device): Do not abort when two disks - with the same number are found, just use issue a warning with - grub_dprintf(), as this error has been reported to be non-fatal. - -2008-07-27 Robert Millan - - * disk/ata.c (grub_ata_dumpinfo): Use grub_dprintf() for debugging - information. - -2008-07-27 Bean - - * fs/fat.c (GRUB_FAT_MAXFILE): New constant. - (grub_fat_find_dir): Ignore case when comparing filename. - -2008-07-27 Bean - - * fs/xfs.c (grub_xfs_dir_header): Change field i8count back to - smallino, as it's more descriptive, and i8count can be confused with - the other field count. - (grub_xfs_iterate_dir): Adjust grub_xfs_dir_entry pointer for small - inode type. - -2008-07-27 Bean - - * commands/crc.c: New file. - - * lib/crc.c: Likewise. - - * include/grub/lib/crc.h: Likewise. - - * util/grub-fstest.c: grub/hexdump.h => grub/lib/hexdump.h. - - * commands/hexdump.c: grub/hexdump.h => grub/lib/hexdump.h. - (hexdump): Move this function to ... - - * lib/hexdump.c: ... here. - - * include/grub/hexdump.h: Renamed to ... - - * include/grub/lib/hexdump.h: ... this. - - * commands/loadenv.c: grub/envblk.h => grub/lib/envblk.h - - * util/grub-editenv.c: Likewise. - - * include/envblk.h: Renamed to ... - - * include/lib/envblk.h: ... this. - - * util/envblk.c: Renamed to ... - - * lib/envblk.c: ... this. - - * conf/common.rmk (grub_fstest_SOURCES): commands/hexdump.c => - lib/hexdump.c. - (grub_editenv_SOURCES): util/envblk.c => lib/envblk.c - (pkglib_MODULES): Add crc.mod. - (hexdump_mod_SOURCES): Add lib/hexdump.c. - (loadenv_mod_SOURCES): util/envblk.c => lib/envblk.c. - (crc_mod_SOURCES): New macro. - (crc_mod_CFLAGS): Likewise. - (crc_mod_LDFLAGS): Likewise. - - * conf/i386-coreboot.rmk (grub_emu_SOURCES): Add lib/hexdump.c. - - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - - * conf/x86_64-efi.rmk (grub_emu_SOURCES): Likewise. - -2008-07-27 Felix Zielcke - - * commands/help.c: Include . - (TERM_WIDTH): Removed. Updated all users. - -2008-07-27 Pavel Roskin - - * util/getroot.c (find_root_device): Rephrase a comment to avoid - spurious warnings about a comment within a comment. - -2008-07-25 Robert Millan - - * util/getroot.c (find_root_device): Skip devices that match - /dev/dm-[0-9]. This lets the real device be found for any type of - abstraction (LVM, EVMS, RAID..). - (grub_guess_root_device): Do not traverse /dev/mapper (for LVM) - and /dev/evms (for EVMS) before traversing /dev. If a /dev/dm-[0-9] - device is found first, find_root_device() will now skip it. - -2008-07-24 Pavel Roskin - - * include/grub/types.h: Use __builtin_bswap32() and - __builtin_bswap64() with gcc 4.3 and newer. - -2008-07-24 Christian Franke - - * util/i386/pc/grub-install.in: If `--debug' is specified, - pass `--verbose' to grub-setup. - Abort script if make_system_path_relative_to_its_root() fails. - -2008-07-24 Bean - - * configure.ac: Fixed a bug caused by the previous cygwin patch, - variable `target_platform' should be `platform'. - -2008-07-24 Bean - - * video/reader/png.c (DEFLATE_HLIT_MAX): Change value. - (grub_png_init_fixed_block): New function. - (grub_png_decode_image_data): Handle fixed huffman code compression. - -2008-07-24 Bean - - * common.rmk (bin_UTILITIES): Add grub-pe2elf. - (grub_pe2elf_SOURCES): New macro. - (CLEANFILES): Add grub-pe2elf. - - * include/grub/efi/pe32.h (GRUB_PE32_SCN_ALIGN_1BYTES): New constant. - (GRUB_PE32_SCN_ALIGN_2BYTES): Likewise. - (GRUB_PE32_SCN_ALIGN_4BYTES): Likewise. - (GRUB_PE32_SCN_ALIGN_8BYTES): Likewise. - (GRUB_PE32_SCN_ALIGN_16BYTES): Likewise. - (GRUB_PE32_SCN_ALIGN_32BYTES): Likewise. - (GRUB_PE32_SCN_ALIGN_64BYTES): Likewise. - (GRUB_PE32_SCN_ALIGN_SHIFT): Likewise. - (GRUB_PE32_SCN_ALIGN_MASK): Likewise. - (GRUB_PE32_SYM_CLASS_EXTERNAL): Likewise. - (GRUB_PE32_SYM_CLASS_STATIC): Likewise. - (GRUB_PE32_SYM_CLASS_FILE): Likewise. - (GRUB_PE32_DT_FUNCTION): Likewise. - (GRUB_PE32_REL_I386_DIR32): Likewise. - (GRUB_PE32_REL_I386_REL32): Likewise. - (grub_pe32_symbol): New structure. - (grub_pe32_reloc): Likewise. - - * util/grub-pe2elf.c: New file. - - * configure.ac: Set TARGET_OBJ2ELF if host os is cygwin. Don't test for - start symbol in non pc platform. - - * genmk.rb: Use TARGET_OBJ2ELF to convert native object format to elf. - - The following patches are from Christian Franke. - - * include/grub/dl.h: Remove .previous, gas supports this only - for ELF format. - - * include/grub/symbol.h [__CYGWIN__] (#define FUNCTION/VARIABLE): - Remove .type, gas supports this only for ELF format. - - * kern/dl.c (grub_dl_resolve_dependencies): Add check for trailing - nullbytes in symbol table. This fixes an infinite loop if table is - zero filled. - - * Makefile.in: Add autoconf replacements TARGET_IMG_LDSCRIPT, - TARGET_IMG_LDFLAGS and EXEEXT. - - * aclocal.m4 (grub_PROG_OBJCOPY_ABSOLUTE): Replace -Wl,-N by - TARGET_IMG_LDFLAGS_AC. - (grub_CHECK_STACK_ARG_PROBE): New function. - - * conf/i386-pc.rmk: Replace -Wl,-N by TARGET_IMG_LDFLAGS. - - * conf/i386-pc-cygwin-ld-img.sc: New linker script. - - * configure.ac: Add check for linker script "conf/${target}-img-ld.c" - to set TARGET_IMG_LD* accordingly. - Add check for Cygwin to set TARGET_MOD_OBJCOPY accordingly. - Add call to grub_CHECK_STACK_ARG_PROBE. - Use TARGET_IMG_LDFLAGS to check start, bss_start, end symbols. - - * genkernsyms.sh.in: Handle HAVE_ASM_USCORE case. - - * genmk.rb: Add EXEEXT to CLEANFILES. - -2008-07-23 Robert Millan - - * Makefile.in (UNICODE_ARROWS, UNICODE_LINES): New variables (they - define the codes for arrows and lines used for the menu). - (ascii.pff): Generate fonts for $(UNICODE_ARROWS) and $(UNICODE_LINES) - as well. - - * util/update-grub_lib.in (font_path): Prefer ascii.pff over complete - fonts, because the latter are too slow. - -2008-07-21 Bean - - * kern/i386/pc/startup.S (gate_a20_try_bios): Change test order for - a20. Run keyboard test last, as it will cause macbook to halt. - -2008-07-18 Pavel Roskin - - * kern/dl.c: Go back to using GRUB_CPU_SIZEOF_VOID_P. We cannot - load foreign architecture modules correctly anyway. Keep - support for loading host architecture modules, whether we - compile them or not. - -2008-07-17 Pavel Roskin - - * configure.ac: Use -m32 or -m64 regardless of whether we had to - change target_cpu. The compiler default can mismatch target_cpu - in any case. - - * disk/efi/efidisk.c: Fix format warnings on x86_64. - * kern/efi/efi.c: Likewise. - - * aclocal.m4 (grub_PROG_TARGET_CC): New macro. Check if the - target compiler is functional. - * configure.ac: Call grub_PROG_TARGET_CC once all target flags - are set up. - - * configure.ac: Default to efi platform for x86_64-apple. Allow - powerpc64 CPU, default to ieee1275 platform for it. Split CPU - adjustments from the rest, only do them if target is not - explicitly given. Merge other adjustments with the final sanity - check. Remove an extraneous check for supported CPU. Be - specific which CPU and which platform is not supported. - - * configure.ac: Default to pc platform for x86_64. - -2008-07-17 Robert Millan - - Partial LinuxBIOS -> Coreboot rename. - - * conf/i386-linuxbios.rmk: Renamed to ... - * conf/i386-coreboot.rmk: ... this. - * Makefile.in (RMKFILES): s/i386-linuxbios.rmk/i386-coreboot.rmk/g. - * configure.ac: Accept "coreboot" as input platform (but maintain - compatibility with "linuxbios"). - * include/grub/i386/linuxbios: Renamed to ... - * include/grub/i386/coreboot: ... this. - -2008-07-17 Bean - - * conf/i386/efi.rmk (pkglib_MODULES): add pci.mod and lspci.mod. - (appleldr_mod_SOURCE): New variable. - (appleldr_mod_CFLAGS): Likewise. - (appleldr_mod_LDFLAGS): Likewise. - (pci_mod_SOURCES): Likewise. - (pci_mod_CFLAGS): Likewise. - (pci_mod_LDFLAGS): Likewise. - (lspci_mod_SOURCES): Likewise. - (lspci_mod_CFLAGS): Likewise. - (lspci_mod_LDFLAGS): Likewise. - - * conf/x86_64-efi.rmk: New file. - - * disk/efi/efidisk.c (grub_efidisk_read): Wrap efi calls with efi_call_N - macro. - (grub_efidisk_write): Likewise. - - * include/efi/api.h (efi_call_0): New macro. - (efi_call_1): Likewise. - (efi_call_2): Likewise. - (efi_call_3): Likewise. - (efi_call_4): Likewise. - (efi_call_5): Likewise. - (efi_call_6): Likewise. - - * include/grub/efi/chainloader.h (grub_chainloader_cmd): Rename to - grub_rescue_cmd_chainloader. - - * include/grub/efi/pe32.h (GRUB_PE32_MACHINE_X86_64): New macro. - (grub_pe32_optional_header): Change some fields based on i386 or - x86_64 platform. - (GRUB_PE32_PE32_MAGIC): Likewise. - - * include/grub/efi/uga_draw.h: New file. - - * include/grub/elf.h (STN_ABS): New constant. - (R_X86_64_NONE): Relocation constant for x86_64. - (R_X86_64_64): Likewise. - (R_X86_64_PC32): Likewise. - (R_X86_64_GOT32): Likewise. - (R_X86_64_PLT32): Likewise. - (R_X86_64_COPY): Likewise. - (R_X86_64_GLOB_DAT): Likewise. - (R_X86_64_JUMP_SLOT): Likewise. - (R_X86_64_RELATIVE): Likewise. - (R_X86_64_GOTPCREL): Likewise. - (R_X86_64_32): Likewise. - (R_X86_64_32S): Likewise. - (R_X86_64_16): Likewise. - (R_X86_64_PC16): Likewise. - (R_X86_64_8): Likewise. - (R_X86_64_PC8): Likewise. - - * include/grub/i386/efi/pci.h: New file. - - * include/grub/i386/linux.h (GRUB_LINUX_EFI_SIGNATURE): - Change it value based on platform. - (GRUB_LINUX_EFI_SIGNATURE_0204): New constant. - (GRUB_E820_RAM): Likewise. - (GRUB_E820_RESERVED): Likewise. - (GRUB_E820_ACPI): Likewise. - (GRUB_E820_NVS): Likewise. - (GRUB_E820_EXEC_CODE): Likewise. - (GRUB_E820_MAX_ENTRY): Likewise. - (grub_e820_mmap): New structure. - (linux_kernel_header): Change the efi field according to different - kernel version, also field from linux_kernel_header. - - * include/grub/kernel.h (grub_module_info): Add padding for x86_64. - - * include/grub/pci.h (GRUB_PCI_ADDR_SPACE_MASK): New constant. - (GRUB_PCI_ADDR_SPACE_MEMORY): Likewise. - (GRUB_PCI_ADDR_SPACE_IO): Likewise. - (GRUB_PCI_ADDR_MEM_TYPE_MASK): Likewise. - (GRUB_PCI_ADDR_MEM_TYPE_32): Likewise. - (GRUB_PCI_ADDR_MEM_TYPE_1M): Likewise. - (GRUB_PCI_ADDR_MEM_TYPE_64): Likewise. - (GRUB_PCI_ADDR_MEM_PREFETCH): Likewise. - (GRUB_PCI_ADDR_MEM_MASK): Likewise. - (GRUB_PCI_ADDR_IO_MASK): Likewise. - - * include/grub/x86_64/efi/kernel.h: New file. - - * include/grub/x86_64/efi/loader.h: Likewise. - - * include/grub/x86_64/efi/machine.h: Likewise. - - * include/grub/x86_64/efi/pci.h: Likewise. - - * include/grub/x86_64/efi/time.h: Likewise. - - * include/grub/x86_64/linux.h: Likewise. - - * include/grub/x86_64/setjmp.h: Likewise. - - * include/grub/x86_64/time.h: Likewise. - - * include/grub/x86_64/types.h: Likewise. - - * kern/dl.c (GRUB_CPU_SIZEOF_VOID_P): Changed to - GRUB_TARGET_SIZEOF_VOID_P. - - * kern/efi/efi.c (grub_efi_locate_protocol): Wrap efi calls. - (grub_efi_locate_handle): Likewise. - (grub_efi_open_protocol): Likewise. - (grub_efi_set_text_mode): Likewise. - (grub_efi_stall): Likewise. - (grub_exit): Likewise. - (grub_reboot): Likewise. - (grub_halt): Likewise. - (grub_efi_exit_boot_services): Likewise. - (grub_get_rtc): Likewise. - - * kern/efi/mm.c (MEMORY_MAP_SIZE): Change to 0x3000 for new models. - (GRUB_CPU_SIZEOF_VOID_P): Changed to GRUB_TARGET_SIZEOF_VOID_P. - (grub_efi_allocate_pages): Wrap efi calls. - (grub_efi_free_pages): Wrap efi calls. - (grub_efi_get_memory_map): Wrap efi calls. - - * kern/x86_64/dl.c: New file. - - * kern/x86_64/efi/callwrap.S: Likewise. - - * kern/x86_64/efi/startup.S: Likewise. - - * loader/efi/appleloader.c: Likewise. - - * loader/efi/chainloader.c (cmdline): New variable. - (grub_chainloader_unload): Wrap efi calls. - (grub_chainloader_boot): Likewise. - (grub_rescue_cmd_chainloader): Wrap efi calls, handle - command line. - - * loader/efi/chainloader_normal.c (chainloader_command): - Change grub_chainloader_cmd to grub_rescue_cmd_chainloader, pass - command line. - - * loader/i386/efi/linux.c (allocate_pages): Change allocation - method. - (grub_e820_add_region): New function. - (grub_linux_boot): Construct e820 map from efi map, handle x86_64 - booting. - (grub_find_video_card): New function. - (grub_linux_setup_video): New function. - (grub_rescue_cmd_linux): Probe for video information. - - * normal/x86_64/setjmp.S: New file. - - * term/efi/console.c (map_char): New function. - (grub_console_putchar): Map unicode char. - (grub_console_checkkey): Wrap efi calls. - (grub_console_getkey): Likewise. - (grub_console_getwh): Likewise. - (grub_console_gotoxy): Likewise. - (grub_console_cls): Likewise. - (grub_console_setcolorstate): Likewise. - (grub_console_setcursor): Likewise. - - * util/i386/efi/grub-mkimage.c: Add support for x86_64. - -2008-07-16 Pavel Roskin - - * loader/i386/efi/linux.c (allocate_pages): Fix warnings in - format strings. - - * util/i386/efi/grub-mkimage.c (get_target_address): Return a - pointer, not an integer. This fixes a warning and prevents - precision loss on 64-bit systems. - (relocate_addresses): Remove unneeded cast. - -2008-07-15 Pavel Roskin - - * kern/i386/ieee1275/init.c: Include grub/cache.h. - - * term/ieee1275/ofconsole.c: Disable code unused on i386. - - * kern/ieee1275/ieee1275.c (grub_ieee1275_get_integer_property): - Fix comparison between signed and unsigned. - - * include/grub/i386/ieee1275/console.h: Declare - grub_console_init() and grub_console_fini(). - - * loader/i386/ieee1275/linux.c (grub_set_bootpath): Remove. - It's empty and unused. - - * fs/ext2.c (grub_ext2_read_block): Initialize blknr in the - beginning to avoid warnings with some compilers. - - * loader/ieee1275/multiboot2.c: Include grub/machine/loader.h. - [__i386__] (grub_mb2_arch_boot): Avoid unnecessary cast. - -2008-07-14 Pavel Roskin - - * kern/env.c (grub_register_variable_hook): Don't copy empty - string, it leaks memory. Pass "" to grub_env_set(), it should - handle constant strings. - - * commands/blocklist.c (grub_cmd_blocklist): Fix format warning. - * commands/cmp.c (grub_cmd_cmp): Likewise. - * kern/dl.c (grub_dl_flush_cache): Likewise. - (grub_dl_load_core): Likewise. - * kern/elf.c (grub_elf32_load_phdrs): Likewise. - (grub_elf64_load_phdrs): Likewise. - -2008-07-13 Pavel Roskin - - * lib/LzmaEnc.c (LzmaEnc_SetProps): Fix warning about comparison - between signed and unsigned. - (LzmaEnc_Finish): Fix warning about an unused parameter. - -2008-07-13 Bean - - * Makefile.in (enable_lzo): New rule. - - * conf/i386-pc.rmk (grub_mkimage_SOURCES): New test with enable_lzo. - - * configure.ac (ENABLE_LZO): New option --enable-lzo. - - * boot/i386/pc/lnxboot.S: #include . - - * include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_RAW_SIZE): Change - its value according to the compression algorithm used, lzo or lzma. - - * util/i386/pc/grub-mkimage.c (compress_kernel): Use different - compression algorithm according to configure macro. - - * kern/i386/pc/startup.S (codestart): Likewise. - - * kern/i386/pc/lzma_decode.S: New file. - - * include/grub/lib/LzFind.h: Likewise. - - * include/grub/lib/LzHash.h: Likewise. - - * include/grub/lib/LzmaDec.h: Likewise. - - * include/grub/lib/LzmaEnc.h: Likewise. - - * include/grub/lib/LzmaTypes.h: Likewise. - - * lib/LzFind.c: Likewise. - - * lib/LzmaDec.c: Likewise. - - * lib/LzmaEnc.c: Likewise. - -2008-07-13 Bean - - * fs/ext2.c (EXT4_EXTENTS_FLAG): New macro. - (grub_ext4_extent_header): New structure. - (grub_ext4_extent): Likewise. - (grub_ext4_extent_idx): Likewise. - (grub_ext4_find_leaf): New function. - (grub_ext2_read_block): Handle extents. - -2008-07-12 Robert Millan - - * util/i386/pc/grub-mkrescue.in: s/grub-install/grub-mkrescue/g. - -2008-07-11 Robert Millan - - * util/grub.d/40_custom.in: New file. Example on how to add custom - entries to /etc/grub.d. - * conf/common.rmk (%, update-grub_SCRIPTS, CLEANFILES): Install - 40_custom (implicitly, by merging all the grub.d rules). - -2008-07-11 Pavel Roskin - - * commands/read.c (grub_getline): Fix invalid memory access. - Don't add newline to the variable value. - - * term/i386/pc/serial.c (GRUB_SERIAL_PORT_NUM): New constant. - [!GRUB_MACHINE_PCBIOS] (serial_hw_io_addr): Add COM2 and COM3. - (serial_hw_get_port): Check validity of the port number. - (grub_cmd_serial): Check return value of serial_hw_get_port(). - -2008-07-07 Pavel Roskin - - * boot/i386/pc/diskboot.S (notification_string): Replace - "Loading kernel" with just "loading". This is shorter, less - confusing and saves a few bytes for possible future changes. - -2008-07-05 Pavel Roskin - - * disk/ata.c (grub_ata_dumpinfo): Don't output addressing and - size for ATAPI devices, they are undefined. Output sector - number in decimal form. - - * disk/ata.c: Use named constants for status bits. - -2008-07-04 Pavel Roskin - - * kern/i386/linuxbios/init.c (grub_machine_init): Cast addr to - grub_addr_t before casting it to the void pointer to fix a - warning. Non-addressable regions are discarded earlier. - (grub_arch_modules_addr): Cast _end to grub_addr_t. - * kern/i386/linuxbios/table.c: Include grub/misc.h. - (check_signature): Don't shadow table_header. - (grub_linuxbios_table_iterate): Cast numeric constants to - grub_linuxbios_table_header_t. - * include/grub/i386/linuxbios/init.h: Add noreturn attribute to - grub_stop(). - - * kern/ieee1275/init.c: Cast _start and _end to grub_addr_t to - prevent warnings. - - * include/grub/misc.h (ALIGN_UP): Avoid unnecessary cast to a - pointer, which can cause warnings. Support 64-bit addresses. - - * util/elf/grub-mkimage.c: Use GRUB_TARGET_SIZEOF_LONG instead - of sizeof(long). This fixes PowerPC image generation on x86_64. - -2008-07-04 Robert Millan - - This fixes a performance issue when pc & gpt partmap iterators - didn't abort iteration even after our hook found what it was - looking for (often causing expensive probes of non-existent drives). - - Some callers relied on previous buggy behaviour, since they would - raise an error when their own hooks caused early abortion of its - iteration. - - * kern/device.c (grub_device_open): Improve error message. - * disk/lvm.c (grub_lvm_open): Likewise. - * disk/raid.c (grub_raid_open): Likewise. - - * partmap/pc.c (pc_partition_map_iterate): Abort parent iteration - when hook requests it, independently of grub_errno. - (pc_partition_map_probe): Do not fail when find_func() caused - early abortion of pc_partition_map_iterate(). - - * partmap/gpt.c (gpt_partition_map_iterate): Abort parent iteration - when hook requests it, independently of grub_errno. - (gpt_partition_map_probe): Do not fail when find_func() caused - early abortion of gpt_partition_map_iterate(). - - * kern/partition.c (grub_partition_iterate): Abort parent iteration - when hook requests it, independently of grub_errno. Do not fail when - part_map_iterate_hook() caused early abortion of p->iterate(). - - * util/biosdisk.c (grub_util_biosdisk_get_grub_dev): Do not fail - when grub_partition_iterate() returned with non-zero. - -2008-07-03 Pavel Roskin - - * disk/ata.c (grub_ata_pio_write): Check status before writing, - like we do in grub_ata_pio_read(). - (grub_ata_readwrite): Always write individual sectors. Fix the - sector count for the remainder. - (grub_ata_write): Enable writing to ATA devices. Correctly - report error for ATAPI devices. - -2008-07-02 Pavel Roskin - - * boot/i386/pc/cdboot.S: Add _start entry to fix a linker - warning. - - * disk/ata.c (grub_ata_readwrite): Don't increment sector number - for every read sector, we already increment it for the whole - batch. This fixes reading more than 256 sectors at once. - - * util/grub-editenv.c (cmd_info): Cast argument to long - explicitly. ptrdiff_t reduces to int on i386. - - * util/grub-editenv.c (main): Be specific which parameter is - missing. - - * disk/memdisk.c (memdisk_addr): Make a pointer to fix warnings. - (memdisk): Make memdisk_orig_addr a pointer. - - * fs/reiserfs.c (grub_reiserfs_read): Fix misuse of grub_size_t - for file offsets, use grub_off_t instead. Fix printf format - warnings. - - * fs/reiserfs.c: Remove #warning, TODO list items don't belong - there. Real unexpected warnings should not drown in the noise - about known problems. - - * commands/hexdump.c (grub_cmd_hexdump): Fix misuse of - grub_disk_addr_t for memory addresses. - - * loader/aout.c (grub_aout_load): Cast load_addr to pointer - explicitly to fix a warning. - - * util/grub-editenv.c (cmd_info): Fix warning in printf format. - - * Makefile.in (MODULE_LDFLAGS): New variable. - * aclocal.m4 (grub_PROG_LD_BUILD_ID_NONE): New macro. Check if - the linker accepts --build-id=none. - * configure.ac: Call grub_PROG_LD_BUILD_ID_NONE. Substitute - MODULE_LDFLAGS. - * genmk.rb: Use MODULE_LDFLAGS when linking modules. - - * fs/xfs.c (struct grub_xfs_dir_header): Use names similar to - those in Linux XFS code. Provide a way to access 64-bit parent - inode. - (grub_xfs_iterate_dir): Use the new names. Avoid reading past - the end of struct grub_xfs_dir_header. - -2008-07-02 Bean - - * include/grub/ieee1275.h (grub_ieee1275_flag): New constant - GRUB_IEEE1275_FLAG_CANNOT_INTERPRET, GRUB_IEEE1275_FLAG_FORCE_CLAIM - and GRUB_IEEE1275_FLAG_NO_ANSI. - - * kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set flag - GRUB_IEEE1275_FLAG_CANNOT_INTERPRET, GRUB_IEEE1275_FLAG_FORCE_CLAIM - and GRUB_IEEE1275_FLAG_NO_ANSI for Open Hackware. - - * kern/ieee1275/ieee1275.c (grub_ieee1275_interpret): Return - immediately if GRUB_IEEE1275_FLAG_CANNOT_INTERPRET is set. - - * kern/ieee1275/init.c (grub_claim_heap): Claim memory directly if - GRUB_IEEE1275_FLAG_FORCE_CLAIM is set. - - * term/ieee1275/ofconsole.c (grub_ofconsole_writeesc): Don't output - esc sequence on non ANSI terminal. - (grub_ofconsole_gotoxy): Emulate backspace key on non ANSI terminal. - - * util/elf/grub-mkimage.c (add_segments): Move ELF header to the - beginning of file. - -2008-07-02 Bean - - * conf/common.rmk (bin_UTILITIES): Add grub-editenv. - (grub_editenv_SOURCES): New variable. - (pkglib_MODULES): Add loadenv.mod. - (loadenv_mod_SOURCES): New variable. - (loadenv_mod_CFLAGS): Likewise. - (loadenv_mod_LDFLAGS): Likewise. - - * include/grub/envblk.h: New file. - - * util/envblk.c: New file. - - * util/grub-editenv.c: New file. - - * commands/loadenv.c: New file. - -2008-07-01 Pavel Roskin - - * include/multiboot2.h (struct multiboot_tag_module): Use char, - not unsigned char. This fixes warnings and is consistent with - other tags. - - * disk/fs_uuid.c (search_fs_uuid): Correctly increment count. - - * normal/parser.y: Define YYENABLE_NLS as 0 to fix warnings. - - * term/tparm.c (analyze): Always set *popcount. - - * loader/i386/pc/linux.c (grub_rescue_cmd_linux): Remove useless - cast to fix a warning. - - * loader/i386/pc/multiboot2.c (grub_mb2_arch_module_alloc): Use - cast to suppress a warning. - - * fs/afs.c (grub_afs_read_block): Return grub_disk_addr_t, as - grub_fshelp_read_file() expects. - - * fs/fat.c: Fix UUID calculation on big-endian systems. We - write uuid as a 32-bit value in CPU byte order, so declare and - use it as such. - - * disk/raid.c: Cast grub_dprintf() arguments to unsigned long - long if the format specifier expects it. - * partmap/gpt.c (gpt_partition_map_iterate): Likewise. - * partmap/pc.c (pc_partition_map_iterate): Likewise. - * fs/ntfs.c (grub_ntfs_uuid): Cast data->uuid to unsigned long - long to fix a warning. - * fs/reiserfs.c (grub_reiserfs_read): Change casts in - grub_dprintf() arguments to fix warnings. - -2008-06-30 Pavel Roskin - - * util/i386/pc/grub-setup.c (setup): Write install_dos_part and - install_bsd_part immediately before core.img is embedded or - modified on disk. This fixes core.img verification if core.img - cannot be embedded. - - * util/i386/pc/grub-setup.c (setup): Use core_path_dev, not - core_path to calculate the blocklist. - Patch from Javier Martín - -2008-06-29 Robert Millan - - * fs/xfs.c (GRUB_XFS_FSB_TO_BLOCK): New macro. Maps filesystem - block to disk block. - (grub_xfs_read_block): Use GRUB_XFS_FSB_TO_BLOCK() on result. - Patch from Niels Böhm - -2008-06-29 Robert Millan - - * util/update-grub_lib.in (font_path): Search for fonts in - /boot/grub first, which is more likely to be readable (we aren't - deciding where fonts live, just looking for them). - -2008-06-26 Pavel Roskin - - * util/biosdisk.c (read_device_map): Don't leave dead map - entries for devices failing stat() check. - - * util/i386/pc/grub-setup.c (setup): Don't reuse core_path, use - core_path_dev for the core.img path on the target device. - -2008-06-26 Robert Millan - - * disk/fs_uuid.c: New file. - * conf/common.rmk (pkglib_MODULES): Add `fs_uuid.mod'. - (fs_uuid_mod_SOURCES, fs_uuid_mod_CFLAGS) - (fs_uuid_mod_LDFLAGS): New variables. - * include/grub/disk.h (grub_disk_dev_id): Add - `GRUB_DISK_DEVICE_UUID_ID'. - * kern/disk.c (grub_disk_dev_iterate): Allow disk devices not to - implement iterate(). - -2008-06-26 Robert Millan - - * util/grub.d/10_linux.in: Avoid passing UUIDs to Linux when either - "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" does not exist, or when a - Linux image includes no initrd. - -2008-06-21 Javier Martín - - * util/i386/pc/grub-setup.c (setup): Remove literal "core.img" in a - call to resolve the core image location that effectively appended the - name twice. - -2008-06-21 Robert Millan - - * util/grub.d/00_header.in: Move last prepare_grub_to_access_device() - call from here ... - - * util/grub.d/10_hurd.in: ... to here ... - * util/grub.d/10_linux.in: ... and here. - -2008-06-19 Robert Millan - - * kern/main.c (grub_main): Export `prefix' variable immediately - after it has been set by grub_machine_set_prefix(). - -2008-06-19 Robert Millan - - * commands/search.c (search_label, search_fs_uuid, search_file): Print - search result when not saving to variable, not the other way around. - When saving to variable, abort iteration as soon as a match is found. - -2008-06-19 Robert Millan - - * util/update-grub_lib.in (prepare_grub_to_access_device): Remove - check for partition that provides /boot/grub. Its logic is flawed, - as it prevents prepare_grub_to_access_device() from being called - multiple times. - -2008-06-19 Robert Millan - - * util/update-grub_lib.in (prepare_grub_to_access_device): Issue - "insmod" command directly when abstraction modules are needed, - instead of relying on GRUB_PRELOAD_MODULES (which had no effect - since it had already been processed). - -2008-06-19 Pavel Roskin - - * conf/i386-efi.rmk: Recompile grub-mkimage.c if Makefile has - changed. This is needed in case GRUB_LIBDIR changes. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-linuxbios.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - -2008-06-18 Pavel Roskin - - * conf/powerpc-ieee1275.rmk (kernel_elf_SOURCES): Rename - kernel_elf_symlist.c to symlist.c for consistency with other - architectures. Update all users. - * conf/sparc64-ieee1275.rmk (kernel_elf_SOURCES): Likewise. - -2008-06-18 Robert Millan - - * util/i386/pc/grub-install.in: If the drive is LVM or RAID, prepend - it in prefix. - - * util/i386/pc/grub-setup.c (main): Don't handle prefix at all. Set - `must_embed' to 1 when root_dev is a RAID device. When dest_dev is - a RAID device, run setup() for all members independently on whether - LVM abstraction is being used. - (setup): Don't handle prefix at all; let grub-mkimage take care of it. - If grub-mkimage has set `*install_dos_part == -2', don't override this - value. - Perform *install_dos_part adjustments independently on whether - we're embedding or not. - Clarify error message when image is too big for embedding. - Remove duplicate *install_dos_part stanza. - -2008-06-17 Robert Millan - - * term/ieee1275/ofconsole.c (fgcolor, bgcolor): Remove variables. - (grub_ofconsole_normal_color, grub_ofconsole_highlight_color): New - variables. - (grub_ofconsole_setcolor, grub_ofconsole_getcolor): Load/store - values in grub_ofconsole_normal_color and - grub_ofconsole_highlight_color (they're not directly related to - background and foreground). - (grub_ofconsole_setcolorstate): Extract background and foreground - from grub_ofconsole_normal_color and grub_ofconsole_highlight_color. - -2008-06-17 Robert Millan - - * util/update-grub_lib.in (prepare_grub_to_access_device): Use - /boot/grub for the check in last commit, not /boot (they could be - different partitions). - -2008-06-16 Robert Millan - - * util/update-grub_lib.in (prepare_grub_to_access_device): If we were - asked to setup access for the same partition that provides /boot, - don't bother using UUIDs since our root already has the value we - want. - -2008-06-16 Robert Millan - - * util/biosdisk.c (convert_system_partition_to_system_disk): Detect - I2O devices. - Patch from Sven Mueller . - -2008-06-16 Robert Millan - - * util/update-grub.in: Check for $EUID instead of $UID. - Reported by Vincent Zweije. - -2008-06-16 Bean - - * fs/ext2.c (grub_ext2_blockgroup): Revert to pre-journal state. - (grub_ext2_read_block): Likewise. - (grub_ext2_read_inode): Likewise. - (grub_ext2_mount): Likewise. - (grub_ext2_close): Likewise. - (grub_ext3_get_journal): Removed. - - * fs/reiserfs.c (grub_reiserfs_get_item): Revert to pre-journal state. - (grub_reiserfs_read_symlink): Likewise. - (grub_reiserfs_mount): Likewise. - (grub_reiserfs_open): Likewise. - (grub_reiserfs_read): Likewise. - (grub_reiserfs_close): Likewise. - (grub_reiserfs_get_journal): Removed. - - * fs/fshelp.c (grub_fshelp_read): Removed. - (grub_fshelp_map_block): Likewise. - - * include/grub/fshelp.h (grub_fshelp_journal_type): Removed. - (grub_fshelp_journal): Likewise. - (grub_fshelp_read): Likewise. - (grub_fshelp_map_block): Likewise. - -2008-06-16 Pavel Roskin - - * conf/powerpc-ieee1275.rmk: Remove -msoft-float, we don't use - floating point anymore. - * include/grub/powerpc/libgcc.h: Leave only necessary exports. - -2008-06-15 Pavel Roskin - - * commands/ls.c (grub_ls_list_files): Use integer calculations - for human readable format, avoid floating point use. - * kern/misc.c (grub_ftoa): Remove. - (grub_vsprintf): Remove floating point support. - -2008-06-15 Robert Millan - - * util/grub.d/10_linux.in: Use the underlying device for loop-AES - devices. - Reported by Max Vozeler. - -2008-06-15 Robert Millan - - * util/i386/pc/grub-mkimage.c (generate_image): If we included a drive - in our prefix, set install_{dos,bsd}_part = -2 to indicate this can be - skipped later. - (main): If a memdisk was requested, add "(memdisk)" drive explicitly to - the beginning of the prefix. - - * kern/i386/pc/init.c (make_install_device): Remove memdisk check. - It is assumed that if we have a memdisk, grub-mkimage has set - grub_prefix to include the "(memdisk)" drive in it. - -2008-06-15 Robert Millan - - * term/i386/pc/console.c [GRUB_MACHINE_LINUXBIOS] (grub_console_init): - Initialize keyboard controller after registering the terminal, so that - grub_printf() can be called from grub_keyboard_controller_init(). - -2008-06-15 Robert Millan - - * fs/sfs.c (grub_sfs_read_extent): Fix the count of nodes in - extent-btree which is written as big endian on disk. - Reported by Alain Greppin . - -2008-06-14 Robert Millan - - * util/i386/efi/grub-install.in (modules): Remove `_chain'. - * util/i386/pc/grub-install.in (modules): Likewise. - -2008-06-13 Pavel Roskin - - * commands/ls.c (grub_ls_list_files): Fix format warnings. - -2008-06-13 Bean - - * commands/hexdump.c (grub_cmd_hexdump): Adjust offset for partition. - - * fs/ext2.c (grub_ext3_get_journal): Fix revoke block handling. - - * fs/fshelp.c (grub_fshelp_map_block): Don't map block 0 as it's used - to indicate sparse block. - -2008-06-12 Pavel Roskin - - * fs/ext2.c (grub_ext2_read_inode): Don't normalize block - number, grub_fshelp_read() does it for us. - - * fs/fshelp.c (grub_fshelp_read): New function. Implement - linear disk read with journal translation. - * fs/ext2.c: Use grub_fshelp_read() instead of grub_disk_read(). - * include/grub/fshelp.h: Declare grub_fshelp_read(). - -2008-06-09 Pavel Roskin - - * fs/minix.c (grub_minix_mount): Handle error reading - superblock. - -2008-06-08 Robert Millan - - * util/i386/pc/grub-setup.c (main): If install drive is an LVM, - don't append the RAID prefix afterwards. - Reported by Clint Adams. - -2008-06-08 Robert Millan - - Based on description from Pavel: - * kern/disk.c (grub_disk_check_range): Rename to ... - (grub_disk_adjust_range): ... this. Add a comment explaining the - tasks performed by this function. - -2008-06-08 Robert Millan - - * include/grub/ntfs.h (struct grub_ntfs_bpb): Rename `serial_number' to - `num_serial' (for consistency with other variables). - (struct grub_ntfs_data): Add `uuid' member. - * fs/ntfs.c (grub_ntfs_mount): Initialize `data->uuid'. - (grub_ntfs_uuid): New function. - (grub_ntfs_fs): Reference grub_ntfs_uuid() in `uuid' struct member. - -2008-06-07 Pavel Roskin - - * util/biosdisk.c (open_device): Revert last change to the - function, it broke installation. The sector needs to be - different dependent on which device is opened. - -2008-06-06 Robert Millan - - Ensure GRUB_KERNEL_MACHINE_DATA_END is always consistent with the - rest of GRUB, and breakage doesn't happen if its value were modified. - - * include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_RAW_SIZE): - Redefine as an offset from `GRUB_KERNEL_MACHINE_DATA_END' instead of - a constant (same value). - * kern/i386/pc/startup.S: Replace hardcoded `0x50' with - `GRUB_KERNEL_MACHINE_DATA_END' (same value). - -2008-06-06 Robert Millan - - * util/biosdisk.c (open_device): Do not modify sector offset when - accessing a partition. kern/disk.c already handles this for us. - -2008-06-06 Robert Millan - - * util/grub-emu.c (grub_machine_init): Move code in this function from - here ... - (main): ... to here (before grub_util_biosdisk_init() call, to prevent - segfault in case grub_printf() is called). - - * util/i386/pc/grub-install.in: Append `--device-map=${device_map}' to - grub_probe. Update all users not to explicitly add it again. - (grub_device): New variable; contains corresponding device for grubdir. - (fs_module, partmap_module, devabstraction_module): Pass - `--device ${grub_device}' to grub_probe to avoid traversing /dev - every time. - -2008-06-05 Robert Millan - - * normal/misc.c (grub_normal_print_device_info): When a filesystem UUID - is found, print it (same layout as with labels). - -2008-06-04 Robert Millan - - * util/biosdisk.c (get_drive): Rename to ... - (find_grub_drive): ... this. Update all users. - - (get_os_disk): Rename to ... - (convert_system_partition_to_system_disk): ... this. Update all users. - - (find_drive): Rename to ... - (find_system_device): ... this. Update all users. - -2008-06-04 Robert Millan - - * util/biosdisk.c (get_os_disk): Handle IDA devices. - * util/grub-mkdevicemap.c (get_mmc_disk_name) - (make_device_map): Likewise. - -2008-06-01 Robert Millan - - * util/biosdisk.c (get_drive): Verify that `map[i].drive' is non-NULL - before dereferencing it. - - * fs/fat.c (struct grub_fat_bpb): Move fat32-specific fields into a - union with fat12/fat16-specific ones. Add some new fields, including - `num_serial' for both versions. - (struct grub_fat_data): Add `uuid' member. - (grub_fat_mount): Refer to fat32-specific fields in `bpb' by their new - names. Initialize `data->uuid' using `num_serial'. - (grub_fat_uuid): New function. - (grub_fat_fs): Reference grub_fat_uuid() in `uuid' struct member. - - * fs/reiserfs.c (grub_reiserfs_superblock): Add `uuid' field. - (grub_reiserfs_uuid): New function. - (grub_reiserfs_fs): Reference grub_reiserfs_uuid() in `uuid' struct - member. - - * fs/xfs.c (grub_xfs_sblock): Add `uuid' field. - (grub_xfs_uuid): New function. - (grub_xfs_fs): Reference grub_reiserfs_uuid() in `uuid' struct member. - -2008-06-01 Robert Millan - - * util/update-grub_lib.in (prepare_grub_to_access_device): Generate - code that is backward compatible with pre-uuid search command. - -2008-05-31 Robert Millan - - * disk/i386/pc/biosdisk.c (grub_biosdisk_iterate): Iterate through - floppies after everything else, to ensure floppy drive isn't accessed - unnecessarily (patch from Bean). - -2008-05-31 Robert Millan - - * commands/search.c (search_label, search_fs_uuid, search_file): Do - not print device names when we were asked to set a variable. - -2008-05-31 Robert Millan - - * term/ieee1275/ofconsole.c (grub_ofconsole_setcursor): Implement - using "cursor-on" and "cursor-off" commands (understood at least by - the Open Firmware flavour on OLPC). - -2008-05-31 Michael Gorven - - * term/terminfo.c (grub_terminfo_set_current): Correct vt100 cursor - on and off sequences. - -2008-05-31 Robert Millan - - * util/update-grub_lib.in: Replace `grub-probe' with `${grub_probe}'. - * util/update-grub.in: Likewise. - -2008-05-30 Pavel Roskin - - * util/biosdisk.c (linux_find_partition): Simplify logic and - make the code more universal. Keep special processing for - devfs, but use a simple rule for all other devices. If the - device ends with a number, append 'p' and the partition number. - Otherwise, append only the partition number. - -2008-05-30 Robert Millan - - * util/update-grub.in (GRUB_DISABLE_LINUX_UUID): Export variable. - * util/grub.d/10_linux.in: If GRUB_DEVICE_UUID is set, and - GRUB_DISABLE_LINUX_UUID isn't true, use the filesystem UUIDs as - the `root' parameter to Linux. - -2008-05-30 Robert Millan - - * commands/search.c (options): Rename --fs_uuid to --fs-uuid. - * util/update-grub_lib.in (prepare_grub_to_access_device): Replace - --fs_uuid with --fs-uuid. - * util/update-grub.in: Allow filesystem UUID probes to fail (since not - all filesystems support them). - -2008-05-30 Robert Millan - - * fs/ext2.c (grub_ext2_uuid): Use `04x' instead of '02x' as - grub_printf() flags, since we're printing in units of 2 bytes. - -2008-05-30 Robert Millan - - * util/grub.d/00_header.in: Remove obsolete comment referencing - convert_system_path_to_grub_path(). - * util/update-grub.in: Likewise. - * util/update-grub_lib.in (is_path_readable_by_grub): New function. - (convert_system_path_to_grub_path): Add a warning message explaining - that this function is deprecated. Rely on is_path_readable_by_grub() - for the readability checks. - (font_path): Use is_path_readable_by_grub() for the readability - check rather than convert_system_path_to_grub_path(). - -2008-05-30 Robert Millan - - * util/update-grub_lib.in (prepare_grub_to_access_device): New function. - * util/update-grub.in: Set `GRUB_FONT_PATH' to the system path, without - converting it first. - * util/grub.d/00_header.in: Use prepare_grub_to_access_device() to setup - grub.cfg for access to font file, and afterwards call it again to set - the root device. - -2008-05-30 Robert Millan - - * commands/search.c (options): Add --fs_uuid option. - (search_fs_uuid): New function. - (grub_cmd_search): Fix --set argument passing. - Use search_fs_uuid() when requested via --fs_uuid. - (grub_search_init): Update help message. - * fs/ext2.c (struct grub_ext2_sblock): Rename `unique_id' to `uuid' - and redeclare it as an array of 16-bit words. - (grub_ext2_uuid): New function. - (grub_ext2_fs): Reference grub_ext2_uuid() in `uuid' struct member. - * include/grub/fs.h (struct grub_fs): Add `uuid' struct member. - * util/update-grub.in (GRUB_DEVICE_UUID, GRUB_DEVICE_BOOT) - (GRUB_DEVICE_BOOT_UUID): New variables. - (GRUB_DRIVE. GRUB_DRIVE_BOOT. GRUB_DRIVE_BOOT_GRUB): Remove. - * util/grub.d/00_header.in: Set root using `search --fs_uuid' command - whenever possible. - * util/grub.d/10_hurd.in: Avoid explicit use of root drive. Instead, - just assume `root' variable has the right value. - * util/grub.d/10_linux.in: Likewise. - * util/grub-probe.c (probe): Probe for filesystem UUID when requested - via PRINT_FS_UUID. - (main): Recognise `-t fs_uuid' argument. - -2008-05-30 Robert Millan - - * util/biosdisk.c (map): Redefine structure to hold information - about GRUB drive name. - (get_drive): Reimplement without assuming (and verifying) BIOS-like - drive names. - (call_hook): Remove. - (grub_util_biosdisk_iterate): Access drive names via `.drive' struct - member. Assume drive has partitions. - (grub_util_biosdisk_open): Access device names via `.device' struct - member. - (open_device): Likewise. - (find_drive): Likewise. - (read_device_map): Adjust map[] usage to match the new struct - definition. Don't check for duplicates (still possible, but not cheap - anymore). - (grub_util_biosdisk_fini): Free malloced buffers referenced by map[]. - (make_device_name): Remove assumption of BIOS-like drive names. - -2008-05-30 Pavel Roskin - - * conf/i386-efi.rmk (normal/execute.c_DEPENDENCIES): Remove, as - compiling execute.c doesn't need grub_script.tab.h anymore. - (normal/command.c_DEPENDENCIES): Likewise. - (normal/function.c_DEPENDENCIES): Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-linuxbios.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - -2008-05-29 Pavel Roskin - - * disk/lvm.c (grub_lvm_scan_device): Check for the buffer end - when scanning metadata for volume group name. - - * include/grub/script.h: Don't include grub_script.tab.h. It's - a generated file, which may only be included from the files with - DEPENDENCIES rules in the makefile. Don't use typedef YYSTYPE, - use union YYSTYPE, as the later allows forward declaration. - * normal/lexer.c: Don't use typedef YYSTYPE, use union YYSTYPE. - -2008-05-29 Robert Millan - - * term/i386/pc/at_keyboard.c: Include `grub/machine/machine.h'. - (OLPC_UP, OLPC_DOWN, OLPC_LEFT, OLPC_RIGHT): New macros. - [GRUB_MACHINE_IEEE1275] (keyboard_map): Add OLPC scan codes - (grub_console_checkkey): Add grub_dprintf() call to report unknown - scan codes. - -2008-05-29 Robert Millan - - * term/i386/pc/at_keyboard.c (grub_console_checkkey): Add support for - control key combinations. - -2008-05-29 Robert Millan - - * util/powerpc/ieee1275/grub-install.in: Move from here ... - * util/ieee1275/grub-install.in: ... to here. - * powerpc-ieee1275.rmk (grub_install_SOURCES): Update location. - * i386-ieee1275.rmk (sbin_SCRIPTS): New variable. - (grub_install_SOURCES): Likewise. - -2008-05-29 Robert Millan - - * fs/affs.c: Update copyright year. - * fs/ext2.c: Likewise. - * fs/fshelp.c: Likewise. - * fs/hfsplus.c: Likewise. - * fs/ntfs.c: Likewise. - * fs/xfs.c: Likewise. - * include/grub/fshelp.h: Likewise. - * util/grub-mkdevicemap.c: Likewise. - -2008-05-28 Robert Millan - - * util/update-grub.in: Allow chmod call to fail, since /boot/grub/ - might need to be fatfs to support some firmware implementations - (e.g. OFW or EFI). - -2008-05-28 Robert Millan - - * util/biosdisk.c (linux_find_partition, get_os_disk): Handle MMC - devices. - * util/grub-mkdevicemap.c (get_mmc_disk_name) - (make_device_map): Likewise. - -2008-05-20 Bean - - * fs/fshelp.c (grub_fshelp_map_block): New function. - (grub_fshelp_find_file): Use 64-bit type for pos and block address. - Use `>>' and `&' operator to avoid 64-bit divide and modulo. - - * include/grub/fshelp.h (grub_fshelp_journal_type): New enum. - (GRUB_FSHELP_JOURNAL_UNUSED_MAPPING): New macro. - (grub_fshelp_journal): New structure. - (grub_fshelp_map_block): New function prototype. - (grub_fshelp_read_file): Use grub_disk_addr_t as block type. - (grub_fshelp_map_block): Likewise. - - * fs/ext2.c (EXT3_FEATURE_COMPAT_HAS_JOURNAL): New macro. - (EXT3_JOURNAL_MAGIC_NUMBER): Likewise. - (EXT3_JOURNAL_DESCRIPTOR_BLOCK): Likewise. - (EXT3_JOURNAL_COMMIT_BLOCK): Likewise. - (EXT3_JOURNAL_SUPERBLOCK_V1): Likewise. - (EXT3_JOURNAL_SUPERBLOCK_V2): Likewise. - (EXT3_JOURNAL_REVOKE_BLOCK): Likewise. - (EXT3_JOURNAL_FLAG_ESCAPE): Likewise. - (EXT3_JOURNAL_FLAG_SAME_UUID): Likewise. - (EXT3_JOURNAL_FLAG_DELETED): Likewise. - (EXT3_JOURNAL_FLAG_LAST_TAG): Likewise. - (grub_ext2_sblock): New members for journal support. - (grub_ext3_journal_header): New structure. - (grub_ext3_journal_revoke_header): Likewise. - (grub_ext3_journal_block_tag): Likewise. - (grub_ext3_journal_sblock): Likewise. - (grub_fshelp_node): New members logfile and journal. - (grub_ext2_read_block): Change block type to grub_disk_addr_t. Use - grub_fshelp_map_block to get real block number. - (grub_ext2_blockgroup): Use grub_fshelp_map_block to get real block - number. - (grub_ext2_read_inode): Likewise. - (grub_ext3_get_journal): New function. - (grub_read_inode): Initialize journal using grub_ext3_get_journal. - (grub_ext2_close): Release memory used by journal. - - * fs/reiserfs.c (REISERFS_MAGIC_STRING): Changed to "ReIsEr". - (REISERFS_MAGIC_DESC_BLOCK): New macro. - (grub_reiserfs_transaction_header): Renamed to - grub_reiserfs_description_block, replace field data with real_blocks. - (grub_reiserfs_commit_block): New structure. - (grub_reiserfs_data): New member journal. - (grub_reiserfs_get_item): Use grub_fshelp_map_block to get real block - number. - (grub_reiserfs_read_symlink): Likewise. - (grub_reiserfs_iterate_dir): Likewise. - (grub_reiserfs_open): Likewise. - (grub_reiserfs_read): Likewise. - (grub_reiserfs_get_journal): New function. - (grub_reiserfs_mount): Use "ReIsEr" as super block magic, as there are - three varieties ReIsErFs, ReIsEr2Fs and ReIsEr3Fs. Initialize journal - using grub_reiserfs_get_journal. - (grub_reiserfs_close): Release memory used by journal. - - * fs/affs.c (grub_affs_read_block): Change block type to - grub_disk_addr_t. Use grub_divmod64 to do 64-bit division. - - * fs/afs.c (grub_afs_read_block): Change block type to grub_disk_addr_t. - - * fs/hfsplus.c (grub_hfsplus_read_block): Likewise. - - * fs/ntfs.c (grub_ntfs_read_block): Likewise. - - * fs/udf.c (grub_udf_read_block): Change block type to - grub_disk_addr_t. Use type cast to avoid warning. - - * fs/xfs.c (grub_xfs_read_block): Likewise. - -2008-05-16 Christian Franke - - * commands/cat.c (grub_cmd_cat): Remove non-ESC keys from keyboard queue - to ensure that break with ESC will always work. - * commands/sleep.c (grub_interruptible_millisleep): Likewise. - Remove ESC from keyboard queue. - -2008-05-16 Christian Franke - - * util/biosdisk.c: [__CYGWIN__] Add includes. - (grub_util_biosdisk_open): Use Linux code also for Cygwin. - (get_os_disk): Move variable declarations to OS specific - parts to avoid warning. - [__GNU__] (get_os_disk): Fix /dev/sdXsN case. - [__CYGWIN__] (get_os_disk): Add Cygwin /dev/sdXN device names. - (grub_util_biosdisk_get_grub_dev): Use Linux code also for - Cygwin. - * util/getroot.c: [__CYGWIN__] Add includes. - (strip_extra_slashes): Fix "/" case. - [__CYGWIN__] (get_win32_path): New function. - [__CYGWIN__] (grub_get_prefix): Add conversion to win32 path. - [__CYGWIN__] (find_root_device): Disable. - [__CYGWIN__] (get_bootsec_serial): New function. - [__CYGWIN__] (find_cygwin_root_device): Likewise. - [__linux__] (grub_guess_root_device): Add early returns to simplify - structure. - [__CYGWIN__] (grub_guess_root_device): Call find_cygwin_root_device. - [__linux__] (grub_util_get_dev_abstraction): Enable LVM and RAID - check for Linux only. - -2008-05-15 Bean - - * kern/i386/pc/startup.S (grub_console_getkey): Workaround for the - keyboard hang problem in apple's intel mac. - -2008-05-09 Robert Millan - - * util/biosdisk.c (linux_find_partition, get_os_disk): Handle Virtio - devices. - * util/grub-mkdevicemap.c (get_virtio_disk_name) - (make_device_map): Likewise. - Reported by Aurelien Jarno - -2008-05-07 Ian Campbell - - * util/biosdisk.c (get_os_disk): Recognise xvd type disks. - * util/grub-mkdevicemap.c (get_xvd_disk_name): New function. - (make_device_map): Output entries for xvd type disks. - -2008-05-07 Robert Millan - - * util/biosdisk.c (linux_find_partition, get_os_disk): Handle CCISS - devices. - * util/grub-mkdevicemap.c (get_cciss_disk_name) - (make_device_map): Likewise. - Reported by Roland Dreier - -2008-05-07 Robert Millan - - * disk/lvm.c (grub_lvm_scan_device): Detect errors in an additional - grub_strstr() call. Correct a few mistakes in failure path handling. - -2008-05-06 Robert Millan - - * util/update-grub_lib.in (make_system_path_relative_to_its_root): - Do not print a trailing slash (therefore, the root directory is an - empty string). - (convert_system_path_to_grub_path): Do not remove trailing slash - from make_system_path_relative_to_its_root() output. - - * util/i386/pc/grub-install.in: Add trailing slash to output from - make_system_path_relative_to_its_root(). - -2008-05-06 Robert Millan - - * util/grub-fstest.c (grub_refresh): Call `fflush (stdout)'. This - ensures that output lines aren't intermangled with those sent to - stderr (via grub_util_info()). - * util/grub-probe.c (grub_refresh): Likewise. - * util/i386/pc/grub-setup.c (grub_refresh): Likewise. - -2008-05-05 Christian Franke - - * util/grub-mkdevicemap.c (get_floppy_disk_name) [__CYGWIN__]: - Add Cygwin device names. - (get_ide_disk_name) [__CYGWIN__]: Likewise. - (get_scsi_disk_name) [__CYGWIN__]: Likewise. - (check_device): Return error instead of success on empty name. - (make_device_map): Move label inside linux specific code to - prevent compiler warning. - -2008-04-30 Robert Millan - - Based on patch from Fabian Greffrath - * util/grub.d/10_linux.in: Add ${GRUB_CMDLINE_LINUX_DEFAULT} to the - first boot option. - * util/update-grub.in: Export GRUB_CMDLINE_LINUX_DEFAULT. - -2008-04-29 Robert Millan - - * docs/grub.cfg: New file (example GRUB configuration). - -2008-04-26 Robert Millan - - * DISTLIST: Sort (sort -u < DISTLIST | sponge DISTLIST). Add - `loader/i386/ieee1275/linux.c', `loader/i386/ieee1275/linux_normal.c' - and `disk/ieee1275/nand.c'. - -2008-04-25 Bean - - * Makefile.in (RMKFILES): Add missing arch i386-ieee1275 and - i386-linuxbios. - - * commands/hexdump.c (grub_cmd_hexdump): Support dumping of device, - change the buffer size to 4096 for cdrom device. - - * conf/i386-ieee1275.rmk (pkglib_MODULES): Add _linux.mod, linux.mod - and nand.mod. - (_linux_mod_SOURCES): New variable. - (_linux_mod_CFLAGS): Likewise. - (_linux_mod_LDFLAGS): Likewise. - (linux_mod_SOURCES): Likewise. - (linux_mod_CFLAGS): Likewise. - (linux_mod_LDFLAGS): Likewise. - (nand_mod_SOURCES): Likewise. - (nand_mod_CFLAGS): Likewise. - (nand_mod_LDFLAGS): Likewise. - - * disk/ieee1275/ofdisk.c (grub_ofdisk_open): Return - GRUB_ERR_UNKNOWN_DEVICE instead of GRUB_ERR_BAD_DEVICE if no device - type property. (nand device in olpc don't have this property) - - * include/grub/disk.h (grub_disk_dev_id): New macro - GRUB_DISK_DEVICE_NAND_ID. - - * include/grub/i386/ieee1275/loader.h (grub_rescue_cmd_linux): New - function prototype. - (grub_rescue_cmd_initrd): Likewise. - - * include/grub/i386/linux.h (GRUB_LINUX_OFW_SIGNATURE): New macro. - (linux_kernel_params): Add new member ofw_signature, ofw_num_items, - ofw_cif_handler and ofw_idt, adjust padding number. - - * include/grub/i386/pc/memory.h (grub_upper_mem): Export it if - GRUB_MACHINE_IEEE1275 is defined. - - * include/grub/ieee1275/ieee1275.h (grub_available_iterate): - Use NESTED_FUNC_ATTR attribute on the hook parameter. - - * kern/powerpc/ieee1275/init.c (grub_claim_heap): Use NESTED_FUNC_ATTR - on nested function heap_init. - (grub_upper_mem): New variable for i386-ieee1275. - (grub_get_extended_memory): New function for i386-ieee1275. - (grub_machine_init): Call grub_get_extended_memory for i386-ieee1275. - - * kern/powerpc/ieee1275/openfw.c (grub_available_iterate): Use - NESTED_FUNC_ATTR on the hook parameter. Don't quit if no device type - property. - - * loader/i386/ieee1275/linux.c: New file. - - * loader/i386/ieee1275/linux_normal.c: New file. - - * disk/ieee1275/nand.c: New file. - -2008-04-18 Thomas Schwinge - - * util/i386/pc/grub-mkrescue.in (grub_mkimage): Don't overwrite correct - value. - * util/powerpc/ieee1275/grub-mkrescue.in (grub_mkimage): Likewise. - -2008-04-18 Robert Millan - - Restructures early code path on ieee1275 to unify grub_main() as - the first C function that is executed in every platform. - - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_init): New prototype. - * kern/i386/ieee1275/startup.S (_start): Jump to grub_main() instead of - cmain(). - * kern/powerpc/ieee1275/crt0.S (_start): Likewise. - * kern/ieee1275/cmain.c (cmain): Rename to ... - * kern/ieee1275/cmain.c (grub_ieee1275_init): ... this. - * kern/ieee1275/init.c (grub_machine_init): Call grub_ieee1275_init() - at the beginning. - -2008-04-18 Robert Millan - - * util/update-grub.in: Fix syntax error when setting - `GRUB_PRELOAD_MODULES'. - Reported by Stephane Chazelas - -2008-04-17 Lubomir Kundrak - - * aclocal.m4 (grub_PROG_OBJCOPY_ABSOLUTE): take only .text - section into account, newer toolchains generate unique build ids - * configure.ac: remove the test for --build-id=none acceptance, - we want build ids to be preserved - * genmk.rb: add -R .note.gnu.build-id to objcopy, so build id - far from other sections don't cause the raw binary images grow - size - -2008-04-15 Robert Millan - - * disk/lvm.c: Update copyright year. - * kern/misc.c: Likewise. - -2008-04-14 Vesa Jaaskelainen - - * disk/lvm.c (grub_lvm_scan_device): Add forgotten failure path when - there is no memory left for physical volume name. - -2008-04-14 Vesa Jaaskelainen - - * disk/lvm.c (grub_lvm_scan_device): Fix logical volume's physical - volume name mapping to support bigger than 9 character names properly. - -2008-04-13 Robert Millan - - * disk/i386/pc/biosdisk.c (grub_biosdisk_rw): Fix CHS limit check, - as per http://www.allensmith.net/Storage/HDDlimit/Int13h.htm - -2008-04-13 Christian Franke - - * util/i386/pc/grub-mkrescue.in: Add --emulation=floppy - to create a floppy emulation boot CD when non emulation mode - does not work. - Enable Joliet CD filesystem extension. - -2008-04-13 Robert Millan - - * kern/misc.c (grub_strncat): Fix off-by-one error. - Reported by Zhang Huan - - * kern/env.c (grub_env_context_close): Clear current context, not - previous one. - Patch from Zhang Huan - - * kern/misc.c (grub_strcat): Minor speed optimization (same code size). - -2008-04-13 Robert Millan - - Improve robustness when handling LVM. - - * disk/lvm.c (grub_lvm_getvalue): Return 0 when `*p' is NULL - (and leave `*p' unmodified). - (grub_lvm_iterate): Don't assume `vg->lvs != NULL' when iterating - through it. - (grub_lvm_memberlist): Don't assume `lv->vg->pvs != NULL' when - iterating through it. - (grub_lvm_open): Don't assume `vg->lvs != NULL' when iterating - through it. - (grub_lvm_scan_device): Check the return value (and fail gracefully - when due) on each grub_lvm_getvalue() or grub_strstr() call. - Don't assume `vg->pvs != NULL' when iterating through it. - -2008-04-13 Robert Millan - - * gendistlist.sh (EXTRA_DISTFILES): Add `genpartmaplist.sh'. - * genmk.rb (partmap): New variable. - (CLEANFILES, PARTMAPFILES): Add #{partmap}. - (#{partmap}): New target rule. - * genpartmaplist.sh: New file. - * Makefile.in (pkglib_DATA): Add partmap.lst. - (partmap.lst): New target rule. - * util/i386/pc/grub-mkrescue.in: Generate grub.cfg that loads needed - modules (including all partition maps), instead of preloading them. - -2007-04-13 Fabian Greffrath - - * util/grub.d/30_os-prober.in: New script. Use `os-prober' and - `linux-boot-prober' (if installed) to detect other operating - systems which are installed on the computer and add them to - the boot menu. - * conf/common.rmk: Build and install 30_os-prober. - -2008-04-12 Robert Millan - - * kern/powerpc/ieee1275/init.c: Move from here ... - * kern/ieee1275/init.c: ... to here. Update all users. - - * kern/powerpc/ieee1275/cmain.c: Move from here ... - * kern/ieee1275/cmain.c: ... to here. Update all users. - - * kern/powerpc/ieee1275/openfw.c: Move from here ... - * kern/ieee1275/openfw.c: ... to here. Update all users. - - * loader/powerpc/ieee1275/multiboot2.c: Move from here ... - * loader/ieee1275/multiboot2.c: ... to here. Update all users. - -2008-04-10 Pavel Roskin - - * configure.ac: Always use "_cv_" in cache variables for - compatibility with Autoconf 2.62. - -2008-04-07 Robert Millan - - Revert grub/machine/init.h addition by Pavel (since it breaks on - i386-ieee1275 and others): - * util/i386/pc/misc.c: Remove grub/machine/init.h. - * util/powerpc/ieee1275/misc.c: Likewise. - -2008-04-07 Robert Millan - - * util/grub-probe.c (probe): Improve error message. - -2008-04-07 Robert Millan - - * util/biosdisk.c (read_device_map): Skip devices that don't exist - (this prevents the presence of a bogus entry from ruining the whole - thing). - -2008-04-06 Pavel Roskin - - * util/biosdisk.c: Include grub/util/biosdisk.h. - * util/grub-fstest.c (execute_command): Make static. - * util/grub-mkdevicemap.c (check_device): Likewise. - * util/i386/pc/misc.c: Include grub/machine/init.h. - * util/powerpc/ieee1275/misc.c: Likewise. - * util/lvm.c: Include grub/util/lvm.h. - * util/misc.c: Include grub/kernel.h, grub/misc.h and - grub/cache.h. - * util/raid.c: Include grub/util/raid.h. - (grub_util_getdiskname): Make static. - - * util/grub-emu.c (main): Remove calls to grub_hostfs_init() and - grub_hostfs_fini(), as they are called from grub_init_all() and - grub_fini_all() respectively. This fixes an infinite loop in - grub-fstest due to double registration of hostfs. - Reported by Christian Franke - -2008-04-05 Pavel Roskin - - * bus/pci.c (grub_pci_iterate): For multifunction devices, probe - all 8 functions. Otherwise, probe function 0 only. - -2008-04-04 Pavel Roskin - - * commands/lspci.c (grub_lspci_iter): Print the bus number - correctly. - - * commands/lspci.c (grub_pci_classes): Fix typos. - (grub_lspci_iter): Don't print func twice. Print vendor ID - before device ID, as it's normally done. - - * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_find_options): - Fix signedness warnings. - * kern/powerpc/ieee1275/openfw.c (grub_available_iterate): - Likewise. - * util/ieee1275/get_disk_name.c: Include config.h so that - _GNU_SOURCE is defined and getline() is declared. Mark an - unused argument as such. Fix a signedness warning. - -2008-04-02 Pavel Roskin - - * genkernsyms.sh.in: Use more robust assignments for CC and - srcdir. Quote srcdir. - * gensymlist.sh.in: Likewise. Assert at the compile time that - the symbol table is not empty. - - * disk/raid.c (grub_raid_memberlist): Fix a signedness warning. - * fs/cpio.c (grub_cpio_read): Likewise. - -2008-04-01 Pavel Roskin - - * disk/ata.c (grub_ata_open): Don't lose precision in disk->id. - * disk/host.c (grub_host_open): Likewise. - * disk/loopback.c (grub_loopback_open): Likewise. - * disk/memdisk.c (grub_memdisk_open): Use a string pointer for - disk->id as in disk/host.c, not a multi-character constant. - - * util/grub-fstest.c (cmd_cmp): Use fseeko(), not fseek(). The - later is obsolete, potentially dangerous and sets a bad example. - * util/i386/efi/grub-mkimage.c (make_header): Likewise. - * util/misc.c (grub_util_get_image_size): Likewise. - - * disk/loopback.c (options): Improve help for "--partitions". - - * normal/arg.c (grub_arg_show_help): Fix spacing of the long - options to align them with the short options, e.g. "echo -e". - -2008-03-31 Bean - - * video/reader/png.c (grub_png_data): New member is_16bit and - image_data. - (grub_png_decode_image_header): Detect 16 bit png image. - (grub_png_convert_image): New function to convert 16 bit image to 8 bit. - (grub_png_decode_png): Call grub_png_convert_image for 16 bit image. - (grub_video_reader_png): Release memory occupied by image_data. - - * fs/ntfs.c (find_attr): Handle non-resident attribute list larger than - 4096 bytes. - (grub_nfs_mount): Skip the test for sector per cluster. - - * include/grub/ntfs.h (MAX_SPC): Removed. - -2008-03-31 Bean - - * conf/common.rmk (pkgdata_MODULES): Add afs.mod. - (grub_probe_SOURCES): Add fs/afs.c. - (grub_fstest_SOURCES): Likewise. - (afs_mod_SOURCES): New variable. - (afs_mod_CFLAGS): Likewise. - (afs_mod_LDFLAGS): Likewise. - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/afs.c. - (grub_emu_SOURCES): Likewise. - - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - - * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - - * fs/afs.c: New file. - -2008-03-30 Pavel Roskin - - * disk/host.c: Include grub/misc.h to fix a warning. - * util/hostfs.c: Use GRUB_MOD_INIT and GRUB_MOD_FINI to fix - warnings about implicit declarations. - - * fs/udf.c (grub_udf_mount): Fix warning about a shadowing a - variable. - * include/grub/i386/loader.h: Change declaration of - grub_linux_boot() to match what grub_loader_set() expects. - * util/getroot.c (grub_guess_root_device): Return const char* to - fix a warning. - * util/grub-probe.c (probe): Fix a warning about uninitialized - abstraction_name variable. - * util/i386/get_disk_name.c (grub_util_get_disk_name): Mark - second argument as unused to fix a warning. - - * loader/i386/pc/multiboot2.c (grub_mb2_arch_elf64_hook): Add - missing grub_error() call. - - * util/update-grub_lib.in: Define datarootdir, since Autoconf - 2.60 and newer uses it to define datadir. - - * commands/sleep.c: Fix warning about implicit declaration. - * disk/memdisk.c: Likewise. - * loader/aout.c: Likewise. - * loader/i386/bsd_normal.c: Likewise. - * util/grub-probe.c: Likewise. - - * commands/i386/cpuid.c (has_longmode): Make static. - * disk/i386/pc/biosdisk.c (cd_drive): Likewise. - * include/grub/i386/bsd.h (bios_memmap_t): Remove, it's unused. - - * kern/i386/pc/startup.S (real_to_prot): Use %cs prefix to load - GDT. This is more robust, as %ds can change. - (grub_biosdisk_rw_int13_extensions): Don't clear %ds before - calling real_to_prot(). - (grub_biosdisk_get_diskinfo_int13_extensions): Likewise. - -2008-03-28 Pavel Roskin - - * kern/i386/pc/startup.S: Assert that uncompressed functions - don't spill beyond GRUB_KERNEL_MACHINE_RAW_SIZE. - * kern/i386/pc/lzo1x.S: Remove all .align directives in the - code, as they push parts of the code (error handlers) beyond - GRUB_KERNEL_MACHINE_RAW_SIZE. Speed is not as important in this - code as correctness and size. - -2008-03-28 Pavel Roskin - - * kern/i386/pc/startup.S - (grub_biosdisk_get_diskinfo_int13_extensions): When converting - data block address to the real mode, keep offset minimal. This - works around a bug in AWARD BIOS on old Athlon systems, which - makes CD detection hang. - -2008-03-26 Pavel Roskin - - * normal/color.c (grub_parse_color_name_pair): Make `name' a - const. - * include/grub/normal.h: Add grub_parse_color_name_pair() - declaration. - -2008-03-24 Bean - - * disk/i386/pc/biosdisk.c (cd_start): Removed. - (cd_count): Removed. - (cd_drive): New variable. - (grub_biosdisk_get_drive): Don't check for (cdN) device. - (grub_biosdisk_call_hook): Likewise. - (grub_biosdisk_iterate): Change cdrom detection method. - (grub_biosdisk_open): Replace cd_start with cd_drive. - (GRUB_MOD_INIT): Use grub_biosdisk_get_cdinfo_int13_extension to - detect cdrom device. - - * include/grub/i386/pc/biosdisk.h (GRUB_BIOSDISK_MACHINE_CDROM_START): - Removed. - (GRUB_BIOSDISK_MACHINE_CDROM_END): Removed. - (GRUB_BIOSDISK_CDTYPE_NO_EMUL): New macro. - (GRUB_BIOSDISK_CDTYPE_1_2_M): Likewise. - (GRUB_BIOSDISK_CDTYPE_1_44_M): Likewise. - (GRUB_BIOSDISK_CDTYPE_2_88_M): Likewise. - (GRUB_BIOSDISK_CDTYPE_HARDDISK): Likewise. - (GRUB_BIOSDISK_CDTYPE_MASK): Likewise. - (grub_biosdisk_cdrp): New structure. - (grub_biosdisk_get_cdinfo_int13_extensions): New function. - - * include/grub/i386/pc/kernel.h (grub_boot_drive): Export this variable. - - * kern/i386/pc/init.c (make_install_device): Don't use (cdN) as root - device. - - * kern/i386/pc/startup.S (grub_biosdisk_get_cdinfo_int13_extensions): - New function. - -2008-03-20 Robert Millan - - Remove 2 TiB limit in ata.mod. - * disk/ata.c (grub_ata_device): Promote `size' to grub_uint64_t. - (grub_ata_dumpinfo): Print sector count with 0x%llx. - (grub_ata_identify): Interpret `&info16[100]' as a pointer to - grub_uint64_t instead of grub_uint32_t. - -2008-03-05 Bean - - * loader/i386/pc/multiboot.c (grub_multiboot_get_bootdev): New function. - (grub_multiboot): Set boot device. - - * boot/i386/pc/lnxboot.S (real_code_2): Set %dh to 0xFF. - -2008-03-02 Bean - - * fs/reiserfs.c (grub_reiserfs_read_symlink): Add 0 at the end of - symlink_buffer. - -2008-03-01 Yoshinori K. Okuji - - * DISTLIST: Added docs/fdl.texi, docs/grub.texi, docs/mdate-sh and - texinfo.tex. - - * docs/grub.texi: New file. Copied from GRUB Legacy, and slightly - modified. - - * docs/fdl.texi: New file. - - * docs/mdate-sh: New file. Copied from gnulib. - * docs/texinfo.tex: Likewise. - - * config.guess: Updated from gnulib. - * install-sh: Likewise. - -2008-02-28 Robert Millan - - * conf/i386-linuxbios.rmk (pkglib_MODULES): Add aout.mod. - (aout_mod_SOURCES): New variable. - (aout_mod_CFLAGS): Likewise. - (aout_mod_LDFLAGS): Likewise. - - * conf/i386-ieee1275.rmk: Likewise. - -2008-02-28 Robert Millan - - * util/update-grub.in: Reorganise terminal validity check. Accept - `ieee1275:console' (OLPC) and `*:gfxterm' as valid too. - Based on suggestion by Franklin PIAT. - -2008-02-28 Fabian Greffrath - - * include/grub/util/getroot.h (grub_util_check_block_device): Export new - function. - * util/getroot.c (grub_util_check_block_device): New function that - returns the given argument if it is a block device and returns NULL else. - * util/grub-probe.c (argument_is_device): New variable. - (probe): Promote device_name from a variable to an argument. Receive - device_name from grub_util_check_block_device() if path is NULL and from - grub_guess_root_device() else. Do not free() device_name anymore. - (options): Introduce new parameter '-d, --device'. - (main): Add description of the new parameter to the help screen. - Rename path variable to argument. Set argument_is_device if the '-d' - option is given. Pass argument to probe() depending on - argument_is_device. - -2008-02-24 Bean - - * fs/iso9660.c (GRUB_ISO9660_VOLDESC_BOOT): New macro. - (GRUB_ISO9660_VOLDESC_PRIMARY): Likewise. - (GRUB_ISO9660_VOLDESC_SUPP): Likewise. - (GRUB_ISO9660_VOLDESC_PART): Likewise. - (GRUB_ISO9660_VOLDESC_END): Likewise. - (grub_iso9660_primary_voldesc): New member escape. - (grub_iso9660_data): New member joliet. - (grub_iso9660_convert_string): New function. - (grub_iso9660_mount): Detect joliet extension. - (grub_iso9660_iterate_dir): Convert filename when joliet is detected. - (grub_iso9660_iso9660_label): Likewise. - - * conf/common.rmk (pkgdata_MODULES): Add udf.mod. - (grub_setup_SOURCES): Add fs/udf.c. - (grub_fstest_SOURCES): Likewise. - (udf_mod_SOURCES): New variable. - (udf_mod_CFLAGS): Likewise. - (udf_mod_LDFLAGS): Likewise. - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/udf.c. - (grub_emu_SOURCES): Likewise. - - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - - * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - - * fs/udf.c: New file. - -2008-02-24 Robert Millan - - * conf/i386-efi.rmk (normal/function.c_DEPENDENCIES) - (normal/lexer.c_DEPENDENCIES): New variables. - * conf/i386-ieee1275.rmk (normal/function.c_DEPENDENCIES) - (normal/lexer.c_DEPENDENCIES): Likewise. - * conf/i386-linuxbios.rmk (normal/function.c_DEPENDENCIES) - (normal/lexer.c_DEPENDENCIES): Likewise. - * conf/i386-pc.rmk (normal/function.c_DEPENDENCIES) - (normal/lexer.c_DEPENDENCIES): Likewise. - * conf/powerpc-ieee1275.rmk (normal/function.c_DEPENDENCIES) - (normal/lexer.c_DEPENDENCIES): Likewise. - * conf/sparc64-ieee1275.rmk (normal/function.c_DEPENDENCIES) - (normal/lexer.c_DEPENDENCIES): Likewise. - -2008-02-23 Robert Millan - - * partmap/gpt.c (grub_gpt_magic): Add `0x' qualifier to each member, - since they were intended to be in hex. This didn't break previously - because of a bug in gpt_partition_map_iterate() (see below). - - (gpt_partition_map_iterate): Replace `grub_memcmp' with `! grub_memcmp' - when checking the validity of GPT header. - Remove `partno', since it always provides the same information as `i'. - -2008-02-21 Yoshinori K. Okuji - - * include/grub/efi/time.h: Fix a wrong comment. - -2008-02-19 Pavel Roskin - - * kern/rescue.c (grub_enter_rescue_mode): Improve initial - message. - -2008-02-19 Bean - - * conf/i386-pc.rmk (pkglib_MODULES): Add aout.mod _bsd.mod and bsd.mod. - (aout_mod_SOURCES): New variable. - (aout_mod_CFLAGS): Likewise. - (aout_mod_LDFLAGS): Likewise. - (_bsd_mod_SOURCES): New variable. - (_bsd_mod_CFLAGS): Likewise. - (_bsd_mod_LDFLAGS): Likewise. - (bsd_mod_SOURCES): New variable. - (bsd_mod_CFLAGS): Likewise. - (bsd_mod_LDFLAGS): Likewise. - - * include/grub/aout.h: New file. - - * include/grub/i386/loader.h (grub_unix_real_boot): New function. - - * include/grub/i386/bsd.h: New file. - - * include/grub/i386/pc/init.h (grub_get_mmap_entry): Use EXPORT_FUNC - to make it public. - - * kern/elf.c (grub_elf32_load): Get the physical address after the hook - function is called, so that it's possible to change it inside the hook. - (grub_elf64_load): Likewise. - (grub_elf_file): Don't close the file if elf header is not found. - (grub_elf_close): Close the file if grub_elf_file fails (The new - grub_elf_file won't close it). - (grub_elf32_size): Use NESTED_FUNC_ATTR for nested function calcsize. - (grub_elf64_size): Likewise. - - * kern/i386/loader.S (grub_unix_real_boot): New function. - - * loader/aout.c: New file. - - * loader/i386/bsd.c: New file. - - * loader/i386/bsd_normal.c: New file. - - * loader/i386/pc/multiboot.c (grub_multiboot): Handle a.out format. - - * loader/multiboot2.c (grub_multiboot2): Reset grub_errno so that it - can test other formats. - -2008-02-19 Robert Millan - - * partmap/gpt.c: Include `'. - (grub_gpt_partition_type_empty): Redefine with macro from - `'. - (gpt_partition_map_iterate): Adjust partition type comparison. - - Export `entry' as partmap-specific `part.data' struct. - (grub_gpt_header, grub_gpt_partentry): Move from here ... - - * include/grub/gpt_partition.h (grub_gpt_header) - (grub_gpt_partentry): ... to here (new file). - - * util/i386/pc/grub-setup.c: Include `'. - - (grub_gpt_partition_type_bios_boot): New const variable, defined - with macro from `'. - - (setup): Replace `first_start' with `embed_region', which keeps - track of the embed region (and is partmap-agnostic). - - Replace find_first_partition_start() with find_usable_region(), - which finds a usable region for embedding using partmap-specific - knowledge (supports PC/MSDOS and GPT). - - Fix all assumptions that the embed region start at sector 1, using - `embed_region.start' from now on. Similarly, use `embed_region.end' - rather than `first_start' to calculate available size. - - In grub_util_info() message, replace "into after the MBR" with an - indication of the specific sector our embed region starts at. - -2008-02-19 Robert Millan - - * DISTLIST: Replace `commands/ieee1275/halt.c' and - `commands/ieee1275/reboot.c' with `commands/halt.c' and - `commands/reboot.c'. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES, reboot_mod_SOURCES) - (halt_mod_SOURCES): Likewise. - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES, reboot_mod_SOURCES) - (halt_mod_SOURCES): Likewise. - -2008-02-17 Christian Franke - - * commands/cat.c (grub_cmd_cat): Add break on GRUB_TERM_ESC key. - -2008-02-17 Robert Millan - - * util/i386/pc/grub-setup.c (setup): In find_first_partition_start(), - set `first_start' to 0 for non-PC/MSDOS partition maps. - -2008-02-16 Robert Millan - - * util/i386/pc/grub-setup.c (setup): In find_first_partition_start(), - do not assume partition map is PC/MSDOS before performing checks that - are specific to that layout. - -2008-02-13 Robert Millan - - * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Remove - `commands/i386/pc/halt.c' and `commands/i386/pc/reboot.c'. - * kern/i386/linuxbios/init.c (grub_halt, grub_reboot): Remove stubs. - -2008-02-13 Yoshinori K. Okuji - - * configure.ac: Only a cosmetic change on the handling of - -fno-stack-protector. - -2008-02-12 Alexandre Boeglin - - * conf/i386-efi.rmk (grub_emu_SOURCES): Replace - commands/i386/pc/halt.c and reboot.c by commands/halt.c and - reboot.c. - (grub_install_SOURCES): Add halt.mod and reboot.mod. - (halt_mod_SOURCES): New variable. - (halt_mod_CFLAGS): Likewise. - (halt_mod_LDFLAGS): Likewise. - (reboot_mod_SOURCES): Likewise. - (reboot_mod_CFLAGS): Likewise. - (reboot_mod_LDFLAGS): Likewise. - - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Replace - commands/ieee1275/halt.c and reboot.c by commands/halt.c and - reboot.c. - (halt_mod_SOURCES): Likewise. - (reboot_mod_SOURCES): Likewise. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Replace - commands/i386/pc/reboot.c by commands/reboot.c. - (reboot_mod_SOURCES): Likewise. - - * commands/i386/pc/reboot.c: merge this file ... - - * commands/ieee1275/reboot.c: ... and this file ... - - * commands/reboot.c: ... to this file. - Add some precompiler directive to include the correct header for - each machine. - - * commands/ieee1275/halt.c: move this file ... - - * commands/halt.c: ... to here. - Add some precompiler directive to include the correct header for - each machine. - - * include/grub/efi/efi.h (grub_reboot): New function declaration. - (grub_halt): Likewise. - - * kern/efi/efi.c (grub_reboot): New function. - (grub_halt): Likewise. - -2008-02-12 Robert Millan - - * util/getroot.c (grub_guess_root_device): Inspect /dev/evms before - /dev (like it is done for /dev/mapper). This doesn't provide support - for EVMS, but at least it is now easy to identify the problem when it - arises. - -2008-02-11 Robert Millan - - * util/biosdisk.c (grub_util_biosdisk_open, linux_find_partition) - (grub_util_biosdisk_get_grub_dev): Check open() exit status by - comparing it with -1, not 0. - -2008-02-10 Robert Millan - - * conf/i386-efi.rmk (grub_emu_SOURCES): Add `disk/raid.c' and - `disk/lvm.c'. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-pc.rmk (grub_setup_SOURCES): Likewise. - - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Move `disk/raid.c' and - `disk/lvm.c' to the end of the list. - * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise. - -2008-02-10 Robert Millan - - * kern/main.c (grub_load_normal_mode): Do not reset `grub_errno'. Call - grub_print_error() instead. This will let user know why we're entering - rescue mode. - Based on suggestions from Sam Morris. - -2008-02-10 Alexandre Boeglin - - * normal/arg.c (grub_arg_parse): If one of the args is "--", call add_arg() - on remaining N args, instead of "--" arg N times. - -2008-02-09 Vesa Jaaskelainen - - * font/manager.c (unknown_glyph): Added variable for unknown glyph. - (fill_with_default_glyph): Changed to use unknown_glyph for fill - pattern for unknown glyphs. - -2008-02-09 Robert Millan - - * configure.ac: Probe for `help2man'. - * Makefile.in (builddir): New variable. - (HELP2MAN): Likewise. Set to `true' when @HELP2MAN@ doesn't provide it, - or otherwise add a few flags/options to it. - (install-local): For every executable utility or script that is - installed, invoke $(HELP2MAN) to install a manpage based on --help - output. - - * util/i386/pc/grub-install.in: Move down `update-grub_lib' sourcing, so - that it doesn't prevent --help from working in build tree. - - * util/i386/pc/grub-mkrescue.in (usage): Replace `grub-devel@gnu.org' - with `bug-grub@gnu.org'. - * util/powerpc/ieee1275/grub-mkrescue.in (usage): Likewise. - * util/update-grub.in (usage): New function. - Implement proper argument check, with support for --help and --version - (as well as existing -y). - -2008-02-09 Christian Franke - - * commands/cat.c (grub_cmd_cat): Print '\r' as hex to - avoid overwriting previous output. - * kern/rescue.c (grub_rescue_cmd_cat): Likewise. - -2008-02-09 Robert Millan - - * normal/menu.c (run_menu): If timeout is set to zero, don't bother - drawing the menu. - -2008-02-09 Robert Millan - - * commands/sleep.c: New file. - * conf/common.rmk (pkglib_MODULES): Add `commands/sleep.c'. - (sleep_mod_SOURCES): New variable. - (sleep_mod_CFLAGS): Likewise. - (sleep_mod_LDFLAGS): Likewise. - -2008-02-09 Robert Millan - - * disk/raid.c (grub_raid_scan_device): Add a pair of sanity checks for - situations in which we can deduce the RAID size and the superblock - doesn't match it. - -2008-02-09 Robert Millan - - * disk/lvm.c [GRUB_UTIL] (grub_lvm_memberlist): New function. Construct - and return a grub_diskmemberlist_t composed of LVM physical volumes. - [GRUB_UTIL] (grub_lvm_dev): Add `memberlist' member. - - * disk/raid.c [GRUB_UTIL] (grub_raid_memberlist): New function. Construct - and return a grub_diskmemberlist_t composed of physical array members. - [GRUB_UTIL] (grub_raid_dev): Add `memberlist' member. - - * include/grub/disk.h [GRUB_UTIL] (grub_disk_memberlist): New struct - prototype. - [GRUB_UTIL] (struct grub_disk_dev): Add `memberlist' function pointer. - [GRUB_UTIL] (struct grub_disk_memberlist): New struct declaration. - [GRUB_UTIL] (grub_disk_memberlist_t): New typedef. - - * util/grub-probe.c (probe): Move partmap probing code from here ... - (probe_partmap): ... to here. - (probe): Use probe_partmap() once for the disk we're probing, and - additionally, when such disk contains a memberlist() struct member, - once for each disk that is contained in the structure returned by - memberlist(). - -2008-02-09 Robert Millan - - * util/grub-probe.c (main): When `verbosity > 1', set `debug' - environment variable to 'all' in order to obtain debug output from - non-util/ code. - * util/i386/pc/grub-setup.c (main): Likewise. - -2008-02-08 Robert Millan - - * disk/raid.c (grub_raid_scan_device): Check for - `array->device[sb.this_disk.number]' rather than for - `array->device[sb.this_disk.number]->name', since the latter is not - guaranteed to be accessible. - -2008-02-08 Robert Millan - - * disk/raid.c: Update copyright. - * fs/cpio.c: Likewise. - * include/grub/raid.h: Likewise. - * loader/i386/pc/multiboot.c: Likewise. - * util/hostfs.c: Likewise. - -2008-02-08 Robert Millan - - * include/grub/raid.h (struct grub_raid_array): Change type of `device' - to a grub_disk_t array. - * disk/raid.c (grub_raid_read): Replace `device[x].disk' accesses with - `device[x]'. - (grub_raid_scan_device): Replace `device[x].name' accesses with - `device[x]->name'. Simplify initialization of `array->device[x]'. - -2008-02-08 Robert Millan - - * disk/raid.c (grub_raid_open, grub_raid_scan_device): Add a few - grub_dprintf() calls. - * kern/disk.c (grub_disk_read): Include grub_errmsg in out of range - error message. - -2008-02-07 Christian Franke - - * util/hostfs.c (grub_hostfs_open): Use fseeko and ftello - instead of fseek and ftell to support large files. - (grub_hostfs_read): Likewise. - -2008-02-07 Robert Millan - - Patch from Jeroen Dekkers. - * disk/raid.c (grub_raid_scan_device): Reset `grub_errno' on disk - failure, since successfully reading all array members might not be - required. - -2008-02-06 Robert Millan - - * util/grub-probe.c (probe): Simplify partmap probing (with the - assumption that the first word up to the underscore equals to - the module name). - -2008-02-06 Christian Franke - - * fs/cpio.c (grub_cpio_find_file): Return GRUB_ERR_NONE - (and set *ofs = 0) instead of GRUB_ERR_FILE_NOT_FOUND on - last block of a cpio or tar stream. - Check for "TRAILER!!!" instead of any empty data - block to detect last block of a cpio stream. - (grub_cpio_dir): Fix constness of variable np. - (grub_cpio_open): Return GRUB_ERR_FILE_NOT_FOUND if - cpio or tar trailer is detected. This fixes a crash - on open of a non existing file. - -2008-02-05 Bean - - * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Get physical - address of entry. - (grub_multiboot_load_elf64): Likewise. - (grub_multiboot): Initialize mbi structure. - - * util/grub-fstest.c: Don't include unused header file script.h. - - * conf/common.rmk (grub-fstest.c_DEPENDENCIES): Move to the beginning - of file. - (grub_fstest_SOURCES): Likewise. - -2008-02-05 Robert Millan - - * include/grub/term.h (GRUB_TERM_LEFT, GRUB_TERM_RIGHT) - (GRUB_TERM_UP, GRUB_TERM_DOWN, GRUB_TERM_HOME, GRUB_TERM_END) - (GRUB_TERM_DC, GRUB_TERM_PPAGE, GRUB_TERM_NPAGE, GRUB_TERM_ESC) - (GRUB_TERM_TAB, GRUB_TERM_BACKSPACE): New macros. - - * kern/i386/pc/startup.S: Include `'. - (translation_table): Replace hardcoded values with macros - provided by `'. - - * term/i386/pc/at_keyboard.c: Include `'. - (keyboard_map): Correct/add a few values, with macros provided - by `'. - (keyboard_map_shift): Zero values that don't differ from their - `keyboard_map' equivalents. - (grub_console_checkkey): Optimize KEYBOARD_STATUS_CAPS_LOCK toggling. - Discard the second scan code that is always sent by Caps lock. - Only use `keyboard_map_shift' when it provides a non-zero value, - otherwise fallback to `keyboard_map'. - -2008-02-04 Bean - - * Makefile.in (enable_grub_fstest): New variable. - - * conf/common.rmk (grub_fstest_init.lst): New rule. - (grub_fstest_init.h): Likewise. - (grub_fstest_init.c): Likewise. - (util/grub-fstest.c_DEPENDENCIES): New variable. - (grub_fstest_SOURCES): Likewise. - - * configure.ac (enable_grub_fstest): Check for --enable-grub-fstest. - - * util/grub-fstest.c: New file. - -2008-02-03 Yoshinori K. Okuji - - Make grub-setup handle a separate root device. - - * util/i386/pc/grub-setup.c (setup): Always open the root device, - so that the root device can be compared with the destination - device. - When embedding the core image, if the root and destination devices - are different, set ROOT_DRIVE to ROOT_DEV->DISK->ID. Otherwise, to - 0xFF. - When not embedding, set ROOT_DRIVE to 0xFF. - -2008-02-03 Yoshinori K. Okuji - - Add support for having a grub directory in a different drive. This - is still only the data handling part. - - * kern/i386/pc/startup.S (multiboot_trampoline): Set %dh to 0xFF. - (codestart): Save %dh in GRUB_ROOT_DRIVE. - (grub_root_drive): New variable. - - * kern/i386/pc/init.c (make_install_device): Use GRUB_ROOT_DRIVE - instead of GRUB_BOOT_DRIVE to construct a device name. Set - GRUB_ROOT_DRIVE to GRUB_BOOT_DRIVE if it is 0xFF, otherwise use it - as it was. - - * include/grub/i386/pc/kernel.h (grub_root_drive): New prototype. - - * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_ROOT_DRIVE): New - macro. - (GRUB_BOOT_MACHINE_DRIVE_CHECK): Set to 0x4f. - - * boot/i386/pc/pxeboot.S (_start): Set %dh to 0xFF. For now, this - is bogus, because PXE booting does not specify any drive - correctly. - - * boot/i386/pc/lnxboot.S (reg_edx): Set the second byte to 0xFF. I - am not sure if this is really correct. - - * boot/i386/pc/cdboot.S: Set %dh to 0xFF, because the root drive - is always identical to the boot drive when booting from a CD. - - * boot/i386/pc/boot.S (MOV_MEM_TO_AL): Removed. Not needed any - longer. - (root_drive): New variable. - (real_start): Unconditionally set %dh to ROOT_DRIVE. - (setup_sectors): Push %dx right after popping it, because %dh will - be modified later. - (copy_buffer): Restore %dx. - -2008-02-03 Robert Millan - - * util/i386/pc/grub-mkrescue.in: Rewrite most of image generation to - use `cdboot.img' for cdrom images. - -2008-02-03 Robert Millan - - * util/grub.d/00_header.in: Issue scripting commands for GRUB to - only setup gfxterm when `font' command has succeeded. - -2008-02-03 Robert Millan - - * loader/multiboot_loader.c [GRUB_MACHINE_LINUXBIOS] - (grub_rescue_cmd_multiboot_loader) - (grub_rescue_cmd_module_loader): Enable multiboot1 calls. - -2008-02-03 Pavel Roskin - - * kern/i386/pc/startup.S (grub_chainloader_real_boot): Pop - %edx and %esi from stack only after grub_gate_a20() is called. - grub_gate_a20() clobbers %edx. - -2008-02-03 Yoshinori K. Okuji - - * configure.ac (AC_INIT): Bumped to 1.96. - - * DISTLIST: Added boot/i386/pc/cdboot.S, bus/pci.c, - commands/lspci.c,disk/memdisk.c, include/grub/pci.h, - include/grub/i386/pc/pci.h, video/readers/jpeg.c, and - video/readers/png.c. - -2008-02-03 Bean - - * conf/i386-pc.rmk (pkglib_IMAGES): Add cdboot.img. - (cdboot_img_SOURCES): New variable. - (cdboot_img_ASFLAGS): New variable. - (cdboot_img_LDFLAGS): New variable. - - * boot/i386/pc/cdboot.S: New file. - - * disk/i386/pc/biosdisk.c (cd_start): New variable. - (cd_count): Likewise. - (grub_biosdisk_get_drive): Add support for cd device. - (grub_biosdisk_call_hook): Likewise. - (grub_biosdisk_iterate): Likewise. - (grub_biosdisk_open): Likewise. - (GRUB_BIOSDISK_CDROM_RETRY_COUNT): New macro. - (grub_biosdisk_rw): Support reading from cd device. - (GRUB_MOD_INIT): Iterate cd devices. - - * include/grub/i386/pc/biosdisk.h (GRUB_BIOSDISK_FLAG_CDROM): New macro. - (GRUB_BIOSDISK_MACHINE_CDROM_START): Likewise. - (GRUB_BIOSDISK_MACHINE_CDROM_END): Likewise. - - * kern/i386/pc/init.c (make_install_device): Check for cd device. - -2008-02-02 Robert Millan - - * commands/read.c: New file. - * conf/common.rmk (pkglib_MODULES): Add `commands/read.c'. - (read_mod_SOURCES): New variable. - (read_mod_CFLAGS): Likewise. - (read_mod_LDFLAGS): Likewise. - -2008-02-02 Robert Millan - - * normal/main.c (grub_normal_execute): Check for `menu->size' when - determining whether menu has to be displayed. - -2008-02-02 Marco Gerards - - * bus/pci.c: New file. - - * include/grub/pci.h: Likewise. - - * include/grub/i386/pc/pci.h: Likewise. - - * commands/lspci.c: Likewise. - - * conf/i386-pc.rmk (pkglib_MODULES): Add `pci.mod' and - `lspci.mod'. - (pci_mod_SOURCES): New variable. - (pci_mod_CFLAGS): Likewise. - (pci_mod_LDFLAGS): Likewise. - (lspci_mod_SOURCES): Likewise. - (lspci_mod_CFLAGS): Likewise. - (lspci_mod_LDFLAGS): Likewise. - -2008-02-02 Bean - - * fs/ufs.c (INODE_BLKSZ): Fix incorrect value. - (grub_ufs_get_file_block): Fix indirect block calculation problem. - - * fs/xfs.c (grub_xfs_sblock): New member log2_dirblk. - (grub_xfs_btree_node): New structure. - (grub_xfs_btree_root): New structure. - (grub_xfs_inode): New members nblocks, extsize, nextents and btree. - (GRUB_XFS_EXTENT_OFFSET): Use exts instead of inode->data.extents. - (GRUB_XFS_EXTENT_BLOCK): Likewise. - (GRUB_XFS_EXTENT_SIZE): Likewise. - (grub_xfs_read_block): Support btree format type. - (grub_xfs_iterate_dir): Use NESTED_FUNC_ATTR in call_hook. - Use directory block as basic unit. - - * fs/fshelp.c (grub_fshelp_read_file): Bug fix for sparse block. - - * aclocal.m4 (grub_i386_CHECK_REGPARM_BUG): Define NESTED_FUNC_ATTR as - __attribute__ ((__regparm__ (1))). - -2008-02-01 Robert Millan - - Correct a mistake in previous commit. - - * conf/i386-pc.rmk (normal/execute.c_DEPENDENCIES): Move to the - top. - (normal/command.c_DEPENDENCIES): New variable. - -2008-02-01 Robert Millan - - * conf/i386-efi.rmk (normal/execute.c_DEPENDENCIES): Move to the - top. - (normal/command.c_DEPENDENCIES): New variable. - (grub-emu_DEPENDENCIES, normal_mod_DEPENDENCIES): Remove variables. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-linuxbios.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - (grub_emu_SOURCES): Add `fs/fshelp.c'. - - * genmk.rb: Add `$(#{src}_DEPENDENCIES)' in targets that require it. - -2008-02-01 Robert Millan - - * kern/disk.c (grub_disk_read, grub_disk_write): Add grub_dprintf() - call at beginning of function. - -2008-01-31 Pavel Roskin - - * util/powerpc/ieee1275/grub-mkrescue.in: New file. - * conf/powerpc-ieee1275.rmk (bin_SCRIPTS): New variable. - (grub_mkrescue_SOURCES): Likewise. - * DISTLIST: Add util/powerpc/ieee1275/grub-mkrescue.in. - -2008-01-30 Robert Millan - - * conf/i386-pc.rmk (sbin_UTILITIES): Remove `grub-probe'. - (util/grub-probe.c_DEPENDENCIES, grub_probe_SOURCES): Moved from here ... - * conf/common.rmk (util/grub-probe.c_DEPENDENCIES) - (grub_probe_SOURCES): ... to here. - - * conf/i386-efi.rmk (sbin_UTILITIES): Remove `grub-probe'. - (util/grub-probe.c_DEPENDENCIES, grub_probe_SOURCES): Remove. - * conf/i386-ieee1275.rmk: Likewise. - * conf/i386-linuxbios.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - -2008-01-30 Tristan Gingold - - * kern/rescue.c: Silently accept empty lines. - -2008-01-29 Bean - - * boot/i386/pc/lnxboot.S (data_start): Code cleanup. - (real_code_2): Code cleanup and change comment style. - (move_memory): Avoid using 32-bit address mode. - -2008-01-29 Bean - - * conf/i386-pc.rmk (pkglib_MODULES): Add `png.mod'. - (png_mod_SOURCES): New variable. - (png_mod_CFLAGS): Likewise. - (png_mod_LDFLAGS): Likewise. - - * video/readers/png.c: New file. - -2008-01-28 Robert Millan - - * include/grub/i386/linuxbios/kernel.h (GRUB_MOD_GAP): New macro. - * kern/powerpc/ieee1275/init.c (grub_arch_modules_addr): Remove - `ifndef GRUB_MOD_GAP' hack. - * util/elf/grub-mkimage.c (add_segments): Likewise. - -2008-01-27 Robert Millan - - * kern/powerpc/ieee1275/init.c (grub_arch_modules_addr): Skip - `GRUB_MOD_GAP' for platforms in which it's not defined. - * util/elf/grub-mkimage.c (add_segments): Likewise. - -2008-01-27 Robert Millan - - Get grub-emu to build again (including parallel builds). - - * conf/i386-pc.rmk (util/grub-emu.c_DEPENDENCIES): Remove variable. - Split into ... - (util/grub-emu.c_DEPENDENCIES): ... this, ... - (normal/execute.c_DEPENDENCIES): ... this, ... - (grub-emu_DEPENDENCIES): ... and this. - - * conf/i386-efi.rmk: Likewise. - * conf/i386-linuxbios.rmk: Likewise. - * conf/i386-ieee1275.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - (grub_emu_SOURCES): Remove duplicated `kern/file.c'. - -2008-01-27 Robert Millan - - * NEWS: Add a few items. - -2008-01-27 Robert Millan - - Fix parallel builds with grub-emu. Based on earlier commit for - grub-probe and grub-setup. - - * conf/i386-pc.rmk (grub-emu_DEPENDENCIES): Renamed to ... - (util/grub-emu.c_DEPENDENCIES): ... this. - * conf/i386-efi.rmk (grub-emu_DEPENDENCIES): Renamed to ... - (util/grub-emu.c_DEPENDENCIES): ... this. - * conf/i386-linuxbios.rmk (grub-emu_DEPENDENCIES): Renamed to ... - (util/grub-emu.c_DEPENDENCIES): ... this. - * conf/i386-ieee1275.rmk (grub-emu_DEPENDENCIES): Renamed to ... - (util/grub-emu.c_DEPENDENCIES): ... this. - * conf/powerpc-ieee1275.rmk (grub-emu_DEPENDENCIES): Renamed to ... - (util/grub-emu.c_DEPENDENCIES): ... this. - -2008-01-27 Pavel Roskin - - * include/grub/powerpc/ieee1275/kernel.h: Introduce GRUB_MOD_GAP - to create a gap between _end and the modules added to the image - with grub-mkrescue. That fixes "CLAIM failed" on PowerMAC. - * kern/powerpc/ieee1275/init.c: Use GRUB_MOD_GAP. - * util/elf/grub-mkimage.c (add_segments): Likewise. - -2008-01-26 Pavel Roskin - - * kern/dl.c (grub_dl_load): Don't abort if prefix is not set, - just return an error. - -2008-01-26 Bean - - * fs/reiserfs.c (grub_fshelp_node): New member next_offset. - (grub_reiserfs_get_item): Save offset of the next item. - (grub_reiserfs_iterate_dir): Use next_offset to find next item. - -2008-01-25 Robert Millan - - * conf/i386-pc.rmk (grub_setup_SOURCES, grub_emu_SOURCES): Regroup to - make all filesystem sources appear together (possibly fixing omissions - while at it). - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-ieee1275.rmk (grub_emu_SOURCES): Likewise. - * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - - * conf/i386-pc.rmk (grub_probe_SOURCES): Likewise. Additionally, - add `kern/file.c'. - * conf/i386-efi.rmk (grub_probe_SOURCES): Likewise. - * conf/i386-ieee1275.rmk (grub_probe_SOURCES): Likewise. - * conf/i386-linuxbios.rmk (grub_probe_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_probe_SOURCES): Likewise. - - * util/grub-probe.c: Include `' and `'. - (probe): Add a sanity check to make sure of our ability to read - requested files when probing for filesystem type. - - * genmk.rb: Update copyright year (2007). - - * include/grub/fs.h (grub_fat_init, grub_fat_fini, grub_ext2_init) - (grub_ext2_fini, grub_ufs_init, grub_ufs_fini, grub_minix_init) - (grub_minix_fini, grub_hfs_init, grub_hfs_fini, grub_jfs_init) - (grub_jfs_fini, grub_xfs_init, grub_xfs_fini, grub_affs_init) - (grub_affs_fini, grub_sfs_init, grub_sfs_fini, grub_iso9660_init) - : Remove function prototypes. - -2008-01-25 Robert Millan - - Revert my previous commits (based on wrong assumption of how grub_errno - works). - - * kern/disk.c (grub_disk_open): Stop resetting grub_errno. - * kern/file.c (grub_file_open): Likewise. - -2008-01-24 Pavel Roskin - - * include/grub/ieee1275/ieee1275.h: Introduce flag for firmwares - that hang if GRUB tries to setup colors. - * term/ieee1275/ofconsole.c (grub_ofconsole_init): Don't set - colors for firmwares that don't support it. - * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_set_flag): - Recognize Open Hack'Ware, set flags to work around its - limitations. - -2008-01-24 Robert Millan - - * kern/file.c (grub_file_open): Do not account previous failures of - unrelated functions when grub_errno is checked for. - Reported by Oleg Strikov. - -2008-01-24 Bean - - * fs/ufs.c (GRUB_UFS_VOLNAME_LEN): New macro. - (grub_ufs_sblock): New member volume name. - (grub_ufs_find_file): Fix string copy bug. - (grub_ufs_label): Implement this function properly. - - * fs/hfs.c (grub_hfs_cnid_type): New enum. - (grub_hfs_iterate_records): Use the correct file number for extents - and catalog file. Fix problem in next index calculation. - (grub_hfs_find_node): Replace recursive function call with loop. - (grub_hfs_iterate_dir): Replace recursive function call with loop. - -2008-01-23 Robert Millan - - * include/grub/i386/ieee1275/loader.h: Include `', - `' and `'. - (grub_multiboot2_real_boot): New function prototype. - - * include/grub/i386/pc/memory.h: Include `'. - [!GRUB_MACHINE_IEEE1275] (grub_lower_mem, grub_upper_mem): Disable. - - * kern/i386/ieee1275/init.c (grub_os_area_addr) - (grub_os_area_size, grub_lower_mem, grub_upper_mem): Remove variables. - -2008-01-23 Robert Millan - - * kern/mm.c (grub_mm_init_region): Replace grub_dprintf() call with - #ifdef'ed out grub_printf(). - -2008-01-23 Robert Millan - - * term/i386/pc/at_keyboard.c (grub_keyboard_isr): #ifdef out - grub_dprintf calls, since they make "debug=all" mode unusable. - (grub_console_checkkey): Likewise. - -2008-01-23 Robert Millan - - * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Add - `term/i386/pc/at_keyboard.c'. - (pkglib_MODULES): Add `serial.mod'. - (serial_mod_SOURCES): New variable. - (serial_mod_CFLAGS): Likewise. - (serial_mod_LDFLAGS): Likewise. - - * include/grub/i386/ieee1275/console.h: Add `'. Remove - `'. - (grub_keyboard_controller_init): New function prototype. - (grub_console_checkkey): Likewise. - (grub_console_getkey): Likewise. - - * kern/powerpc/ieee1275/init.c (grub_machine_init): Initialize AT - keyboard on i386. - - * term/ieee1275/ofconsole.c (grub_ofconsole_term): On i386, use - grub_ofconsole_checkkey() and grub_ofconsole_getkey() for input. - -2008-01-23 Robert Millan - - * kern/i386/pc/init.c (make_install_device): When memdisk image is - present, "(memdisk)/boot/grub" becomes the default prefix. - - * util/i386/pc/grub-mkrescue.in: Switch to a minimal core.img plus - a memdisk tarball with all the modules. Add --overlay=DIR option that - allows users to overlay additional files into the image. - -2008-01-23 Robert Millan - - * conf/i386-ieee1275.rmk (kernel_elf_SOURCES): Add `machine/loader.h' - and `machine/memory.h'. - (pkglib_MODULES): Add `multiboot.mod' and `_multiboot.mod'. - (_multiboot_mod_SOURCES): New variable. - (_multiboot_mod_CFLAGS): Likewise. - (_multiboot_mod_LDFLAGS): Likewise. - (multiboot_mod_SOURCES): Likewise. - (multiboot_mod_CFLAGS): Likewise. - (multiboot_mod_LDFLAGS): Likewise. - - * include/grub/i386/ieee1275/loader.h: New file. - - * include/grub/i386/ieee1275/machine.h: Likewise. - - * include/grub/i386/ieee1275/memory.h: Likewise. - - * include/grub/i386/pc/init.h (grub_os_area_addr): Remove (redundant) - variable declaration. - (grub_os_area_size): Likewise. - - * kern/i386/ieee1275/init.c (grub_os_area_addr, grub_os_area_size) - (grub_lower_mem, grub_upper_mem): New variables. - (grub_stop_floppy): New function (just to make - grub_multiboot2_real_boot() happy). - - * kern/i386/ieee1275/startup.S: Include `', - `', `' and `'. - (grub_stop): New function. - Include `"../realmode.S"' and `"../loader.S"'. - - * loader/multiboot_loader.c: Include `'. - Replace `__i386__' #ifdefs with `GRUB_MACHINE_PCBIOS'. - - * loader/powerpc/ieee1275/multiboot2.c (grub_mb2_arch_boot): On i386, - rely on grub_multiboot2_real_boot() for final boot. - -2008-01-22 Robert Millan - - * disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): When - `GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY' flag is set, skip any - device that doesn't look like an SD card. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): Add - `GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY' flag. - * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_set_flag): Detect - OLPC laptop, and set `GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY' when - found. - -2008-01-22 Robert Millan - - * kern/powerpc/ieee1275/init.c (grub_claim_heap): Add sanity check to - avoid claiming over our own code. - -2008-01-22 Bean - - * conf/i386-pc.rmk (pkglib_MODULES): Add `jpeg.mod'. - (jpeg_mod_SOURCES): New variable. - (jpeg_mod_CFLAGS): Likewise. - (jpeg_mod_LDFLAGS): Likewise. - - * video/readers/jpeg.c : New file. - -2008-01-22 Bean - - * fs/cpio.c (grub_cpio_find_file): Return GRUB_ERR_FILE_NOT_FOUND when - there are no more items. - -2008-01-21 Robert Millan - - * kern/mm.c (grub_mm_init_region): Improve debug message. - -2008-01-21 Robert Millan - - * conf/i386-pc.rmk (GRUB_MEMORY_MACHINE_LINK_ADDR): New variable. - (kernel_img_LDFLAGS): Use `GRUB_MEMORY_MACHINE_LINK_ADDR' as link - address. - (grub_mkimage_CFLAGS): Propagate `GRUB_MEMORY_MACHINE_LINK_ADDR' as - a C macro. - * include/grub/i386/pc/memory.h (GRUB_MEMORY_MACHINE_UPPER): New macro. - Indicates start of upper memory. - * util/i386/pc/grub-mkimage.c: Include `'. - (generate_image): Abort when image size is big enough to corrupt - upper memory. - - * include/grub/i386/pc/vga.h: Include `'. - (GRUB_MEMORY_MACHINE_VGA_ADDR): Alias for `GRUB_MEMORY_MACHINE_UPPER'. - * term/i386/pc/vga.c (VGA_MEM): Use `GRUB_MEMORY_MACHINE_VGA_ADDR' - instead of hardcoding 0xA0000. - * video/i386/pc/vbe.c: Include `'. - (grub_vbe_set_video_mode): Use `GRUB_MEMORY_MACHINE_VGA_ADDR' - instead of hardcoding 0xA0000. - -2008-01-21 Robert Millan - - * disk/memdisk.c (memdisk_size): New variable. - (grub_memdisk_open): Replace grub_arch_memdisk_size() call with - `memdisk_size'. - (grub_memdisk_init): Initialize `memdisk_size'. Reallocate memdisk - image to dynamic memory. - (grub_memdisk_fini): Replace grub_arch_memdisk_size() call with - `memdisk_size'. Free memdisk block. - -2008-01-21 Robert Millan - - Fix detection of very small filesystems (like tar). - - * fs/reiserfs.c (grub_reiserfs_mount): When disk is too small to - contain a ReiserFS, abort with GRUB_ERR_BAD_FS rather than - GRUB_ERR_OUT_OF_RANGE (which made the upper layer think there's - a problem with this disk). - -2008-01-21 Robert Millan - - * disk/i386/pc/biosdisk.c (grub_biosdisk_iterate): Add debug message - on grub_biosdisk_rw_standard() error. - -2008-01-21 Robert Millan - - * include/grub/ieee1275/ieee1275.h: Add 2008 to Copyright line for - recent changes. - * kern/elf.c: Likewise. - * kern/ieee1275/ieee1275.c: Likewise. - * kern/powerpc/ieee1275/openfw.c: Likewise. - * term/ieee1275/ofconsole.c: Likewise. - -2008-01-21 Robert Millan - - * include/grub/i386/pc/kernel.h: Include `'. - - * include/grub/kernel.h (grub_arch_memdisk_addr) - (grub_arch_memdisk_size): Moved from here ... - - * include/grub/i386/pc/kernel.h (grub_arch_memdisk_addr) - (grub_arch_memdisk_size): ... to here. - -2008-01-21 Robert Millan - - Mostly based on bugfix from Bean. - - * kern/elf.c (grub_elf32_phdr_iterate): Use `NESTED_FUNC_ATTR' - attribute with hook() parameter. - (grub_elf32_load): Use `NESTED_FUNC_ATTR' with grub_elf32_load_segment() - declaration. - (grub_elf64_phdr_iterate): Use `NESTED_FUNC_ATTR' - attribute with hook() parameter. - (grub_elf64_load): Use `NESTED_FUNC_ATTR' with grub_elf64_load_segment() - declaration. - -2008-01-21 Robert Millan - - * conf/i386-pc.rmk (kernel_img_HEADERS): Add `machine/kernel.h'. - (pkglib_MODULES): Add `memdisk.mod'. - (memdisk_mod_SOURCES): New variable. - (memdisk_mod_CFLAGS): Likewise. - (memdisk_mod_LDFLAGS): Likewise. - - * disk/memdisk.c: New file. - - * include/grub/disk.h (grub_disk_dev_id): Add - `GRUB_DISK_DEVICE_MEMDISK_ID'. - - * include/grub/i386/pc/kernel.h - (GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE): New macro. - (GRUB_KERNEL_MACHINE_PREFIX): Increment by 4. - (grub_kernel_image_size): New variable declaration. - (grub_total_module_size): Likewise. - (grub_memdisk_image_size): Likewise. - - * include/grub/i386/pc/memory.h - (GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR): New macro. - - * include/grub/kernel.h: Include `'. - (grub_arch_memdisk_addr): New variable declaration. - (grub_arch_memdisk_size): Likewise. - - * kern/i386/pc/init.c (grub_arch_memdisk_addr): New function. - (grub_arch_memdisk_size): Likewise. - - * kern/i386/pc/startup.S (grub_memdisk_image_size): New variable. - (codestart): Replace hardcoded `0x100000' with - `GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR' macro. - - * util/i386/pc/grub-mkimage.c: Include `'. - (generate_image): Add `memdisk_path' parameter. When `memdisk_path' is - not NULL, append the contents of the file it refers to, at the end of - the compressed kernel image. Initialize `grub_memdisk_image_size' - variable (at `GRUB_KERNEL_MACHINE_MEMDISK_IMAGE_SIZE' offset). - (options): Add "memdisk"|'m' option. - (main): Parse --memdisk|-m option, and pass user-provided path as - parameter to generate_image(). - -2008-01-20 Robert Millan - - * kern/sparc64/ieee1275/openfw.c (grub_devalias_iterate): Copy debug - grub_dprintf() calls from here ... - * kern/powerpc/ieee1275/openfw.c (grub_devalias_iterate): ... to here. - -2008-01-20 Robert Millan - - Fix detection of "real mode" when /options/real-mode? doesn't exist. - - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_mmu): New variable - declaration. - * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_mmu): New variable. - (grub_ieee1275_find_options): If `grub_ieee1275_mmu' is 0, set - `GRUB_IEEE1275_FLAG_REAL_MODE'. - (cmain): Initialize `grub_ieee1275_mmu' (using /chosen/mmu integer - property). - * kern/powerpc/ieee1275/openfw.c (grub_map): Rely on pre-initialized - `grub_ieee1275_mmu' rather than obtaining a handler on every call. - -2008-01-19 Robert Millan - - Get rid of confusing function (superseded by - `grub_ieee1275_get_integer_property') - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_decode_int_4): Remove - prototype. - * kern/ieee1275/ieee1275.c (grub_ieee1275_decode_int_4): Remove - function. - * term/ieee1275/ofconsole.c (grub_ofconsole_init): Avoid use of - grub_ieee1275_decode_int_4(), by obtaining integer properties directly - in native endianness from grub_ieee1275_get_integer_property(). - -2008-01-19 Robert Millan - - * kern/powerpc/ieee1275/openfw.c (grub_halt): Issue "power-off" - command after "shut-down", since implementations differ on which - the command for halt is. - -2008-01-19 Robert Millan - - * include/grub/i386/linuxbios/console.h: Add header protection. - (grub_keyboard_controller_init): New function prototype. - * term/i386/pc/at_keyboard.c (KEYBOARD_COMMAND_ISREADY): New macro. - (KEYBOARD_COMMAND_READ): Likewise. - (KEYBOARD_COMMAND_WRITE): Likewise. - (KEYBOARD_SCANCODE_SET1): Likewise. - (grub_keyboard_controller_write): New function. - (grub_keyboard_controller_read): Likewise. - (grub_keyboard_controller_init): Likewise. - - * term/i386/pc/console.c: Include `'. - (grub_console_init): On coreboot/LinuxBIOS, call - grub_keyboard_controller_init(). - -2008-01-19 Robert Millan - - PowerPC changes provided by Pavel Roskin. - - * kern/powerpc/ieee1275/cmain.c (cmain): Don't take any arguments. - * kern/powerpc/ieee1275/crt0.S: Store r5 in grub_ieee1275_entry_fn, - don't rely on cmain() doing it. - * kern/i386/ieee1275/startup.S (_start): Store %eax in - grub_ieee1275_entry_fn, don't rely on cmain() doing it. - -2008-01-16 Robert Millan - - * include/grub/i386/linuxbios/memory.h - (GRUB_MEMORY_MACHINE_LINUXBIOS_TABLE_ADDR): Remove macro. - * kern/i386/linuxbios/table.c (grub_linuxbios_table_iterate): Do not - receive `table_header' as argument. Instead, probe for it in the - known memory ranges where it can be present. - (grub_available_iterate): Do not pass a fixed `table_header' address - to grub_linuxbios_table_iterate(). - -2008-01-15 Robert Millan - - * configure.ac: Add `i386-ieee1275' to the list of supported targets. - * conf/i386-ieee1275.rmk: New file. - * include/grub/i386/ieee1275/console.h: Likewise. - * include/grub/i386/ieee1275/ieee1275.h: Likewise. - * include/grub/i386/ieee1275/kernel.h: Likewise. - * include/grub/i386/ieee1275/time.h: Likewise. - * kern/i386/ieee1275/init.c: Likewise. - * kern/i386/ieee1275/startup.S: Likewise. - -2008-01-15 Robert Millan - - * kern/misc.c (grub_vsprintf): Do not reset `longlongfmt' to zero - when pointers are 32-bit (but still do set it to one when they are - 64-bit). - -2008-01-15 Robert Millan - - * include/grub/ieee1275/ieee1275.h - (grub_ieee1275_get_integer_property): New function prototype. - - * kern/ieee1275/ieee1275.c: Include `'. - (grub_ieee1275_get_integer_property): New function. Wraps around - grub_ieee1275_get_property() to handle endianness. - - * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_find_options): Replace - grub_ieee1275_get_property() with grub_ieee1275_get_integer_property() - where appropriate. - * kern/powerpc/ieee1275/openfw.c (grub_available_iterate): Likewise. - (grub_map): Likewise. - * kern/sparc64/ieee1275/openfw.c (grub_map): Likewise. - -2008-01-15 Bean - - * normal/execute.c (grub_script_exec_argument_to_string): Check for undefined variable. - (grub_script_execute_cmdline): Reset grub_errno. - - * normal/main.c (read_config_file): Reset grub_errno. - - * normal/parse.y (script_init): New. - (script): Move function and menuentry here. - (delimiter): New. - (command): Add delimiter at the end of command. - (commands): Adjust to match the new command. - (commandblock): Remove grub_script_lexer_record_start. - (menuentry): Add grub_script_lexer_record_start, use the new commands. - (if): Use the new commands. - - * conf/common.rmk (pkgdata_MODULES): Add echo.mod. - -2008-01-15 Robert Millan - - * normal/menu.c (run_menu): Move timeout message from here ... - (print_timeout): ... to here. - (run_menu): Use print_timeout() once during initial draw to print - the whole message, and again in every clock tick to update only - the number of seconds. - -2008-01-15 Robert Millan - - * kern/powerpc/ieee1275/openfw.c (grub_available_iterate): Obtain - actual size of `available' from grub_ieee1275_get_property(), and - restrict parsing to that bound. - -2008-01-15 Christian Franke - - * util/grub-emu.c: Replace by . - (argp_program_version): Remove variable. - (argp_program_bug_address): Likewise. - (options): Convert from struct argp_option to struct option. - (struct arguments): Remove. - (parse_opt): Remove. - (usage): New function. - (main): Replace struct args members by simple variables. - Replace argp_parse() by getopt_long(). - Add switch to evaluate options. - Add missing "(...)" around root_dev in prefix string. - -2008-01-14 Robert Millan - - * kern/powerpc/ieee1275/init.c (grub_exit): Reimplement as a wrapper - for grub_ieee1275_exit(), in order to improve portability. - -2008-01-14 Robert Millan - - * util/grub.d/10_linux.in (prefix): Define. - (exec_prefix): Likewise. Both definitions are later used by `libdir'. - -2008-01-13 Pavel Roskin - - * disk/ieee1275/ofdisk.c (grub_ofdisk_open): Don't use - grub_errno if no errors have been detected. - -2008-01-12 Robert Millan - - * include/grub/util/getroot.h (grub_dev_abstraction_types): New enum. - (grub_util_get_dev_abstraction): New function prototype. - - * util/getroot.c: Include `' - (grub_util_get_grub_dev): Move detection of abstraction type to ... - (grub_util_get_dev_abstraction): ... here (new function). - - * util/grub-probe.c: Convert PRINT_* to an enum. Add - `PRINT_ABSTRACTION'. - (probe): Probe for abstraction type when requested. - (main): Understand `--target=abstraction'. - - * util/i386/efi/grub-install.in: Add abstraction module to core - image when it is found to be necessary. - * util/i386/pc/grub-install.in: Likewise. - * util/powerpc/ieee1275/grub-install.in: Likewise. - - * util/update-grub_lib.in (font_path): Return system path without - converting to GRUB path. - * util/update-grub.in: Convert system path returned by font_path() - to a GRUB path. Use `grub-probe -t abstraction' to determine what - abstraction module is needed for loading fonts (if any). Export - that as `GRUB_PRELOAD_MODULES'. - * util/grub.d/00_header.in: Process `GRUB_PRELOAD_MODULES' (print - insmod commands). - -2008-01-12 Yoshinori K. Okuji - - Remove some unused code from reiserfs. - - * fs/reiserfs.c (struct grub_reiserfs_key) - [GRUB_REISERFS_KEYV2_BITFIELD]: Removed offset and type. - (struct grub_reiserfs_node_body): Removed. - (grub_reiserfs_get_key_v2_type) [GRUB_REISERFS_KEYV2_BITFIELD]: - Likewise. - (grub_reiserfs_get_key_offset) [GRUB_REISERFS_KEYV2_BITFIELD]: - Likewise. - (grub_reiserfs_set_key_offset) [GRUB_REISERFS_KEYV2_BITFIELD]: - Likewise. - (grub_reiserfs_set_key_offset) [GRUB_REISERFS_KEYV2_BITFIELD]: - Likewise. - (grub_reiserfs_set_key_type) [GRUB_REISERFS_KEYV2_BITFIELD]: - Likewise. - (grub_reiserfs_iterate_dir) [GRUB_REISERFS_KEYV2_BITFIELD]: - Likewise. - (grub_reiserfs_open) [GRUB_REISERFS_KEYV2_BITFIELD]: Likewise. - (grub_reiserfs_read) [GRUB_REISERFS_KEYV2_BITFIELD]: Likewise. - (grub_reiserfs_dir) [GRUB_REISERFS_KEYV2_BITFIELD]: Likewise. - -2008-01-10 Robert Millan - - * util/update-grub_lib.in (grub_file_is_not_garbage): New function. - Determines if a file is garbage left by packaging systems, etc. - * util/update-grub.in: Use grub_file_is_not_garbage() as a condition - for processing /etc/grub.d scripts. - * util/grub.d/10_hurd.in: Fix `GRUB_DISTRIBUTOR' comparison. - * util/grub.d/10_linux.in: Likewise. Use grub_file_is_not_garbage() - as a condition for processing Linux images. - -2008-01-10 Pavel Roskin - - * include/grub/powerpc/libgcc.h (__ucmpdi2): New export. Needed - to compile reiserfs.c on PowerPC. - -2008-01-10 Robert Millan - - * kern/device.c (grub_device_iterate): Do not abort device iteration - when one of the devices cannot be opened. - * kern/disk.c (grub_disk_open): Do not account previous failures of - unrelated functions when grub_errno is checked for. - -2008-01-08 Robert Millan - - * loader/i386/pc/linux.c (grub_rescue_cmd_linux): For - `! grub_linux_is_bzimage', change order of address comparison to make - it more intuitive, and improve "too big zImage" error message. - -2008-01-08 Robert Millan - - * Makefile.in (uninstall): Handle `$(update-grub_SCRIPTS)' and - `$(update-grub_DATA)'. - (distcheck): Fix race condition when invoking `$(MAKE)' on multiple - targets. - -2008-01-07 Robert Millan - - * boot/i386/pc/boot.S (boot_drive_check): Add a comment indicating - which instruction is modified by grub-setup during installation - (since it wasn't obvious by only looking at this file). - -2008-01-07 Robert Millan - - * TODO: Rewrite. Just refer to the wiki and the BTS instead of - listing actual TODO items. - -2008-01-06 Yoshinori K. Okuji - - * fs/reiserfs.c (grub_reiserfs_get_key_v2_type): Handle endianness - correctly. - (grub_reiserfs_get_key_offset): Likewise. - (grub_reiserfs_set_key_offset): Likewise. - (grub_reiserfs_set_key_type): Likewise. - (grub_reiserfs_iterate_dir): Return 1 if found, otherwise 0. - - (GRUB_REISERFS_KEYV2_BITFIELD): Undefined. Probably it would be - better to remove the bitfield version completely. - -2008-01-06 Yoshinori K. Okuji - - * fs/reiserfs.c (grub_reiserfs_iterate_dir): ENTRY_ITEM must be - allocated from the heap, due to the fshelp implementation. - (grub_reiserfs_dir): Free NODE, due to the same reason. - -2008-01-06 Yoshinori K. Okuji - - Mostly from Vincent Pelletier: - - * fs/reiserfs.c: New file. - - * conf/common.rmk (pkglib_MODULES): Added reiserfs.mod. - (reiserfs_mod_SOURCES): New variable. - (reiserfs_mod_CFLAGS): Likewise. - (reiserfs_mod_LDFLAGS): Likewise. - - * DISTLIST: Added boot/i386/pc/lnxboot.S, commands/hexdump.c, - disk/ata.c, fs/cpio.c, fs/ntfscomp.c, fs/reiserfs.c, - include/grub/ntfs.h, include/grub/i386/pc/machine.h, and - normal/color.c. - -2008-01-06 Robert Millan - - * normal/color.c: Remove `'. - -2008-01-05 Jeroen Dekkers - - * include/grub/normal.h: Include . - -2008-01-05 Robert Millan - - * util/i386/pc/grub-setup.c (usage): Replace obsolete `(hd0,0)' in - usage example with `(hd0,1)'. - Reported by Samuel Thibault. - -2008-01-05 Robert Millan - - * kern/i386/loader.S (grub_linux_is_bzimage): New variable. - (grub_linux_boot_zimage): Rename to ... - (grub_linux_boot): ... this. - (grub_linux_boot_bzimage): Merge with `grub_linux_boot_zimage'. - (grub_linux_boot_zimage): Conditionalize zImage copy. - - * include/grub/i386/loader.h (grub_linux_is_bzimage): Add prototype. - (grub_linux_boot_bzimage): Remove prototype. - (grub_linux_boot_zimage): Rename to ... - (grub_linux_boot): ... this. - - * loader/i386/pc/linux.c (big_linux): Replace with `grub_linux_is_bzimage'. - (grub_linux_boot): Remove function. - -2008-01-05 Robert Millan - - * include/grub/normal.h (grub_env_write_color_normal): New prototype. - (grub_env_write_color_highlight): Likewise. - (grub_wait_after_message): Likewise. - - * normal/color.c: New file. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `normal/color.c'. - (normal_mod_DEPENDENCIES): Likewise. - - * conf/i386-efi.rmk (grub_emu_SOURCES): Add `normal/color.c'. - (normal_mod_DEPENDENCIES): Likewise. - - * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Add `normal/color.c'. - (normal_mod_DEPENDENCIES): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add `normal/color.c'. - (normal_mod_DEPENDENCIES): Likewise. - - * normal/menu_entry.c (run): Rely on grub_wait_after_message() - for waiting after a message is printed. - * normal/main.c (read_config_file): Likewise. - (grub_normal_init): Register grub_env_write_color_normal() and - grub_env_write_color_highlight() hooks. Mark `color_normal' and - `color_highlight' variables as global. - - * normal/menu.c (grub_wait_after_message): New function. - (grub_color_menu_normal): New variable. Replaces ... - (GRUB_COLOR_MENU_NORMAL): ... this macro. - (grub_color_menu_highlight): New variable. Replaces ... - (GRUB_COLOR_MENU_HIGHLIGHT): ... this macro. - (draw_border): Set color state to `GRUB_TERM_COLOR_NORMAL' instead of - `GRUB_TERM_COLOR_STANDARD'. - (print_message): Use `grub_setcolorstate' to reload colors. Rename - `normal_code' and `highlight_code' to `old_color_normal' and - `old_color_highlight', respectively. - (grub_menu_init_page): Update colors when drawing the menu, based on - `menu_color_normal' and `menu_color_highlight' variables. - (grub_menu_run): Rely on grub_wait_after_message() for waiting after - a message is printed. - -2008-01-05 Robert Millan - - * kern/env.c (grub_env_context_open): Propagate hooks for global - variables to new context. - - * kern/main.c (grub_set_root_dev): Export `root' variable. - -2008-01-05 Robert Millan - - * util/biosdisk.c (get_os_disk): Check for devfs-style IDE and SCSI - discs unconditionally, since udev and others have options to provide - them. - -2008-01-05 Robert Millan - - * normal/completion.c (iterate_dir): Skip `.' and `..' directories. - -2008-01-04 Christian Franke - - * kern/i386/pc/init.c (grub_machine_init): Fix evaluation - of eisa_mmap. - -2008-01-03 Pavel Roskin - - * kern/i386/linuxbios/init.c: Put "void" to all function - declarations with no arguments. - * kern/powerpc/ieee1275/init.c: Likewise. - * term/i386/pc/at_keyboard.c: Likewise. - * term/i386/pc/vga_text.c: Likewise. - * util/grub-mkdevicemap.c: Likewise. - -2008-01-02 Robert Millan - - * loader/i386/pc/multiboot.c (grub_multiboot_load_elf32): Improve error - message when loaded image is out of bounds. - (grub_multiboot_load_elf64): Likewise. - -2008-01-02 Pavel Roskin - - * util/grub.d/10_linux.in: Try version without ".old" when - looking for initrd. It's better to use initrd from the newer - kernel of the same version than no initrd at all. - -2008-01-01 Robert Millan - - * util/biosdisk.c (get_os_disk): Fix check for IDE or SCSI discs. - -2008-01-01 Vesa Jaaskelainen - - * include/grub/video.h: Added grub_video_unmap_color and - grub_video_get_active_render_target. - (grub_video_adapter): Added unmap_color and get_active_render_target. - - * video/video.c: Added grub_video_unmap_color and - grub_video_get_active_render_target. - (grub_video_get_info): Changed method to accept NULL pointer as an - argument to allow detection of active video adapter. - - * video/i386/pc/vbe.c: Renamed grub_video_vbe_unmap_color as - grub_video_vbe_unmap_color_int. - Added grub_video_vbe_unmap_color and - grub_video_vbe_get_active_render_target. - (grub_video_vbe_adapter): Added unmap_color and - get_active_render_target. - - * video/i386/pc/vbeblit.c: Replaced grub_video_vbe_unmap_color usage - with grub_video_vbe_unmap_color_int. - - * term/gfxterm.c (DEFAULT_STANDARD_COLOR): Added. - (DEFAULT_NORMAL_COLOR): Likewise. - (DEFAULT_HIGHLIGHT_COLOR) Likewise. - (DEFAULT_FG_COLOR): Removed. - (DEFAULT_BG_COLOR): Likewise. - (DEFAULT_CURSOR_COLOR): Changed value. - (grub_virtual_screen): Added standard_color_setting, - normal_color_setting, highlight_color_setting and term_color. - (grub_virtual_screen): Removed fg_color_setting and bg_color_setting. - (bitmap_width): Added. - (bitmap_height): Likewise. - (bitmap): Likewise. - (set_term_color): Likewise. - (grub_virtual_screen_setup): Changed to use new terminal coloring - settings. - (grub_gfxterm_init): Added init for bitmap. - (grub_gfxterm_fini): Added destroy for bitmap. - (redraw_screen_rect): Updated to use background bitmap and new - terminal coloring. - (scroll_up): Added optimization for case when there is no bitmap. - (grub_gfxterm_cls): Fixed to use correct background color. - (grub_virtual_screen_setcolorstate): Changed to use new terminal - coloring. - (grub_virtual_screen_setcolor): Likewise. - (grub_virtual_screen_getcolor): Added. - (grub_gfxterm_background_image_cmd): Likewise. - (grub_video_term): Added setcolor and getcolor. - (MOD_INIT): Added registration of background_image command. - (MOD_TERM): Added unregistration for background_image command. - -2007-12-30 Pavel Roskin - - * loader/multiboot_loader.c: Fix multiboot command - unregistration. Fix all typos in the word "multiboot". - -2007-12-29 Pavel Roskin - - * util/grub.d/10_linux.in: Refactor search for initrd. Add - support for initrd names used in Fedora. - -2007-12-26 Bean - - * conf/common.rmk (pkgdata_MODULES): Add cpio.mod. - (cpio_mod_SOURCES): New variable. - (cpio_mod_CFLAGS): Likewise. - (cpio_mod_LDFLAGS): Likewise. - - * fs/cpio.c: New file. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add cpio.c. - - * conf/i386-efi.rmk (grub_emu_SOURCES): Likewise. - - * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - -2007-12-25 Robert Millan - - * include/grub/term.h (struct grub_term): Add `getcolor' function. - (grub_getcolor): New function. - - * kern/term.c (grub_getcolor): New function. - * normal/menu.c (GRUB_COLOR_MENU_NORMAL): New macro. - (GRUB_COLOR_MENU_HIGHLIGHT): New macro. - (print_entry): Set normal and highlight colors to - `GRUB_COLOR_MENU_NORMAL' and `GRUB_COLOR_MENU_HIGHLIGHT', - respectively, before printing and restore them to old - values afterwards. - (grub_menu_init_page): Likewise. Fill an additional colored space - that would otherwise be left blank. - - * term/efi/console.c (grub_console_getcolor): New function. - (struct grub_console_term.getcolor): New variable. - * term/i386/pc/console.c (grub_console_getcolor): New function. - (struct grub_console_term.getcolor): New variable. - * term/ieee1275/ofconsole.c (grub_ofconsole_getcolor): New function. - (struct grub_console_term.getcolor): New variable. - - * term/i386/pc/serial.c (grub_serial_setcolor): Remove function. - (struct grub_console_term.setcolor): Remove variable. - * term/i386/pc/vesafb.c (grub_virtual_screen_setcolor): Remove function. - (struct grub_console_term.setcolor): Remove variable. - * term/i386/pc/vga.c (grub_vga_setcolor): Remove function. - (struct grub_console_term.setcolor): Remove variable. - * term/gfxterm.c (grub_virtual_screen_setcolor): Remove function. - (struct grub_console_term.setcolor): Remove variable. - -2007-12-25 Robert Millan - - * configure.ac: Search for possible unifont.hex locations, and - define UNIFONT_HEX if found. - - * Makefile.in (UNIFONT_HEX): Define variable. - (DATA): Rename to ... - (PKGLIB): ... this. Update all users. - (PKGDATA): New variable. - (pkgdata_IMAGES): Rename to ... - (pkglib_IMAGES): ... this. Update all users. - (pkgdata_MODULES): Rename to ... - (pkglib_MODULES): ... this. Update all users. - (pkgdata_PROGRAMS): Rename to ... - (pkglib_PROGRAMS): ... this. Update all users. - (pkgdata_DATA): Rename to ... - (pkglib_DATA): ... this. Update all users. - (CLEANFILES): Redefine to `$(pkglib_DATA) $(pkgdata_DATA)'. - (unicode.pff, ascii.pff): New rules. - (all-local): Add `$(PKGDATA)' dependency. - (install-local): Process `$(PKGDATA)'. - - * util/update-grub_lib.in (font_path): Search for *.pff files in - a few more locations, including `${pkgdata}'. - -2007-12-23 Robert Millan - - Patch from Bean : - * disk/loopback.c (grub_loopback_read): Add missing bit shift to - `size'. - -2007-12-21 Bean - - * conf/common.rmk (pkgdata_MODULES): Add ntfscomp.mod. - (ntfscomp_mod_SOURCES): New variable. - (ntfscomp_mod_CFLAGS): Likewise. - (ntfscomp_mod_LDFLAGS): Likewise. - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/ntfscomp.c. - (grub_probe_SOURCES): Likewise. - (grub_emu_SOURCES): Likewise. - - * conf/i386-efi.rmk (grub_probe_SOURCES): Add fs/ntfscomp.c. - (grub_emu_SOURCES): Likewise. - - * conf/i386-linuxbios.rmk (grub_probe_SOURCES): Add fs/ntfscomp.c. - (grub_emu_SOURCES): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_probe_SOURCES): Add fs/ntfscomp.c. - (grub_emu_SOURCES): Likewise. - - * fs/ntfs.c (grub_ntfscomp_func): New variable. - (read_run_list): Renamed to grub_ntfs_read_run_list. - (decomp_nextvcn): Moved to ntfscomp.c. - (decomp_getch): Likewise. - (decomp_get16): Likewise. - (decomp_block): Likewise. - (read_block): Likewise. - (read_data): Partially moved to ntfscomp.c. - (fixup): Change unsigned to grub_uint16_t. - (read_mft): Change unsigned long to grub_uint32_t. - (read_attr): Likewise. - (read_data): Likewise. - (read_run_data): Likewise. - (read_run_list): Likewise. - (read_mft): Likewise. - - * fs/ntfscomp.c: New file. - - * include/grub/ntfs.h: New file. - -2007-12-16 Robert Millan - - * util/grub-mkdevicemap.c (make_device_map): Iterate up to 20 for - IDE disk check, since Linux is known to support 20 IDE disks. - Reported by Colin Watson. - -2007-12-15 Bean - - * conf/i386-pc.rmk (pkgdata_IMAGES): Add lnxboot.img. - (lnxboot_img_SOURCES): New variable. - (lnxboot_img_ASFLAGS): Likewise. - (lnxboot_img_LDFLAGS): Likewise. - - * boot/i386/pc/lnxboot.S: New file. - -2007-11-24 Pavel Roskin - - * configure.ac: Test if '--build-id=none' is supported by the - linker. If yes, add it to TARGET_LDFLAGS. Build ID causes - objcopy to generate incorrect binary files (binutils - 2.17.50.0.18-1 as shipped by Fedora 8). - * aclocal.m4 (grub_PROG_OBJCOPY_ABSOLUTE): Use LDFLAGS when - linking, so that build ID doesn't break the test. - -2007-11-24 Pavel Roskin - - * include/grub/i386/time.h: use "void" in the argument list - of grub_cpu_idle(). - * include/grub/powerpc/time.h: Likewise. - * include/grub/sparc64/time.h: Likewise. - -2007-11-18 Christian Franke - - * util/console.c (grub_ncurses_getkey): Change curses KEY_* mapping, - now return control chars instead of GRUB_CONSOLE_KEY_* constants. - This fixes the problem that function keys did not work in grub-emu. - -2007-11-18 Christian Franke - - * disk/host.c (grub_host_open): Remove attribute unused from - name parameter. Add check for "host". This fixes the problem - that grub-emu does not find partitions. - -2007-11-18 Christian Franke - - * util/hostfs.c (is_dir): New function. - (grub_hostfs_dir): Handle missing dirent.d_type case. - (grub_hostfs_read): Add missing fseek(). - (grub_hostfs_label): Clear label pointer. This fixes a crash - of grub-emu on "ls (host)". - -2007-11-18 Christian Franke - - * include/grub/i386/pc/init.h (struct grub_machine_mmap_entry): - Add attribute packed, gcc 3.4.4 on Cygwin aligns this - to 64 bit boundary by default. - -2007-11-18 Bean - - * conf/common.rmk (pkgdata_MODULES): Add hexdump.mod. - (hexdump_mod_SOURCES): New variable. - (hexdump_mod_CFLAGS): Likewise. - (hexdump_mod_LDFLAGS): Likewise. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add command/hexdump.c. - - * conf/i386-efi.rmk (grub_emu_SOURCES): Add command/hexdump.c. - - * conf/i386-linuxbios.rmk (grub_emu_SOURCES): Add command/hexdump.c. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add command/hexdump.c. - - * include/grub/hexdump.h: New file. - - * commands/hexdump.c: New file. - -2007-11-10 Robert Millan - - * commands/i386/pc/play.c (beep_off): Switch order of arguments - in grub_outb() calls. - (beep_on): Likewise. - -2007-11-10 Christian Franke - - * normal/menu.c (run_menu): Check for empty menu to avoid crash. - (grub_menu_run): Likewise. - -2007-11-10 Robert Millan - - * include/grub/i386/efi/machine.h: New file. - * include/grub/i386/linuxbios/machine.h: Likewise. - * include/grub/i386/pc/machine.h: Likewise. - * include/grub/powerpc/ieee1275/machine.h: Likewise. - * include/grub/sparc64/ieee1275/machine.h: Likewise. - - * term/i386/pc/serial.c: Include . - (serial_hw_io_addr): New variable. - (serial_hw_get_port): Obtain port address from `serial_hw_io_addr' - instead of `(unsigned short *) 0x400'. - -2007-11-10 Bean - - * fs/ntfs.c (read_block): Fix a bug caused by adjacent blocks. - -2007-11-10 Vesa Jaaskelainen - - * conf/i386-pc.rmk (pkgdata_MODULES): Added vga.mod. - (vga_mod_SOURCES): Added. - (vga_mod_CFLAGS): Likewise. - (vga_mod_LDFLAGS): Likewise. - - * term/i386/pc/vga.c (get_map_mask): Switch order of arguments in - grub_outb() calls. - (set_map_mask): Likewise. - (set_read_map): Likewise. - (set_read_address): Likewise. - (vga_font): Removed variable. - (get_vga_glyph): Removed function. - (invalidate_char): Likewise. - (write_char): Changed to use grub_font_get_glyph() for font - information. - (grub_vga_putchar): Likewise. - (grub_vga_getcharwidth): Likewise. - -2007-11-10 Vesa Jaaskelainen - - * conf/i386-pc.rmk (boot_img_LDFLAGS): Use COMMON_LDFLAGS for target - flags. - (pxeboot_img_LDFLAGS): Likewise. - (diskboot_img_LDFLAGS): Likewise. - (kernel_img_LDFLAGS): Likewise. - -2007-11-06 Robert Millan - - * term/i386/pc/serial.c (serial_hw_put): Switch order of arguments - in grub_outb() calls. - (serial_hw_init): Likewise. - -2007-11-05 Robert Millan - - * util/update-grub.in: Allow files in ${update_grub_dir} to contain - spaces. Skip non-regular files. - -2007-11-05 Robert Millan - - * kern/disk.c (grub_disk_firmware_fini) - (grub_disk_firmware_is_tainted): New variables. - - * include/grub/disk.h (grub_disk_firmware_fini) - (grub_disk_firmware_is_tainted): Likewise. - - * disk/i386/pc/biosdisk.c (GRUB_MOD_FINI(biosdisk)): Moved from here ... - (grub_disk_biosdisk_fini): ... to here. - (GRUB_MOD_FINI(biosdisk)): Implement using grub_disk_biosdisk_fini(). - (GRUB_MOD_INIT(biosdisk)): Abort when `grub_disk_firmware_is_tainted' - is set. Register grub_disk_biosdisk_fini() in - `grub_disk_firmware_fini'. - - * disk/ata.c: Remove `'. - (GRUB_MOD_INIT(ata)): Remove grub_biosdisk_fini() call. - Use `grub_disk_firmware_is_tainted' and `grub_disk_firmware_fini' - to finish existing firmware disk interface. - - * conf/i386-linuxbios.rmk (pkgdata_MODULES): Add `ata.mod'. - (ata_mod_SOURCES): New variable. - (ata_mod_CFLAGS): Likewise. - (ata_mod_LDFLAGS): Likewise. - -2007-11-05 Robert Millan - - * disk/ata.c: Remove `'. Include `'. - (grub_ata_wait): Reimplement using grub_millisleep(). - - * include/grub/misc.h (grub_div_roundup): Fix parenthesization. - * include/grub/i386/time.h (grub_cpu_idle): Disable `hlt' instruction. - -2007-11-03 Marco Gerards - - * term/i386/pc/vga_text.c: Include . - (CRTC_ADDR_PORT): New macro. - (CRTC_DATA_PORT): Likewise. - (CRTC_CURSOR): Likewise. - (CRTC_CURSOR_ADDR_HIGH): Likewise. - (CRTC_CURSOR_ADDR_LOW): Likewise. - (update_cursor): New function. - (grub_console_real_putchar): Call `update_cursor'. - (grub_console_gotoxy): Likewise. - (grub_console_cls): Set the default color when clearing the - screen. - (grub_console_setcursor): Implemented. - -2007-11-03 Marco Gerards - - * disk/ata.c (grub_ata_pio_read): Don't wait for the command to - become activate. - (grub_ata_pio_write): Likewise. - - (grub_atapi_identify): Wait after issuing an ATA command. - (grub_atapi_packet): Likewise. - (grub_ata_identify): Likewise. - (grub_ata_readwrite): Likewise. - -2007-11-03 Marco Gerards - - * disk/ata.c (grub_ata_pio_read): Detect and return the error code. - (grub_ata_pio_write): Likewise. - (grub_ata_readwrite): Use `grub_error', instead of - returning `grub_errno'. - -2007-11-03 Marco Gerards - - * disk/ata.c (grub_ata_readwrite): Call grub_ata_pio_read and - grub_ata_pio_write once for every single sector, instead of for - multiple sectors. - -2007-10-31 Robert Millan - - * configure.ac: Add `i386-linuxbios' to the list of supported targets. - - * conf/i386-linuxbios.rmk: New file. - - * kern/i386/pc/hardware.c: Likewise. - * term/i386/pc/at_keyboard.c: Likewise. - * term/i386/pc/vga_text.c: Likewise. - - * include/grub/i386/linuxbios/boot.h: Likewise. - * include/grub/i386/linuxbios/console.h: Likewise. - * include/grub/i386/linuxbios/init.h: Likewise. - * include/grub/i386/linuxbios/kernel.h: Likewise. - * include/grub/i386/linuxbios/loader.h: Likewise. - * include/grub/i386/linuxbios/memory.h: Likewise. - * include/grub/i386/linuxbios/serial.h: Likewise. - * include/grub/i386/linuxbios/time.h: Likewise. - - * kern/i386/linuxbios/init.c: Likewise. - * kern/i386/linuxbios/startup.S: Likewise. - * kern/i386/linuxbios/table.c: Likewise. - -2007-10-31 Marco Gerards - - * conf/i386-pc.rmk (pkgdata_MODULES): Add `ata.mod'. - (ata_mod_SOURCES): New variable. - (ata_mod_CFLAGS): Likewise. - (ata_mod_LDFLAGS): Likewise. - - * disk/ata.c: New file. - - * include/grub/disk.h (grub_disk_dev_id): Add - `GRUB_DISK_DEV_ATA_ID'. - -2007-10-31 Robert Millan - - * include/grub/i386/pc/init.h (grub_lower_mem): Moved from here ... - * include/grub/i386/pc/memory.h (grub_lower_mem): ... to here. - - * include/grub/i386/pc/init.h (grub_upper_mem): Moved from here ... - * include/grub/i386/pc/memory.h (grub_upper_mem): ... to here. - - * include/grub/i386/pc/memory.h: Include `' and - `'. - - * loader/i386/pc/multiboot.c: Include `'. - -2007-10-27 Robert Millan - - * include/grub/types.h (ULONG_MAX): Define macro. - -2007-10-22 Robert Millan - - * kern/i386/pc/startup.S: Remove `"kern/i386/realmode.S"'. Include - `"../realmode.S"'. - Remove `"kern/i386/loader.S"'. Include `"../loader.S"'. - -2007-10-22 Robert Millan - - * conf/i386-pc.rmk (kernel_img_SOURCES): Remove `disk/i386/pc/biosdisk.c'. - (pkgdata_MODULES): Add `biosdisk.mod'. - (biosdisk_mod_SOURCES, biosdisk_mod_CFLAGS, biosdisk_mod_LDFLAGS): New - variables. - - * disk/i386/pc/biosdisk.c: Include `'. - (grub_biosdisk_init): Replace with ... - (GRUB_MOD_INIT(biosdisk)): ... this. - (grub_biosdisk_fini): Replace with ... - (GRUB_MOD_FINI(biosdisk)): ... this. - - * kern/i386/pc/init.c: Remove `'. - (grub_machine_init): Remove call to grub_biosdisk_init(). - (grub_machine_fini): Remove call to grub_machine_fini(). - - * util/i386/pc/grub-install.in (modules): Add `biosdisk'. - -2007-10-22 Robert Millan - - * include/grub/time.h: New file. - * include/grub/i386/time.h: Likewise. - * include/grub/powerpc/time.h: Likewise. - * include/grub/sparc64/time.h: Likewise. - - * include/grub/i386/pc/time.h (KERNEL_TIME_HEADER): Rename all - instances to ... - (KERNEL_MACHINE_TIME_HEADER): ... this. - * include/grub/powerpc/ieee1275/time.h (KERNEL_TIME_HEADER): Rename all - instances to ... - (KERNEL_MACHINE_TIME_HEADER): ... this. - * include/grub/sparc64/ieee1275/time.h (KERNEL_TIME_HEADER): Rename all - instances to ... - (KERNEL_MACHINE_TIME_HEADER): ... this. - - * kern/i386/efi/init.c: Include `'. - (grub_millisleep): New function. - * kern/i386/pc/init.c: Include `'. - (grub_millisleep): New function. - * kern/powerpc/ieee1275/init.c: Include `'. - Remove `grub/machine/time.h' include. - (grub_millisleep): New function. - * kern/sparc64/ieee1275/init.c: Include `'. - Remove `grub/machine/time.h' include. - (grub_millisleep): New function. - - * include/grub/misc.h (grub_div_roundup): New function. - - * kern/misc.c: Include `'. - (grub_millisleep_generic): New function. - - * conf/i386-efi.rmk (kernel_mod_HEADERS): Remove `i386/efi/time.h'. - Add `time.h'. - * conf/i386-pc.rmk (kernel_img_HEADERS): Remove `machine/time.h'. - Add `time.h'. - * conf/powerpc-ieee1275.rmk (kernel_elf_HEADERS): Remove - `machine/time.h'. Add `time.h'. - * conf/sparc64-ieee1275.rmk (kernel_elf_HEADERS): Likewise. - -2007-10-21 Robert Millan - - * include/grub/misc.h (grub_max): New function. - -2007-10-21 Robert Millan - - * util/misc.c (grub_util_info): Call fflush() before returning. - -2007-10-20 Robert Millan - - * genmk.rb (Image): Copy `extra_flags' from here ... - (PModule): ... to here. Use it in `#{obj}: #{src}' rule. - - * commands/i386/cpuid.c (grub_cmd_cpuid): Add __attribute__ ((unused)) - to `argc' and `args' arguments. - -2007-10-17 Robert Millan - - * kern/i386/loader.S: New file. - - * kern/i386/pc/startup.S (grub_linux_prot_size): Moved from here ... - * kern/i386/loader.S (grub_linux_prot_size)... to here. - * kern/i386/pc/startup.S (grub_linux_tmp_addr): Moved from here ... - * kern/i386/loader.S (grub_linux_tmp_addr)... to here. - * kern/i386/pc/startup.S (grub_linux_real_addr): Moved from here ... - * kern/i386/loader.S (grub_linux_real_addr)... to here. - * kern/i386/pc/startup.S (grub_linux_boot_zimage): Moved from here ... - * kern/i386/loader.S (grub_linux_boot_zimage)... to here. - * kern/i386/pc/startup.S (grub_linux_boot_bzimage): Moved from here ... - * kern/i386/loader.S (grub_linux_boot_bzimage)... to here. - * kern/i386/pc/startup.S (grub_multiboot_real_boot): Moved from here ... - * kern/i386/loader.S (grub_multiboot_real_boot)... to here. - * kern/i386/pc/startup.S (grub_multiboot2_real_boot): Moved from here ... - * kern/i386/loader.S (grub_multiboot2_real_boot)... to here. - - * kern/i386/realmode.S: New file. - - * kern/i386/pc/startup.S (protstack): Moved from here ... - * kern/i386/realmode.S (protstack)... to here. - * kern/i386/pc/startup.S (gdt): Moved from here ... - * kern/i386/realmode.S (gdt)... to here. - * kern/i386/pc/startup.S (prot_to_real): Moved from here ... - * kern/i386/realmode.S (prot_to_real)... to here. - - * kern/i386/pc/startup.S: Include `kern/i386/loader.S' and - `kern/i386/realmode.S'. - -2007-10-17 Robert Millan - - * include/grub/i386/loader.h: New file. - - * include/grub/i386/pc/loader.h (grub_linux_prot_size) - (grub_linux_tmp_addr, grub_linux_real_addr, grub_os_area_addr) - (grub_os_area_size, grub_linux_boot_zimage, grub_linux_boot_bzimage) - (grub_multiboot_real_boot, grub_multiboot2_real_boot) - (grub_rescue_cmd_linux, grub_rescue_cmd_initrd): Moved from here ... - * include/grub/i386/loader.h (grub_linux_prot_size) - (grub_linux_tmp_addr, grub_linux_real_addr, grub_os_area_addr) - (grub_os_area_size, grub_linux_boot_zimage, grub_linux_boot_bzimage) - (grub_multiboot_real_boot, grub_multiboot2_real_boot) - (grub_rescue_cmd_linux, grub_rescue_cmd_initrd): ... to here. - - * include/grub/i386/pc/loader.h: Include `grub/cpu/loader.h'. - -2007-10-15 Robert Millan - - * normal/misc.c (grub_normal_print_device_info): Do not probe for - filesystem when dev->disk is unset. - Do probe for filesystem even when dev->disk->has_partitions is set. - In case a filesystem is found, always report it. - In case it isn't, if dev->disk->has_partitions is set, report that - a partition table was found instead of reporting that no filesystem - could be identified. - -2007-10-12 Robert Millan - - * conf/powerpc-ieee1275.rmk (grub_mkimage_SOURCES): Replace reference - to util/powerpc/ieee1275/grub-mkimage.c with util/elf/grub-mkimage.c. - - * include/grub/types.h (grub_host_to_target16): New macro. - (grub_host_to_target32): Likewise. - (grub_host_to_target64): Likewise. - (grub_target_to_host16): Likewise. - (grub_target_to_host32): Likewise. - (grub_target_to_host64): Likewise. - - * include/grub/powerpc/ieee1275/kernel.h (GRUB_IEEE1275_MOD_ALIGN): - Renamed from to ... - (GRUB_MOD_ALIGN): ...this. Update all users. - - * util/elf/grub-mkimage.c (load_note): Replace grub_cpu_to_be32 with - grub_host_to_target32. - Replace grub_be_to_cpu32 with grub_target_to_host32. - (load_modules): Likewise. - (add_segments): Replace grub_be_to_cpu16 with grub_target_to_host16. - Replace grub_be_to_cpu32 with grub_target_to_host32. - Replace grub_cpu_to_be16 with grub_host_to_target16. - Replace grub_cpu_to_be32 grub_host_to_target32. - -2007-10-12 Robert Millan - - * util/powerpc/ieee1275/grub-mkimage.c: Moved to ... - * util/elf/grub-mkimage.c: ... here. - - * DISTLIST: Add `util/elf/grub-mkimage.c'. Remove - `util/powerpc/ieee1275/grub-mkimage.c'. - -2007-10-07 Robert Millan - - * kern/powerpc/ieee1275/init.c: Rename HEAP_LIMIT to HEAP_MAX_ADDR, - and make it easier to figure out. - Add HEAP_MIN_SIZE and HEAP_MAX_ADDR definitions. - (grub_claim_heap): Use HEAP_MAX_ADDR rather than taking a parameter. - Do not avoid claiming a region above HEAP_MAX_ADDR if that would - leave us with less than HEAP_MIN_SIZE total heap. - Avoid our total amount of heap to surpass HEAP_MAX_SIZE. - -2007-10-03 Robert Millan - - * include/grub/i386/io.h: New file. - * commands/i386/pc/play.c (inb): Removed. - (outb): Removed. - Include grub/cpu/io.h. Replace inb() with grub_inb() and outb() - with grub_outb(). - * term/i386/pc/serial.c (inb): Removed. - (outb): Removed. - Include grub/cpu/io.h. Replace inb() with grub_inb() and outb() - with grub_outb(). - * term/i386/pc/vga.c (inb): Removed. - (outb): Removed. - Include grub/cpu/io.h. Replace inb() with grub_inb() and outb() - with grub_outb(). - -2007-10-02 Robert Millan - - * conf/i386-efi.rmk (grub_emu_SOURCES): Add util/hostfs.c. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - Reported by Marcin Kurek. - -2007-09-07 Robert Millan - - * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_test_flag): Detect - SmartFirmware version updates (as released by Sven Luther), and avoid - setting GRUB_IEEE1275_FLAG_NO_PARTITION_0 or - GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS unless the running version is - known broken. - -2007-09-03 Yoshinori K. Okuji - - From Hitoshi Ozeki: - * kern/i386/pc/init.c (compact_mem_regions): Decrease NUM_REGIONS - when merging two regions. - -2007-09-03 Yoshinori K. Okuji - - * kern/rescue.c (grub_enter_rescue_mode): Free ARGS. - * normal/completion.c (grub_normal_do_completion): Likewise. - Reported by Hitoshi Ozeki. - -2007-09-03 Yoshinori K. Okuji - - Do not use devices at boot in chainloading. - - * loader/i386/pc/chainloader.c (boot_drive): New variable. - (boot_part_addr): Likewise. - (grub_chainloader_boot): Simply call grub_chainloader_real_boot - with BOOT_DRIVE and BOOT_PART_ADDR. - (grub_chainloader_cmd): Set BOOT_DRIVE and BOOT_PART_ADDR. - Reported by Hitoshi Ozeki . - -2007-08-29 Robert Millan - - Patch from Simon Peter : - * genmk.rb (Utility): Append $(#{src}_DEPENDENCIES) to #{obj} targets. - * conf/i386-pc.rmk: Replace grub-probe_DEPENDENCIES with - util/grub-probe.c_DEPENDENCIES. Replace grub-setup_DEPENDENCIES with - util/i386/pc/grub-setup.c_DEPENDENCIES. - * conf/i386-efi.rmk: Replace grub-probe_DEPENDENCIES with - util/grub-probe.c_DEPENDENCIES. - * conf/powerpc-ieee1275.rmk: Likewise. - -2007-08-28 Robert Millan - - * util/i386/get_disk_name.c: New. Implement grub_util_get_disk_name() - to tell grub-mkdevicemap how to name devices. - * util/ieee1275/get_disk_name.c: Likewise (using "ofpathname -a" - feature). - - * conf/i386-efi.rmk (grub_mkdevicemap_SOURCES): Add - util/i386/get_disk_name.c. - * conf/i386-pc.rmk (grub_mkdevicemap_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_mkdevicemap_SOURCES): Add - util/ieee1275/get_disk_name.c. - - * include/grub/util/misc.h: grub_util_get_disk_name() declaration. - - * DISTLIST: Add util/i386/get_disk_name.c and - util/ieee1275/get_disk_name.c. - - * util/grub-mkdevicemap.c: Replace device naming logic with - grub_util_get_disk_name() calls. - -2007-08-20 Robert Millan - - * normal/menu.c (run_menu): Refer to seconds as "s" not "seconds" - (so that it works for both plural and singular quantities). - -2007-08-05 Robert Millan - - * util/grub.d/10_linux.in (test_gt): Strip out vmlinu[xz]- prefix - so that [xz] isn't taken into account when determining order. - -2007-08-02 Marco Gerards - - * DISTLIST: Add `disk/host.c', `fs/ntfs.c', `include/multiboot.h', - `include/multiboot2.h', `include/grub/elfload.h', - `include/multiboot.h', `include/grub/multiboot.h', - `include/grub/multiboot_loader.h', `include/grub/multiboot2.h', - `include/grub/i386/pc/biosdisk.h', `include/grub/util/biosdisk.h', - `kern/elf.c', `loader/multiboot_loader.c', - `loader/multiboot_loader_normal.c', `loader/multiboot2.c', - `loader/i386/pc/multiboot2.c', - `loader/powerpc/ieee1275/multiboot2.c', `util/hostfs.c' and - `util/i386/pc/grub-mkrescue.in'. Remove - `include/grub/biosdisk.h', `include/grub/i386/pc/multiboot.h', - `include/grub/i386/pc/util/biosdisk.h' and - `include/grub/powerpc/ieee1275/multiboot.h'. - -2007-08-02 Bean - - * conf/common.rmk (pkgdata_MODULES): Add ntfs.mod. - (ntfs_mod_SOURCES): New variable. - (ntfs_mod_CFLAGS): Likewise. - (ntfs_mod_LDFLAGS): Likewise. - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/ntfs.c. - (grub_probe_SOURCES): Likewise. - (grub_emu_SOURCES): Likewise. - - * conf/i386-efi.rmk (grub_probe_SOURCES): Add fs/ntfs.c. - (grub_emu_SOURCES): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_probe_SOURCES): Add fs/ntfs.c. - (grub_emu_SOURCES): Likewise. - - * conf/misc.c (grub_utf16_to_utf8): Fix unicode conversion bug. - - * fs/ntfs.c: New file. - -2007-08-02 Bean - - * disk.h (grub_disk): Use NESTED_FUNC_ATTR. - - * file.h (grub_file): Likewise. - - * fshelp.h (grub_fshelp_read_file): Likewise. - - * util/i386/pc/grub-setup.c (setup): Likewise. - (save_first_sector): Likewise. - (save_blocklists): Likewise. - - * fs/affs.c (grub_affs_read_file): Likewise. - - * fs/ext2.c (grub_ext2_read_file): Likewise. - - * fs/fat.c (grub_fat_read_data): Likewise. - - * fs/fshelp.c (grub_fshelp_read_file): Likewise. - - * fs/hfs.c (grub_hfs_read_file): Likewise. - - * fs/hfsplus.c (grub_hfsplus_read_file): Likewise. - - * fs/jfs.c (grub_jfs_read_file): Likewise. - - * fs/minix.c (grub_minix_read_file): Likewise. - - * fs/sfs.c (grub_sfs_read_file): Likewise. - - * fs/ufs.c (grub_ufs_read_file): Likewise. - - * fs/xfs.c (grub_xfs_read_file): Likewise. - - * command/blocklist.c (read_blocklist): Likewise. - (print_blocklist): Likewise. - -2007-08-02 Marco Gerards - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `disk/host.c' and - `util/hostfs.c'. - - * disk/host.c: New file. - - * util/hostfs.c: Likewise. - - * fs/hfsplus.c (grub_hfsplus_mount): When reading out of disk, - return `GRUB_ERR_BAD_FS'. - * fs/sfs.c (grub_sfs_mount): Likewise. - * fs/xfs.c (grub_xfs_mount): Likewise. - - * include/grub/disk.h (enum grub_disk_dev_id): Add - `GRUB_DISK_DEVICE_HOST_ID'. - - * util/grub-emu.c (main): Initialize and de-initialize hostfs. - -2007-07-24 Jerone Young - - * conf/i386-pc.rmk: Add Multiboot loader and multiboot 2 to multiboot - modules for compilation. - * conf/powerpc-ieee1275.rmk: Likewise. - - * include/multiboot.h: Move multiboot definitions to one file. Rename - many definitions to not get grub specific. - * include/multiboot2.h: Create header with multiboot 2 definitions. - * include/grub/multiboot.h: Header for grub specific function - prototypes and definitions. - * include/grub/multiboot2.h: Likewise. - * include/grub/multiboot_loader.h: Likewise. - * include/grub/i386/pc/multiboot.h: Removed. - * include/grub/powerpc/ieee1275/multiboot.h: Removed. - - * loader/multiboot_loader.c: Created to act as a proxy for multiboot 1 - and 2 to allow for one multiboot and module commands. - * loader/multiboot2.c: Add multiboot2 functionality. - * loader/i386/pc/multiboot.c: Modify for new multiboot header location - and definition names. - * loader/i386/pc/multiboot2.c: Created to add i386 specific multiboot - 2 functions. - * loader/powerpc/ieee1275/multiboot2.c: Created to add powerpc - ieee1275 specific multiboot2 code. - - * kern/i386/pc/startup.S: Change headers and definition names for - multiboot. Add function grub_multiboot2_real_boot for multiboot 2. - -2007-07-22 Robert Millan - - * geninitheader.sh: Process file specified in first parameter rather - than hardcoding grub_modules_init.lst. - * geninit.sh: Likewise. Also, construct header name dynamically rather - than hardcoding grub_modules_init.h. - - * conf/common.rmk: Rename grub_modules_init.[ch] files associated with - grub-emu to grub_emu_init.[ch]. Add rules to build analogous - grub_probe_init.[ch] and grub_setup_init.[ch]. - - * conf/powerpc-ieee1275.rmk (grub_emu_DEPENDENCIES): Replace - grub_modules_init.h with grub_emu_init.h. - (grub_probe_DEPENDENCIES, grub_probe_SOURCES): Add new - grub_probe_init.[ch] files. - * conf/i386-efi.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - (grub_setup_DEPENDENCIES, grub_setup_SOURCES): Add new - grub_setup_init.[ch] files. - - * util/grub-emu.c: Replace grub_modules_init.h with grub_emu_init.h. - * util/grub-probe.c: Include grub_probe_init.h. Use grub_init_all() - to initialize modules rather than a list of hardcoded functions. - * util/i386/pc/grub-setup.c: Include grub_setup_init.h. Use - grub_init_all() to initialize modules rather than a list of hardcoded - functions. - -2007-07-22 Robert Millan - - * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_find_options): Set - GRUB_IEEE1275_FLAG_NO_PARTITION_0 flag when running on SmartFirmware. - -2007-07-22 Robert Millan - - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): Add - GRUB_IEEE1275_FLAG_BROKEN_OUTPUT flag. - * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_find_options): Set this - flag when running on SmartFirmware. - * term/ieee1275/ofconsole.c (grub_ofconsole_init): Avoid running - "output-device output" command when GRUB_IEEE1275_FLAG_BROKEN_OUTPUT - was set. - - * kern/powerpc/ieee1275/openfw.c (grub_ieee1275_encode_devname): - Increase partno when GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS flag is set, - rather than decreasing it. - - * util/i386/pc/grub-setup.c (setup): When embedding is required, but - there's not enough space to do it, fail in the same way as when it - can't be done because there are no partitions. - - * util/powerpc/ieee1275/grub-install.in: Improve error message shown - when nvsetenv failed. - -2007-07-22 Yoshinori K. Okuji - - * conf/i386-pc.rmk (CLEANFILES): Removed for grub-mkrescue, - because this rule is automatically generated. - (grub-mkrescue): Removed for the same reason as above. - -2007-07-22 Yoshinori K. Okuji - - Migrate to GNU General Public License Version 3. - - * COPYING: Replaced with the plain text version of GPLv3. - - * config.guess: Updated from gnulib. - * config.sub: Likewise. - - * geninit.sh: Output a GPLv3 copyright notice. - * geninitheader.sh: Likewise. - * genmodsrc.sh: Likewise. - * gensymlist.sh.in: Likewise. - - * boot/i386/pc/boot.S: Upgraded to GPLv3. - * boot/i386/pc/diskboot.S: Likewise. - * boot/i386/pc/pxeboot.S: Likewise. - * commands/blocklist.c: Likewise. - * commands/boot.c: Likewise. - * commands/cat.c: Likewise. - * commands/cmp.c: Likewise. - * commands/configfile.c: Likewise. - * commands/echo.c: Likewise. - * commands/help.c: Likewise. - * commands/ls.c: Likewise. - * commands/search.c: Likewise. - * commands/terminal.c: Likewise. - * commands/test.c: Likewise. - * commands/videotest.c: Likewise. - * commands/i386/cpuid.c: Likewise. - * commands/i386/pc/halt.c: Likewise. - * commands/i386/pc/play.c: Likewise. - * commands/i386/pc/reboot.c: Likewise. - * commands/i386/pc/vbeinfo.c: Likewise. - * commands/i386/pc/vbetest.c: Likewise. - * commands/ieee1275/halt.c: Likewise. - * commands/ieee1275/reboot.c: Likewise. - * commands/ieee1275/suspend.c: Likewise. - * disk/loopback.c: Likewise. - * disk/lvm.c: Likewise. - * disk/raid.c: Likewise. - * disk/efi/efidisk.c: Likewise. - * disk/i386/pc/biosdisk.c: Likewise. - * disk/ieee1275/ofdisk.c: Likewise. - * font/manager.c: Likewise. - * fs/affs.c: Likewise. - * fs/ext2.c: Likewise. - * fs/fat.c: Likewise. - * fs/fshelp.c: Likewise. - * fs/hfs.c: Likewise. - * fs/hfsplus.c: Likewise. - * fs/iso9660.c: Likewise. - * fs/jfs.c: Likewise. - * fs/minix.c: Likewise. - * fs/sfs.c: Likewise. - * fs/ufs.c: Likewise. - * fs/xfs.c: Likewise. - * hello/hello.c: Likewise. - * include/grub/acorn_filecore.h: Likewise. - * include/grub/arg.h: Likewise. - * include/grub/bitmap.h: Likewise. - * include/grub/boot.h: Likewise. - * include/grub/cache.h: Likewise. - * include/grub/device.h: Likewise. - * include/grub/disk.h: Likewise. - * include/grub/dl.h: Likewise. - * include/grub/elfload.h: Likewise. - * include/grub/env.h: Likewise. - * include/grub/err.h: Likewise. - * include/grub/file.h: Likewise. - * include/grub/font.h: Likewise. - * include/grub/fs.h: Likewise. - * include/grub/fshelp.h: Likewise. - * include/grub/gzio.h: Likewise. - * include/grub/hfs.h: Likewise. - * include/grub/kernel.h: Likewise. - * include/grub/loader.h: Likewise. - * include/grub/lvm.h: Likewise. - * include/grub/misc.h: Likewise. - * include/grub/mm.h: Likewise. - * include/grub/net.h: Likewise. - * include/grub/normal.h: Likewise. - * include/grub/parser.h: Likewise. - * include/grub/partition.h: Likewise. - * include/grub/pc_partition.h: Likewise. - * include/grub/raid.h: Likewise. - * include/grub/rescue.h: Likewise. - * include/grub/script.h: Likewise. - * include/grub/setjmp.h: Likewise. - * include/grub/symbol.h: Likewise. - * include/grub/term.h: Likewise. - * include/grub/terminfo.h: Likewise. - * include/grub/tparm.h: Likewise. - * include/grub/types.h: Likewise. - * include/grub/video.h: Likewise. - * include/grub/efi/api.h: Likewise. - * include/grub/efi/chainloader.h: Likewise. - * include/grub/efi/console.h: Likewise. - * include/grub/efi/console_control.h: Likewise. - * include/grub/efi/disk.h: Likewise. - * include/grub/efi/efi.h: Likewise. - * include/grub/efi/pe32.h: Likewise. - * include/grub/efi/time.h: Likewise. - * include/grub/i386/linux.h: Likewise. - * include/grub/i386/setjmp.h: Likewise. - * include/grub/i386/types.h: Likewise. - * include/grub/i386/efi/kernel.h: Likewise. - * include/grub/i386/efi/loader.h: Likewise. - * include/grub/i386/efi/time.h: Likewise. - * include/grub/i386/pc/biosdisk.h: Likewise. - * include/grub/i386/pc/boot.h: Likewise. - * include/grub/i386/pc/chainloader.h: Likewise. - * include/grub/i386/pc/console.h: Likewise. - * include/grub/i386/pc/init.h: Likewise. - * include/grub/i386/pc/kernel.h: Likewise. - * include/grub/i386/pc/loader.h: Likewise. - * include/grub/i386/pc/memory.h: Likewise. - * include/grub/i386/pc/multiboot.h: Likewise. - * include/grub/i386/pc/serial.h: Likewise. - * include/grub/i386/pc/time.h: Likewise. - * include/grub/i386/pc/vbe.h: Likewise. - * include/grub/i386/pc/vbeblit.h: Likewise. - * include/grub/i386/pc/vbefill.h: Likewise. - * include/grub/i386/pc/vbeutil.h: Likewise. - * include/grub/i386/pc/vga.h: Likewise. - * include/grub/ieee1275/ieee1275.h: Likewise. - * include/grub/ieee1275/ofdisk.h: Likewise. - * include/grub/powerpc/libgcc.h: Likewise. - * include/grub/powerpc/setjmp.h: Likewise. - * include/grub/powerpc/types.h: Likewise. - * include/grub/powerpc/ieee1275/biosdisk.h: Likewise. - * include/grub/powerpc/ieee1275/console.h: Likewise. - * include/grub/powerpc/ieee1275/ieee1275.h: Likewise. - * include/grub/powerpc/ieee1275/kernel.h: Likewise. - * include/grub/powerpc/ieee1275/loader.h: Likewise. - * include/grub/powerpc/ieee1275/multiboot.h: Likewise. - * include/grub/powerpc/ieee1275/time.h: Likewise. - * include/grub/powerpc/ieee1275/util/biosdisk.h: Likewise. - * include/grub/sparc64/libgcc.h: Likewise. - * include/grub/sparc64/setjmp.h: Likewise. - * include/grub/sparc64/types.h: Likewise. - * include/grub/sparc64/ieee1275/console.h: Likewise. - * include/grub/sparc64/ieee1275/ieee1275.h: Likewise. - * include/grub/sparc64/ieee1275/kernel.h: Likewise. - * include/grub/sparc64/ieee1275/time.h: Likewise. - * include/grub/util/biosdisk.h: Likewise. - * include/grub/util/getroot.h: Likewise. - * include/grub/util/lvm.h: Likewise. - * include/grub/util/misc.h: Likewise. - * include/grub/util/raid.h: Likewise. - * include/grub/util/resolve.h: Likewise. - * io/gzio.c: Likewise. - * kern/device.c: Likewise. - * kern/disk.c: Likewise. - * kern/dl.c: Likewise. - * kern/elf.c: Likewise. - * kern/env.c: Likewise. - * kern/err.c: Likewise. - * kern/file.c: Likewise. - * kern/fs.c: Likewise. - * kern/loader.c: Likewise. - * kern/main.c: Likewise. - * kern/misc.c: Likewise. - * kern/mm.c: Likewise. - * kern/parser.c: Likewise. - * kern/partition.c: Likewise. - * kern/rescue.c: Likewise. - * kern/term.c: Likewise. - * kern/efi/efi.c: Likewise. - * kern/efi/init.c: Likewise. - * kern/efi/mm.c: Likewise. - * kern/i386/dl.c: Likewise. - * kern/i386/efi/init.c: Likewise. - * kern/i386/efi/startup.S: Likewise. - * kern/i386/pc/init.c: Likewise. - * kern/i386/pc/lzo1x.S: Likewise. - * kern/i386/pc/startup.S: Likewise. - * kern/ieee1275/ieee1275.c: Likewise. - * kern/powerpc/cache.S: Likewise. - * kern/powerpc/dl.c: Likewise. - * kern/powerpc/ieee1275/cmain.c: Likewise. - * kern/powerpc/ieee1275/crt0.S: Likewise. - * kern/powerpc/ieee1275/init.c: Likewise. - * kern/powerpc/ieee1275/openfw.c: Likewise. - * kern/sparc64/cache.S: Likewise. - * kern/sparc64/dl.c: Likewise. - * kern/sparc64/ieee1275/init.c: Likewise. - * kern/sparc64/ieee1275/openfw.c: Likewise. - * loader/efi/chainloader.c: Likewise. - * loader/efi/chainloader_normal.c: Likewise. - * loader/i386/efi/linux.c: Likewise. - * loader/i386/efi/linux_normal.c: Likewise. - * loader/i386/pc/chainloader.c: Likewise. - * loader/i386/pc/chainloader_normal.c: Likewise. - * loader/i386/pc/linux.c: Likewise. - * loader/i386/pc/linux_normal.c: Likewise. - * loader/i386/pc/multiboot.c: Likewise. - * loader/i386/pc/multiboot_normal.c: Likewise. - * loader/powerpc/ieee1275/linux.c: Likewise. - * loader/powerpc/ieee1275/linux_normal.c: Likewise. - * normal/arg.c: Likewise. - * normal/cmdline.c: Likewise. - * normal/command.c: Likewise. - * normal/completion.c: Likewise. - * normal/execute.c: Likewise. - * normal/function.c: Likewise. - * normal/lexer.c: Likewise. - * normal/main.c: Likewise. - * normal/menu.c: Likewise. - * normal/menu_entry.c: Likewise. - * normal/misc.c: Likewise. - * normal/parser.y: Likewise. - * normal/script.c: Likewise. - * normal/i386/setjmp.S: Likewise. - * normal/powerpc/setjmp.S: Likewise. - * normal/sparc64/setjmp.S: Likewise. - * partmap/acorn.c: Likewise. - * partmap/amiga.c: Likewise. - * partmap/apple.c: Likewise. - * partmap/gpt.c: Likewise. - * partmap/pc.c: Likewise. - * partmap/sun.c: Likewise. - * term/gfxterm.c: Likewise. - * term/terminfo.c: Likewise. - * term/efi/console.c: Likewise. - * term/i386/pc/console.c: Likewise. - * term/i386/pc/serial.c: Likewise. - * term/i386/pc/vesafb.c: Likewise. - * term/i386/pc/vga.c: Likewise. - * term/ieee1275/ofconsole.c: Likewise. - * util/biosdisk.c: Likewise. - * util/console.c: Likewise. - * util/genmoddep.c: Likewise. - * util/getroot.c: Likewise. - * util/grub-emu.c: Likewise. - * util/grub-mkdevicemap.c: Likewise. - * util/grub-probe.c: Likewise. - * util/lvm.c: Likewise. - * util/misc.c: Likewise. - * util/raid.c: Likewise. - * util/resolve.c: Likewise. - * util/update-grub.in: Likewise. - * util/update-grub_lib.in: Likewise. - * util/grub.d/00_header.in: Likewise. - * util/grub.d/10_hurd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - * util/i386/efi/grub-install.in: Likewise. - * util/i386/efi/grub-mkimage.c: Likewise. - * util/i386/pc/grub-install.in: Likewise. - * util/i386/pc/grub-mkimage.c: Likewise. - * util/i386/pc/grub-mkrescue.in: Likewise. - * util/i386/pc/grub-setup.c: Likewise. - * util/i386/pc/misc.c: Likewise. - * util/powerpc/ieee1275/grub-install.in: Likewise. - * util/powerpc/ieee1275/grub-mkimage.c: Likewise. - * util/powerpc/ieee1275/misc.c: Likewise. - * video/bitmap.c: Likewise. - * video/video.c: Likewise. - * video/i386/pc/vbe.c: Likewise. - * video/i386/pc/vbeblit.c: Likewise. - * video/i386/pc/vbefill.c: Likewise. - * video/i386/pc/vbeutil.c: Likewise. - * video/readers/tga.c: Likewise. - -2007-07-02 Robert Millan - - * conf/i386-efi.rmk: Replace obsolete reference to - util/i386/pc/biosdisk.c with util/biosdisk.c, and util/i386/pc/getroot.c - with util/getroot.c. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk: Likewise. - - * util/grub-emu.c (main): Fix unchecked pointer handling. - -2007-07-02 Robert Millan - - * util/i386/efi/grub-install.in: Allow `grub_probe --target=partmap' - invocation to fail, in order to support partition-less media. - - * util/i386/pc/grub-install.in: Likewise. - - * util/powerpc/ieee1275/grub-install.in: Use grub-probe to determine - which fs or partmap modules are needed (akin to its sister scripts). - - Also use grub-probe to get rid of unportable /proc/mounts check. - - Print the same informational message that the other scripts do, before - exiting. - -2007-06-23 Robert Millan - - * util/update-grub_lib.in (font_path): New function. Determine whether - a font file can be found and, if so, echo the GRUB path to it. - - * util/update-grub.in: Handle multiple terminals depending on user - input, platform availability and font file presence. Propagate - variables of our findings to /etc/grub.d/ children. - - * util/grub.d/00_header.in: Handle multiple terminals, based on - environment setup by update-grub. - -2007-06-23 Robert Millan - - * conf/i386-pc.rmk (pkgdata_MODULES): Add serial.mod. - -2007-06-21 Robert Millan - - * include/grub/i386/pc/kernel.h: Define GRUB_KERNEL_MACHINE_DATA_END to - indicate end of data section in kernel image. - * include/grub/i386/efi/kernel.h: Define GRUB_KERNEL_MACHINE_PREFIX and - GRUB_KERNEL_MACHINE_DATA_END. - - * kern/i386/pc/startup.S: Do not initialize grub_prefix, only reserve - space for it. - * kern/i386/efi/startup.S: Likewise. - - * util/i386/pc/grub-mkimage.c: Initialize grub_prefix to /boot/grub - during image generation. Implement --prefix option to override this - patch. - * util/i386/efi/grub-mkimage.c: Likewise. - - * util/update-grub_lib.in (convert_system_path_to_grub_path): Split - code to make path relative to its root into a separate function. - - * util/i386/pc/grub-install.in: Use newly provided - make_system_path_relative_to_its_root() to convert ${grubdir}, then - pass the result to grub-install --prefix. - -2007-06-13 Robert Millan - - * include/grub/util/misc.h: Define DEFAULT_DIRECTORY and - DEFAULT_DEVICE_MAP. - * util/grub-emu.c: Use above definitions from misc.h instead of - defining them. - * util/grub-mkdevicemap.c: Likewise. - * util/i386/pc/grub-setup.c: Likewise. - * util/grub-probe.c: Likewise. - (probe): Abort with grub_util_error() when either - grub_guess_root_device or grub_util_get_grub_dev fails. - -2007-06-12 Robert Millan - - * normal/command.c (grub_command_execute): Use NULL rather than 0 for - "pager" assignment. - * util/biosdisk.c (grub_util_biosdisk_get_grub_dev): Likewise for - "pcdata". - * util/grub-probe.c (probe): Likewise for "drive_name". - -2007-06-11 Robert Millan - - * util/i386/pc/grub-mkrescue.in: Pad both floppy images with zeroes, - not just the cdrom one. - -2007-06-11 Robert Millan - - * util/i386/pc/grub-mkrescue.in: Add "set -e". - Add --pkglibdir=DIR option to override pkglibdir. - Mention --image-type=TYPE in help output. - Fix --grub-mkimage (it was a no-op). - Abort gracefully when no parameter is given. - -2007-06-11 Robert Millan - - * util/i386/pc/grub-mkrescue.in: New file. - * conf/i386-pc.rmk: Add its build declarations. Put it in bin_SCRIPTS. - * Makefile.in: Handle bin_SCRIPTS. - -2007-06-10 Vesa Jaaskelainen - - * term/gfxterm.c (grub_gfxterm_init): Added support for specifying - list of video modes. - -2007-06-06 Robert Millan - - * util/update-grub_lib.in (convert_system_path_to_grub_path): Abort if - file doesn't exist, or if it is in a filesystem grub can't read. - - * util/update-grub.in: Set fallback for GRUB_FS check to "unknown". Do - not abort if GRUB_DRIVE could not be defined. Rearrange generated - header comment to fit in 80 columns when the variables are resolved. - - * util/grub.d/00_header.in: Only set root variable when GRUB_DRIVE - could be identified by update-grub. Remove redundant check for - unifont.pff existence (since convert_system_path_to_grub_path now - handles that). - -2007-06-04 Robert Millan - - * conf/i386-efi.rmk (grub_probe_SOURCES): Add partmap/apple.c. - - * conf/i386-pc.rmk (grub_probe_SOURCES): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_probe_SOURCES): Add partmap/pc.c. - -2007-06-04 Robert Millan - - * conf/powerpc-ieee1275.rmk: Enable grub-mkdevicemap and grub-probe. - - * include/grub/partition.h: Declare grub_apple_partition_map_init and - grub_apple_partition_map_fini. - - * util/biosdisk.c - (grub_util_biosdisk_open): Replace BLKGETSIZE with BLKGETSIZE64 (needed - to access >2 TiB disks). - - Print disk->total_sectors with %llu instead of %lu, since this - variable is always 64-bit (prevents wrong disk size from being displayed - on either >2 TiB disk or big-endian CPU). - - (grub_util_biosdisk_get_grub_dev): Convert gpt_partition_map handling - into a generic case that supports all (sane) partition maps. - - Stop using grub_cpu_to_le32() on dos_part / bsd_part since it actually - breaks big-endian. - - * util/grub-probe.c: Call grub_apple_partition_map_init() before probe() - and grub_apple_partition_map_fini() after that. - -2007-06-01 Robert Millan - - * util/update-grub.in: Export GRUB_CMDLINE_LINUX. - - * util/grub.d/00_header.in: Only enable gfxterm when - convert_system_path_to_grub_path() succeeds. - -2007-05-20 Robert Millan - - * util/update-grub_lib.in: New file. - * DISTLIST: Add update-grub_lib.in. - * conf/common.rmk: Generate update-grub_lib and install it in - $(lib_DATA). - * Makefile.in: Add install routine for $(lib_DATA). - - * util/grub.d/00_header.in: Use convert_system_path_to_grub_path() - function provided by update-grub_lib to support arbitrary paths of - unifont.pff. - * util/update-grub.in: Use convert_system_path_to_grub_path() to - initialize GRUB_DRIVE_BOOT and GRUB_DRIVE_BOOT_GRUB variables. - -2007-05-19 Robert Millan - - * commands/i386/cpuid.c: New module. - * DISTLIST: Add it. - * conf/i386-efi.rmk: Enable cpuid.mod. - * conf/i386-pc.rmk: Likewise. - -2007-05-18 Jeroen Dekkers - - * kern/disk.c (grub_disk_read): Check return value of - grub_realloc(). - -2007-05-18 Jeroen Dekkers - - * util/getroot.c (grub_util_get_grub_dev): Support partitionable - arrays. - * disk/raid.c (grub_raid_open): Likewise. - -2007-05-17 Jeroen Dekkers - - * util/biosdisk.c (linux_find_partition): Allocate real_dev on the - stack instead of on the heap. - - * kern/disk.c (grub_disk_read): Make sure tmp_buf is big enough - before doing a read on it. - - * configure.ac: Only use -fno-stack-protector for the target - environment. - -2007-05-17 Jeroen Dekkers - - * video/i386/pc/vbe.c (grub_video_vbe_create_render_target): Add - __attribute_ ((unused)) to mode_type argument. - - * util/getroot.c (grub_guess_root_device): Fix #endif. - - * kern/misc.c (memcmp): Fix prototype. - - * include/grub/partition.h [GRUB_UTIL] - (grub_gpt_partition_map_init): Add prototype. - (grub_gpt_partition_map_fini): Likewise. - - * fs/jfs.c (struct grub_jfs_inode): Put __attribute__ ((packed) - at the right place. - - * fs/fat.c (grub_fat_mount): Replace ~0UL with ~0U. - (grub_fat_read_data): Likewise. - (grub_fat_find_dir): Likewise. - - * font/manager.c (find_glyph): Make table a const. - (grub_font_get_glyph): Remove bitmap from if statement. - -2007-05-16 Jeroen Dekkers - - * util/getroot.c (grub_guess_root_device): Remove RAID and LVM - code, first search for device in /dev/mapper, then in /dev. - (grub_util_get_grub_dev): New function. - * include/grub/util/getroot.h (grub_util_get_grub_dev): Add - prototype. - * util/grub-probe.c (probe): Remove check for RAID, call - grub_util_get_grub_dev() instead of - grub_util_biosdisk_get_grub_dev(). - * util/grub-emu.c (main): Call grub_util_get_grub_dev() instead of - grub_util_biosdisk_get_grub_dev(). - * util/i386/pc/grub-setup.c (main): Likewise. - -2007-05-16 Robert Millan - - * DISTLIST: Update for the latest changes. - * conf/i386-pc.rmk: Use the new paths for util/getroot.c, - util/grub-mkdevicemap.c, util/grub-probe.c and util/biosdisk.c. - * util/grub-emu.c: Replace grub/i386/pc/util/biosdisk.h with - grub/util/biosdisk.h. - * util/i386/pc/grub-setup.c: Replace grub/machine/util/biosdisk.h with - grub/util/biosdisk.h. - -2007-05-16 Robert Millan - - * util/grub.d/00_header.in: Set default gfxmode to `640x480'. - -2007-05-16 Robert Millan - - * util/i386/efi/grub-install.in: New. - * conf/i386-efi.rmk: Enable grub-mkdevicemap, grub-probe and the - newly added grub-install. - * util/biosdisk.c: Remove unnecessary grub/machine/biosdisk.h - include. - * util/getroot.c: Replace grub/i386/pc/util/biosdisk.h with - grub/util/biosdisk.h. - * util/grub-probe.c: Replace grub/machine/util/biosdisk.h with - grub/util/biosdisk.h. - -2007-05-16 Robert Millan - - * include/grub/i386/pc/util/biosdisk.h: Moved to ... - * include/grub/util/biosdisk.h: ... here. - * util/i386/pc/biosdisk.c: Moved to ... - * util/biosdisk.c: ... here. - * util/i386/pc/getroot.c: Moved to ... - * util/getroot.c: ... here. - * util/i386/pc/grub-mkdevicemap.c: Moved to ... - * util/grub-mkdevicemap.c: ... here. - * util/i386/pc/grub-probe.c: Moved to ... - * util/grub-probe.c: ... here. - -2007-05-15 Robert Millan - - * util/update-grub.in: Remove duplicated line in grub.cfg header - message. - -2007-05-13 Robert Millan - - * util/update-grub.in: Fix a few assumptions about the devices holding - /, /boot and /boot/grub being the same. - * util/grub.d/00_header.in: Likewise. - * util/grub.d/10_hurd.in: Likewise. - * util/grub.d/10_linux.in: Likewise. - - * util/grub.d/10_linux.in: Implement Linux image sorting with arbitrary - patterns. Use that to define the `.old' suffix as older than `'. - - * util/grub.d/00_header.in: Set default gfxmode to `800x600x16'. - - * util/update-grub.in: Add a reference to ${sysconfdir}/default/grub in - the grub.cfg header message. - -2007-05-11 Robert Millan - - * util/update-grub.in: Create device.map if it doesn't already exist, - before attempting to run grub-probe. - Check for grub-probe and grub-mkdevicemap with the same code - grub-install is using. - Remove test mode. - -2007-05-09 Jeroen Dekkers - - * Makefile.in: Add the datarootdir autoconf variable. - -2007-05-09 Robert Millan - - * util/i386/pc/grub-probe.c (probe): When detecting partition map, - fail gracefully if dev->disk->partition == NULL. - -2007-05-07 Robert Millan - - * util/i386/pc/grub-probe.c: Add `grub-probe -t partmap' parameter to - determine partition map module. - * util/i386/pc/grub-install.in: Use this feature to decide which - partition module to load, instead of hardcoding pc and gpt. - -2007-05-07 Robert Millan - - * Makefile.in: Fix assumption that $(srcdir) has a trailing slash when - source directory differs from build directory. - -2007-05-05 Robert Millan - - * util/powerpc/ieee1275/grub-install.in: Fix syntax error in pkglibdir - initialisation. - -2007-05-05 Robert Millan - - * util/update-grub.in: Create ${grub_prefix} if it doesn't exist. - -2007-05-05 Robert Millan - - * util/grub.d/10_linux.in: Allow the administrator to insert Linux - command-line arguments via ${GRUB_CMDLINE_LINUX}. - -2007-05-05 Robert Millan - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add partmap/gpt.c. - (grub_probe_SOURCES): Likewise. - * util/i386/pc/biosdisk.c (grub_util_biosdisk_get_grub_dev): Detect - GPT and initialize dos_part and bsd_part accordingly. - * util/i386/pc/grub-setup.c (setup): Ditto for install_dos_part and - install_bsd_part. - (main): Activate gpt module for use during partition identification, - and deactivate it afterwards. - * util/i386/pc/grub-install.in: Add gpt module to core.img. - * util/i386/pc/grub-probe.c (main): Activate gpt module for use during - partition identification, and deactivate it afterwards. - -2007-05-05 Robert Millan - - * term/i386/pc/console.c (grub_console_fini): Call - grub_term_set_current() before grub_term_unregister(). - -2007-05-04 Robert Millan - - * DISTLIST: Add util/update-grub.in, util/grub.d/00_header.in, - util/grub.d/10_hurd.in, util/grub.d/10_linux.in and util/grub.d/README. - * Makefile.in: Build update-grub_SCRIPTS. Install update-grub_SCRIPTS - and update-grub_DATA. - * conf/common.rmk: Build and install update-grub components. - * conf/common.mk: Regenerate. - * util/update-grub.in: New. Core of update-grub. - * util/grub.d/00_header.in: New. Generates grub.cfg header. - * util/grub.d/10_hurd.in: New. Generates boot entries for the Hurd. - * util/grub.d/10_linux.in: New. Generates boot entries for Linux. - * util/grub.d/README: New. Document grub.d directory layout. - -2007-05-01 Robert Millan - - * util/grub-emu.c: Move initialization functions - grub_util_biosdisk_init() and grub_init_all() before - grub_util_biosdisk_get_grub_dev(), which relies on them. - -2007-04-19 Robert Millan - - * util/powerpc/ieee1275/grub-install.in: Initialize ${bindir}, since - it is used later. - -2007-04-18 Jerone Young - - * kernel/elf.c: Add missing parenthesis for conditional statement - stanza. - -2007-04-10 Jerone Young - - * util/i386/pc/getroot.c: Update so that if root device is /dev/root , - continue on and look for device node with real device name. - -2007-04-10 Jerone Young - - * configure.ac: Add argument for autoconf to use transformation - ability. - * Makefile.in: Add autoconf package transformation code. - * util/i386/pc/grub-install.in: Likewise. - * util/powerpc/ieee1275/grub-install.in: Likewise. - -2007-03-19 Yoshinori K. Okuji - - * fs/ext2.c (EXT2_GOOD_OLD_REVISION): New macro. - (EXT2_GOOD_OLD_INODE_SIZE): Likewise. - (EXT2_REVISION): Likewise. - (EXT2_INODE_SIZE): Likewise. - (struct grub_ext2_block_group): Added a missing member - "used_dirs". - (grub_ext2_read_inode): Divide by the inode size in a superblock - instead of 128 to obtain INODES_PER_BLOCK. - Use the macro EXT2_INODE_SIZE instead of directly using - SBLOCK->INODE_SIZE. - -2007-03-18 Yoshinori K. Okuji - - * fs/ext2.c (grub_ext2_read_inode): Use the inode size in a - superblock instead of the structure size to compute an - offset. This fixes the problem that GRUB could not read a - filesystem when inode size is different from 128-byte. - -2007-03-05 Marco Gerards - - * normal/main.c (read_config_file): When "menu" is not set, create - an initial context. - -2007-02-21 Hollis Blanchard - - * kern/powerpc/ieee1275/init.c (HEAP_SIZE): Removed. - (HEAP_LIMIT): New macro. - (grub_claim_heap): Claim memory up to `heaplimit'. - -2007-02-21 Hollis Blanchard - - * conf/powerpc-ieee1275.rmk (kernel_elf_LDFLAGS): Link at 64KB. - * kern/powerpc/ieee1275/init.c (_end): Add declaration. - (_start): Likewise. - (grub_arch_modules_addr): Return address after `_end'. - * util/powerpc/ieee1275/grub-mkimage.c: Include grub/misc.h. - (load_modules): Use new parameter as `p_paddr' and `p_vaddr'. - (add_segments): Calculate `_end' from phdr size and location. - (ALIGN_UP): Moved to ... - * include/grub/misc.h: here. - * include/grub/powerpc/ieee1275/kernel.h (GRUB_IEEE1275_MOD_ALIGN): - New macro. - (GRUB_IEEE1275_MODULE_BASE): Removed. - -2007-02-20 Hollis Blanchard - - * kern/powerpc/ieee1275/openfw.c (grub_available_iterate): Correct - loop boundary. - -2007-02-20 Hollis Blanchard - - * include/grub/elfload.h (grub_elf32_load_hook_t): Return grub_err_t. - All users updated. - (grub_elf64_load_hook_t): Likewise. - * kern/elf.c: Call `grub_error_push' before `grub_error'. Improve - debug output. - -2007-02-20 Hollis Blanchard - - * kern/mm.c: Update copyright. - (grub_mm_debug): Correct syntax error. - (grub_mm_dump_free): New function. - (grub_debug_free): Call `grub_free'. - * include/grub/mm.h: Update copyright. - (grub_mm_dump_free): Add declaration. - -2007-02-12 Hollis Blanchard - - * include/grub/ieee1275/ieee1275.h: Update copyright. - * kern/powerpc/ieee1275/init.c: Likewise. - * kern/powerpc/ieee1275/openfw.c: Likewise. - - * loader/powerpc/ieee1275/linux.c: Likewise. - * include/grub/elfload.h: Likewise. - * kern/elf.c: Likewise. - (grub_elf32_load): Pass `base' and `size' parameters. Update all - callers. - (grub_elf64_load): Likewise. - (grub_elf32_load_segment): Move to a nested function. - (grub_elf64_load_segment): Likewise. - -2007-02-12 Hollis Blanchard - - * include/grub/ieee1275/ieee1275.h (grub_available_iterate): New - prototype. - * kern/powerpc/ieee1275/init.c (grub_heap_start): Removed. - (grub_heap_len): Likewise. - (HEAP_SIZE): New macro. - (grub_claim_heap): New function. - (grub_machine_init): Don't claim heap directly. Call - `grub_claim_heap'. - * kern/powerpc/ieee1275/openfw.c: Include alloca.h. - (grub_available_iterate): New function. - -2007-02-03 Thomas Schwinge - - * aclocal.m4 (grub_CHECK_STACK_PROTECTOR): New definition. - * configure.ac: Use it for testing the HOST and TARGET compilers. - -2006-12-13 Thomas Schwinge - - * Makefile.in (enable_grub_emu): New variable. - * configure.ac (--enable-grub-emu): New option. - Do the checks for (n)curses only if `--enable-grub-emu' is requested. - * conf/i386-efi.rmk (sbin_UTILITIES): Add `grub-emu' only if requested. - * conf/i386-pc.rmk: Likewise. - * conf/powerpc-ieee1275.rmk: Likewise. - * conf/sparc64-ieee1275.rmk (bin_UTILITIES): Likewise. - -2006-12-12 Marco Gerards - - * include/grub/err.h (grub_err_t): Add `GRUB_ERR_MENU'. - - * kern/env.c (grub_env_unset): Don't free the member `value' when - the type is GRUB_ENV_VAR_DATA, in this case it's a user defined - pointer. - - * normal/main.c (current_menu): Removed. - (free_menu): Unset the `menu' environment variable. - (grub_normal_menu_addentry): Make use of the environment variable - `menu', instead of using the global `current_menu'. Allocate - memory for the sourcecode of this entry. - (read_config_file): New argument `nested', changed all callers. - Only in the case of a new context, initialize a new menu. Set the - `menu' environment variable. - (grub_normal_execute): Don't set and unset the environment - variable `menu' here anymore. Only free the menu when leaving the - context. - - * util/i386/pc/biosdisk.c (linux_find_partition): Fixed a memory - leak. - -2006-12-11 Marco Gerards - - * normal/menu_entry.c (run): Fix off by one bug so the last line - is executed. Move the loader check to outside the loop. - -2006-12-08 Hollis Blanchard - - * kern/powerpc/ieee1275/cmain.c (cmain): Mark r3 and r4 as `UNUSED'. - -2006-11-25 Yoshinori K. Okuji - - * util/i386/pc/grub-mkimage.c (generate_image): Fix the offset of - the number of sectors. Reported by Andrey Shuvikov - . - -2006-11-11 Jeroen Dekkers - - * kern/disk.c (grub_disk_read): When there is a read error, always - try to read only the necessary data. - - * conf/i386-pc.rmk (grub_probe_SOURCES): Add disk/lvm.c and - disk/raid.c. - * include/grub/disk.h [GRUB_UTIL] (grub_raid_init): New - prototype. - [GRUB_UTIL] (grub_raid_fini): Likewise. - [GRUB_UTIL] (grub_lvm_init): Likewise. - [GRUB_UTIL] (grub_lvm_fini): Likewise. - * util/i386/pc/grub-probe.c (probe): Check whether DEVICE_NAME is - RAID device and copy DEVICE_NAME to DRIVE_NAME in that case. - (main): Call grub_raid_init(), grub_lvm_init(), grub_lvm_fini() - and grub_raid_fini(). - -2006-11-09 Jeroen Dekkers - - * include/grub/types.h (__unused): Rename to UNUSED. - * kern/elf.c (grub_elf32_size): Use UNUSED instead of __unused. - (grub_elf64_size): Likewise. - -2006-11-03 Hollis Blanchard - - * kern/elf.c (grub_elf_file): Call grub_file_seek. Call - grub_error_push and grub_error_pop in the error-handling path. - (grub_elf32_load_segment): Only call grub_file_read with non-zero - length. - -2006-11-03 Hollis Blanchard - - * conf/i386-efi.rmk (grub_emu_SOURCES): Add kern/elf.c. - * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - (kernel_elf_SOURCES): Likewise. - * conf/i386-efi.rmk (kernel_mod_HEADERS): Add elfload.h and cache.h. - * conf/i386-pc.rmk (kernel_mod_HEADERS): Likewise. - * conf/powerpc-ieee1275.rmk (kernel_elf_HEADERS): Likewise. - * conf/sparc64-ieee1275.rmk (kernel_elf_HEADERS): Likewise. - * conf/common.rmk (pkgdata_MODULES): Add elf.mod. - (elf_mod_SOURCES): New variable. - (elf_mod_CFLAGS): Likewise. - (elf_mod_LDFLAGS): Likewise. - * include/grub/types.h (__unused): New macro. - * include/grub/elfload.h: New file. - * kern/elf.c: Likewise. - * loader/powerpc/ieee1275/linux.c: Include elfload.h. - (ELF32_LOADMASK): New macro. - (ELF64_LOADMASK): Likewise. - (vmlinux): Removed. - (grub_linux_load32): New function. - (grub_linux_load64): Likewise. - (grub_rescue_cmd_linux): Call grub_linux_load32 or grub_linux_load64. - Use grub_elf_t instead of grub_file_t. - -2006-11-02 Hollis Blanchard - - * kern/ieee1275/ieee1275.c (grub_ieee1275_set_color): Add - `catch_result' to struct set_color_args. - -2006-10-28 Yoshinori K. Okuji - - * normal/menu.c: Include grub/script.h. - * normal/menu_entry.c: Likewise. - * include/grub/normal.h: Do not include grub/script.h. - -2006-10-27 Hollis Blanchard - - * kern/disk.c (grub_disk_read): Correct debug printf formatting. - -2006-10-27 Hollis Blanchard - - * kern/disk.c (grub_disk_open): Print debug messages when opening a - disk. - (grub_disk_close): Print debug messages when closing a disk. - (grub_disk_read): Print debug messages when disk read fails. - * kern/fs.c (grub_fs_probe): Print debug messages when detecting - filesystem type. - * kern/partition.c: Include misc.h. - (grub_partition_iterate): Print debug messages when detecting - partition type. - -2006-10-27 Hollis Blanchard - - * disk/ieee1275/ofdisk.c (grub_ofdisk_read): Return error if `status' - is negative. - * kern/ieee1275/ieee1275.c (IEEE1275_IHANDLE_INVALID): Change to 0. - -2006-10-26 Hollis Blanchard - - * kern/powerpc/ieee1275/openfw.c (grub_ieee1275_encode_devname): - Reverse GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS test. - -2006-10-25 Jeroen Dekkers - - * disk/lvm.c (grub_lvm_scan_device): Malloc sizeof(*lv) bytes - instead of sizeof(lv). Patch by Michael Guntsche. - -2006-10-18 Jeroen Dekkers - - * disk/lvm.c: Rename VGS to VG_LIST. - (grub_lvm_iterate): Change VGS->LV to VG-LV. - (grub_lvm_open): Likewise. - Thanks to Michael Guntsche for finding this bug. - -2006-10-15 Yoshinori K. Okuji - - * configure.ac (AC_INIT): Bumped to 1.95. - -2006-10-14 Robert Millan - - * util/i386/pc/getroot.c (grub_guess_root_device): Don't compare os_dev - with "/dev/.static/dev/md". - -2006-10-14 Yoshinori K. Okuji - - * util/i386/pc/grub-probe.c (probe): Print DEVICE_NAME instead of - DRIVE_NAME when grub_util_biosdisk_get_grub_dev fails. Open - DRIVE_NAME instead of DEVICE_NAME. Make sure that DEVICE_NAME and - DRIVE_NAME are always freed. - - * util/i386/pc/biosdisk.c (make_device_name): Add one into - DOS_PART, as a DOS partition is counted from one instead of zero - now. Reported by Robert Millan. - -2006-10-14 Robert Millan - - * util/i386/pc/getroot.c (grub_guess_root_device): Stop using - grub_util_biosdisk_get_grub_dev to convert system device to GRUB device. - * util/grub-emu.c (main): Use grub_util_biosdisk_get_grub_dev with the - string returned by grub_guess_root_device. - * util/i386/pc/grub-setup.c: Likewise. - * util/i386/pc/grub-probefs.c: Likewise. - - * util/i386/pc/grub-probefs.c: Rename to ... - * util/i386/pc/grub-probe.c: ... this. - * DISTLIST: Remove grub-probefs, add grub-probe. - * conf/i386-efi.rmk: Likewise. - * conf/i386-pc.rmk: Likewise. - * util/i386/pc/grub-install.in: Likewise. - - * util/i386/pc/grub-probe.c: Add --target=(fs|device|drive) option to - choose which information we want to print. - -2006-10-14 Yoshinori K. Okuji - - * DISTLIST: Added commands/echo.c, disk/lvm.c, disk/raid.c, - include/grub/bitmap.h, include/grub/lvm.h, include/grub/raid.h, - include/grub/i386/pc/vbeutil.h, include/grub/util/lvm.h, - include/grub/util/raid.h, util/lvm.c, util/raid.c, video/bitmap.c, - video/readers/tga.c and video/i386/pc/vbeutil.c. - -2006-10-14 Jeroen Dekkers - - Added support for RAID and LVM. - - * disk/lvm.c: New file. - * disk/raid.c: Likewise. - * include/grub/lvm.h: Likewise. - * include/grub/raid.h: Likewise. - * include/grub/util/lvm.h: Likewise. - * include/grub/util/raid.h: Likewise. - * util/lvm.c: Likewise. - * util/raid.c: Likewise. - - * include/grub/disk.h (grub_disk_dev_id): Add - GRUB_DISK_DEVICE_RAID_ID and GRUB_DISK_DEVICE_LVM_ID. - (grub_disk_get_size): New prototype. - * kern/disk.c (grub_disk_open): Check whether grub_partition_probe() - returns a partition. - (grub_disk_get_size): New function. - - * kern/i386/pc/init.c (make_install_device): Copy the prefix - verbatim if grub_install_dos_part is -2. - - * util/i386/pc/getroot.c (grub_guess_root_device): Support RAID - and LVM devices. - - * util/i386/pc/grub-setup.c (setup): New argument - MUST_EMBED. Force embedding of GRUB when the argument is - true. Close FILE before returning. - (main): Add support for RAID and LVM. - - * conf/common.rmk: Add RAID and LVM modules. - * conf/i386-pc.rmk (grub_setup_SOURCES): Add util/raid.c and - util/lvm.c. - (grub_emu_SOURCES): Add disk/raid.c and disk/lvm.c. - - * kern/misc.c (grub_strstr): New function. - * include/grub/misc.h (grub_strstr): New prototype. - -2006-10-10 Tristan Gingold - - * include/grub/efi/api.h (GRUB_EFI_ERROR_CODE): Long constant. - -2006-10-05 Tristan Gingold - - * kern/misc.c (grub_strtoull): Guess the base only if not - specified. - -2006-10-01 Hollis Blanchard - - * kern/powerpc/ieee1275/cmain.c (cmain): Remove incomplete Old World - PowerMac support. - -2006-10-01 Hollis Blanchard - - * disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): Cast `size' to long. - - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_next_property): - Remove `flags' argument. All callers changed. - * kern/ieee1275/ieee1275.c (IEEE1275_PHANDLE_ROOT): Removed. - (IEEE1275_IHANDLE_INVALID): New variable. - (IEEE1275_CELL_INVALID): New variable. - (grub_ieee1275_finddevice, grub_ieee1275_get_property, - grub_ieee1275_get_property_length, grub_ieee1275_instance_to_package, - grub_ieee1275_package_to_path, grub_ieee1275_instance_to_path, - grub_ieee1275_peer, grub_ieee1275_child, grub_ieee1275_open, - grub_ieee1275_claim, grub_ieee1275_set_property): Error-check return - codes from Open Firmware. All callers updated. - (grub_ieee1275_next_property): Directly return Open Firmware return - code. - * kern/powerpc/ieee1275/cmain.c (grub_ieee1275_find_options): - Standardize error checking from `grub_ieee1275_get_property'. - * kern/powerpc/ieee1275/openfw.c (grub_devalias_iterate): Rename - `devalias' to `aliases'. Correct comments. Consolidate error paths. - -2006-10-01 Hollis Blanchard - - * kern/ieee1275/ieee1275.c (grub_ieee1275_instance_to_path): Rename - `instance_to_package_args' to `instance_to_path_args'. - - * kern/powerpc/ieee1275/init.c (grub_machine_init): Use - `grub_ieee1275_chosen'. - - * term/ieee1275/ofconsole.c (grub_ofconsole_init): Call - `grub_ieee1275_interpret'. - -2006-09-25 Hollis Blanchard - - * util/powerpc/ieee1275/grub-mkimage.c: Include config.h. - -2006-09-25 Hollis Blanchard - - * include/grub/powerpc/libgcc.h (__floatdisf): New prototype. - (__cmpdi): Likewise. - - * kern/powerpc/ieee1275/openfw.c (grub_devalias_iterate): Pass 0 as - `flags' to `grub_ieee1275_next_property'. Change `pathlen' to type - `grub_ssize_t'. - - * kern/powerpc/ieee1275/cmain.c: Include grub/misc.h. - - * loader/powerpc/ieee1275/linux.c (grub_linux_boot): Change `actual' - to type `grub_ssize_t'. - (grub_rescue_cmd_linux): Cast -1 to `grub_off_t'. - -2006-09-22 Marco Gerards - - * normal/script.c (grub_script_create_cmdmenu): Skip leading - newlines. - -2006-09-22 Marco Gerards - - * commands/echo.c: New file. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `commands/echo.c'. - - * conf/common.rmk (echo_mod_SOURCES): New variable. - (echo_mod_CFLAGS): Likewise. - (echo_mod_LDFLAGS): Likewise. - -2006-09-22 Marco Gerards - - * normal/main.c (get_line): Malloc memory instead of using - preallocated memory. Removed the arguments `cmdline' and - `max_len'. Updated all callers. - -2006-09-22 Marco Gerards - - * conf/i386-efi.rmk (grub_emu_DEPENDENCIES): New variable. - (normal_mod_DEPENDENCIES): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_emu_DEPENDENCIES): Likewise. - (normal_mod_DEPENDENCIES): Likewise. - - * conf/sparc64-ieee1275.rmk (normal_mod_DEPENDENCIES): Likewise. - -2006-09-22 Johan Rydberg - - * genmk.rb: Add DEPENDENCIES variables to modules, utilities, and - programs. - * conf/i386-pc.rmk (grub_emu_DEPENDENCIES): Declare. - (normal_mod_DEPENDENCIES): Likewise. - * conf/i386-pc.mk: Regenerate. - * conf/i386-efi.mk: Likewise - * conf/common.mk: Likewise. - * conf/powerpc-ieee1275.mk: Likewise. - * conf/sparc64-ieee1275.mk: Likewise. - -2006-09-22 Robert Millan - - Sync with i386 version. - * conf/powerpc-ieee1275.rmk (bin_UTILITIES): Remove grub-emu, add grub-mkimage. - * conf/powerpc-ieee1275.rmk (sbin_UTILITIES): Remove grub-mkimage, add grub-emu. - -2006-09-21 Robert Millan - - Import from GRUB Legacy (lib/device.c): - * util/i386/pc/grub-mkdevicemap.c (get_i2o_disk_name): New function. - (init_device_map) [__linux__]: Add support for I2O devices. - -2006-09-14 Marco Gerards - - * conf/i386-pc.rmk (COMMON_LDFLAGS): Use `-m32' instead of - `-melf_i386'. - -2006-09-14 Robert Millan - - * util/i386/pc/grub-install.in: Skip menu.lst when removing - /boot/grub/*.lst. - - * util/i386/pc/getroot.c: Don't recurse into dotdirs (e.g. ".static"). - - * util/i386/pc/grub-mkdevicemap.c: Make sure the floppy device exists - before adding it to device.map. - -2006-08-15 Johan Rydberg - - * genmk.rb: Let GCC generate dependencies the first time it - compiles a file; using the -MD option. - * conf/common.mk: Regenerate. - * conf/i386-pc.mk: Likewise. - * conf/i386-efi.mk: Likewise. - * conf/powerpc-ieee1275.mk: Likewise. - * conf/sparc64-ieee1275.mk: Likewise. - -2006-08-04 Yoshinori K. Okuji - - Move the prototypes of grub_setjmp and grub_longjmp to - cpu/setjmp.h, so that each architecture may specify different - attributes. - - * include/grub/i386/setjmp.h (grub_setjmp): New prototype. - (grub_longjmp): Likewise. - * include/grub/powerpc/setjmp.h (grub_setjmp): Likewise.. - (grub_longjmp): Likewise. - * include/grub/sparc64/setjmp.h (grub_setjmp): Likewise.. - (grub_longjmp): Likewise. - - * include/grub/setjmp.h [!GRUB_UTIL] (grub_setjmp): Removed. - [!GRUB_UTIL] (grub_longjmp): Removed. - -2006-08-01 Pelletier Vincent - - * kern/ieee1275/ieee1275.c (grub_ieee1275_set_color): IEEE1275 - "color!" method does not return any value. - -2006-07-29 Vesa Jaaskelainen - - * include/grub/bitmap.h: New file. - - * include/grub/i386/pc/vbeutil.h: Likewise. - - * video/bitmap.c: Likewise. - - * video/readers/tga.c: Likewise. - - * video/i386/pc/vbeutil.c: Likewise. - - * commands/videotest.c: Code cleanup and updated to reflect to new - video API. - - * term/gfxterm.c: Likewise. - - * video/video.c: Likewise. - - * conf/i386-pc.rmk (pkgdata_MODULES): Added tga.mod and bitmap.mod. - (vbe_mod_SOURCES): Added video/i386/pc/vbeutil.c. - (bitmap_mod_SOURCES): New entry. - (bitmap_mod_CFLAGS): Likewise. - (bitmap_mod_LDFLAGS): Likewise. - (tga_mod_SOURCES): Likewise. - (tga_mod_CFLAGS): Likewise. - (tga_mod_LDFLAGS): Likewise. - - * include/grub/video.h (grub_video_blit_operators): New enum type. - (grub_video_render_target): Changed as forward declaration and moved - actual definition to be video driver specific. - (grub_video_adapter.blit_bitmap): Added blitting operator. - (grub_video_adapter.blit_render_target): Likewise. - (grub_video_blit_bitmap): Likewise. - (grub_video_blit_render_target): Likewise. - - * include/grub/i386/pc/vbe.h (grub_video_render_target): Added - driver specific render target definition. - (grub_video_vbe_map_rgba): Added driver internal helper. - (grub_video_vbe_unmap_color): Updated to use - grub_video_i386_vbeblit_info. - (grub_video_vbe_get_video_ptr): Likewise. - - * include/grub/i386/pc/vbeblit.h - (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8A8): Updated to use - grub_video_i386_vbeblit_info. - (grub_video_i386_vbeblit_R8G8B8_R8G8B8A8): Likewise. - (grub_video_i386_vbeblit_index_R8G8B8A8): Likewise. - (grub_video_i386_vbeblit_R8G8B8A8_R8G8B8): Likewise. - (grub_video_i386_vbeblit_R8G8B8_R8G8B8): Likewise. - (grub_video_i386_vbeblit_index_R8G8B8): Likewise. - (grub_video_i386_vbeblit_index_index): Likewise. - (grub_video_i386_vbeblit_R8G8B8X8_R8G8B8X8): New blitter function. - (grub_video_i386_vbeblit_R8G8B8_R8G8B8X8): Likewise. - (grub_video_i386_vbeblit_index_R8G8B8X8): Likewise. - (grub_video_i386_vbeblit_blend): Added generic blitter for blend - operator. - (grub_video_i386_vbeblit_replace): Added generic blitter for replace - operator. - - * video/i386/pc/vbeblit.c: Updated to reflect changes on - include/grub/i386/pc/vbeblit.h. - - * include/grub/i386/pc/vbefill.h (grub_video_i386_vbefill_R8G8B8A8): - Updated to use grub_video_i386_vbeblit_info. - (grub_video_i386_vbefill_R8G8B8): Likewise. - (grub_video_i386_vbefill_index): Likewise. - (grub_video_i386_vbefill): Added generic filler. - - * video/i386/pc/vbefill.c: Updated to reflect changes on - include/grub/i386/pc/vbefill.h. - - * video/i386/pc/vbe.c (grub_video_vbe_get_video_ptr): Updated to use - grub_video_i386_vbeblit_info. - (grub_video_vbe_unmap_color): Likewise. - (grub_video_vbe_blit_glyph): Likewise. - (grub_video_vbe_scroll): Likewise. - (grub_video_vbe_draw_pixel): Removed function. - (grub_video_vbe_get_pixel): Likewise. - (grub_video_vbe_fill_rect): Moved all blitters to vbefill.c and - updated code to use it. - (common_blitter): Added common blitter for render target and bitmap. - (grub_video_vbe_blit_bitmap): Updated to use common_blitter. - (grub_video_vbe_blit_render_target): Likewise. - -2006-07-30 Johan Rydberg - - * kern/efi/efi.c (grub_efi_set_text_mode): Assume console already - is in text mode if there is no console control protocol instance - available. - -2006-07-29 Vesa Jaaskelainen - - * include/grub/video.h: Code cleanup. - - * include/grub/i386/pc/vbe.h: Likewise. - - * video/i386/pc/vbe.c: Likewise. - - * video/i386/pc/vbeblit.c: Likewise. - - * video/i386/pc/vbefill.c: Likewise. - - * video/video.c: Likewise. Also added more comments. - -2006-07-29 Vesa Jaaskelainen - - * disk/i386/pc/biosdisk.c (struct grub_biosdisk_drp): Moved to ... - (struct grub_biosdisk_dap): Likewise. - - * include/grub/i386/pc/biosdisk.h: ... to here. Also corrected - linkage settings for all functions. - -2006-07-12 Marco Gerards - - * configure.ac (--enable-mm-debug): Fix typo. - - * genkernsyms.sh.in: Use proper quoting for `CC'. - -2006-07-02 Jeroen Dekkers - - * conf/i386-pc.rmk (COMMON_ASFLAGS): Add "-m32". - (normal_mod_ASFLAGS): Remove "-m32". - -2006-06-14 Yoshinori K. Okuji - - * util/misc.c: Include config.h. - [!HAVE_MEMALIGN]: Do not include malloc.h. - (grub_memalign): Use posix_memalign, if present. Then, use - memalign, if present. Otherwise, emit an error. - - * util/grub-emu.c: Do not include malloc.h. - - * include/grub/util/misc.h: Include unistd.h. This is required for - FreeBSD, because off_t is defined in unistd.h. Reported by Harley - D. Eades III . - - * configure.ac (AC_GNU_SOURCE): Added. - (AC_CHECK_FUNCS): Check posix_memalign and memalign for the host - type. - -2006-06-09 Yoshinori K. Okuji - - * loader/i386/pc/linux.c (grub_rescue_cmd_initrd): Make sure that - ADDR_MAX does not exceed GRUB_LINUX_INITRD_MAX_ADDRESS. - -2006-06-07 Jeroen Dekkers - - * include/grub/types.h (grub_host_addr_t): Rename to - grub_target_addr_t. - (grub_host_off_t): Rename to grub_target_off_t. - (grub_host_size_t): Rename to grub_target_size_t. - (grub_host_ssize_t): Rename to grub_target_ssize_t. - Refer to GRUB_TARGET_SIZEOF_VOID_P to define those variables. - - * include/grub/kernel.h (struct grub_module_header): Change type - of OFFSET to grub_target_off_t and type of SIZE to grub_target_size_t. - (grub_module_info): Likewise. - -2006-06-05 Yoshinori K. Okuji - - * loader/i386/pc/linux.c (grub_rescue_cmd_initrd): The conditional - of checking LINUX_MEM_SIZE was reverse. Reported by Jesus - Velazquez . - -2006-06-05 Yoshinori K. Okuji - - Count partitions from 1 instead of 0 in the string representation - of partitions. Still use 0-based internally. - - * partmap/sun.c (grub_sun_is_valid): A cosmetic change. - (sun_partition_map_iterate): Use grub_partition_t instead of - struct grub_partition *. Cast DESC->START_CYLINDER to - grub_uint64_t after converting the endian. - (sun_partition_map_probe): Subtract 1 for PARTNUM. - (sun_partition_map_get_name): Add 1 to P->INDEX. - - * partmap/pc.c (grub_partition_parse): Subtract 1 for - PCDATA->DOS_PART. - (pc_partition_map_get_name): Add 1 into PCDATA->DOS_PART. - - * partmap/gpt.c (gpt_partition_map_iterate): Initialize PARTNO to - zero instead of one. - (gpt_partition_map_probe): Subtract 1 for PARTNUM. - (gpt_partition_map_get_name): Add 1 into P->INDEX. - - * partmap/apple.c (apple_partition_map_iterate): Change the type - of POS to unsigned. - (apple_partition_map_probe): Subtract 1 for PARTNUM. - (apple_partition_map_get_name): Add 1 into P->INDEX. - - * partmap/amiga.c (amiga_partition_map_iterate): Change the type - of POS to unsigned. - (amiga_partition_map_iterate): Cast NEXT to grub_off_t to - calculate the offset of a partition. - (amiga_partition_map_probe): Subtract 1 for PARTNUM. - (amiga_partition_map_get_name): Add 1 into P->INDEX. - - * partmap/acorn.c (acorn_partition_map_find): Change the type of - SECTOR to grub_disk_addr_t. - (acorn_partition_map_iterate): Likewise. - (acorn_partition_map_probe): Subtract 1 for PARTNUM. - Change the type of SECTOR to grub_disk_addr_t. Declare P on the - top. - (acorn_partition_map_get_name): Add 1 into P->INDEX. - - * kern/i386/pc/init.c (make_install_device): Add 1 into - GRUB_INSTALL_DOS_PART. - - * fs/iso9660.c (grub_iso9660_mount): Fixed a reversed - conditional. - -2006-06-04 Yoshinori K. Okuji - - Clean up the code to support 64-bit addressing in disks and - files. This change is not enough for filesystems yet. - - * util/i386/pc/grub-setup.c (struct boot_blocklist): Change the - type of "start" to grub_uint64_t. - (setup): Change the types of KERNEL_SECTOR and FIRST_SECTOR to - grub_disk_addr_t * and grub_disk_addr_t. Fix the format string in - save_first_sector and save_blocklists. Use grub_le_to_cpu64 to - convert addresses. - - * util/i386/pc/biosdisk.c (open_device): Change the type of SECTOR - to grub_disk_addr_t. - - * partmap/gpt.c (gpt_partition_map_iterate): Fix the format - string. - - * partmap/pc.c (pc_partition_map_iterate): Likewise. - - * partmap/amiga.c (amiga_partition_map_iterate): Cast RDSK.MAGIC - to char *. - - * normal/script.c (grub_script_parse): Remove unused MEMFREE. - - * normal/parser.y (YYLTYPE_IS_TRIVIAL): New macro. - - * normal/lexer.c (grub_script_yyerror): Specify unused to LEX. - - * loader/i386/pc/multiboot.c (grub_multiboot_load_elf64): Cast -1 - to grub_off_t, to detect an error from grub_file_seek. - (grub_multiboot_load_elf32): Likewise. - - * kern/misc.c (grub_strtoul): Use grub_strtoull. Return the - maximum unsigned long value when an overflow is detected. - (grub_strtoull): New function. - (grub_divmod64): Likewise. - (grub_lltoa): use grub_divmod64. - - * kern/fs.c (struct grub_fs_block): Change the type of "offset" to - grub_disk_addr_t. - (grub_fs_blocklist_open): Increase P if P is not NULL to advance - the pointer to next character. Use grub_strtoull instead of - grub_strtoul. - (grub_fs_blocklist_read): Change the types of SECTOR, OFFSET and - SIZE to grub_disk_addr_t, grub_off_t and grub_size_t, - respectively. - - * kern/file.c (grub_file_read): Prevent an overflow of LEN, as the - return value is signed. - (grub_file_seek): Change the type of OLD to grub_off_t. Do not - test if OFFSET is less than zero, as OFFSET is unsigned now. - - * kern/disk.c (struct grub_disk_cache): Change the type of - "sector" to grub_disk_addr_t. - (grub_disk_cache_get_index): Change the type of SECTOR to - grub_disk_addr_t. Calculate the hash with SECTOR casted to - unsigned after shifting. - (grub_disk_cache_invalidate): Change the type of SECTOR to - grub_disk_addr_t. - (grub_disk_cache_unlock): Likewise. - (grub_disk_cache_store): Likewise. - (grub_disk_check_range): Change the types of SECTOR, OFFSET, SIZE, - START and LEN to grub_disk_addr_t *, grub_off_t *, grub_size_t, - grub_disk_addr_t and grub_uint64_t, respectively. - (grub_disk_read): Use an unsigned variable REAL_OFFSET for the - body, as the value of OFFSET is tweaked by - grub_disk_check_range. Change the types of START_SECTOR, LEN and - POS to grub_disk_addr_t, grub_size_t and grub_size_t, - respectively. - (grub_disk_write): Use an unsigned variable REAL_OFFSET for the - body, as the value of OFFSET is tweaked by - grub_disk_check_range. Change the types of LEN and N to - grub_size_t. - - * io/gzio.c (struct grub_gzio): Change the types of "data_offset" - and "saved_offset" to grub_off_t. - (test_header): Cast BUF to char *. - (get_byte): Cast GZIO->DATA_OFFSET to grub_off_t. Cast GZIO->INBUF - to char *. - (grub_gzio_read): Change the types of OFFSET and SIZE to - grub_off_t and grub_size_t, respectively. - - * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_FORCE_LBA): - Removed. - (GRUB_BOOT_MACHINE_BOOT_DRIVE): Changed to 0x4c. - (GRUB_BOOT_MACHINE_KERNEL_ADDRESS): Changed to 0x40. - (GRUB_BOOT_MACHINE_KERNEL_SEGMENT): Changed to 0x42. - (GRUB_BOOT_MACHINE_DRIVE_CHECK): Changed to 0x4e. - (GRUB_BOOT_MACHINE_LIST_SIZE): Increased to 12. - - * include/grub/types.h (grub_off_t): Unconditionally set to - grub_uint64_t. - (grub_disk_addr_t): Changed to grub_uint64_t. - - * include/grub/partition.h (struct grub_partition): Change the - types of "start", "len" and "offset" to grub_disk_addr_t, - grub_uint64_t and grub_disk_addr_t, respectively. - (grub_partition_get_start): Return grub_disk_addr_t. - (grub_partition_get_len): Return grub_uint64_t. - - * include/grub/misc.h (grub_strtoull): New prototype. - (grub_divmod64): Likewise. - - * include/grub/fshelp.h (grub_fshelp_read_file): Change the types - of SECTOR, LEN and FILESIZE to grub_disk_addr_t, grub_size_t and - grub_off_t, respectively. - All callers and references changed. - - * include/grub/fs.h (struct grub_fs): Change the type of LEN to - grub_size_t in "read". - All callers and references changed. - - * include/grub/file.h (struct grub_file): Change the types of - "offset" and "size" to grub_off_t and grub_off_t, - respectively. Change the type of SECTOR to grub_disk_addr_t in - "read_hook". - (grub_file_read): Change the type of LEN to grub_size_t. - (grub_file_seek): Return grub_off_t. Change the type of OFFSET to - grub_off_t. - (grub_file_size): Return grub_off_t. - (grub_file_tell): Likewise. - All callers and references changed. - - * include/grub/disk.h (struct grub_disk_dev): Change the types of - SECTOR and SIZE to grub_disk_addr_t and grub_size_t in "read" and - "write". - (struct grub_disk): Change the type of "total_sectors" to - grub_uint64_t. Change the type of SECTOR to grub_disk_addr_t in - "read_hook". - (grub_disk_read): Change the types of SECTOR, OFFSET and SIZE to - grub_disk_addr_t, grub_off_t and grub_size_t, respectively. - (grub_disk_write): Likewise. - All callers and references changed. - - * fs/iso9660.c (grub_iso9660_susp_iterate): Cast parameters to - char * for grub_strncmp to silence gcc. - (grub_iso9660_mount): Likewise. - (grub_iso9660_mount): Likewise. - (grub_iso9660_read_symlink): Likewise. Also, remove the nonsense - return statement. - (grub_iso9660_iterate_dir): Likewise. - (grub_iso9660_label): Cast DATA->VOLDESC.VOLNAME to char *. - - * fs/hfs.c (grub_hfs_read_file): Change the types of SECTOR and - LEN to grub_disk_addr_t and grub_size_t, respectively. - - * fs/hfsplus.c (grub_hfsplus_read_file): Likewise. - - * fs/jfs.c (grub_jfs_read_file): Likewise. - - * fs/minix.c (grub_jfs_read_file): Likewise. - - * fs/sfs.c (grub_jfs_read_file): Likewise. - - * fs/ufs.c (grub_jfs_read_file): Likewise. - - * fs/xfs.c (grub_jfs_read_file): Likewise. - - * fs/fat.c (grub_fat_read_data): Change the types of SECTOR, LEN - and SIZE to grub_disk_addr_t, grub_size_t and grub_size_t, - respectively. - - * fs/ext2.c (grub_ext2_read_block): When an error happens, set - BLKNR to -1 instead of returning GRUB_ERRNO. - (grub_ext2_read_file): Change the types of SECTOR and - LEN to grub_disk_addr_t and grub_size_t, respectively. - - * fs/affs.c (grub_affs_read_file): Change the types of SECTOR and - LEN to grub_disk_addr_t and grub_size_t, respectively. - - * font/manager.c (grub_font_get_glyph): Cast BITMAP to char * for - grub_file_read. - - * disk/ieee1275/ofdisk.c (grub_ofdisk_read): Fix the format - string. Do not cast SECTOR explicitly. - - * disk/i386/pc/biosdisk.c (grub_biosdisk_open): Change the type of - TOTAL_SECTORS to grub_uint64_t. Do not mask DRP->TOTAL_SECTORS. - (grub_biosdisk_rw): Change the types of SECTOR and SIZE to - grub_disk_addr_t and grub_size_t, respectively. If the sector is - over 2TB and LBA mode is not supported, raise an error. - (get_safe_sectors): New function. - (grub_biosdisk_read): Use get_safe_sectors. - (grub_biosdisk_write): Likewise. - - * disk/efi/efidisk.c (grub_efidisk_read): Fix the format string. - (grub_efidisk_write): Likewise. - - * disk/loopback.c (delete_loopback): Cosmetic changes. - (grub_cmd_loopback): Likewise. Also, test NEWDEV->FILENAME - correctly. - (grub_loopback_open): Likewise. - (grub_loopback_read): Likewise. Also, change the type of POS to - grub_off_t, and fix the usage of grub_memset. - - * commands/i386/pc/play.c: Include grub/machine/time.h. - - * commands/ls.c (grub_ls_list_files): Use "llu" instead of "d" to - print FILE->SIZE. - - * commands/configfile.c: Include grub/env.h. - - * commands/cmp.c (grub_cmd_cmp): Do not use ERR, but use - GRUB_ERRNO directly instead. Change the type of POS to - grub_off_t. Follow the coding standard. - - * commands/blocklist.c: Include grub/partition.h. - (grub_cmd_blocklist): Return an error if the underlying device is - not a disk. Take the starting sector of a partition into account, - if a partition is used. - - * boot/i386/pc/diskboot.S (bootloop): Adapted to the new offset of - a length field. - (lba_mode): Support 64-bit addresses. - (chs_mode): Likewise. - (copy_buffer): Adapted to the new offsets of a length field and a - segment field. - (blocklist_default_start): Allocate 64-bit space. - - * boot/i386/pc/boot.S (force_lba): Removed. - (boot_drive): Moved to under KERNEL_SECTOR. - (kernel_sector): Moved to under KERNEL_SEGMENT. Allocate 64-bit - space. - (real_start): Set %si earlier. Remove code for FORCE_LBA, since it - is useless. - (lba_mode): Refactored to support a 64-bit address. More size - optimization. - (setup_sectors): Likewise. - -2006-06-04 Yoshinori K. Okuji - - * DISTLIST: Added include/grub/i386/linux.h. Removed - include/grub/i386/pc/linux.h - - * configure.ac (AC_INIT): Bumped to 1.94. - - * config.guess: Updated from gnulib. - * config.sub: Likewise. - * install-sh: Likewise. - * mkinstalldirs: Likewise. - -2006-06-02 Yoshinori K. Okuji - - * conf/common.rmk (grub_modules_init.lst): Depended on - grub_emu_SOURCES, excluding grub_emu_init.c, instead of - MODSRCFILES. - - * genmk.rb (PModule::rule): Reverted the previous change. - -2006-06-02 Yoshinori K. Okuji - - * conf/common.rmk (grub_modules_init.lst): Depends on - $(MODSRCFILES). Grep only the files in $(MODSRCFILES). Make sure - that the target does not exist before producing. - (grub_modules_init.h): Remove the target before generating. - (grub_emu_init.c): Likewise. - - * genmk.rb (PModule::rule): Add source files into MODSRCFILES. - -2006-05-31 Jeroen Dekkers - - * configure.ac: Don't set host_m32 for x86_64. Also reset LIBS - for the target-specific tests. Make sure that we also have the - up-to-date target variables for those tests. - -2006-05-31 Yoshinori K. Okuji - - * genmk.rb (Image::rule): Prefix CFLAGS or ASFLAGS with TARGET_. - (PModule::rule): Likewise. - -2006-05-31 Yoshinori K. Okuji - - * genmk.rb (Image::rule): Set FLAG to CFLAGS or ASFLAGS instead of - TARGET_CFLAGS or TARGET_ASFLAGS. There is no reason why - target-specific flags should be prefixed. - (PModule::rule): Likewise. - -2006-05-30 Yoshinori K. Okuji - - * configure.ac (CMP): Check if cmp is available explicitly. - -2006-05-29 Yoshinori K. Okuji - - * util/powerpc/ieee1275/grub-install.in (host_cpu): Removed. - (target_cpu): New variable. - (pkglibdir): Use target_cpu instead of host_cpu. - - * util/i386/pc/grub-install.in (host_cpu): Removed. - (target_cpu): New variable. - (pkglibdir): Use target_cpu instead of host_cpu. - - * util/genmoddep.c: Removed. - - * kern/efi/mm.c (filter_memory_map): Use GRUB_CPU_SIZEOF_VOID_P - instead of GRUB_HOST_SIZEOF_VOID_P. - * kern/dl.c: Likewise. - - * include/grub/i386/types.h (GRUB_HOST_SIZEOF_VOID_P): Renamed to - ... - (GRUB_TARGET_SIZEOF_VOID_P): ... this. - (GRUB_HOST_SIZEOF_LONG): Renamed to ... - (GRUB_TARGET_SIZEOF_LONG): ... this. - (GRUB_HOST_WORDS_BIGENDIAN): Renamed to ... - (GRUB_TARGET_WORDS_BIGENDIAN): ... this. - * include/grub/powerpc/types.h (GRUB_HOST_SIZEOF_VOID_P): Renamed - to ... - (GRUB_TARGET_SIZEOF_VOID_P): ... this. - (GRUB_HOST_SIZEOF_LONG): Renamed to ... - (GRUB_TARGET_SIZEOF_LONG): ... this. - (GRUB_HOST_WORDS_BIGENDIAN): Renamed to ... - (GRUB_TARGET_WORDS_BIGENDIAN): ... this. - * include/grub/sparc64/types.h (GRUB_HOST_SIZEOF_VOID_P): Renamed - to ... - (GRUB_TARGET_SIZEOF_VOID_P): ... this. - (GRUB_HOST_SIZEOF_LONG): Renamed to ... - (GRUB_TARGET_SIZEOF_LONG): ... this. - (GRUB_HOST_WORDS_BIGENDIAN): Renamed to ... - (GRUB_TARGET_WORDS_BIGENDIAN): ... this. - - * include/grub/types.h [!GRUB_UTIL] (GRUB_CPU_SIZEOF_VOID_P): Use - GRUB_TARGET_SIZEOF_VOID_P instead of GRUB_HOST_SIZEOF_VOID_P. - [!GRUB_UTIL] (GRUB_CPU_SIZEOF_LONG): Use GRUB_TARGET_SIZEOF_LONG - instead of GRUB_HOST_SIZEOF_LONG. - [!GRUB_UTIL]: Refer to GRUB_TARGET_WORDS_BIGENDIAN instead of - GRUB_HOST_WORDS_BIGENDIAN to define or undefine - GRUB_CPU_WORDS_BIGENDIAN. - Refer to SIZEOF_VOID_P instead of GRUB_HOST_SIZEOF_VOID_P to - define grub_host_addr_t, grub_host_off_t, grub_host_size_t and - grub_host_ssize_t. - - * conf/i386-efi.rmk (noinst_UTILITIES): Removed. - (genmoddep_SOURCES): Likewise. - * conf/i386-pc.rmk (noinst_UTILITIES): Likewise. - (genmoddep_SOURCES): Likewise. - * conf/conf/powerpc-ieee1275.rmk (noinst_UTILITIES): Likewise. - (genmoddep_SOURCES): Likewise. - * conf/conf/conf/sparc64-ieee1275.rmk (noinst_UTILITIES): - Likewise. - (genmoddep_SOURCES): Likewise. - - * genmoddep.awk: New file. - - * genmk.rb (Image::rule): Use TARGET_CC, TARGET_CPPFLAGS, - TARGET_CFLAGS, TARGET_ASFLAGS and TARGET_LDFLAGS instead of CC, - CPPFLAGS, CFLAGS, ASFLAGS and LDFLAGS, respectively. - (PModule::rule): Likewise. - (Program::rule): Likewise. - (Utility::rule): Use CC, CPPFLAGS, CFLAGS and LDFLAGS instead of - BUILD_CC, BUILD_CPPFLAGS, BUILD_CFLAGS and BUILD_LDFLAGS, - respectively. - - * configure.ac: Rewritten intensively to use host and target - instead of build and host, respectively. - - * Makefile.in (pkglibdir): Use target_cpu instead of host_cpu. - (host_cpu): Removed. - (target_cpu): New variable. - (CPPFLAGS): Added @CPPFLAGS@ and -DGRUB_LIBDIR=\"$(pkglibdir)\". - (BUILD_CC): Removed. - (BUILD_CFLAGS): Likewise. - (BUILD_CPPFLAGS): Likewise. - (TARGET_CC): New variable. - (TARGET_CFLAGS): Likewise. - (TARGET_CPPFLAGS): Likewise. - (TARGET_LDFLAGS): Likewise. - (AWK): Likewise. - (include): Use target_cpu instead of host_cpu. - (moddep.lst:): Use genmoddep.awk instead of genmoddep. - - * DISTLIST: Added genmoddep.awk. Removed util/genmoddep.c. - -2006-05-29 Vesa Jaaskelainen - - * include/grub/script.h (grub_script_cmdif): Renamed field 'bool' to - 'exec_to_evaluate'. Renamed field 'true' to 'exec_on_true'. Renamed - field 'false' to 'exec_on_false'. - (grub_script_create_cmdif): Renamed argument names to reflect above - changes. - - * normal/execute.c (grub_script_execute_cmdif): Likewise. - - * normal/script.c (grub_script_create_cmdif): Likewise. - -2006-05-28 Yoshinori K. Okuji - - * fs/hfsplus.c (grub_hfsplus_btree_recoffset): Moved to near the - top. - (grub_hfsplus_btree_recptr): Likewise. - (grub_hfsplus_find_block): Do not take RETRY any longer. Use - FILEBLOCK both to pass a block number and store next block - number. - (grub_hfsplus_read_block): Rewritten heavily to support an extent - overflow file correctly. Specify errors appropriately, because - fshelp expects that GRUB_ERRNO is set when fails. Reuse - grub_hfsplus_btree_recptr to get the pointer to a found key. - (grub_hfsplus_btree_search): Return 1 instead of 0 when no match - is found. - - * conf/i386-efi.rmk (pkgdata_MODULES): Added _linux.mod and - linux.mod. - (_linux_mod_SOURCES): New variable. - (_linux_mod_CFLAGS): Likewise. - (_linux_mod_LDFLAGS): Likewise. - (linux_mod_SOURCES): Likewise. - (linux_mod_CFLAGS): Likewise. - (linux_mod_LDFLAGS): Likewise. - - * DISTLIST: Added loader/i386/efi/linux.c, - loader/i386/efi/linux_normal.c and - include/grub/i386/efi/loader.h. - - * loader/i386/efi/linux.c: New file. - * loader/i386/efi/linux_normal.c: Likewise. - * include/grub/i386/efi/loader.h: Likewise. - -2006-05-27 Yoshinori K. Okuji - - * commands/blocklist.c: New file. - - * DISTLIST: Added commands/blocklist.c. - - * term/efi/console.c (grub_console_highlight_color): Use a lighter - color for the background, and a darker color for the foreground. - (grub_console_checkkey): Return READ_KEY. - (grub_console_cls): Set the background to - GRUB_EFI_BACKGROUND_BLACK temporarily to clean out the screen. - - * kern/efi/efi.c (grub_efi_exit_boot_services): New function. - - * include/grub/i386/linux.h (struct linux_kernel_params): Fixed - the size of "padding5", "hd0_drive_info" and "hd1_drive_info". - - * include/grub/efi/efi.h (grub_efi_exit_boot_services): New - prototype. - - * include/grub/efi/api.h (GRUB_EFI_TEXT_ATTR): Do not shift - BG. The spec is wrong again. - - * include/grub/normal.h [GRUB_UTIL] (grub_blocklist_init): New - prototype. - [GRUB_UTIL] (grub_blocklist_fini): Likewise. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Added - commands/blocklist.c. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - - * conf/common.rmk (pkgdata_MODULES): Added blocklist.mod. - (blocklist_mod_SOURCES): New variable. - (blocklist_mod_CFLAGS): Likewise. - (blocklist_mod_LDFLAGS): Likewise. - -2006-05-20 Yoshinori K. Okuji - - * boot/i386/pc/boot.S (real_start): Set %si earlier to eliminate - duplication. - (lba_mode): Use %eax more intensively to reduce the code size. - -2006-05-20 Marco Gerards - - * normal/lexer.c (grub_script_yylex): Don't filter out newlines. - - * normal/parser.y (commandblock): Defined as . A subroutine - for `menuentry'. - (script): Accept leading newlines. - (newlines): New rule to describe 0 or more newlines. - (commands): Accept `command' with trailing newline. Fixed the - order in which arguments were passed to `grub_script_add_cmd'. - Accept commands separated by newlines. - (function): Changed to accept newlines. - (menuentry) Rewritten. - - * normal/script.c (grub_script_create_cmdmenu): Add new entries in - front of the list, instead of to the end. - -2006-05-19 Yoshinori K. Okuji - - * util/i386/pc/grub-install.in (bindir): New variable. - (grub_mkimage): Use BINDIR instead of SBINDIR. Reported by Lee - Shaver . - -2006-05-14 Yoshinori K. Okuji - - * kern/i386/pc/startup.S: Include grub/cpu/linux.h instead of - grub/machine/linux.h - * loader/i386/pc/linux.c: Likewise. - - * include/grub/i386/pc/linux.h: Moved to ... - * include/grub/i386/linux.h: ... here. - - * include/grub/i386/linux.h (struct linux_kernel_params): New - struct. - -2006-05-09 Vesa Jaaskelainen - - * video/i386/pc/vbe.c (grub_video_vbe_fill_rect): Corrected bounds - checking. - (grub_video_vbe_blit_glyph): Likewise. - (grub_video_vbe_blit_bitmap): Likewise. - (grub_video_vbe_blit_render_target): Likewise. - -2006-05-09 Yoshinori K. Okuji - - * configure.ac (--with-platform): Properly quote the square - brackets. - -2006-05-08 Marco Gerards - - * conf/powerpc-ieee1275.rmk (grubof_HEADERS): Renamed from - this... - (kernel_elf_HEADERS): ...to this. Updated all users. - (grubof_symlist.c): Renamed from this... - (kernel_elf_symlist.c): ...to this. Updated all users. - (pkgdata_PROGRAMS): Changed `grubof' to `kernel.elf'. - (grubof_SOURCES): Renamed from this... - (kernel_elf_SOURCES): ...to this. - (grubof_HEADERS): Renamed from this... - (kernel_elf_HEADERS): ...to this. - (grubof_CFLAGS): Renamed from this... - (kernel_elf_CFLAGS): ...to this. - (grubof_ASFLAGS): Renamed from this... - (kernel_elf_ASFLAGS): ...to this. - (grubof_LDFLAGS): Renamed from this... - (kernel_elf_LDFLAGS): ...to this. - - * conf/sparc64-ieee1275.rmk (grubof_HEADERS): Renamed from - this... - (kernel_elf_HEADERS): ...to this. Updated all users. - (grubof_symlist.c): Renamed from this... - (kernel_elf_symlist.c): ...to this. Updated all users. - (pkgdata_PROGRAMS): Changed `grubof' to `kernel.elf'. - (grubof_SOURCES): Renamed from this... - (kernel_elf_SOURCES): ...to this. - (grubof_HEADERS): Renamed from this... - (kernel_elf_HEADERS): ...to this. - (grubof_CFLAGS): Renamed from this... - (kernel_elf_CFLAGS): ...to this. - (grubof_ASFLAGS): Renamed from this... - (kernel_elf_ASFLAGS): ...to this. - (grubof_LDFLAGS): Renamed from this... - (kernel_elf_LDFLAGS): ...to this. - - * util/powerpc/ieee1275/grub-mkimage.c (add_segments): Use - `kernel.elf' instead of `grubof'. - -2006-05-08 Yoshinori K. Okuji - - Add --with-platform to configure. Use pkglibdir instead of - pkgdatadir. This is reported by Roger Leigh. - - * util/powerpc/ieee1275/grub-install.in (datadir): Removed. - (host_vendor): Likewise. - (host_os): Likewise. - (pkgdatadir): Likewise. - (platform): New variable. - (pkglibdir): Likewise. - Use PKGLIBDIR instead of PKGDATADIR. - - * util/i386/pc/grub-install.in (datadir): Removed. - (host_vendor): Likewise. - (host_os): Likewise. - (pkgdatadir): Likewise. - (platform): New variable. - (pkglibdir): Likewise. - Use PKGLIBDIR instead of PKGDATADIR. - - * util/powerpc/ieee1275/grub-mkimage.c (usage): Use GRUB_LIBDIR - instead of GRUB_DATADIR. - (main): Likewise. - * util/i386/pc/grub-mkimage.c (usage): Likewise. - (main): Likewise. - * util/i386/efi/grub-mkimage.c (usage): Likewise. - (main): Likewise. - - * configure.ac (--with-platform): New option. - Use PLATFORM instead of HOST_VENDOR to specify a platform. - - * Makefile.in: Include a makefile based on PLATFORM instead of - HOST_VENDOR. - (pkgdatadir): Not appended by the machine type. - (pkglibdir): Appended by the machine type. - (host_vendor): Removed. - (platform): New variable. - (BUILD_CPPFLAGS): Specify GRUB_LIBDIR instead of GRUB_DATADIR. - (install-local): Use PKGLIBDIR instead of PKGDATADIR. - (uninstall): Likewise. - -2006-05-07 Yoshinori K. Okuji - - Use the environment context in the menu. Remove the commands - "default" and "timeout", and use variables instead. - - * normal/menu.c: Include grub/env.h. - (print_entry): Cast TITLE to silence gcc. - (get_timeout): New function. - (set_timeout): Likewise. - (get_entry_number): Likewise. - (run_menu): Use a default entry, a fallback entry and a timeout - in the environment variables "default", "fallback" and - "timeout". Also, tweak the default entry if it is not within the - current menu entries. - (grub_menu_run): Use a fallback entry in the environment variable - "fallback". - - * normal/main.c (read_config_file): Do not initialize - NEWMENU->DEFAULT_ENTRY, NEWMENU->FALLBACK_ENTRY or - NEWMENU->TIMEOUT. - (grub_normal_execute): Use a data slot to store the menu. - - * include/grub/normal.h (struct grub_menu): Removed default_entry, - fallback_entry and timeout. - (struct grub_menu_list): Removed. - (grub_menu_list_t): Likewise. - (struct grub_context): Likewise. - (grub_context_t): Likewise. - (grub_context_get): Likewise. - (grub_context_get_current_menu): Likewise. - (grub_context_push_menu): Likewise. - (grub_context_pop_menu): Likewise. - (grub_default_init): Likewise. - (grub_default_fini): Likewise. - (grub_timeout_init): Likewise. - (grub_timeout_fini): Likewise. - - * conf/sparc64-ieee1275.rmk (pkgdata_MODULES): Removed default.mod - and timeout.mod. - (normal_mod_SOURCES): Removed normal/context.c. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Removed - commands/default.c, commands/timeout.c and normal/context.c. - (normal_mod_SOURCES): Removed normal/context.c. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Removed commands/default.c, - commands/timeout.c and normal/context.c. - (normal_mod_SOURCES): Removed normal/context.c. - - * conf/i386-efi.rmk (grub_emu_SOURCES): Removed - commands/default.c, commands/timeout.c and normal/context.c. - (normal_mod_SOURCES): Removed normal/context.c. - - * conf/common.rmk (pkgdata_MODULES): Removed default.mod and - timeout.mod. - (default_mod_SOURCES): Removed. - (default_mod_CFLAGS): Likewise. - (default_mod_LDFLAGS): Likewise. - (timeout_mod_SOURCES): Removed. - (timeout_mod_CFLAGS): Likewise. - (timeout_mod_LDFLAGS): Likewise. - - * DISTLIST: Removed commands/default.c, commands/timeout.c and - normal/context.c. - - * commands/default.c: Removed. - * commands/timeout.c: Likewise. - * normal/context.c: Likewise. - -2006-05-07 Vesa Jaaskelainen - - * kern/i386/pc/startup.S (grub_exit): Added missing .code32 tag. - -2006-05-02 Yoshinori K. Okuji - - * kern/env.c (struct grub_env_context): Removed "sorted". Renamed - "next" to "prev" for readability. - (struct grub_env_sorted_var): New struct. - (grub_env_context): Renamed to ... - (initial_context): ... this. - (grub_env_var_context): Renamed to ... - (current_context): ... this. - (grub_env_find): Look only at CURRENT_CONTEXT. - (grub_env_context_open): Rewritten to copy exported variables from - previous context. - (grub_env_context_close): Rewritten according to the new - scheme. Also, add an assertion to prevent the initial context from - removed. - (grub_env_insert): Removed the code for the sorted list. - (grub_env_remove): Likewise. - (grub_env_export): Simply mark the variable with - GRUB_ENV_VAR_GLOBAL. - (grub_env_set): A cosmetic change for naming consistency. - (grub_env_get): Likewise. - (grub_env_unset): Likewise. - (grub_env_iterate): Rewritten to sort variables within this - function. - (grub_register_variable_hook): Fixed for naming consistency. Call - grub_env_find again, only if NAME is not found at the first time. - (mangle_data_slot_name): New function. - (grub_env_set_data_slot): Likewise. - (grub_env_get_data_slot): Likewise. - (grub_env_unset_data_slot): Likewise. - - * include/grub/env.h (grub_env_var_type): New enum. - (GRUB_ENV_VAR_LOCAL): New constant. - (GRUB_ENV_VAR_GLOBAL): Likewise. - (GRUB_ENV_VAR_DATA): Likewise. - (struct grub_env_var): Removed "sort_next" and "sort_prevp". Added - "type". - (grub_env_set): Replace VAR with NAME for consistency. - (grub_register_variable_hook): Likewise. - (grub_env_export): Specify the name of the argument. - (grub_env_set_data_slot): New prototype. - (grub_env_get_data_slot): Likewise. - (grub_env_unset_data_slot): Likewise. - -2006-04-30 Yoshinori K. Okuji - - Extend the loader so that GRUB can accept a loader which comes - back to GRUB when a loaded image exits. Also, this change adds - support for a chainloader on EFI. - - * term/efi/console.c: Include grub/misc.h. - (grub_console_checkkey): Display a scan code on the top for - debugging. This will be removed once the EFI port gets stable. - Correct the scan code mapping. - - * kern/efi/mm.c (sort_memory_map): Sort in a descending order to - allocate memory from larger regions, in order to reduce the number - of allocated regions. Otherwise, the MacOSX loader panics. - (filter_memory_map): Avoid less than 1MB for compatibility with - other loaders. - (add_memory_regions): Allocate from the tail of a region, if - possible, to avoid allocating a region near to 1MB, for the MacOSX - loader. - - * kern/efi/init.c (grub_efi_set_prefix): Specify - GRUB_EFI_IMAGE_HANDLE to grub_efi_get_loaded_image. - - * kern/efi/efi.c (grub_efi_get_loaded_image): Accept a new - argument IMAGE_HANDLE and specify it to get a loaded image. - (grub_arch_modules_addr): Specify GRUB_EFI_IMAGE_HANDLE to - grub_efi_get_loaded_image. - (grub_efi_get_filename): Divide the length by the size of - grub_efi_char16_t. - (grub_efi_get_device_path): New function. - (grub_efi_print_device_path): Print End Device Path nodes. Divide - the length by the size of grub_efi_char16_t for a file path device - path node. - - * kern/loader.c (grub_loader_noreturn): New variable. - (grub_loader_set): Accept a new argument NORETURN. Set - GRUB_LOADER_NORETURN to NORETURN. - All callers changed. - (grub_loader_boot): If GRUB_LOADER_NORETURN is false, do not call - grub_machine_fini. - - * include/grub/efi/efi.h (grub_efi_get_device_path): New - prototype. - (grub_efi_get_loaded_image): Take an argument to specify an image - handle. - - * include/grub/loader.h (grub_loader_set): Added one more argument - NORETURN. - - * disk/efi/efidisk.c (make_devices): Use grub_efi_get_device_path - instead of grub_efi_open_protocol. - (grub_efidisk_get_device_name): Likewise. - (grub_efidisk_close): Print a newline. - (grub_efidisk_get_device_handle): Fixed to use - GRUB_EFI_DEVICE_PATH_SUBTYPE instead of - GRUB_EFI_DEVICE_PATH_TYPE. - - * disk/efi/efidisk.c (device_path_guid): Moved to ... - * kern/efi/efi.c (device_path_guid): ... here. - - * conf/i386-efi.rmk (pkgdata_MODULES): Added _chain.mod and - chain.mod. - (kernel_mod_HEADERS): Added efi/disk.h. - (_chain_mod_SOURCES): New variable. - (_chain_mod_CFLAGS): Likewise. - (_chain_mod_LDFLAGS): Likewise. - (chain_mod_SOURCES): Likewise. - (chain_mod_CFLAGS): Likewise. - (chain_mod_LDFLAGS): Likewise. - - * DISTLIST: Added include/grub/efi/chainloader.h, - loader/efi/chainloader.c and loader/efi/chainloader_normal.c. - - * include/grub/efi/chainloader.h: New file. - * loader/efi/chainloader.c: Likewise. - * loader/efi/chainloader_normal.c: Likewise. - -2006-04-30 Marco Gerards - - * commands/configfile.c (grub_cmd_source): New function. - (GRUB_MOD_INIT): Register the commands `source' and `.'. - (GRUB_MOD_FINI): De-register the commands `source' and `.'. - -2006-04-30 Marco Gerards - - * normal/execute.c (grub_script_execute_cmd): Change the return - type to `grub_err_t'. Correctly return the error. - (grub_script_execute_cmdline): In case a command line is not a - command or a function, try to interpret it as an assignment. - -2006-04-30 Yoshinori K. Okuji - - * fs/hfsplus.c (grub_hfsplus_read_block): Fixed a memory leak. - (grub_hfsplus_iterate_dir): Reordered to skip unknown nodes. Also, - skip a node whose name is obviously invalid as UTF-16, - i.e. contains a NUL character. Stop the iteration when the last - directory entry is found. Instead of using the return value of - grub_hfsplus_btree_iterate_node, store the value in RET and use - it, because the iterator can be stopped by the last directory - entry. - -2006-04-30 Marco Gerards - - * include/grub/env.h (grub_env_export): New prototype. Reported - by Jan C. Kleinsorge . - -2006-04-30 Marco Gerards - - * fs/hfsplus.c (grub_hfsplus_iterate_dir): Correctly calculate the - size of the extents in a catalog file record. - -2006-04-29 Marco Gerards - - * commands/configfile.c (grub_cmd_configfile): Execute the - configfile within its own context. - - * include/grub/env.h (grub_env_context_open): New prototype. - (grub_env_context_close): Likewise. - - * kern/env.c (grub_env): Removed. - (grub_env_sorted): Likewise. - (grub_env_context): New variable. - (grub_env_var_context): Likewise. - (grub_env_find): Search both the active context and the global - context. - (grub_env_context_open): New function. - (grub_env_context_close): Likewise. - (grub_env_insert): Likewise. - (grub_env_remove): Likewise. - (grub_env_export): Likewise. - (grub_env_set): Changed to use helper functions to avoid code - duplication. - (grub_env_iterate): Rewritten so both the current context and the - global context are being used. - - * normal/command.c (export_command): New function. - (grub_command_init): Register the `export' function. - -2006-04-26 Yoshinori K. Okuji - - * util/i386/pc/grub-mkimage.c (compress_kernel): Cast arguments - explicitly to suppress gcc's warnings. - * fs/fat.c (grub_fat_find_dir): Likewise. - (grub_fat_label): Likewise. - * fs/xfs.c (grub_xfs_read_inode): Likewise. - (grub_xfs_mount): Likewise. - (grub_xfs_label): Likewise. - * fs/affs.c (grub_affs_mount): Likewise. - (grub_affs_label): Likewise. - (grub_affs_iterate_dir): Likewise. - * fs/sfs.c (grub_sfs_mount): Likewise. - (grub_sfs_iterate_dir): Likewise. - * fs/ufs.c (grub_ufs_lookup_symlink): Likewise. - * fs/hfs.c (grub_hfs_mount): Likewise. - (grub_hfs_cmp_catkeys): Likewise. - (grub_hfs_find_dir): Likewise. - (grub_hfs_dir): Likewise. - (grub_hfs_label): Likewise. - * fs/jfs.c (grub_jfs_mount): Likewise. - (grub_jfs_opendir): Likewise. - (grub_jfs_getent): Likewise. - (grub_jfs_lookup_symlink): Likewise. - (grub_jfs_label): Likewise. - * fs/hfsplus.c (grub_hfsplus_cmp_catkey): Likewise. - (grub_hfsplus_iterate_dir): Likewise. - (grub_hfsplus_btree_iterate_node): Made static. - - * util/grub-emu.c (prefix): New variable. - (grub_machine_set_prefix): New function. - (main): Do not set the environment variable "prefix" here. Only - set PREFIX, which is used later by grub_machine_set_prefix. - - * include/grub/video.h: Do not include grub/symbol.h. - (grub_video_register): Not exported. This symbol is not defined in - the kernel. - (grub_video_unregister): Likewise. - (grub_video_iterate): Likewise. - (grub_video_setup): Likewise. - (grub_video_restore): Likewise. - (grub_video_get_info): Likewise. - (grub_video_get_blit_format): Likewise. - (grub_video_set_palette): Likewise. - (grub_video_get_palette): Likewise. - (grub_video_set_viewport): Likewise. - (grub_video_get_viewport): Likewise. - (grub_video_map_color): Likewise. - (grub_video_map_rgb): Likewise. - (grub_video_map_rgba): Likewise. - (grub_video_fill_rect): Likewise. - (grub_video_blit_glyph): Likewise. - (grub_video_blit_bitmap): Likewise. - (grub_video_blit_render_target): Likewise. - (grub_video_scroll): Likewise. - (grub_video_swap_buffers): Likewise. - (grub_video_create_render_target): Likewise. - (grub_video_delete_render_target): Likewise. - (grub_video_set_active_render_target): Likewise. - - * include/grub/symbol.h [GRUB_SYMBOL_GENERATOR] (EXPORT_FUNC): - Undefined. - [GRUB_SYMBOL_GENERATOR] (EXPORT_VAR): Likewise. - - * conf/sparc64-ieee1275.rmk (grubof_symlist.c): Depended on - config.h. Use gensymlist.sh instead of $(srcdir)/gensymlist.sh. - (kernel_syms.lst): Depended on config.h. Use genkernsyms.sh - instead of $(srcdir)/genkernsyms.sh. - - * conf/powerpc-ieee1275.rmk (grubof_symlist.c): Depended on - config.h. Use gensymlist.sh instead of $(srcdir)/gensymlist.sh. - (kernel_syms.lst): Depended on config.h. Use genkernsyms.sh - instead of $(srcdir)/genkernsyms.sh. - - * conf/i386-pc.rmk (symlist.c): Depended on config.h. Use - gensymlist.sh instead of $(srcdir)/gensymlist.sh. - (kernel_syms.lst): Depended on config.h. Use genkernsyms.sh - instead of $(srcdir)/genkernsyms.sh. - - * conf/i386-efi.rmk (symlist.c): Depended on config.h. Use - gensymlist.sh instead of $(srcdir)/gensymlist.sh. - (kernel_syms.lst): Depended on config.h. Use genkernsyms.sh - instead of $(srcdir)/genkernsyms.sh. - - * configure.ac (AC_CONFIG_FILES): Added gensymlist.sh and - genkernsyms.sh. - - * Makefile.in (DISTCLEANFILES): Added gensymlist.sh and - genkernsyms.sh. - (gensymlist.sh): New target. - (genkernsyms.sh): Likewise. - - * DISTLIST: Removed genkernsyms.sh and gensymlist.sh. Added - genkernsyms.sh.in and gensymlist.sh.in. - - * genkernsyms.sh: Removed. - * gensymlist.sh: Likewise. - - * genkernsyms.sh.in: New file. - * gensymlist.sh.in: Likewise. - -2006-04-25 Hollis Blanchard - - * kern/powerpc/ieee1275/init.c (grub_machine_set_prefix): Do not - clobber "prefix", since we may have already set it manually. - -2006-04-25 Hollis Blanchard - - * kern/misc.c (abort): New alias for grub_abort. - -2006-04-25 Yoshinori K. Okuji - - A new machine-specific function "grub_machine_set_prefix" is - defined. This is called after loading modules, so that a prefix - initialization can use modules. Also, this change adds an - intensive debugging feature for the memory manager via the - configure option "--enable-mm-debug". - - * partmap/gpt.c (gpt_partition_map_iterate): Add one more into - PART.LEN. - - * kern/sparc64/ieee1275/init.c (abort): Removed. - (grub_stop): Likewise. - (grub_exit): New function. - (grub_set_prefix): Renamed to ... - (grub_machine_set_prefix): ... this. - (grub_machine_init): Do not call grub_set_prefix. - - * kern/powerpc/ieee1275/init.c (grub_set_prefix): Renamed to ... - (grub_machine_set_prefix): ... this. - (grub_machine_init): Do not call grub_set_prefix. - - * kern/i386/pc/init.c (grub_machine_set_prefix): New function. - (grub_machine_init): Do not set the prefix here. - - * kern/i386/efi/init.c (grub_machine_set_prefix): New function. - - * kern/efi/init.c: Include grub/mm.h. - (grub_efi_set_prefix): New function. - - * kern/efi/efi.c (grub_exit): Call grub_efi_fini. - (grub_efi_get_filename): New function. - (grub_print_device_path): Renamed to ... - (grub_efi_print_device_path): ... this. - - * kern/mm.c [MM_DEBUG] (grub_malloc): Undefined. - [MM_DEBUG] (grub_realloc): Likewise. - [MM_DEBUG] (grub_free): Likewise. - [MM_DEBUG] (grub_memalign): Likewise. - [MM_DEBUG] (grub_mm_debug): New variable. - [MM_DEBUG] (grub_debug_malloc): New function. - [MM_DEBUG] (grub_debug_free): New function. - [MM_DEBUG] (grub_debug_realloc): New function. - [MM_DEBUG] (grub_debug_memalign): New function. - - * kern/misc.c (grub_abort): Print a newline to distinguish - the message. - - * kern/main.c (grub_main): Call grub_machine_set_prefix and - grub_set_root_dev after loading modules. This is necessary when - setting a prefix depends on modules. - - * include/grub/efi/efi.h (grub_print_device_path): Renamed to ... - (grub_efi_print_device_path): ... this. - (grub_efi_get_filename): New prototype. - (grub_efi_set_prefix): Likewise. - - * include/grub/efi/disk.h: Include grub/efi/api.h, grub/symbol.h - and grub/disk.h. - (grub_efidisk_get_device_handle): New prototype. - (grub_efidisk_get_device_name): Likewise. - - * include/grub/mm.h: Include config.h. - (MM_DEBUG): Removed. - [MM_DEBUG && !GRUB_UTIL] (grub_mm_debug): New prototype. - [MM_DEBUG && !GRUB_UTIL] (grub_malloc): New macro. - [MM_DEBUG && !GRUB_UTIL] (grub_realloc): Likewise. - [MM_DEBUG && !GRUB_UTIL] (grub_memalign): Likewise. - [MM_DEBUG && !GRUB_UTIL] (grub_free): Likewise. - [MM_DEBUG && !GRUB_UTIL] (grub_debug_malloc): New prototype. - [MM_DEBUG && !GRUB_UTIL] (grub_debug_realloc): New prototype. - [MM_DEBUG && !GRUB_UTIL] (grub_debug_memalign): New prototype. - [MM_DEBUG && !GRUB_UTIL] (grub_debug_free): New prototype. - - * include/grub/kernel.h (grub_machine_set_prefix): New prototype. - - * disk/efi/efidisk.c: Include grub/partition.h. - (iterate_child_devices): New function. - (add_device): First, compare only last device path nodes, so that - devices are sorted by the types. - (grub_efidisk_get_device_handle): New function. - (grub_efidisk_get_device_name): Likewise. - - * configure.ac (--enable-mm-debug): New option to enable the - memory manager debugging feature. This makes the binary much - bigger, so is disabled by default. - -2006-04-23 Yoshinori K. Okuji - - Use grub_abort instead of grub_stop, and grub_exit must be - define in each architecture now. Also, this change adds support - for EFI disks. - - * util/i386/pc/grub-probefs.c: Include grub/term.h. - (grub_getkey): New function. - (grub_term_get_current): Likewise. - - * util/i386/pc/grub-setup.c: Include grub/term.h. - (grub_getkey): New function. - (grub_term_get_current): Likewise. - - * util/misc.c (grub_stop): Renamed to ... - (grub_exit): ... this. - - * kern/powerpc/ieee1275/init.c (abort): Renamed to ... - (grub_exit): ... this. - (grub_machine_init): Use grub_abort instead of abort. - (grub_stop): Removed. - - * kern/powerpc/ieee1275/cmain.c (cmain): Use grub_abort instead of - abort. - - * kern/i386/pc/startup.S (grub_exit): New function. - (cold_reboot): New label. - - * kern/efi/init.c: Include grub/efi/disk.h and grub/env.h. - (grub_efi_init): Call grub_efidisk_init. - (grub_efi_fini): Call grub_efidisk_fini. - - * kern/efi/efi.c: Include grub/mm.h. - (grub_efi_console_control_guid): Renamed to ... - (console_control_guid): ... this. - (grub_efi_loaded_image_guid): Renamed to ... - (loaded_image_guid): ... this. - (grub_efi_locate_handle): New function. - (grub_efi_open_protocol): Likewise. - (grub_efi_set_text_mode): Use CONSOLE_CONTROL_GUID instead of - GRUB_EFI_CONSOLE_CONTROL_GUID. - (grub_efi_exit): Removed. - (grub_stop): Likewise. - (grub_efi_get_loaded_image): Use grub_efi_open_protocol. - (grub_exit): New function. - (grub_print_device_path): Likewise. - - * kern/rescue.c (grub_rescue_cmd_exit): New function. - (grub_enter_rescue_mode): Register "exit". - - * kern/misc.c (grub_real_dprintf): A cosmetic change. - (grub_abort): New function. - - * kern/err.c (grub_fatal): Use grub_abort instead of grub_stop. - - * include/grub/sparc64/ieee1275/kernel.h (abort): Removed. - - * include/grub/powerpc/ieee1275/kernel.h (abort): Removed. - - * include/grub/efi/efi.h (grub_efi_exit): Removed. - (grub_print_device_path): New prototype. - (grub_efi_locate_handle): Likewise. - (grub_efi_open_protocol): Likewise. - - * include/grub/efi/disk.h (grub_efidisk_fini): New file. - * disk/efi/efidisk.c: Likewise. - - * DISTLIST: Added disk/efi/efidisk.c and include/grub/efi/disk.h. - - * include/grub/efi/console_control.h - (GRUB_EFI_CONSOLE_CONTROL_GUID): Use an array for the last 8 bytes. - - * include/grub/efi/api.h (GRUB_EFI_LOADED_IMAGE_GUID): Specify the - last 8 bytes as an array. - (GRUB_EFI_DISK_IO_GUID): New macro. - (GRUB_EFI_BLOCK_IO_GUID): Likewise. - (GRUB_EFI_DEVICE_PATH_GUID): Likewise. - (grub_efi_ipv6_address_t): Change the type to grub_uint16_t from - grub_uint8_t. - (struct grub_efi_guid): Use an array to specify the last 8 bytes. - (struct grub_efi_device_path): Rename the member "sub_type" to - "subtype". - (GRUB_EFI_DEVICE_PATH_TYPE): New macro. - (GRUB_EFI_DEVICE_PATH_SUBTYPE): Likewise. - (GRUB_EFI_DEVICE_PATH_LENGTH): Likewise. - (GRUB_EFI_END_DEVICE_PATH_TYPE): Likewise. - (GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE): Likewise. - (GRUB_EFI_END_THIS_DEVICE_PATH_SUBTYPE): Likewise. - (GRUB_EFI_END_ENTIRE_DEVICE_PATH): Likewise. - (GRUB_EFI_NEXT_DEVICE_PATH): Likewise. - (GRUB_EFI_HARDWARE_DEVICE_PATH_TYPE): Likewise. - (GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE): Likewise. - (struct grub_efi_pci_device_path): New structure. - (grub_efi_pci_device_path_t): New type. - (GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_pccard_device_path): New structure. - (grub_efi_pccard_device_path_t): New type. - (GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_memory_mapped_device_path): New structure. - (grub_efi_memory_mapped_device_path_t): New type. - (GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_vendor_device_path): New structure. - (grub_efi_vendor_device_path_t): New type. - (GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_controller_device_path): New structure. - (grub_efi_controller_device_path_t): New type. - (GRUB_EFI_ACPI_DEVICE_PATH_TYPE): New macro. - (GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE): Likewise. - (struct grub_efi_acpi_device_path): New structure. - (grub_efi_acpi_device_path_t): New type. - (GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_expanded_acpi_device_path): New structure. - (grub_efi_expanded_acpi_device_path_t): New type. - (GRUB_EFI_EXPANDED_ACPI_HIDSTR): New macro. - (GRUB_EFI_EXPANDED_ACPI_UIDSTR): Likewise. - (GRUB_EFI_EXPANDED_ACPI_CIDSTR): Likewise. - (GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE): Likewise. - (GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE): Likewise. - (struct grub_efi_atapi_device_path): New structure. - (grub_efi_atapi_device_path_t): New type. - (GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_fibre_channel_device_path): New structure. - (grub_efi_fibre_channel_device_path_t): New type. - (GRUB_EFI_1394_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_1394_device_path): New structure. - (grub_efi_1394_device_path_t): New type. - (GRUB_EFI_USB_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_usb_device_path): New structure. - (grub_efi_usb_device_path_t): New type. - (GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_usb_class_device_path): New structure. - (grub_efi_usb_class_device_path_t): New type. - (GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_i2o_device_path): New structure. - (grub_efi_i2o_device_path_t): New type. - (GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_mac_address_device_path): New structure. - (grub_efi_mac_address_device_path_t): New type. - (GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_ipv4_device_path): New structure. - (grub_efi_ipv4_device_path_t): New type. - (GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_ipv6_device_path): New structure. - (grub_efi_ipv6_device_path_t): New type. - (GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_infiniband_device_path): New structure. - (grub_efi_infiniband_device_path_t): New type. - (GRUB_EFI_UART_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_uart_device_path): New structure. - (grub_efi_uart_device_path_t): New type. - (GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_vendor_messaging_device_path): New structure. - (grub_efi_vendor_messaging_device_path_t): New type. - (GRUB_EFI_MEDIA_DEVICE_PATH_TYPE): New macro. - (GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE): Likewise. - (struct grub_efi_hard_drive_device_path): New structure. - (grub_efi_hard_drive_device_path_t): New type. - (GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_cdrom_device_path): New structure. - (grub_efi_cdrom_device_path_t): New type. - (GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_vendor_media_device_path): New structure. - (grub_efi_vendor_media_device_path_t): New type. - (GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_file_path_device_path): New structure. - (grub_efi_file_path_device_path_t): New type. - (GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE): New macro. - (struct grub_efi_protocol_device_path): New structure. - (grub_efi_protocol_device_path_t): New type. - (GRUB_EFI_BIOS_DEVICE_PATH_TYPE): New macro. - (GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE): Likewise. - (struct grub_efi_bios_device_path): New structure. - (grub_efi_bios_device_path_t): New type. - (struct grub_efi_disk_io): New structure. - (grub_efi_disk_io_t): New type. - (struct grub_efi_block_io_media): New structure. - (grub_efi_block_io_media_t): New type. - (struct grub_efi_block_io): New structure. - (grub_efi_block_io_t): New type. - - * include/grub/misc.h (grub_stop): Removed. - (grub_exit): New prototype. - (grub_abort): Likewise. - - * include/grub/disk.h (enum grub_disk_dev_id): Added - GRUB_DISK_DEVICE_EFIDISK_ID. - - * conf/i386-efi.rmk (kernel_mod_SOURCES): Added - disk/efi/efidisk.c. - (kernel_syms.lst): Remove the target if an error occurs. - -2006-04-22 Yoshinori K. Okuji - - * kern/misc.c (grub_lltoa): Rewritten the decimal conversion part, - as it was simply too buggy. - -2006-04-21 Yoshinori K. Okuji - - * kern/misc.c (grub_lltoa): New function. - (grub_vsprintf): Added support for the long long suffix, - i.e. "ll". - -2006-04-20 Hollis Blanchard - - * Makefile.in (LDFLAGS): Add variable. - (LD): Remove variable. - * configure.ac: Add -m32 to LDFLAGS. - * genmk.rb (PModule#rule): Use $(CC) instead of $(LD). - * conf/powerpc-ieee1275.rmk (COMMON_LDFLAGS): Add variable. - (grubof_LDFLAGS): Use $(COMMON_LDFLAGS). - (_linux_mod_LDFLAGS, linux_mod_LDFLAGS, normal_mod_LDFLAGS, - suspend_mod_LDFLAGS, reboot_mod_LDFLAGS, halt_mod_LDFLAGS): New - variables. - * conf/sparc64-ieee1275.rmk (COMMON_LDFLAGS): Add -nostdlib. - * conf/i386-pc.rmk (COMMON_LDFLAGS): Add -nostdlib. - * conf/i386-efi.rmk (COMMON_LDFLAGS): Add -nostdlib. - -2006-04-20 Vesa Jaaskelainen - - * term/gfxterm.c (grub_gfxterm_getcharwidth): Fixed character - length for unknown glyph. - -2006-04-20 Yoshinori K. Okuji - - Add support for pre-loaded modules into the EFI port. - - * util/i386/efi/grub-mkimage.c (make_mods_section): Rewritten - completely. Accept one more argument DIR. The caller has changed. - - * kern/i386/efi/init.c (grub_arch_modules_addr): Removed. - - * kern/efi/efi.c: Include grub/efi/pe32.h and grub/kernel.h. - (grub_efi_loaded_image_guid): New variable. - (grub_efi_get_loaded_image): New function. - (grub_arch_modules_addr): Likewise. - - * include/grub/efi/efi.h (grub_efi_get_loaded_image): New - prototype. - - * include/grub/efi/api.h (GRUB_EFI_LOADED_IMAGE_GUID): New macro. - (struct grub_efi_loaded_image): New structure. - (grub_efi_loaded_image_t): New type. - -2006-04-20 Yoshinori K. Okuji - - * loader/i386/pc/linux.c (grub_rescue_cmd_linux): Compare the file - size with GRUB_OS_AREA_SIZE as grub_size_t instead of - grub_ssize_t. Reported by Jeff Chua . - -2006-04-19 Roger Leigh - - * DISTLIST: Added `util/powerpc/ieee1275/grub-install.in'. - -2006-04-19 Yoshinori K. Okuji - - * DISTLIST: Added include/grub/efi/console.h, - include/grub/efi/time.h, include/grub/i386/efi/kernel.h, - kern/efi/init.c, kern/efi/mm.c, and term/efi/console.c. - - * include/grub/efi/console.h: New file. - * include/grub/efi/time.h: Likewise. - * include/grub/i386/efi/kernel.h: Likewise. - * kern/efi/init.c: Likewise. - * kern/efi/mm.c: Likewise. - * term/efi/console.c: Likewise. - - * kern/i386/efi/init.c: Do not include grub/machine/time.h. - (grub_stop): Removed. - (grub_get_rtc): Likewise. - (grub_machine_init): Simply call grub_efi_init. - (grub_machine_fini): Call grub_efi_fini. - - * kern/efi/efi.c: Include grub/machine/time.h and grub/term.h. - (grub_efi_output_string): Removed. - (grub_efi_stall): New function. - (grub_stop): Likewise. - (grub_get_rtc): Likewise. - - * include/grub/efi/efi.h (grub_efi_output_string): Removed. - (grub_efi_stall): New prototype. - (grub_efi_allocate_pages): Likewise. - (grub_efi_free_pages): Likewise. - (grub_efi_get_memory_map): Likewise. - (grub_efi_mm_init): Likewise. - (grub_efi_mm_fini): Likewise. - (grub_efi_init): Likewise. - (grub_efi_fini): Likewise. - - * include/grub/i386/efi/time.h: Do not include - grub/symbol.h. Include grub/efi/time.h. - (GRUB_TICKS_PER_SECOND): Removed. - (grub_get_rtc): Likewise. - - * include/grub/efi/api.h (struct grub_efi_memory_descriptor): - Added padding. The EFI spec is buggy. - (GRUB_EFI_BLACK): New macro. - (GRUB_EFI_BLUE): Likewise. - (GRUB_EFI_GREEN): Likewise. - (GRUB_EFI_CYAN): Likewise. - (GRUB_EFI_RED): Likewise. - (GRUB_EFI_MAGENTA): Likewise. - (GRUB_EFI_BROWN): Likewise. - (GRUB_EFI_LIGHTGRAY): Likewise. - (GRUB_EFI_BRIGHT): Likewise. - (GRUB_EFI_DARKGRAY): Likewise. - (GRUB_EFI_LIGHTBLUE): Likewise. - (GRUB_EFI_LIGHTGREEN): Likewise. - (GRUB_EFI_LIGHTCYAN): Likewise. - (GRUB_EFI_LIGHTRED): Likewise. - (GRUB_EFI_LIGHTMAGENTA): Likewise. - (GRUB_EFI_YELLOW): Likewise. - (GRUB_EFI_WHITE): Likewise. - (GRUB_EFI_BACKGROUND_BLACK): Likewise. - (GRUB_EFI_BACKGROUND_BLUE): Likewise. - (GRUB_EFI_BACKGROUND_GREEN): Likewise. - (GRUB_EFI_BACKGROUND_CYAN): Likewise. - (GRUB_EFI_BACKGROUND_RED): Likewise. - (GRUB_EFI_BACKGROUND_MAGENTA): Likewise. - (GRUB_EFI_BACKGROUND_BROWN): Likewise. - (GRUB_EFI_BACKGROUND_LIGHTGRAY): Likewise. - (GRUB_EFI_TEXT_ATTR): Likewise. - - * conf/i386-efi.rmk (kernel_mod_SOURCES): Added kern/efi/efi.c, - kern/efi/init.c, kern/efi/mm.c, and term/efi/console.c. - (kernel_mod_HEADERS): Added efi/time.h. - -2006-04-18 Yoshinori K. Okuji - - * DISTLIST: Added conf/i386-efi.mk, conf/i386-efi.rmk, - include/grub/efi/api.h, include/grub/efi/console_control.h, - include/grub/efi/efi.h, include/grub/efi/pe32.h, - include/grub/i386/efi/time.h, kern/efi/efi.c, - kern/i386/efi/init.c, kern/i386/efi/startup.S, - and util/i386/efi/grub-mkimage.c. - - * Makefile.in (RMKFILES): Added i386-efi.rmk. - - * genmk.rb (PModule#rule): Do not export symbols if - #{prefix}_EXPORTS is set to "no". - - * conf/i386-efi.mk: New file. - * conf/i386-efi.rmk: Likewise. - * include/grub/efi/api.h: Likewise. - * include/grub/efi/console_control.h: Likewise. - * include/grub/efi/efi.h: Likewise. - * include/grub/efi/pe32.h: Likewise. - * include/grub/i386/efi/time.h: Likewise. - * kern/efi/efi.c: Likewise. - * kern/i386/efi/init.c: Likewise. - * kern/i386/efi/startup.S: Likewise. - * util/i386/efi/grub-mkimage.c: Likewise. - -2006-04-17 Marco Gerards - - * include/grub/script.h: Include and - "grub_script.tab.h". - (struct grub_lexer_param): New struct. - (struct grub_parser_param): Likewise. - (grub_script_create_arglist): Pass the state in an argument. - (grub_script_add_arglist): Likewise. - (grub_script_create_cmdline): Likewise. - (grub_script_create_cmdblock): Likewise. - (grub_script_create_cmdif): Likewise. - (grub_script_create_cmdmenu): Likewise. - (grub_script_add_cmd): Likewise. - (grub_script_arg_add): Likewise. - (grub_script_lexer_ref): Likewise. - (grub_script_lexer_deref): Likewise. - (grub_script_lexer_record_start): Likewise. - (grub_script_lexer_record_stop): Likewise. - (grub_script_mem_record): Likewise. - (grub_script_mem_record_stop): Likewise. - (grub_script_malloc): Likewise. - (grub_script_yylex): Likewise. - (grub_script_yyparse): Likewise. - (grub_script_yyerror): Likewise. - (grub_script_yylex): Likewise. - (grub_script_lexer_init): Return the state. - - * normal/lexer.c (grub_script_lexer_state): Removed variable. - (grub_script_lexer_done): Likewise. - (grub_script_lexer_getline): Likewise. - (grub_script_lexer_refs): Likewise. - (script): Likewise. - (newscript): Likewise. - (record): Likewise. - (recording): Likewise. - (recordpos): Likewise. - (recordlen): Likewise. - (grub_script_lexer_init): Return the state instead of setting - global variables. - (grub_script_lexer_ref): Use the newly added argument for state - instead of globals. - (grub_script_lexer_deref): Likewise. - (grub_script_lexer_record_start): Likewise. - (grub_script_lexer_record_stop): Likewise. - (recordchar): Likewise. - (nextchar): Likewise. - (grub_script_yylex2): Likewise. - (grub_script_yylex): Likewise. - (grub_script_yyerror): Likewise. - - * normal/parser.y (func_mem): Removed variable. - (menu_entry): Likewise. - (err): Likewise. - (%lex-param): New parser option. - (%parse-param): Likewise. - (script): Always return the AST. - (argument): Pass the state around. - (arguments): Likewise. - (grubcmd): Likewise. - (commands): Likewise. - (function): Likewise. - (menuentry): Likewise. - (if_statement): Likewise. - (if): Likewise. - - * normal/script.c (grub_script_memused): Removed variable. - (grub_script_parsed): Likewise. - (grub_script_malloc): Added a state argument. Use that instead of - global variables. - (grub_script_mem_record): Likewise. - (grub_script_mem_record_stop): Likewise. - (grub_script_arg_add): Likewise. - (grub_script_add_arglist): Likewise. - (grub_script_create_cmdline): Likewise. - (grub_script_create_cmdif): Likewise. - (grub_script_create_cmdmenu): Likewise. - (grub_script_add_cmd): Likewise. - (grub_script_parse): Setup the state before calling the parser. - -2006-04-16 Marco Gerards - - * normal/command.c (grub_command_init): Remove the title command. - - * normal/lexer.c (grub_script_yylex): Renamed from this... - (grub_script_yylex2): ... to this. - (grub_script_yylex): New function. Temporary - introduced to filter some tokens. - (grub_script_yyerror): Print a newline. - - * normal/main.c (read_config_file): Output information about the - lines that contain errors. Wait for a key after all lines have - been processed. Don't return an empty menu. - - * normal/parser.y (func_mem): Don't initialize. - (menu_entry): Likewise. - (err): New variable. - (script): Don't return anything when an error was encountered. - (ws, returns): Removed rules. - (argument): Disabled concatenated variable support. - (arguments): Remove explicit separators. - (grubcmd): Likewise. - (function): Likewise. - (menuentry): Likewise. - (if): Likewise. - (commands): Likewise. Add error handling. - - * normal/script.c (grub_script_create_cmdline): If - `grub_script_parsed' is 0, assume the parser encountered an error. - -2006-04-02 Yoshinori K. Okuji - - * configure.ac: Add support for EFI. Fix the typo - BUILD_LDDFLAGS. Restore the LDFLAGS after testing. - -2006-04-01 Vesa Jaaskelainen - - * util/unifont2pff.rb: Removed unnecessary byte ordering. Now - foreign multibyte characters should be shown correctly. - -2006-04-01 Vesa Jaaskelainen - - * normal/main.c (grub_normal_menu_addentry): Fixed menu size - calculation. - (read_config_file): Made it to close file before returning. - -2006-03-31 Vesa Jaaskelainen - - * DISTLIST: Added include/grub/i386/pc/vbeblit.h, - include/grub/i386/pc/vbefill.h, video/i386/pc/vbeblit.c, - video/i386/pc/vbefill.c. - - * conf/i386-pc.rmk (vbe_mod_SOURCES): Added video/i386/pc/vbeblit.c, - video/i386/pc/vbefill.c. - - * include/grub/video.h (grub_video_blit_format): New enum. - (grub_video_mode_info): Added new member blit_format. - (grub_video_get_blit_format): New function prototype. - - * include/grub/i386/pc/vbe.h (grub_video_vbe_get_video_ptr): New - function prototype. - (grub_video_vbe_map_rgb): Likewise. - (grub_video_vbe_unmap_color): Likewise. - - * include/grub/i386/pc/vbeblit.h: New file. - - * include/grub/i386/pc/vbefill.h: New file. - - * video/video.c (grub_video_get_blit_format): New function. - (grub_video_vbe_get_video_ptr): Re-declared as non-static. - (grub_video_vbe_map_rgb): Likewise. - (grub_video_vbe_unmap_color): Likewise. - - * video/i386/pc/vbe.c (grub_video_vbe_fill_rect): Changed to use more - optimized fills. - (grub_video_vbe_blit_render_target): Changed to use more optimized - blits. - (grub_video_vbe_setup): Added detection for optimized settings. - (grub_video_vbe_create_render_target): Likewise. - - * video/i386/pc/vbeblit.c: New file. - - * video/i386/pc/vbefill.c: New file. - -2006-03-30 Vesa Jaaskelainen - - * font/manager.c (grub_font_get_glyph): Removed font fixup from - here... - - * util/unifont2pff.rb: ... and moved it to here. Improved argument - parsing to support both hex and dec ranges. If filename was missing - show usage information. - -2006-03-14 Vesa Jaaskelainen - - * DISTLIST: Added include/grub/video.h, term/gfxterm.c, - video/video.c, commands/videotest.c. Removed term/i386/pc/vesafb.c. - - * conf/i386-pc.rmk (pkgdata_MODULES): Added video.mod, - gfxterm.mod, videotest.mod. Removed vga.mod, vesafb.mod. - (video_mod_SOURCES): Added. - (video_mod_CFLAGS): Likewise. - (video_mod_LDFLAGS): Likewise. - (gfxterm_mod_SOURCES): Likewise. - (gfxterm_mod_CFLAGS): Likewise. - (gfxterm_mod_LDFLAGS): Likewise. - (videotest_mod_SOURCES): Likewise. - (videotest_mod_CFLAGS): Likewise. - (videotest_mod_LDFLAGS): Likewise. - (vesafb_mod_SOURCES): Removed. - (vesafb_mod_CFLAGS): Likewise. - (vesafb_mod_LDFLAGS): Likewise. - (vga_mod_SOURCES): Likewise. - (vga_mod_CFLAGS): Likewise. - (vga_mod_LDFLAGS): Likewise. - - * commands/videotest.c: New file. - - * font/manager.c (fill_with_default_glyph): Modified to use - grub_font_glyph. - (grub_font_get_glyph): Likewise. - (fontmanager): Renamed from this... - (font_manager): ... to this. - - * include/grub/font.h (grub_font_glyph): Added new structure. - (grub_font_get_glyph): Modified to use grub_font_glyph. - - * include/grub/misc.h (grub_abs): Added as inline function. - - * include/grub/video.h: New file. - - * include/grub/i386/pc/vbe.h (GRUB_VBE_STATUS_OK): New macro. - (GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL): Likewise. - (GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR): Likewise. - (grub_vbe_get_controller_info): Renamed from this... - (grub_vbe_bios_get_controller_info): ... to this. - (grub_vbe_get_mode_info): Renamed from this... - (grub_vbe_bios_get_mode_info): ... to this. - (grub_vbe_set_mode): Renamed from this... - (grub_vbe_bios_set_mode): ... to this. - (grub_vbe_get_mode): Renamed from this... - (grub_vbe_bios_get_mode): ... to this. - (grub_vbe_set_memory_window): Renamed from this... - (grub_vbe_bios_set_memory_window): ... to this. - (grub_vbe_get_memory_window): Renamed from this... - (grub_vbe_bios_get_memory_window): ... to this. - (grub_vbe_set_scanline_length): Renamed from this... - (grub_vbe_set_scanline_length): ... to this. - (grub_vbe_get_scanline_length): Renamed from this... - (grub_vbe_bios_get_scanline_length): ... to this. - (grub_vbe_set_display_start): Renamed from this... - (grub_vbe_bios_set_display_start): ... to this. - (grub_vbe_get_display_start): Renamed from this... - (grub_vbe_bios_get_display_start): ... to this. - (grub_vbe_set_palette_data): Renamed from this... - (grub_vbe_bios_set_palette_data): ... to this. - (grub_vbe_set_pixel_rgb): Removed. - (grub_vbe_set_pixel_index): Likewise. - - * kern/i386/pc/startup.S (grub_vbe_get_controller_info): Renamed - from this... - (grub_vbe_bios_get_controller_info): ... to this. - (grub_vbe_get_mode_info): Renamed from this... - (grub_vbe_bios_get_mode_info): ... to this. - (grub_vbe_set_mode): Renamed from this... - (grub_vbe_bios_set_mode): ... to this. - (grub_vbe_get_mode): Renamed from this... - (grub_vbe_bios_get_mode): ... to this. - (grub_vbe_set_memory_window): Renamed from this... - (grub_vbe_bios_set_memory_window): ... to this. - (grub_vbe_get_memory_window): Renamed from this... - (grub_vbe_bios_get_memory_window): ... to this. - (grub_vbe_set_scanline_length): Renamed from this... - (grub_vbe_set_scanline_length): ... to this. - (grub_vbe_get_scanline_length): Renamed from this... - (grub_vbe_bios_get_scanline_length): ... to this. - (grub_vbe_set_display_start): Renamed from this... - (grub_vbe_bios_set_display_start): ... to this. - (grub_vbe_get_display_start): Renamed from this... - (grub_vbe_bios_get_display_start): ... to this. - (grub_vbe_set_palette_data): Renamed from this... - (grub_vbe_bios_set_palette_data): ... to this. - (grub_vbe_bios_get_controller_info): Fixed problem with registers - getting corrupted after calling it. Added more pushes and pops. - (grub_vbe_bios_set_mode): Likewise. - (grub_vbe_bios_get_mode): Likewise. - (grub_vbe_bios_get_memory_window): Likewise. - (grub_vbe_bios_set_scanline_length): Likewise. - (grub_vbe_bios_get_scanline_length): Likewise. - (grub_vbe_bios_get_display_start): Likewise. - (grub_vbe_bios_set_palette_data): Likewise. - - * normal/cmdline.c (cl_set_pos): Refresh the screen. - (cl_insert): Likewise. - (cl_delete): Likewise. - - * term/gfxterm.c: New file. - - * term/i386/pc/vesafb.c: Removed file. - - * video/video.c: New file. - - * video/i386/pc/vbe.c (real2pm): Added new function. - (grub_video_vbe_draw_pixel): Likewise. - (grub_video_vbe_get_video_ptr): Likewise. - (grub_video_vbe_get_pixel): Likewise - (grub_video_vbe_init): Likewise. - (grub_video_vbe_fini): Likewise. - (grub_video_vbe_setup): Likewise. - (grub_video_vbe_get_info): Likewise. - (grub_video_vbe_set_palette): Likewise. - (grub_video_vbe_get_palette): Likewise. - (grub_video_vbe_set_viewport): Likewise. - (grub_video_vbe_get_viewport): Likewise. - (grub_video_vbe_map_color): Likewise. - (grub_video_vbe_map_rgb): Likewise. - (grub_video_vbe_map_rgba): Likewise. - (grub_video_vbe_unmap_color): Likewise. - (grub_video_vbe_fill_rect): Likewise. - (grub_video_vbe_blit_glyph): Likewise. - (grub_video_vbe_blit_bitmap): Likewise. - (grub_video_vbe_blit_render_target): Likewise. - (grub_video_vbe_scroll): Likewise. - (grub_video_vbe_swap_buffers): Likewise. - (grub_video_vbe_create_render_target): Likewise. - (grub_video_vbe_delete_render_target): Likewise. - (grub_video_vbe_set_active_render_target): Likewise. - (grub_vbe_set_pixel_rgb): Remove function. - (grub_vbe_set_pixel_index): Likewise. - (index_color_mode): Remove static variable. - (active_mode): Likewise. - (framebuffer): Likewise. - (bytes_per_scan_line): Likewise. - (grub_video_vbe_adapter): Added new static variable. - (framebuffer): Likewise. - (render_target): Likewise. - (initial_mode): Likewise. - (mode_in_use): Likewise. - (mode_list): Likewise. - -2006-03-10 Marco Gerards - - * configure.ac (AC_INIT): Bumped to 1.93. - - * DISTLIST: Added `include/grub/hfs.h'. - -2006-02-01 Yoshinori K. Okuji - - * boot/i386/pc/boot.S (general_error): Before looping, try INT - 18H, which might help the BIOS falling back to next boot media. - -2006-01-25 Yoshinori K. Okuji - - * util/i386/pc/grub-install.in: Escape a backslash. Reported by - Poe Chen . - -2006-01-17 Marco Gerards - - * include/grub/normal.h: Include . - (grub_command_list): Removed struct. - (grub_command_list_t): Removed type. - (grub_menu_entry): Remove members `num' and `command_list'. Add - members `commands' and `sourcecode'. - * include/grub/script.h: Add inclusion guards. - (grub_script_cmd_menuentry): New struct. - (grub_script_execute_menuentry): New prototype. - (grub_script_lexer_record_start): Likewise. - (grub_script_lexer_record_stop): Likewise. - * normal/execute.c (grub_script_execute_menuentry): New function. - * normal/lexer.c (record, recording, recordpos, recordlen): New - variables. - (grub_script_lexer_record_start): New function. - (grub_script_lexer_record_stop): Likewise. - (recordchar): Likewise. - (nextchar): Likewise. - (grub_script_yylex): Use `nextchar' to fetch new characters. Use - 2048 as the buffer size. Add the tokens `menuentry' and `@'. - * normal/main.c: Include and - (current_menu): New variable. - (free_menu): Mainly rewritten. - (grub_normal_menu_addentry): New function. - (read_config_file): Rewritten. - * normal/menu.c (run_menu_entry): Mainly rewritten. - * normal/menu_entry.c (make_screen): Rewritten the code to insert - the menu entry. - (run): Mainly rewritten. - * normal/parser.y (menu_entry): New variable. - (GRUB_PARSER_TOKEN_MENUENTRY): New token. - (menuentry): New rule. - (command): Add `menuentry'. - (if_statement): Allow additional returns before `fi'. - * normal/script.c (grub_script_create_cmdmenu): New function. - -2006-01-03 Marco Gerards - - * INSTALL: GNU Bison is required. - * configure.ac: Rewritten the test to detect Bison. - * Makefile.in (YACC): New variable. Reported by Xun Sun - . - -2006-01-03 Marco Gerards - - * fs/hfsplus.c (grub_hfsplus_read_block): Convert the offset of - the HFS+ filesystem to filesystem blocks. - (grub_hfsplus_iterate_dir): Cast the `fileinfo' assignment so a - GCC warning is silenced. - -2006-01-03 Marco Gerards - - * partmap/apple.c (apple_partition_map_iterate): Convert the data - read from disk from big endian to host byte order. - -2006-01-03 Hollis Blanchard - - * fs/hfs.c: Include . Added reference to the official - documentation. - (GRUB_HFS_EMBED_HFSPLUS_SIG): New macro. - (grub_hfs_mount): Grammar fix in error. Make sure this is not an - embedded HFS+ filesystem. - (GRUB_HFS_MAGIC, grub_hfs_extent, grub_hfs_datarecord_t) - (grub_hfs_sblock): Move from here... - * include/grub/hfs.h: To here... New file. - * fs/hfsplus.c: Include . Added reference to the official - documentation. - (GRUB_HFSPLUS_MAGIC, GRUB_HFSPLUSX_MAGIC, GRUB_HFSPLUS_SBLOCK): - New macros. - (grub_hfsplus_volheader): Change type of member `magic' to - `grub_uint16_t'. - (grub_hfsplus_data): Add new member `embedded_offset'. - (grub_hfsplus_read_block): Add the HFS+ wrapper offset to the - returned block. - (grub_hfsplus_mount): Read the HFS+ wrapper if it exists. - Calculate the offset. - -2005-12-25 Yoshinori K. Okuji - - * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_DRP_ADDR): - Removed. - (GRUB_BOOT_MACHINE_DRP_SIZE): Likewise. - -2005-12-25 Yoshinori K. Okuji - - * kern/env.c (grub_env_set): Check if ENV->VALUE instead of - ENV->NAME is NULL after allocating ENV->VALUE. - -2005-12-25 Marco Gerards - - * kern/env.c (grub_env_set): Rewritten the error handling code. - -2005-12-25 Yoshinori K. Okuji - - * geninit.sh: Made more robust, and more portable. - -2005-12-25 Marco Gerards - - Add support for Apple HFS+ filesystems. - - * fs/hfsplus.c: New file. - - * DISTLIST: Added `fs/hfsplus.c'. - - * conf/common.rmk (pkgdata_MODULES): Add `hfsplus.mod'. - (hfsplus_mod_SOURCES): New variable. - (hfsplus_mod_CFLAGS): Likewise. - (hfsplus_mod_LDFLAGS): Likewise. - * conf/i386-pc.rmk (grub_setup_SOURCES): Add `fs/hfsplus.c'. - (grub_setup_SOURCES): Likewise. - (grub_mkdevicemap_SOURCES): Likewise. - (grub_emu_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - - * fs/fshelp.c (grub_fshelp_log2blksize): New function. - - * include/grub/fshelp.h (grub_fshelp_log2blksize): new prototype. - -2005-12-25 Yoshinori K. Okuji - - * DISTLIST: Added geninitheader.sh, geninit.sh, commands/test.c, - commands/i386/pc/play.c, conf/common.mk, conf/common.rmk, - include/grub/parser.h, include/grub/script.h, kern/parser.c, - kern/sparc64/cache.S, normal/execute.c, normal/function.c, - normal/lexer.c, normal/parser.y, normal/script.c, and - partmap/gpt.c. - Removed kern/sparc64/cache.c. - - * conf/common.rmk (DISTCLEANFILES): Added grub_script.tab.c, - grub_script.tab.h, grub_modules_init.lst, grub_modules_init.h, - grub_emu_init.c. - - * configure.ac (AC_INIT): Bumped to 1.92. - -2005-12-24 Vesa Jaaskelainen - - * kern/err.c (grub_error_push): Added new function to support error - stacks. - (grub_error_pop): Likewise. - (grub_error_stack_items): New local variable to support error stacks. - (grub_error_stack_pos): Likewise. - (grub_error_stack_assert): Likewise. - (GRUB_ERROR_STACK_SIZE): Added new define to configure maximum error - stack depth. - (grub_print_error): Added support to print errors from error stack. - - * include/grub/err.h (grub_error_push): Added function prototype. - (grub_error_pop): Likewise. - -2005-12-09 Hollis Blanchard - - * configure.ac: Accept `powerpc64' as host_cpu. - (amd64): Rename to `biarch32'. - - * kern/powerpc/cache.S (grub_arch_sync_caches): Handle - non-cacheline-aligned addresses. - - * kern/dl.c (grub_dl_load_core): Add grub_dprintf messages. - (grub_dl_flush_cache): Likewise. Only call `grub_arch_sync_caches' - if `size' is non-zero. - -2005-12-03 Marco Gerards - - * conf/common.rmk (grub_modules_init.lst): Use `-printf "%P\n"' - and `cd' to make sure the filename is not prefixed with a - directory name. - (pkgdata_MODULES): Add `gpt.mod'. - (gpt_mod_SOURCES): New variable. - (gpt_mod_CFLAGS): Likewise. - (gpt_mod_LDFLAGS): Likewise. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `partmap/gpt.c'. - - * include/grub/pc_partition.h (GRUB_PC_PARTITION_TYPE_GPT_DISK): - New macro. - - * partmap/gpt.c: New file. - - * partmap/pc.c (pc_partition_map_iterate): Don't continue when a - GPT partition map is detected. - -2005-12-03 Vincent Pelletier - - * commands/i386/pc/play.c: New file. - * conf/i386-pc.rmk (pkgdata_MODULES): Added play.mod. - (play_mod_SOURCES, play_mod_CFLAGS, play_mod_LDFLAGS): New - macros. - -2005-11-27 Marco Gerards - - * include/grub/dl.h (GRUB_MOD_INIT): Use `__attribute__ - ((unused))' to silence gcc warning. - -2005-11-26 Hollis Blanchard - - * configure.ac: Correct `AC_PROG_YACC' test. - -2005-11-22 Hollis Blanchard - - * util/powerpc/ieee1275/grub-install.in: Run the mount point - check before installing files. - -2005-11-22 Mike Small - - * util/powerpc/ieee1275/grub-install.in (grubdir): Fixed partition - number regex so multidigit numbers are recognized correctly. - -2005-11-22 Mike Small - - * loader/powerpc/ieee1275/linux.c (grub_rescue_cmd_linux): Add a - debugging message before attempting to claim memory. - (grub_rescue_cmd_initrd): Add a claim debugging message and try - multiple addresses in case of failure. - -2005-11-22 Hollis Blanchard - - * term/tparm.c (get_space): Remove empty `if' statement. - - * fs/ufs.c (grub_ufs_find_file): Remove `grub_le_to_cpu32'. - - * kern/parser.c (check_varstate): Rename `state' to 's'. - -2005-11-22 Hollis Blanchard - - * partmap/acorn.c: Change `unsigned' to `unsigned int'. Move all - variable definitions to the beginning of each function. Sort stack - variables by size. - (find): Rename to `acorn_partition_map_find'. Cast `grub_disk_read' - `buf' argument to `char *'. - -2005-11-22 Hollis Blanchard - - * conf/powerpc-ieee1275.rmk: Include conf/common.mk. - (pkgdata_MODULES): Removed fshelp.mod, fat.mod, ext2.mod, ufs.mod, - minix.mod, hfs.mod, jfs.mod, xfs.mod, affs.mod, sfs.mod, - hello.mod, boot.mod, terminal.mod, ls.mod, cmp.mod, cat.mod, - help.mod, font.mod, terminfo.mod, amiga.mod, apple.mod, pc.mod, - sun.mod, acorn.mod, loopback.mod, default.mod, timeout.mod, - configfile.mod, search.mod, gzio.mod and test.mod. - (symlist.c, grub_script.tab.c, grub_script.tab.h, kernel_syms.lst) - (grub_modules_init.lst, grub_modules_init.h, grub_emu_init.c) - (fshelp_mod_SOURCES, fshelp_mod_CFLAGS, fshelp_mod_LDFLAGS) - (fat_mod_SOURCES, fat_mod_CFLAGS, fat_mod_LDFLAGS) - (ext2_mod_SOURCES, ext2_mod_CFLAGS, ext2_mod_LDFLAGS) - (ufs_mod_SOURCES, ufs_mod_CFLAGS, ufs_mod_LDFLAGS) - (minix_mod_SOURCES, minix_mod_CFLAGS, minix_mod_LDFLAGS) - (hfs_mod_SOURCES, hfs_mod_CFLAGS, hfs_mod_LDFLAGS, jfs_mod_SOURCES) - (jfs_mod_CFLAGS, jfs_mod_LDFLAGS, iso9660_mod_SOURCES) - (iso9660_mod_CFLAGS, iso9660_mod_LDFLAGS, xfs_mod_SOURCES) - (xfs_mod_CFLAGS, xfs_mod_LDFLAGS, affs_mod_SOURCES) - (affs_mod_CFLAGS, affs_mod_LDFLAGS, sfs_mod_SOURCES) - (sfs_mod_CFLAGS, sfs_mod_LDFLAGS, hello_mod_SOURCES) - (hello_mod_CFLAGS, hello_mod_LDFLAGS, boot_mod_SOURCES) - (boot_mod_CFLAGS, boot_mod_LDFLAGS, terminal_mod_SOURCES) - (terminal_mod_CFLAGS, terminal_mod_LDFLAGS, ls_mod_SOURCES) - (ls_mod_CFLAGS, ls_mod_LDFLAGS, cmp_mod_SOURCES, cmp_mod_CFLAGS) - (cmp_mod_LDFLAGS, cat_mod_SOURCES, cat_mod_CFLAGS, cat_mod_LDFLAGS) - (help_mod_SOURCES, help_mod_CFLAGS, help_mod_LDFLAGS) - (font_mod_SOURCES, font_mod_CFLAGS, font_mod_LDFLAGS) - (terminfo_mod_SOURCES, terminfo_mod_CFLAGS, terminfo_mod_LDFLAGS) - (amiga_mod_SOURCES, amiga_mod_CFLAGS, amiga_mod_LDFLAGS) - (apple_mod_SOURCES, apple_mod_CFLAGS, apple_mod_LDFLAG): Removed. - - * conf/common.mk (grub_modules_init.lst): Use `find' instead of - `grep --include'. - (pkgdata_MODULES): Add test.mod. - -2005-11-18 Timothy Baldwin - - * genmk.rb: Fixed list rules moved to Makefile.in. Recognise - appending to variables with "+=". - (PModule): Use full pathname to generate *.lst filenames. - - * Makefile.in: Fixed list rules moved from genmk.rb. - (.DELETE_ON_ERROR): New special target. - (RMKFILES): Add common.rmk and sparc64-ieee1275.rmk. - - * conf/i386-pc.rmk: Include conf/common.mk. - (pkgdata_MODULES): Removed fshelp.mod, fat.mod, ext2.mod, ufs.mod, - minix.mod, hfs.mod, jfs.mod, xfs.mod, affs.mod, sfs.mod, - hello.mod, boot.mod, terminal.mod, ls.mod, cmp.mod, cat.mod, - help.mod, font.mod, terminfo.mod, amiga.mod, apple.mod, pc.mod, - sun.mod, acorn.mod, loopback.mod, default.mod, timeout.mod, - configfile.mod, search.mod, gzio.mod and test.mod. - (symlist.c, grub_script.tab.c, grub_script.tab.h, kernel_syms.lst) - (grub_modules_init.lst, grub_modules_init.h, grub_emu_init.c) - (fshelp_mod_SOURCES, fshelp_mod_CFLAGS, fshelp_mod_LDFLAGS) - (fat_mod_SOURCES, fat_mod_CFLAGS, fat_mod_LDFLAGS) - (ext2_mod_SOURCES, ext2_mod_CFLAGS, ext2_mod_LDFLAGS) - (ufs_mod_SOURCES, ufs_mod_CFLAGS, ufs_mod_LDFLAGS) - (minix_mod_SOURCES, minix_mod_CFLAGS, minix_mod_LDFLAGS) - (hfs_mod_SOURCES, hfs_mod_CFLAGS, hfs_mod_LDFLAGS, jfs_mod_SOURCES) - (jfs_mod_CFLAGS, jfs_mod_LDFLAGS, iso9660_mod_SOURCES) - (iso9660_mod_CFLAGS, iso9660_mod_LDFLAGS, xfs_mod_SOURCES) - (xfs_mod_CFLAGS, xfs_mod_LDFLAGS, affs_mod_SOURCES) - (affs_mod_CFLAGS, affs_mod_LDFLAGS, sfs_mod_SOURCES) - (sfs_mod_CFLAGS, sfs_mod_LDFLAGS, hello_mod_SOURCES) - (hello_mod_CFLAGS, hello_mod_LDFLAGS, boot_mod_SOURCES) - (boot_mod_CFLAGS, boot_mod_LDFLAGS, terminal_mod_SOURCES) - (terminal_mod_CFLAGS, terminal_mod_LDFLAGS, ls_mod_SOURCES) - (ls_mod_CFLAGS, ls_mod_LDFLAGS, cmp_mod_SOURCES, cmp_mod_CFLAGS) - (cmp_mod_LDFLAGS, cat_mod_SOURCES, cat_mod_CFLAGS, cat_mod_LDFLAGS) - (help_mod_SOURCES, help_mod_CFLAGS, help_mod_LDFLAGS) - (font_mod_SOURCES, font_mod_CFLAGS, font_mod_LDFLAGS) - (terminfo_mod_SOURCES, terminfo_mod_CFLAGS, terminfo_mod_LDFLAGS) - (amiga_mod_SOURCES, amiga_mod_CFLAGS, amiga_mod_LDFLAGS) - (apple_mod_SOURCES, apple_mod_CFLAGS, apple_mod_LDFLAG): Move from - here... - * conf/common.rmk: ... to here. New file. - - * conf/common.mk: New file. - -2005-11-18 Yoshinori K. Okuji - - * conf/powerpc-ieee1275.rmk (grub_script.tab.h): Unified to ... - (grub_script.tab.c): ... here. - - * conf/sparc64-ieee1275.rmk (grub_script.tab.h): Unified to ... - (grub_script.tab.c): ... here. - - * conf/i386-pc.rmk (grub_script.tab.h): Unified to ... - (grub_script.tab.c): ... here. - - * normal/command.c (grub_command_find): Fixed a memory leak of - MODULE_NAME. Reported by Mike Small . - -2005-11-13 Timothy Baldwin - - * include/grub/symbol.h: (FUNCTION): Use double quotes instead of - "@" which marks the start of a comment on ARM. - (VARIABLE): Likewise. - -2005-11-13 Timothy Baldwin - - Add support for Linux/ADFS partition tables. - - * partmap/acorn.c: New file. - - * include/grub/acorn_filecore.h: Likewise. - - * DISTLIST: Added `partmap/acorn.c' and - `include/grub/acorn_filecore.h'. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add - `partmap/acorn.c'. - (pkgdata_MODULES): Add `acorn.mod'. - (acorn_mod_SOURCES): New variable. - (acorn_mod_CFLAGS): Likewise. - - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Add - `partmap/acorn.c'. - (pkgdata_MODULES): Add `acorn.mod'. - (acorn_mod_SOURCES): New variable. - (acorn_mod_CFLAGS): Likewise. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `partmap/acorn.c'. - (pkgdata_MODULES): Add `acorn.mod'. - (acorn_mod_SOURCES): New variable. - (acorn_mod_CFLAGS): Likewise. - (acorn_mod_LDFLAGS): Likewise. - - * include/types.h (grub_disk_addr_t): New typedef. - -2005-11-13 Marco Gerards - - * geninit.sh: New file. - - * geninitheader.sh: Likewise. - - * commands/boot.c (grub_boot_init, grub_boot_fini): Removed. - * commands/cat.c (grub_cat_init, grub_cat_fini): Likewise. - * commands/cmp.c (grub_cmp_init, grub_cmp_fini): Likewise. - * commands/configfile.c (grub_configfile_init) - (grub_configfile_fini): Likewise. - * commands/default.c (grub_default_init, grub_default_fini): - Likewise. - * commands/help.c (grub_help_init, grub_help_fini): Likewise. - * commands/ls.c (grub_ls_init, grub_ls_fini): Likewise. - * commands/search.c (grub_search_init, grub_search_fini): Likewise. - * commands/terminal.c (grub_terminal_init, grub_terminal_fini): - Likewise. - * commands/test.c (grub_test_init, grub_test_fini): Likewise. - * commands/timeout.c (grub_timeout_init, grub_timeout_fini): - Likewise. - * commands/i386/pc/halt.c (grub_halt_init, grub_halt_fini): Likewise. - * commands/ieee1275/halt.c (grub_halt_init, grub_halt_fini): - Likewise. - * commands/i386/pc/reboot.c (grub_reboot_init, grub_reboot_fini): - Likewise. - * commands/ieee1275/reboot.c (grub_reboot_init, grub_reboot_fini): - Likewise. - * disk/loopback.c (grub_loop_init, grub_loop_fini): Likewise. - * fs/affs.c (grub_affs_init, grub_affs_fini): Likewise. - * fs/ext2.c (grub_ext2_init, grub_ext2_fini): Likewise. - * fs/fat.c (grub_fat_init, grub_fat_fini): Likewise. - * fs/hfs.c (grub_hfs_init, grub_hfs_fini): Likewise. - * fs/iso9660.c (grub_iso9660_init, grub_iso9660_fini): Likewise. - * fs/jfs.c (grub_jfs_init, grub_jfs_fini): Likewise. - * fs/minix.c (grub_minix_init, grub_minix_fini): Likewise. - * fs/sfs.c (grub_sfs_init, grub_sfs_fini): Likewise. - * fs/ufs.c (grub_ufs_init, grub_ufs_fini): Likewise. - * fs/xfs.c (grub_xfs_init, grub_xfs_fini): Likewise. - * normal/main.c (grub_normal_init, grub_normal_fini): Likewise. - * partmap/amiga.c (grub_amiga_partition_map_init) - (grub_amiga_partition_map_fini): Likewise. - * partmap/apple.c (grub_apple_partition_map_init) - (grub_apple_partition_map_fini): Likewise. - * partmap/pc.c (grub_pc_partition_map_init) - (grub_pc_partition_map_fini): Likewise. - * partmap/sun.c (grub_sun_partition_map_init, - grub_sun_partition_map_fini): Likewise. - * term/terminfo.c (grub_terminal_init, grub_terminal_fini): - Likewise. - - * util/grub-emu.c: Include . - (main): Don't initialize and de-initialize any modules directly, - use `grub_init_all' and `grub_fini_all' instead. - - * term/i386/pc/vesafb.c (grub_vesafb_init): Renamed to - `grub_vesafb_mod_init'. - (grub_vesafb_fini): Renamed to `grub_vesafb_mod_fini'. Updated - all users. - * term/i386/pc/vga.c (grub_vga_init): Renamed to - `grub_vga_mod_init'. Updated all users. - (grub_vga_fini): Renamed to `grub_vga_mod_fini'. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `grub_emu_init.c'. - (grub_modules_init.lst, grub_modules_init.h, grub_emu_init.c): New - rules. - - * include/grub/dl.h (GRUB_MOD_INIT): Add argument `name'. - Generate a function to initialize the module in utilities. - Updated all callers. - (GRUB_MOD_FINI): Add argument `name'. Generate a function to - initialize the module in utilities. Updated all callers. - -2005-11-09 Hollis Blanchard - - * term/ieee1275/ofconsole.c (grub_ofconsole_cls): Use both the ANSI - escape sequence and a literal ^L to clear the screen. - - * commands/ieee1275/suspend.c (grub_cmd_suspend): Clear the screen - when returning from Open Firmware. - -2005-11-09 Hollis Blanchard - - * term/ieee1275/ofconsole.c (grub_ofconsole_width): New variable. - (grub_ofconsole_height): Likewise. - (grub_ofconsole_putchar): If `grub_curr_x' exceeds console width, - manually insert a '\n'. - (grub_ofconsole_getwh): Set and return `grub_ofconsole_width' and - `grub_ofconsole_height'. Return early if these are already set. - -2005-11-07 Vincent Pelletier - - * conf/sparc64-ieee1275.rmk (grub_emu_SOURCES): Add - `commands/test.c', `fs/affs.c', `fs/sfs.c', `fs/xfs.c', - `normal/execute.c', `normal/lexer.c', `io/gzio.c', - `kern/parser.c', `grub_script.tab.c', `normal/function.c' - and `normal/script.c'. - (normal_mod_SOURCES): `normal/execute.c', `normal/lexer.c', - `grub_script.tab.c', `normal/function.c' and `normal/script.c'. - (test_mod_SOURCES): New variable. - (test_mod_CFLAGS): Likewise. - (test_mod_LDFLAGS): Likewise. - (pkgdata_MODULES): Add `test.mod'. - (grub_script.tab.c): New rule. - (grub_script.tab.h): Likewise. - -2005-11-07 Marco Gerards - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add - `commands/test.c', `normal/execute.c', `normal/lexer.c', - `grub_script.tab.c', `normal/function.c' and `normal/script.c'. - (normal_mod_SOURCES): `normal/execute.c', `normal/lexer.c', - `grub_script.tab.c', `normal/function.c' and `normal/script.c'. - (test_mod_SOURCES): New variable. - (test_mod_CFLAGS): Likewise. - (pkgdata_MODULES): Add `test.mod'. - (grub_script.tab.c): New rule. - (grub_script.tab.h): Likewise. - -2005-11-06 Marco Gerards - - Add initial scripting support. - - * commands/test.c: New file. - * include/grub/script.h: Likewise. - * normal/execute.c: Likewise. - * normal/function.c: Likewise. - * normal/lexer.c: Likewise. - * normal/parser.y: Likewise. - * normal/script.c: Likewise. - - * configure.ac: Add `AC_PROG_YACC' test. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `commands/test.c', - `normal/execute.c', `normal/lexer.c', `grub_script.tab.c', - `normal/function.c' and `normal/script.c'. - (normal_mod_SOURCES): `normal/execute.c', `normal/lexer.c', - `grub_script.tab.c', `normal/function.c' and `normal/script.c'. - (test_mod_SOURCES, test_mod_CFLAGS, test_mod_LDFLAGS): New - variables. - (pkgdata_MODULES): Add `test.mod'. - (grub_script.tab.c): New rule. - (grub_script.tab.h): Likewise. - - * include/grub/err.h (grub_err_t): Add `GRUB_ERR_TEST_FAILURE'. - - * include/grub/normal.h (grub_test_init): New prototype. - (grub_test_fini): Likewise. - - * normal/command.c: Include . - (grub_command_execute): Rewritten. - - * util/grub-emu.c (main): Call `grub_test_init' and - `grub_test_fini'. - -2005-11-03 Hollis Blanchard - - * kern/powerpc/ieee1275/init.c (grub_get_rtc): Initialize `msecs' - to 0. - * term/ieee1275/ofconsole.c (grub_ofconsole_checkkey): Return -1 if - there are no pending characters. - -2005-11-03 Hollis Blanchard - - * kern/powerpc/ieee1275/openfw.c (grub_ieee1275_get_devname): Use - `grub_strndup' to drop device arguments. Replace unnecessary - `grub_strndup' with `grub_strdup'. - -2005-11-03 Hollis Blanchard - - * kern/term.c (grub_cls): Do not call grub_cur_term->cls() if the - `debug' environment variable has been set. - -2005-11-02 Hollis Blanchard - - * Makefile.in (install-local): Use $(DATA). - (uninstall): Likewise. - * conf/powerpc-ieee1275.rmk (bin_UTILITIES): Move grub-mkimage... - (sbin_UTILITIES): ... to here. - (sbin_SCRIPTS): New variable. - (grub_install_SOURCES): New variable. - * util/powerpc/ieee1275/grub-install.in: New file. - * util/powerpc/ieee1275/grub-mkimage.c (kernel_path): Remove - variable. - (add_segments): Call `grub_util_get_path'. - -2005-10-28 Yoshinori K. Okuji - - From Timothy Baldwin: - * commands/ls.c (grub_ls_list_files): Close FILE with - grub_file_close. - * kern/misc.c (grub_vsprintf): Terminate the string S with NUL. - -2005-10-24 Marco Gerards - - * include/grub/parser.h: New file. - - * kern/parser.c: Likewise. - - * conf/i386-pc.rmk (kernel_img_SOURCES): Add `kern/parser.c'. - (grub_setup_SOURCES): Likewise. - (grub_probefs_SOURCES): Likewise. - (grub_emu_SOURCES): Likewise. - (kernel_img_HEADERS): Add `parser.h'. - - * conf/powerpc-ieee1275.rmk (grubof_HEADERS): Add `parser.h'. - (grub_emu_SOURCES): Add `kern/parser.c'. - (grubof_SOURCES): Likewise. - - * conf/sparc64-ieee1275.rmk (grubof_HEADERS): Add `parser.h'. - (grubof_SOURCES): Add `kern/parser.c'. - - * include/grub/misc.h (grub_split_cmdline): Removed prototype. - - * kern/misc.c (grub_split_cmdline): Removed function. - - * kern/rescue.c: Include . - (grub_enter_rescue_mode): Use `grub_parser_split_cmdline' instead - of `grub_split_cmdline'. - - * normal/command.c: Include . - (grub_command_execute): Use `grub_parser_split_cmdline' instead - of `grub_split_cmdline'. - - * normal/completion.c: Include . - (cmdline_state): New variable. - (iterate_dir): End the filename with a quote depending on the - command line state. - (get_state): new function. - (grub_normal_do_completion): Use `grub_parser_split_cmdline' to - split the arguments and determine the current argument. When the - argument string is not quoted, escape all spaces. - -2005-10-23 Vincent Pelletier - - * normal/sparc64/setjmp.S: New file. - -2005-10-23 Vincent Pelletier - - * include/grub/sparc64/libgcc.h: New file. - * conf/sparc64-ieee1275.rmk (COMMON_ASFLAGS): Remove -Av9. - (normal_mod_SOURCES): Use normal/sparc64/setjmp.S instead of - normal/sparc64/setjmp.c. - -2005-10-23 Vincent Pelletier - - * kern/sparc64/dl.c: Rewritten for SPARCV9 ELF. - * kern/sparc64/cache.S: New file. - * kern/sparc64/cache.c: Removed. - * conf/sparc64-ieee1275.rmk (COMMON_ASFLAGS): Add -Av9. - (COMMON_CFLAGS): Add -mno-app-regs. Remove -mcpu=v9 and - -mtune=ultrasparc. - (COMMON_LDFLAGS): Add -melf64_sparc. - (grubof_HEADERS): Add sparc64/libgcc.h and machine/kernel.h. - (grubof_SOURCES): Use cache.S instead of cache.c. - (grubof_LDFLAGS): Add -mno-app-regs. Replace "-Xlinker - --oformat -Xlinker elf64-sparc" by "-Bstatic,-melf64_sparc". - (pkgdata_MODULES): Uncomment. Leave linux.mod and _linux.mod - commented though. - (normal_mod_SOURCES): Add normal/completion.c and normal/misc.c. - (_linux_mod_SOURCES, _linux_mod_CFLAGS, linux_mod_SOURCES) - (linux_mod_CFLAGS): Commented out. - (_linux_mod_LDFLAGS, linux_mod_LDFLAGS): New macro, commented - out because module isn't built. - (fshelp_mod_LDFLAGS, fat_mod_LDFLAGS, ext2_mod_LDFLAGS) - (ufs_mod_LDFLAGS, minix_mod_LDFLAGS, hfs_mod_LDFLAGS) - (jfs_mod_LDFLAGS, iso9660_mod_LDFLAGS, normal_mod_LDFLAGS) - (hello_mod_LDFLAGS, boot_mod_LDFLAGS, terminal_mod_LDFLAGS) - (ls_mod_LDFLAGS, cmp_mod_LDFLAGS, cat_mod_LDFLAGS) - (font_mod_LDFLAGS, amiga_mod_LDFLAGS, apple_mod_LDFLAGS) - (pc_mod_LDFLAGS, sun_mod_LDFLAGS, loopback_mod_LDFLAGS) - (suspend_mod_LDFLAGS, reboot_mod_LDFLAGS, halt_mod_LDFLAGS) - (help_mod_LDFLAGS, default_mod_LDFLAGS, timeout_mod_LDFLAGS) - (configfile_mod_LDFLAGS, search_mod_LDFLAGS, xfs_mod_SOURCES) - (xfs_mod_CFLAGS, xfs_mod_LDFLAGS, affs_mod_SOURCES) - (affs_mod_CFLAGS, affs_mod_LDFLAGS, sfs_mod_SOURCES) - (sfs_mod_CFLAGS, sfs_mod_LDFLAGS, gzio_mod_SOURCES) - (gzio_mod_CFLAGS, gzio_mod_LDFLAGS): New macro. - -2005-10-20 Yoshinori K. Okuji - - * util/i386/pc/grub-probefs.c (main): Call grub_xfs_init and - grub_xfs_fini. Do not call grub_hfs_init or grub_hfs_fini any - longer, because HFS should not be used on PC. - -2005-10-20 Timothy Baldwin - - * io/gzio.c (grub_gzio_read): Use OFFSET instead of FILE->OFFSET - consistently within the loop. - -2005-10-15 Marco Gerards - - * fs/xfs.c (grub_xfs_iterate_dir): Detect an error if part of a - directory can not be read. - -2005-10-15 Yoshinori K. Okuji - - * configure.ac (AC_INIT): Increase the version number to 1.91. - - * DISTLIST: Added include/grub/terminfo.h, include/grub/tparm.h, - include/grub/i386/pc/serial.h, term/terminfo.c, term/tparm.c and - term/i386/pc/serial.c. - -2005-10-15 Yoshinori K. Okuji - - * kern/file.c (grub_file_seek): Seeking to an offset equal to a - file size must be permitted. - - * kern/i386/pc/startup.S (multiboot_trampoline): Fix a mistake - between %ah and %al. - -2005-10-15 Yoshinori K. Okuji - - * fs/xfs.c (grub_xfs_iterate_dir): Change the type of BLK to - grub_uint64_t. - Call the hook with a NUL-terminated filename. - (grub_xfs_mount): Use grub_be_to_cpu32 instead of - grub_cpu_to_be32. - - * kern/term.c (cursor_state): New variable. - (grub_term_set_current): Reset the cursor state on a new - terminal. - (grub_setcursor): Rewritten to use CURSOR_STATE. - (grub_getcursor): New function. - - * include/grub/term.h (grub_getcursor): New prototype. - - * io/gzio.c (test_header): Align BUF for accessing it as 32-bit - integers on ARM. Reported by Timothy Baldwin - . - -2005-10-11 Marco Gerards - - * fs/sfs.c (grub_sfs_open): Don't free `data->label' if it is not - allocated. - (grub_sfs_dir): Likewise. - -2005-10-09 Marco Gerards - - Add support for the SFS filesystem. - - * fs/sfs.c: New file. - - * DISTLIST: Added `fs/sfs.c'. - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add `fs/sfs.c'. - (grub_probefs_SOURCES): Likewise. - (grub_emu_SOURCES): Likewise. - (pkgdata_MODULES): Add `sfs.mod'. - (sfs_mod_SOURCES): New variable. - (sfs_mod_CFLAGS): Likewise. - (sfs_mod_LDFLAGS): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add `fs/sfs.c'. - (pkgdata_MODULES): Add `sfs.mod'. - (sfs_mod_SOURCES): New variable. - (sfs_mod_CFLAGS): Likewise. - - * util/grub-emu.c (main): Call `grub_sfs_init' and - `grub_sfs_fini'. - - * include/grub/fs.h (grub_sfs_init): New prototype. - (grub_sfs_fini): Likewise. - -2005-10-07 Marco Gerards - - Add support for the AFFS filesystem. - - * fs/affs.c: New file. - - * DISTLIST: Added `fs/affs.c'. - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add `fs/affs.c'. - (grub_probefs_SOURCES): Likewise. - (grub_emu_SOURCES): Likewise. - (pkgdata_MODULES): Add `affs.mod'. - (affs_mod_SOURCES): New variable. - (affs_mod_CFLAGS): Likewise. - (affs_mod_LDFLAGS): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add `fs/affs.c'. - (pkgdata_MODULES): Add `affs.mod'. - (affs_mod_SOURCES): New variable. - (affs_mod_CFLAGS): Likewise. - - * util/grub-emu.c (main): Call `grub_affs_init' and - `grub_affs_fini'. - - * include/grub/fs.h (grub_affs_init): New prototype. - (grub_affs_fini): Likewise. - -2005-10-01 Marco Gerards - - * fs/xfs.c (grub_xfs_iterate_dir): Add parentheses. - -2005-10-01 Marco Gerards - - * configure.ac: Accept `x86_64' as host_cpu. In that case add - `-m32' to CFLAGS. - - * genmk.rb (class PModule): Always use `$(#{prefix}_LDFLAGS)' when - linking. - - * conf/i386-pc.rmk (COMMON_CFLAGS): Add `-m32'. - (COMMON_LDFLAGS): New variable. - (kernel_img_LDFLAGS): Include `COMMON_FLAGS'. - (_chain_mod_LDFLAGS, fshelp_mod_LDFLAGS, fat_mod_LDFLAGS) - (ext2_mod_LDFLAGS, ufs_mod_LDFLAGS, minix_mod_LDFLAGS) - (hfs_mod_LDFLAGS, jfs_mod_LDFLAGS, iso9660_mod_LDFLAGS) - (xfs_mod_LDFLAGS, _linux_mod_LDFLAGS, linux_mod_LDFLAGS) - (normal_mod_LDFLAGS, hello_mod_LDFLAGS, boot_mod_LDFLAGS) - (terminal_mod_LDFLAGS, ls_mod_LDFLAGS, cmp_mod_LDFLAGS) - (cat_mod_LDFLAGS, help_mod_LDFLAGS, reboot_mod_LDFLAGS) - (halt_mod_LDFLAGS, vga_mod_LDFLAGS, font_mod_LDFLAGS) - (terminfo_mod_LDFLAGS, serial_mod_LDFLAGS, _multiboot_mod_LDFLAGS) - (multiboot_mod_LDFLAGS, amiga_mod_LDFLAGS, apple_mod_LDFLAGS) - (pc_mod_LDFLAGS, sun_mod_LDFLAGS, loopback_mod_LDFLAGS) - (default_mod_LDFLAGS, timeout_mod_LDFLAGS, configfile_mod_LDFLAGS) - (vbe_mod_LDFLAGS, vesafb_mod_LDFLAGS, vbeinfo_mod_LDFLAGS) - (vbetest_mod_LDFLAGS, search_mod_LDFLAGS, gzio_mod_LDFLAGS): New - variables. - (normal_mod_ASFLAGS): Add `-m32'. - - * include/grub/types.h (grub_host_addr_t, grub_host_off_t) - (grub_host_size_t, grub_host_ssize_t): New types. - (grub_addr_t, grub_off_t, grub_size_t, grub_ssize_t): Make type - dependent of `GRUB_CPU_SIZEOF_VOID_P' instead on - `GRUB_HOST_SIZEOF_VOID_P'. - - * include/grub/kernel.h (struct grub_module_header): Type of - member offset changed to `grub_host_off_t'. Type of member size - changed to `grub_host_size_t'. - (struct grub_module_info): Type of member offset changed to - `grub_host_off_t'. Type of member size changed to - `grub_host_size_t'. - -2005-09-29 Yoshinori K. Okuji - - Make GRUB's kernel compliant to Multiboot Specification. - - * kern/i386/pc/startup.S (multiboot_header): New label. - (multiboot_entry): Likewise. - (multiboot_trampoline): Likewise. - - * include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_RAW_SIZE): - Increased to 0x4A0. - - * fs/xfs.c (grub_xfs_iterate_dir): Fix a syntax error. You may not - put parentheses after a question mark. - [!GRUB_UTIL] (my_mod): New variable. - - * util/grub-emu.c (main): Call grub_xfs_init and grub_xfs_fini. - -2005-09-28 Marco Gerards - - Adds support for the XFS filesystem. Btrees are not supported - yet. - - * fs/xfs.c: New file. - - * DISTLIST: Added `fs/xfs.c'. - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add `fs/xfs.c'. - (grub_probefs_SOURCES): Likewise. - (grub_emu_SOURCES): Likewise. - (pkgdata_MODULES): Add `xfs.mod'. - (xfs_mod_SOURCES): New variable. - (xfs_mod_CFLAGS): Likewise. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add `fs/xfs.c'. - (pkgdata_MODULES): Add `xfs.mod'. - (xfs_mod_SOURCES): New variable. - (xfs_mod_CFLAGS): Likewise. - - * util/grub-emu.c (main): Call `grub_xfs_init' and - `grub_xfs_fini'. - - * include/grub/fs.h (grub_xfs_init): New prototype. - (grub_xfs_fini): Likewise. - - -2005-09-18 Vesa Jaaskelainen - - * video/i386/pc/vbe.c (grub_vbe_set_video_mode): In indexed - color modes, allow greater than 16 colors to be configured as - a default palette. - -2005-09-03 Yoshinori K. Okuji - - * normal/completion.c (complete_arguments): Add the qualifier - const into OPTIONS. - - From Omniflux : - * include/grub/terminfo.h: New file. - * include/grub/tparm.h: Likewise. - * include/grub/i386/pc/serial.h: Likewise. - * term/terminfo.c: Likewise. - * term/tparm.c: Likewise. - * term/i386/pc/serial.c: Likewise. - * conf/i386-pc.rmk (pkgdata_MODULES): Added terminfo.mod and - serial.mod. - (terminfo_mod_SOURCES): New variable. - (terminfo_mod_CFLAGS): Likewise. - (serial_mod_SOURCES): Likewise. - (serial_mod_CFLAGS): Likewise. - -2005-08-31 Yoshinori K. Okuji - - * DISTLIST: Replaced boot/powerpc/ieee1275/crt0.S and - boot/powerpc/ieee1275/cmain.c with kern/powerpc/ieee1275/crt0.S - and kern/powerpc/ieee1275/cmain.c, respectively. - - * boot/powerpc/ieee1275/crt0.S: Moved to ... - * kern/powerpc/ieee1275/crt0.S: ... here. - - * boot/powerpc/ieee1275/cmain.c: Moved to ... - * kern/powerpc/ieee1275/cmain.c: ... here. - - * conf/powerpc-ieee1275.rmk (grubof_SOURCES): Use - kern/powerpc/ieee1275/crt0.S and kern/powerpc/ieee1275/cmain.c - instead of boot/powerpc/ieee1275/crt0.S and - boot/powerpc/ieee1275/cmain.c, respectively. - - * boot/i386/pc/boot.S (lba_mode): Do not store the total number of - sectors. It was not used anyway. - -2005-08-30 Hollis Blanchard - - * term/ieee1275/ofconsole.c (grub_ofconsole_getcharwidth): Fix - `unused parameter' warning. - -2005-08-30 Hollis Blanchard - - * term/ieee1275/ofconsole.c (grub_ofconsole_getcharwidth): New - function. - (grub_ofconsole_term): Specify grub_ofconsole_getcharwidth as - getcharwidth. - -2005-08-28 Marco Gerards - - * include/grub/normal.h (enum grub_completion_type): Added - `GRUB_COMPLETION_TYPE_ARGUMENT'. - - * normal/cmdline.c (print_completion): Handle - the `GRUB_COMPLETION_TYPE_ARGUMENT' type. - * normal/menu_entry.c (store_completion): Likewise. - - * normal/completion.c (complete_arguments): New function. - (grub_normal_do_completion): Call `complete_arguments' when the - current words start with a dash. - -2005-08-27 Marco Gerards - - * conf/powerpc-ieee1275.rmk (pkgdata_MODULES): Fix typo (use - `gzio.mod' instead of `io.mod'). - -2005-08-22 Yoshinori K. Okuji - - * gendistlist.sh (EXTRA_DISTFILES): Added genfslist.sh. - (DISTDIRS): Added io and video. - Rewrite the search routine to make an output consistently. - - * DISTLIST: Added conf/sparc64-ieee1275.mk, - conf/sparc64-ieee1275.rmk, include/grub/gzio.h, - include/grub/ieee1275/ieee1275.h, include/grub/ieee1275/ofdisk.h, - io/gzio.c, kern/sparc64/cache.c, kern/sparc64/dl.c, - kern/sparc64/ieee1275/init.c, kern/sparc64/ieee1275/openfw.c and - util/powerpc/ieee1275/misc.c. - - * include/grub/gzio.h: New file. - * io/gzio.c: Likewise. - - * kern/file.c (grub_file_close): Call grub_device_close only if - FILE->DEVICE is not NULL. - - * include/grub/mm.h [!NULL] (NULL): New macro. - - * include/grub/err.h (GRUB_ERR_BAD_GZIP_DATA): New constant. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Added io/gzip.c. - (pkgdata_MODULES): Added gzio.mod. - (gzio_mod_SOURCES): New variable. - (gzio_mod_CFLAGS): Likewise. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Added io/gzip.c. - (pkgdata_MODULES): Added gzio.mod. - (gzio_mod_SOURCES): New variable. - (gzio_mod_CFLAGS): Likewise. - - * commands/cat.c: Include grub/gzio.h. - (grub_cmd_cat): Use grub_gzfile_open instead of - grub_file_open. - - * commands/cmp.c: Include grub/gzio.h. - (grub_cmd_cmp): Use grub_gzfile_open instead of - grub_file_open. - - * loader/i386/pc/multiboot.c: Include grub/gzio.h. - (grub_rescue_cmd_multiboot): Use grub_gzfile_open instead of - grub_file_open. - (grub_rescue_cmd_module): Likewise. - -2005-08-21 Vincent Pelletier - - * conf/sparc64-ieee1275.rmk (grubof_SOURCES): The first file must be - kern/sparc64/ieee1275/init.c because it contains _start. - * conf/sparc64-ieee1275.mk: Generated from conf/sparc64-ieee1275.rmk. - -2005-08-21 Vincent Pelletier - - * configure.ac: Add support for sparc64 host with ieee1275 - firmware. - * configure: Generated from configure.ac. - * disk/ieee1275/ofdisk.c (grub_ofdisk_open): Use grub_ssize_t - instead of int. - (grub_ofdisk_read): Likewise. - (grub_ofdisk_open): Use %p to print pointer values, and cast the - pointers as (void *) to remove a warning. - (grub_ofdisk_close): Likewise. - (grub_ofdisk_read): Likewise. - * kern/ieee1275/ieee1275.c (grub_ieee1275_exit): This never - returns, so make it return void to remove a warning. - * include/grub/ieee1275/ieee1275.h (grub_ieee1275_exit): - Corresponding prototype change. - * kern/mm.c (grub_mm_init_region): Use %p to print pointer - values, and cast the pointers as (void *) to remove a warning. - (grub_mm_dump): Likewise. - * conf/sparc64-ieee1275.mk: New file. - * conf/sparc64-ieee1275.rmk: Likewise. - * include/grub/sparc64/setjmp.h: Likewise. - * include/grub/sparc64/types.h: Likewise. - * include/grub/sparc64/ieee1275/console.h: Likewise. - * include/grub/sparc64/ieee1275/ieee1275.h: Likewise. - * include/grub/sparc64/ieee1275/kernel.h: Likewise. - * include/grub/sparc64/ieee1275/time.h: Likewise. - * kern/sparc64/cache.c: Likewise. - * kern/sparc64/dl.c: Likewise. - * kern/sparc64/ieee1275/init.c: Likewise. - * kern/sparc64/ieee1275/openfw.c: Likewise. - -2005-08-21 Yoshinori K. Okuji - - * util/console.c (grub_ncurses_putchar): If C is greater than - 0x7f, set C to a question mark. - (grub_ncurses_getcharwidth): New function. - (grub_ncurses_term): Specify grub_ncurses_getcharwidth as - getcharwidth. - - * normal/menu.c (print_entry): Made aware of Unicode. First, - convert TITLE to UCS-4, and predict the cursor position by - grub_getcharwidth. - - * include/grub/misc.h (grub_utf8_to_ucs4): Specify the qualifier - const to SRC. - * kern/misc.c (grub_utf16_to_utf8): Likewise. - -2005-08-20 Yoshinori K. Okuji - - * loader/powerpc/ieee1275/linux.c (grub_rescue_cmd_linux): Specify - the boot file by the option BOOT_IMAGE. Use grub_stpcpy instead of - grub_strcat. - - * loader/i386/pc/linux.c (grub_rescue_cmd_linux): Specify the boot - file by the option BOOT_IMAGE. Use grub_stpcpy instead of - grub_strcpy and grub_strlen. Take it into account that a space - character is inserted as a delimiter. - -2005-08-20 Yoshinori K. Okuji - - * partmap/pc.c (pc_partition_map_iterate): Include the value of an - invalid magic in the error. - - * commands/search.c: New file. - - * util/grub-emu.c (main): Call grub_search_init and - grub_search_fini. - - * kern/rescue.c (grub_rescue_print_disks): Removed. - (grub_rescue_print_devices): New function. - (grub_rescue_cmd_ls): Use grub_device_iterate with - grub_rescue_print_devices instead of grub_disk_dev_iterate with - grub_rescue_print_disks. - - * kern/partition.c (grub_partition_iterate): Return the result of - PARTMAP->ITERATE instead of GRUB_ERRNO. - - * kern/device.c: Include grub/partition.h. - (grub_device_iterate): New function. - - * include/grub/partition.h (grub_partition_iterate): Return int - instead of grub_err_t. - - * include/grub/normal.h [GRUB_UTIL] (grub_search_init): New - prototype. - [GRUB_UTIL] (grub_search_fini): Likewise. - - * include/grub/device.h (grub_device_iterate): New prototype. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Added - commands/search.c. - (pkgdata_MODULES): Added search.mod. - (search_mod_SOURCES): New variable. - (search_mod_CFLAGS): Likewise. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Added commands/search.c. - (pkgdata_MODULES): Added search.mod. - (search_mod_SOURCES): New variable. - (search_mod_CFLAGS): Likewise. - - * commands/ls.c (grub_ls_list_disks): Renamed to ... - (grub_ls_list_devices): ... this, and use grub_device_iterate. - All callers changed. - - * DISTLIST: Added commands/search.c. - -2005-08-20 Yoshinori K. Okuji - - * kern/term.c (grub_putchar): Use grub_utf8_to_ucs4 for the - conversion. - (grub_getcharwidth): New function. - - * kern/misc.c (grub_utf8_to_ucs4): New function. - - * include/grub/term.h (struct grub_term): Added a new member - "getcharwidth". - (grub_getcharwidth): New prototype. - - * include/grub/misc.h (grub_utf8_to_ucs4): New prototype. - - * term/i386/pc/console.c (map_char): New function. Segregated from - grub_console_putchar. - (grub_console_putchar): Use map_char. - (grub_console_getcharwidth): New function. - (grub_console_term): Specified grub_console_getcharwidth as - getcharwidth. - - * term/i386/pc/vga.c (grub_vga_getcharwidth): New function. - (grub_vga_term): Specified grub_vga_getcharwidth as getcharwidth. - - * term/i386/pc/vesafb.c (grub_virtual_screen_setup): Return - GRUB_ERRNO. - (grub_vesafb_init): Do not use RC. Instead, use GRUB_ERRNO. Rely - on grub_strtoul completely. - (write_char): Declare local variables in the beginning of the - function. - (grub_vesafb_getcharwidth): New function. - (grub_vesafb_term): Specified grub_vesafb_getcharwidth as - getcharwidth. - -2005-08-19 Yoshinori K. Okuji - - * DISTLIST: Replace commands/i386/pc/vbe_list_modes.c and - commands/i386/pc/vbe_test.c with commands/i386/pc/vbeinfo.c and - commands/i386/pc/vbetest.c. - - * video/i386/pc/vbe.c (grub_vbe_probe): If INFOBLOCK is not NULL, - call grub_vbe_get_controller_info again, because the returned - information is volatile. - (grub_vbe_set_video_mode): Mostly rewritten. - (grub_vbe_get_video_mode): Use grub_vbe_probe and use - grub_vbe_status_t correctly. - (grub_vbe_get_video_mode_info): Likewise. - (grub_vbe_set_pixel_rgb): Use a switch statement rather than - several if statements. - - * commands/i386/pc/vbe_list_modes.c: Renamed to ... - * commands/i386/pc/vbeinfo.c: ... this. - - * commands/i386/pc/vbe_test.c: Renamed to ... - * commands/i386/pc/vbetest.c: ... this. - - * commands/i386/pc/vbeinfo.c (grub_cmd_vbe_list_modes): Renamed to - ... - (grub_cmd_vbeinfo): ... this. Save video modes before - iterating. Skip a video mode, if it is not available, not enough - information is given or it is monochrome. Show the memory - model. Leave the interpretation of MODEVAR to grub_strtoul - completely. - (GRUB_MOD_INIT): Rename vbe_list_modes to vbeinfo. - (GRUB_MOD_FINI): Likewise. - - * commands/i386/pc/vbetest.c (grub_cmd_vbe_test): Renamed to ... - (grub_cmd_vbetest): ... this. Don't print unnecessarily. Use - grub_err_t instead of grub_uint32_t. Don't use SPTR. Remove a - duplicated grub_env_get. Leave the interpretation of MODEVAR to - grub_strtoul completely. - (real2pm): Removed. - (GRUB_MOD_INIT): Rename vbe_test to vbetest. - (GRUB_MOD_FINI): Likewise. - - * normal/misc.c: Include grub/mm.h. - - * conf/i386-pc.rmk (pkgdata_MODULES): Replaced vbe_test.mod and - vbe_list_modes with vbetest.mod and vbeinfo.mod. - (vbe_list_modes_mod_SOURCES): Removed. - (vbe_list_modes_mod_CFLAGS): Likewise. - (vbe_test_mod_SOURCES): Likewise. - (vbe_test_mod_CFLAGS): Likewise. - (vbeinfo_mod_SOURCES): New variable. - (vbeinfo_mod_CFLAGS): Likewise. - (vbetest_mod_SOURCES): Likewise. - (vbetest_mod_CFLAGS): Likewise. - -2005-08-18 Yoshinori K. Okuji - - * normal/misc.c: New file. - - * DISTLIST: Added normal/misc.c. - - * partmap/amiga.c (amiga_partition_map_iterate): Add an argument - DISK to HOOK. Call HOOK with DISK. - * partmap/apple.c (apple_partition_map_iterate): Likewise. - * partmap/pc.c (pc_partition_map_iterate): Likewise. - * partmap/sun.c (sun_partition_map_iterate): Likewise. - - * normal/menu_entry.c (struct screen): Added a new member - "completion_shown". - (completion_buffer): New global variable. - (make_screen): Set SCREEN->COMPLETION_SHOWN to zero. - (store_completion): New function. - (complete): Likewise. - (clear_completions): Likewise. - (grub_menu_entry_run): If SCREEN->COMPLETION_SHOWN is non-zero, - call clear_completions and reset SCREEN->COMPLETION_SHOWN. If C is - a tab, call complete. - - * normal/completion.c (disk_dev): Removed. - (print_simple_completion): Likewise. - (print_partition_completion): Likewise. - (print_func): New global variable. - (add_completion): Do not take the arguments WHAT or PRINT any - longer. Added a new argument TYPE. Instead of printing directly, - call PRINT_FUNC if not NULL. - All callers changed. - (complete_device): Use a local variable DEV instead of - DISK_DEV. Do not move CURRENT_WORD to the end of a device name. - (grub_normal_do_completion): Take a new argument HOOK. Do not - initialize DISK_DEV. Initialize PRINT_FUNC to HOOK. If RET is an - empty string, return NULL instead. - All callers changed. - - * normal/cmdline.c (print_completion): New function. - - * kern/partition.c (grub_partition_iterate): Add an argument DISK - to HOOK. - All callers changed. - - * kern/disk.c (grub_print_partinfo): Removed. - - * include/grub/partition.h (struct grub_partition_map): Add a new - argument DISK into HOOK of ITERATE. - (grub_partition_iterate): Add a new argument DISK to HOOK. - - * include/grub/normal.h (enum grub_completion_type): New enum. - (grub_completion_type_t): New type. - (GRUB_COMPLETION_TYPE_COMMAND): New constant. - (GRUB_COMPLETION_TYPE_DEVICE): Likewise. - (GRUB_COMPLETION_TYPE_PARTITION): Likewise. - (GRUB_COMPLETION_TYPE_FILE): Likewise. - (grub_normal_do_completion): Added a new argument HOOK. - (grub_normal_print_device_info): New prototype. - - * include/grub/disk.h (grub_print_partinfo): Removed. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Added normal/misc.c. - (normal_mod_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - (normal_mod_SOURCES): Likewise. - - * commands/ls.c (grub_ls_list_disks): Use - grub_normal_print_device_info instead of grub_print_partinfo. Free - PNAME. - (grub_ls_list_files): Use grub_normal_print_device_info instead of - duplicating the code. - -2005-08-16 Vesa Jaaskelainen - - * commands/i386/pc/vbe_list_modes.c: Update source formatting to - follow GCS more precisely. - * commands/i386/pc/vbe_test.c: Likewise. - * include/grub/i386/pc/vbe.h: Likewise. - * term/i386/pc/vesafb.c: Likewise. - * video/i386/pc/vbe.c: Likewise. - -2005-08-16 Vesa Jaaskelainen - - * DISTLIST: Added term/i386/pc/vesafb.c - DISTLIST: Added video/i386/pc/vbe.c - DISTLIST: Added commands/i386/pc/vbe_list_modes.c. - DISTLIST: Added commands/i386/pc/vbe_test.c. - * commands/i386/pc/vbe_list_modes.c: New file. - * commands/i386/pc/vbe_test.c: Likewise. - * term/i386/pc/vesafb.c: Likewise. - * video/i386/pc/vbe.c: Likewise. - * include/grub/i386/pc/vbe.h (GRUB_VBE_DEFAULT_VIDEO_MODE): Added define. - (grub_vbe_probe) Added prototype. - (grub_vbe_set_video_mode) Likewise. - (grub_vbe_get_video_mode) Likewise. - (grub_vbe_get_video_mode_info) Likewise. - (grub_vbe_set_pixel_rgb) Likewise. - (grub_vbe_set_pixel_index) Likewise. - * conf/i386-pc.rmk (pkgdata_MODULES): Added vbe.mod. - (pkgdata_MODULES): Added vesafb.mod. - (pkgdata_MODULES): Added vbe_list_modes.mod. - (pkgdata_MODULES): Added vbe_test.mod. - (vbe_mod_SOURCES): Added. - (vbe_mod_CFLAGS): Likewise. - (vesafb_mod_SOURCES): Likewise. - (vesafb_mod_CFLAGS): Likewise. - (vbe_list_modes_mod_SOURCES): Likewise. - (vbe_list_modes_mod_CFLAGS): Likewise. - (vbe_test_mod_SOURCES): Likewise. - (vbe_test_mod_CFLAGS): Likewise. - -2005-08-14 Yoshinori K. Okuji - - * normal/command.c (grub_command_execute): If INTERACTIVE is - false and GRUB_COMMAND_FLAG_NO_ECHO is not specified, print - CMDLINE. Disable the pager if INTERACTIVE is true. - All callers are changed. - - * normal/main.c (grub_normal_execute): Read command.lst and fs.lst - before reading a config file. - * normal/main.c (read_config_file): Even if a command is not - found, register it if it is within an entry. - - * util/grub-emu.c: Include sys/types.h and unistd.h. - (options): Added --hold. - (struct arguments): Added a new member "hold". - (parse_opt): If KEY is 'H', set ARGS->HOLD to ARG or -1 if ARG is - missing. - (main): Initialize ARGS.HOLD to zero. Wait until ARGS.HOLD is - cleared by a debugger, if it is not zero. - - * include/grub/normal.h (grub_command_execute): Add an argument - INTERACTIVE. - -2005-08-14 Vesa Jaaskelainen - - * DISTLIST: Added include/grub/i386/pc/vbe.h. - -2005-08-13 Yoshinori K. Okuji - - * aclocal.m4 (grub_I386_CHECK_REGPARM_BUG): Replace the test - program with another one, because the old one didn't detect a bug - in gcc-3.4. Always use regparm 2, because the new test is still - not enough for gcc-4.0. Someone must investigate a simple test - case which detects a bug in gcc-4.0. - -2005-08-12 Yoshinori K. Okuji - - * DISTLIST: Added normal/completion.c. - - * normal/completion.c: New file. - - * term/i386/pc/console.c (grub_console_getwh): New function. - (grub_console_term): Assign grub_console_getwh to getwh. - - * normal/cmdline.c (grub_tab_complete): Removed. Now the same - function is defined in normal/completion.c as - grub_normal_do_completion. - (grub_cmdline_get): Use grub_normal_do_completion instead of - grub_tab_complete. - - * kern/partition.c (grub_partition_map_iterate): Return 1 if HOOK - returns non-zero, otherwise return 0. - (grub_partition_iterate): First, probe the partition map. Then, - call ITERATE only for this partition map. - - * kern/misc.c (grub_strncmp): Rewritten. - - * kern/disk.c (grub_disk_dev_iterate): Return 1 if P->ITERATE - returns non-zero. Otherwise return 0. - - * include/grub/partition.h (grub_partition_map_iterate): Return - int instead of void. - - * include/grub/normal.h (grub_normal_do_completion): New prototype. - - * include/grub/misc.h (grub_strncmp): Change the type of N to - grub_size_t. - - * include/grub/disk.h (grub_disk_dev_iterate): Return int instead - of void. - - * normal/menu.c (draw_border): Cast GRUB_TERM_BORDER_WIDTH to - unsigned explicitly before comparing it with I. - - * kern/main.c (grub_env_write_root): Add the attribute unused into - VAR. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Added - normal/completion.c. - (normal_mod_SOURCES): Likewise. - * conf/i386-pc.rmk (grub_emu_SOURCES): Likewise. - (normal_mod_SOURCES): Likewise. - - * normal/command.c (grub_iterate_commands): If ITERATE returns - non-zero, return one immediately. - -2005-08-09 Vesa Jaaskelainen - - * conf/i386-pc.rmk (kernel_img_HEADERS): Added machine/vbe.h. - * kern/i386/pc/startup.S: Updated Global Descriptor table's - descriptions. - (grub_vbe_get_controller_info): New function. - (grub_vbe_get_mode_info): Likewise. - (grub_vbe_set_mode): Likewise. - (grub_vbe_get_mode): Likewise. - (grub_vbe_set_memory_window): Likewise. - (grub_vbe_get_memory_window): Likewise. - (grub_vbe_set_scanline_length): Likewise. - (grub_vbe_get_scanline_length): Likewise. - (grub_vbe_set_display_start): Likewise. - (grub_vbe_get_display_start): Likewise. - (grub_vbe_set_palette_data): Likewise. - * include/grub/i386/pc/vbe.h: New file. - -2005-08-08 Hollis Blanchard - - * conf/powerpc-ieee1275.rmk (grubof_SOURCES): Replaced - kern/ieee1275/of.c with kern/ieee1275/ieee1275.c. - * DISTLIST: Likewise. - * kern/ieee1275/of.c: Moved to ... - * kern/ieee1275/ieee1275.c: ... here. - -2005-08-08 Hollis Blanchard - - * term/ieee1275/ofconsole.c: Include . - (grub_ofconsole_getwh): Cast -1 to type grub_ieee1275_ihandle_t. - Pass 0 as `end' parameter to grub_strtoul(). - -2005-08-08 Hollis Blanchard - - * include/grub/powerpc/ieee1275/console.h: Do not include - . Do not include . Remove ASM_FILE - ifdef. - (grub_console_cur_color): Remove i386-specific prototype. - (grub_console_real_putchar): Likewise. - (grub_console_checkkey): Likewise. - (grub_console_getkey): Likewise. - (grub_console_getxy): Likewise. - (grub_console_gotoxy): Likewise. - (grub_console_cls): Likewise. - (grub_console_setcursor): Likewise. - * kern/powerpc/ieee1275/init.c: Don't include . - Include . - * term/ieee1275/ofconsole.c: Likewise. - -2005-08-08 Yoshinori K. Okuji - - * Makefile.in (LIBLZO): New variable. - - * configure.ac: Check for LZO version 2. - - * util/i386/pc/grub-mkimage.c [HAVE_LZO_LZO1X_H]: Include - lzo/lzo1x.h instead of lzo1x.h. - - * conf/i386-pc.rmk (grub_mkimage_LDFLAGS): Use $(LIBLZO) instead - of -llzo. - - * util/i386/pc/grub-setup.c (main): Do not free PREFIX - twice. Reported by Vladimir Serbinenko . - - * partmap/pc.c (pc_partition_map_probe): Restore P->DATA after - copying the data from PARTITION to P. - -2005-08-07 Yoshinori K. Okuji - - * kern/rescue.c (grub_rescue_cmd_rmmod): If the reference count is - negative, unload the module. - - * util/i386/pc/grub-setup.c (setup): The name of the PC partition - map is "pc_partition_map" but not "pc". - (usage): Fix the description. The options are --boot-image and - --core-image but not --boot-file or --core-file. - (main): If not specified explicitly, make BOOT_FILE and CORE_FILE - based on DEFAULT_BOOT_FILE and DEFAULT_CORE_FILE with DIR or - DEFAULT_DIRECTORY. - - * util/i386/pc/grub-install.in: Do not specify --boot-file or - --core-file. Specify INSTALL_DEVICE as an argument. - - * util/console.c: Include config.h. - [HAVE_NCURSeS_CURSES_H]: Include ncurses/curses.h. - [HAVE_NCURSES_H]: Include ncurses.h. - [HAVE_CURSES_H]: Include curses.h. - [!A_NORMAL] (A_NORMAL): Defined as zero. - [!A_STANDOUT] (A_STANDOUT): Likewise. - - * conf/i386-pc.rmk (grub_emu_LDFLAGS): Use $(LIBCURSES) instead of - -lncurses. - * conf/powerpc-ieee1275.rmk (grub_emu_LDFLAGS): Likewise. - - * configure.ac: Check for curses libraries and headers. - - * Makefile.in (LIBCURSES): New variable. - - * genmk.rb (Script::rule): Set the executable bits. - - * util/i386/pc/biosdisk.c (grub_util_biosdisk_get_grub_dev): The - name of the PC partition map is "pc_partition_map" but not "pc". - -2005-08-07 Yoshinori K. Okuji - - * util/i386/pc/grub-install.in (grub_probefs): New variable. - (modules): Likewise. - (usage): Added descriptions for --modules and --grub-probefs. - Handle --modules and --grub-probefs. Save the arguments in MODULES - and GRUB_PROBEFS, respectively. - Auto-detect a filesystem module against GRUBDIR. If the result is - empty and modules are not specified explicitly, abort the - installation. Add the result to MODULES. - - * DISTLIST: Removed boot/powerpc/ieee1275/ieee1275.c, - disk/powerpc/ieee1275/ofdisk.c, - include/grub/powerpc/ieee1275/init.h and - term/powerpc/ieee1275/ofconsole.c. - Added disk/ieee1275/ofdisk.c, kern/ieee1275/of.c and - term/ieee1275/ofconsole.c. - - * include/grub/powerpc/ieee1275/console.h: Resurrected. - - * COPYING: Upgraded to the latest version. Only the address of the - FSF office has changed. - -2005-08-07 Yoshinori K. Okuji - - * conf/powerpc-ieee1275.rmk (grubof_SOURCES): Replaced - kern/ieee1275.c with kern/ieee1275/of.c. - - * kern/ieee1275.c: Moved to ... - * kern/ieee1275/of.c: ... here. - -2005-08-06 Yoshinori K. Okuji - - * conf/i386-pc.rmk (kernel_img_HEADERS): Reordered for - readability. - - * config.guess: Updated to the latest version from gnulib. - * config.sub: Likewise. - * install.sh: Likewise. - * mkinstalldirs: Likewise. - - * include/grub/console.h: Removed. This file is arch-specific. Do - not put this in include/grub. - - * include/grub/i386/pc/console.h: Resurrected. - - * util/console.c: Include grub/machine/console.h instead of - grub/console.h. - * util/grub-emu.c: Likewise. - -2005-08-04 Marco Gerards - - * kern/term.c (grub_putcode): Use `grub_getwh' instead of - hardcoded value. - - From Vincent Pelletier - * include/grub/term.h (GRUB_TERM_WIDTH, GRUB_TERM_HEIGHT): - Redefined to use grub_getwh. - (grub_term): New member named getwh. - (grub_getwh): New prototype. - * kern/term.c (grub_getwh): New function. - * term/i386/pc/console.c (grub_console_getwh): New function. - (grub_console_term): New member `getwh'. - * term/i386/pc/vga.c (grub_vga_getwh): New function. - (grub_vga_term): New member `getwh'. - * term/ieee1275/ofconsole.c (grub_ofconsole_readkey): Use - grub_ssize_t. - (grub_ofconsole_getw): New function. - (grub_ofconsole_init): Use grub_ssize_t and unsigned char. - (grub_ofconsole_term): New field named getwh and new initial - value. - -2005-08-03 Hollis Blanchard - - * include/grub/powerpc/ieee1275/ieee1275.h: Move ... - * include/grub/ieee1275/ieee1275.h: ... to here. All users updated. - Move `abort', `grub_reboot', and `grub_halt' prototypes ... - * include/grub/powerpc/ieee1275/kernel.h: ... to here. - * commands/ieee1275/halt.c: Include instead - of . - * commands/ieee1275/reboot.c: Likewise. - * boot/powerpc/ieee1275/ieee1275.c: Move ... - * kern/ieee1275.c: ... to here. All users updated. Change all - parameter structs to use new type `grub_ieee1275_cell_t'. - * term/powerpc/ieee1275/ofconsole.c: Move ... - * term/ieee1275/ofconsole.c: ... to here. All users updated. - * disk/powerpc/ieee1275/ofdisk.c: Move ... - * disk/ieee1275/ofdisk.c: ... to here. All users updated. - * boot/powerpc/ieee1275/cmain.c: Change `grub_ieee1275_entry_fn' type - to return int. - * include/grub/i386/pc/console.h: Move to include/grub/console.h. - Remove unused prototypes. All users updated. - * include/grub/powerpc/ieee1275/console.h: Removed. - * include/grub/powerpc/ieee1275/ieee1275.h: Define - `grub_ieee1275_cell_t'. - * kern/powerpc/ieee1275/openfw.c: Include . - Cast comparisons with -1 to the correct type. - * loader/powerpc/ieee1275/linux.c (kernel_entry_t): Change parameter - type to match `grub_ieee1275_entry_fn'. - -2005-08-01 Yoshinori K. Okuji - - * DISTLIST: Added util/i386/pc/grub-probefs.c. - - * conf/i386-pc.rmk (sbin_UTILITIES): Added grub-probefs. - (grub_setup_SOURCES): Removed partmap/amiga.c, partmap/apple.c and - partmap/sun.c. - (grub_probefs_SOURCES): New variable. - - * util/i386/pc/grub-probefs.c: New file. - - * util/i386/pc/grub-setup.c (main): Call - grub_pc_partition_map_init, grub_ufs_init, grub_minix_init, - grub_hfs_init and grub_jfs_init to initialize the system. Call - grub_ufs_fini, grub_minix_fini, grub_hfs_fini, grub_jfs_init and - grub_pc_partition_map_fini to finish the system. - -2005-07-31 Yoshinori K. Okuji - - * loader/i386/pc/multiboot.c (grub_multiboot_is_elf32): New - function. - (grub_multiboot_load_elf32): Likewise. - (grub_multiboot_is_elf64): Likewise. - (grub_multiboot_load_elf64): Likewise. - (grub_multiboot_load_elf): Likewise. - (grub_rescue_cmd_multiboot): Call grub_multiboot_load_elf to load - an ELF32 or ELF64 file. - This is based on a patch from Ruslan Nikolaev . - - From Serbinenko Vladimir : - * kern/disk.c (grub_print_partinfo): Check if FS->LABEL is not - NULL before calling FS->LABEL. - * fs/fat.c (grub_fat_dir): Initialize DIRNAME to NULL. - * commands/ls.c (grub_ls_list_files): Show labels, if possible. - (grub_ls_list_disks): Check if FS and FS->LABEL are not NULL - before calling FS->LABEL. - -2005-07-26 Yoshinori K. Okuji - - * util/i386/pc/grub-install.in (datadir): New variable. - (libdir): Removed. - (pkgdatadir): New variable. - (pkglibdir): Removed. - -2005-07-24 Yoshinori K. Okuji - - * DISTLIST: Added util/i386/pc/grub-install.in. - - * util/i386/pc/grub-install.in: New file. - - * conf/i386-pc.rmk (sbin_SCRIPTS): New variable. - (grub_install_SOURCES): Likewise. - - * genmk.rb: Added support for scripts. - (Script): New class. - (scripts): New variable. - - * Makefile.in (install-local): Install sbin_SCRIPTS by - INSTALL_SCRIPT. - (uninstall): Remove sbin_SCRIPTS. - - * util/i386/pc/grub-setup.c (main): If the argument is not a GRUB - device, try to get a GRUB device by - grub_util_biosdisk_get_grub_dev. - Free DEST_DEV. - - * util/i386/pc/grub-mkdevicemap.c (usage): Remove a duplicated - description for --device-map. - -2005-07-20 Yoshinori K. Okuji - - Change the semantics of variable hooks. They now return strings - instead of error values. - - * util/i386/pc/grub-setup.c: Include grub/env.h. - (setup): Use grub_device_set_root instead of grub_env_set. - - * kern/rescue.c (grub_rescue_cmd_root): Use grub_env_set and - grub_env_get instead of grub_device_set_root and - grub_device_get_root, respectively. - - * kern/main.c (grub_env_write_root): New function. - (grub_set_root_dev): Register grub_env_write_hook for "root". Use - grub_env_set instead of grub_device_set_root. - - * kern/env.c (HASHSZ): Reduced to 13, because GRUB does not need - many variables. - (grub_env_set): Set ENV->VALUE to the result of ENV->WRITE_HOOK - rather than calling ENV->WRITE_HOOK afterwards. - (grub_env_get): Return the result of ENV->READ_HOOK rather than - passing a pointer of a pointer. - (grub_register_variable_hook): Change the types of "read_hook" and - "write_hook" to grub_env_read_hook_t and grub_env_write_hook_t, - respectively. - Allocate the default empty string on the heap, because this string - may be freed later. - - * kern/device.c: Include grub/env.h. - (grub_device_set_root): Removed. - (grub_device_get_root): Likewise. - (grub_device_open): Use grub_env_get instead of - grub_device_get_root. - - * include/grub/env.h (grub_env_read_hook_t): New type. - (grub_env_write_hook_t): Likewise. - (grub_env_var): Change the types of "read_hook" and "write_hook" - to grub_env_read_hook_t and grub_env_write_hook_t, respectively. - (grub_register_variable_hook): Likewise. - - * include/grub/device.h (grub_device_set_root): Removed. - (grub_device_set_root): Likewise. - - * fs/fat.c (grub_fat_dir): Make a copy of PATH in DIRNAME, and - make sure that DIRNAME terminates with '/', so that - grub_fat_find_dir will fail if PATH is not a directory. - - * commands/ls.c (grub_ls_list_files): Remove the qualifier const - from DIRNAME. - Use the qualifier auto for print_files and print_files_long. - If FS->DIR sets GRUB_ERRNO to GRUB_ERR_BAD_FILE_TYPE, try DIRNAME - as a regular file. - Put a newline only if there is no error. - (grub_cmd_ls): Remove grub_ls_print_files, because this is not - used. - -2005-07-20 Yoshinori K. Okuji - - * kern/partition.c (grub_partition_probe): Initialize PART to - NULL. Otherwise, when no partition map is registered, this returns - a garbage. - -2005-07-19 Yoshinori K. Okuji - - * partmap/apple.c (apple_partition_map_iterate): Check if POS - equals GRUB_DISK_SECTOR_SIZE to see if the partition table is - valid. - -2005-07-18 Yoshinori K. Okuji - - * commands/ls.c (grub_ls_list_disks): Print the filesystem - information on each device, if it does not have partitions. Print - "Device" instead of "Disk", because this function is not specific - to disk devices. - - * normal/main.c (grub_rescue_cmd_normal): Make the variable CONFIG - static to ensure that it is put on the memory rather than a - register. - -2005-07-17 Yoshinori Okuji - - * commands/cat.c (GRUB_MOD_INIT): Use better documentation. - (grub_cat_init): Likewise. - * loader/i386/pc/chainloader_normal.c (GRUB_MOD_INIT): Likewise. - (options): Likewise. - * commands/configfile.c (GRUB_MOD_INIT): Likewise. - (grub_configfile_init): Likewise. - * font/manager.c (GRUB_MOD_INIT): Likewise. - * commands/help.c (GRUB_MOD_INIT): Likewise. - (grub_help_init): Likewise. - * normal/command.c (grub_command_init): Likewise. - * loader/i386/pc/linux_normal.c (GRUB_MOD_INIT): Likewise. - * disk/loopback.c (grub_loop_init): Likewise. - (GRUB_MOD_INIT): Likewise. - * commands/ls.c (grub_ls_init): Likewise. - (GRUB_MOD_INIT): Likewise. - (options): Likewise. - * commands/boot.c (grub_boot_init): Likewise. - (GRUB_MOD_INIT): Likewise. - * loader/i386/pc/multiboot_normal.c (GRUB_MOD_INIT): Likewise. - * commands/i386/pc/reboot.c (grub_reboot_init): Likewise. - (GRUB_MOD_INIT): Likewise. - * commands/cmp.c (grub_cmp_init): Likewise. - (GRUB_MOD_INIT): Likewise. - - * normal/arg.c: Use <> instead of "" to include header files. - (SHORT_ARG_HELP): New macro. - (SHORT_ARG_USAGE): Likewise. - (help_options): Specify SHORT_ARG_HELP and SHORT_ARG_USAGE instead - of 'h' and 'u' for help and usage, respectively. Use more GNU-like - descriptions. - (find_short): Check if C is 'h' or 'u' explicitly. - (grub_arg_show_help): Use space characters instead of tabs. Treat - SHORT_ARG_HELP and SHORT_ARG_USAGE exceptionally so that -h and -u - are shown with --help and --usage only if they are not used for - the command itself. - (parse_option): Use SHORT_ARG_HELP and SHORT_ARG_USAGE instead of - 'h' and 'u'. - - * include/grub/arg.h (struct grub_arg_option): Add the qualifier - const into "longarg". Change the type of "shortarg" to int. - -2005-07-17 Yoshinori Okuji - - * boot/i386/pc/boot.S (boot_drive_check): New label. - - * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_DRIVE_CHECK): New - macro. - - * util/i386/pc/grub-setup.c (setup): Added a workaround for BIOSes - which do not pass a boot drive correctly. Copied from GRUB Legacy. - -2005-07-17 Yoshinori Okuji - - * kern/i386/pc/startup.S (gate_a20_try_system_control_port_a): - When turning off Gate A20, skip the check and return immediately, - because this is not fatal usually. - -2005-07-17 Yoshinori Okuji - - * conf/i386-pc.rmk (pxeboot_img_LDFLAGS): The text address should - be 0x7C00 instead of 0x8000. - - * boot/i386/pc/pxeboot.S: Rewritten. - - * kern/i386/pc/startup.S (gate_a20_try_bios): No need to specify - EXT_C. - (gate_a20_check_state): Read a byte from 0x108000. Invert the - result. - -2005-07-16 Yoshinori K. Okuji - - * kern/i386/pc/startup.S (grub_gate_a20): Rewritten for - robustness. This routine now supports a BIOS call and System - Control Port A to modify the gate A20. - - * include/grub/i386/pc/kernel.h (GRUB_KERNEL_MACHINE_RAW_SIZE): - Increased to 0x440. - -2005-07-12 Hollis Blanchard - - * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_open): dprintf the - device path and resulting ihandle. - (grub_ofdisk_close): dprintf the ihandle being closed. - (grub_ofdisk_read): dprintf function parameters. - * kern/mm.c (grub_mm_init_region): Likewise. - * loader/powerpc/ieee1275/linux.c: Remove extra whitespace. - (grub_linux_boot): dprintf the Linux entry point, initrd address and - size, and boot arguments. - (grub_rescue_cmd_linux): dprintf each ELF segment's address and size - before loading into memory. - (grub_rescue_cmd_initrd): dprintf the initrd's address and size - before loading into memory. - -2005-07-12 Yoshinori K. Okuji - - * kern/mm.c: Added much documentation. - (GRUB_MM_ALIGN_LOG2): When GRUB_CPU_SIZEOF_VOID_P is - 8, set to 5 instead of 8. - -2005-07-10 Yoshinori Okuji - - * DISTLIST: Added util/i386/pc/grub-mkimage.c. - - * conf/i386-pc.rmk (sbin_UTILITIES): Added grub-mkdevicemap. - (grub_mkdevicemap_SOURCES): New variable. - - * util/i386/pc/grub-mkdevicemap.c: New file. Mostly copied from - lib/device.c of GRUB Legacy. - -2005-07-10 Yoshinori Okuji - - * commands/ls.c (grub_ls_list_files): Check if *PATH is NUL - instead of PATH is NULL. - -2005-07-09 Vincent Pelletier - - * commands/cmp.c (BUFFER_SIZE): New macro. - (grub_cmd_cmp): Close the right file at the right time. Compare - only data just read. Don't report files of different size as - identical. Dynamically allocate buffers. Move variable - declarations at the beginning of function. - -2005-07-09 Yoshinori Okuji - - * aclocal.m4 (grub_I386_CHECK_REGPARM_BUG): The return value was - reverse. - -2004-07-04 Vincent Pelletier - - * normal/cmdline.c (grub_cmdline_get): Don't fallback on ctrl-d - when backspace is pressed at beginning of line. - -2005-07-03 Yoshinori Okuji - - * DISTLIST: Added genfslist.sh. - - * normal/main.c (fs_module_list): New variable. - (autoload_fs_module): New function. - (read_fs_list): Likewise. - (grub_normal_execute): Call read_fs_list. - - * kern/fs.c (grub_fs_autoload_hook): New variable. - (grub_fs_probe): Added support for auto-loading. - - * include/grub/normal.h (struct grub_fs_module_list): New struct. - (grub_fs_module_list_t): New type. - - * include/grub/fs.h (grub_fs_autoload_hook_t): New type. - (grub_fs_autoload_hook): New prototype. - - * genfslist.sh: New file. - - * genmk.rb: Added a rule to generate a filesystem list. - -2005-06-30 Marco Gerards - - * configure.ac: Fix the test for cross-compiling. - - * genmk.rb (Program): Use `$(CC)' instead of `$(BUILD_CC)'. Don't - define GRUB_UTIL anymore. - - * util/powerpc/ieee1275/grub-mkimage.c (load_note): Endian fixes - so this function works on other systems than just big endian. - (load_modules): Likewise. - (add_segments): Likewise. - -2005-06-23 Hollis Blanchard - - * kern/misc.c (grub_vsprintf): Add `longfmt'. If format string - contains `l' modifier, get a long from va_arg(). - -2005-06-23 Yoshinori K. Okuji - - * kern/mm.c (grub_free): If the next free block which is being - merged is the first free block, set the first block to the block - being freed. - Reported by Vincent Guffens . - -2005-05-08 Hollis Blanchard - - * boot/powerpc/ieee1275/cmain.c (cmain): Initialize - `grub_ieee1275_chosen'. - -2005-05-08 Hollis Blanchard - - * boot/powerpc/ieee1275/cmain.c (module_info): Remove definition. - (grub_ieee1275_chosen): New variable. - (cmain): Initialize and use `grub_ieee1275_chosen' instead of - `chosen'. - * boot/powerpc/ieee1275/crt0.S (init_stack): Remove stack space. - * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_get_property): - Rename first argument to `phandle' for consistency. - (grub_ieee1275_get_property_length): Likewise. - (grub_ieee1275_next_property): Likewise. Change type of first argument - to grub_ieee1275_phandle_t. - * include/grub/powerpc/ieee1275/ieee1275.h (grub_ieee1275_entry_fn): - Move export next to declaration. - (grub_ieee1275_chosen): New variable. - * include/grub/powerpc/ieee1275/kernel.h (GRUB_IEEE1275_MODULE_BASE): - Correct cosmetic typo. - * kern/powerpc/ieee1275/init.c (grub_set_prefix): Use - `grub_ieee1275_chosen'. - * kern/powerpc/ieee1275/openfw.c (grub_map): Likewise. - * loader/powerpc/ieee1275/linux.c (grub_linux_boot): Likewise. - (grub_rescue_cmd_linux): Set `initrd_addr' to 0. - * term/powerpc/ieee1275/ofconsole.c (grub_ofconsole_refresh): Use - `grub_ieee1275_chosen'. - -2005-05-10 Hollis Blanchard - - * boot/powerpc/ieee1275/cmain.c (cmain): Remove code to parse - /chosen/bootargs. - * kern/powerpc/ieee1275/init.c (grub_machine_init): Parse - /chosen/bootargs as "variable=value" pairs. - -2005-05-08 Vincent Pelletier - - * include/grub/misc.h (grub_dprintf): New macro. - (grub_real_dprintf): New prototype. - (grub_strword): Likewise. - (grub_iswordseparator): Likewise. - * kern/misc.c (grub_real_dprintf): New function. - (grub_strword): Likewise. - (grub_iswordseparator): Likewise. - -2005-04-30 Hollis Blanchard - - * boot/powerpc/ieee1275/cmain.c: Don't include grub/machine/init.h. - (roundup): Remove macro. - (grub_ieee1275_flags): Make static. - (grub_ieee1275_realmode): Remove. - (grub_ieee1275_test_flag): New function. - (grub_ieee1275_set_flag): Likewise. - (find_options): Rename to `grub_ieee1275_find_options'; update - callers. Set GRUB_IEEE1275_FLAG_REAL_MODE and - GRUB_IEEE1275_FLAG_0_BASED_PARTITIONS. - (cmain): New prototype. - (cmain): Use `grub_ieee1275_set_flag' instead of accessing - `grub_ieee1275_flags' directly. - * conf/powerpc-ieee1275.rmk (grubof_HEADERS): Remove - machine/biosdisk.h. - * disk/powerpc/ieee1275/ofdisk.c: Include grub/machine/ofdisk.h. - Don't include grub/machine/init.h. - (grub_ofdisk_open): Call `grub_ieee1275_test_flag'. - * include/grub/powerpc/ieee1275/ieee1275.h (grub_ieee1275_flags): - Remove prototype. - (grub_ieee1275_realmode): Likewise. - (grub_ieee1275_flag): New enum. - (grub_ieee1275_test_flag): New prototype. - (grub_ieee1275_set_flag): New prototype. - * include/grub/powerpc/ieee1275/init.h: Remove file. - * include/grub/powerpc/ieee1275/ofdisk.h: New file. - * kern/powerpc/ieee1275/init.c: Don't include grub/machine/init.h. - Include grub/machine/console.h. Include grub/machine/ofdisk.h. - (grub_machine_fini): Don't call `grub_ieee1275_release'. Remove - comment. - * kern/powerpc/ieee1275/openfw.c (grub_claimmap): Call - `grub_ieee1275_test_flag'. - (grub_ieee1275_encode_devname): Likewise. - -2005-04-21 Hollis Blanchard - - * include/grub/powerpc/ieee1275/ieee1275.h - (grub_ieee1275_encode_devname): New prototype. - (grub_ieee1275_get_filename): Likewise. - * kern/powerpc/ieee1275/init.c (grub_translate_ieee175_path): New - function. - (grub_set_prefix): Likewise. - (grub_machine_init): Call grub_set_prefix. - * kern/powerpc/ieee1275/openfw.c: Fix typos. - (grub_parse_type): New enum. - (grub_ieee1275_get_devargs): New function. - (grub_ieee1275_get_devname): Likewise. - (grub_ieee1275_parse_args): Likewise. - (grub_ieee1275_get_filename): Likewise. - (grub_ieee1275_encode_devname): Likewise. - -2005-03-30 Marco Gerards - - * kern/powerpc/ieee1275/init.c (grub_machine_fini): Don't call - `grub_loader_unset'. - -2005-03-26 Hollis Blanchard - - * commands/ieee1275/halt.c (grub_cmd_halt): Call grub_halt - instead of grub_ieee1275_interpret. - (grub_halt_init): New function. - (grub_halt_fini): Likewise. - (GRUB_MOD_INIT): Correct message grammar. - * commands/ieee1275/reboot.c (grub_cmd_reboot): Call grub_reboot - instead of grub_ieee1275_interpret. - (grub_reboot_init): New function. - (grub_reboot_fini): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Replace - commands/i386/pc/halt.c, commands/i386/pc/reboot.c, and - util/i386/pc/misc.c with commands/ieee1275/halt.c, - commands/ieee1275/reboot.c, and util/powerpc/ieee1275/misc.c. - * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_fini): New - function. - * include/grub/powerpc/ieee1275/console.h (grub_console_fini): - Add prototype. - * include/grub/powerpc/ieee1275/ieee1275.h (grub_reboot): Add - prototype. - (grub_halt): Likewise. - * include/grub/powerpc/ieee1275/init.h: Remove inaccurate comment. - (cmain): Remove __attribute__((unused)). - * kern/powerpc/ieee1275/init.c (grub_heap_start): New variable. - (grub_heap_len): Likewise. - (grub_machine_fini): New function. - * kern/powerpc/ieee1275/openfw.c (grub_reboot): New function. - (grub_halt): Likewise. - * term/powerpc/ieee1275/ofconsole.c (grub_console_fini): New - function. - * util/powerpc/ieee1275/misc.c: New file. - -2005-03-19 Yoshinori K. Okuji - - * DISTLIST: New file. - * gendistlist.sh: Likewise. - - * Makefile.in (COMMON_DISTFILES): Removed. - (BOOT_DISTFILES): Likewise. - (CONF_DISTFILES): Likewise. - (DISK_DISTFILES): Likewise. - (FS_DISTFILES): Likewise. - (INCLUDE_DISTFILES): Likewise. - (KERN_DISTFILES): Likewise. - (LOADER_DISTFILES): Likewise. - (TERM_DISTFILES): Likewise. - (UTIL_DISTFILES): Likewise. - (DISTFILES): Likewise. - (uninstall): Uninstall files in $(pkgdata_DATA). - (DISTLIST): New target. - (distdir): Use the contents of the file DISTLIST to get a list of - distributed files. - -2005-03-18 Yoshinori K. Okuji - - * fs/fat.c (grub_fat_mount): Ignore the 3rd bit of a media - descriptor. This is ported from GRUB Legacy. - - * gencmdlist.sh: Added an extra semicolon to make it work with - old sed versions. Reported by Robert Bihlmeyer - . - -2005-03-08 Yoshinori Okuji - - Automatic loading of commands is supported. - - * normal/main.c (read_command_list): New function. - (grub_normal_execute): Call read_command_list. - - * normal/command.c (grub_register_command): Return zero or CMD. - Allocate CMD->NAME from the heap. - Initialize CMD->MODULE_NAME to zero. - Find the same name as well. If the same command is found and it is - a dummy command, overwrite members. If it is not a dummy command, - return zero. - (grub_unregister_command): Free Q->NAME and Q->MODULE_NAME. - (grub_command_find): If a dummy command is found, load a module - and retry to find a command only once. - - * normal/cmdline.c (grub_tab_complete): Call grub_command_find to - make sure that each command is loaded. - - * include/grub/normal.h (GRUB_COMMAND_FLAG_NOT_LOADED): New - macro. - (struct grub_command): Remove const from the member `name'. - Add a new member `module_name'. - (grub_register_command): Return grub_command_t. - - * commands/help.c (grub_cmd_help): Call grub_command_find to make - sure that each command is loaded. - - * genmk.rb (PModule::rule): Specify a module name without the - suffix ".mod" to gencmdlist.sh. - -2005-03-02 Yoshinori K. Okuji - - * gencmdlist.sh: New file. - - * genmk.rb (PModule::rule): Generate a rule for a command list. - Clean command.lst. - Generate command.lst from $(COMMANDFILES). - - * Makefile.in (COMMON_DISTFILES): Added gencmdlist.sh. - (DATA): Added $(pkgdata_DATA). - (install-local): Install files in $(pkgdata_DATA). - -2005-03-02 Yoshinori K. Okuji - - * term/i386/pc/vga.c (debug_command): Removed. - (GRUB_MOD_INIT): Do not register the command "debug". - - From Hollis Blanchard: - * commands/configfile.c: New file. - * conf/i386-pc.rmk (grub_emu_SOURCES): Added - commands/configfile.c. - (pkgdata_MODULES): Added configfile.mod. - (configfile_mod_SOURCES): New variable. - (configfile_mod_CFLAGS): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Added - commands/configfile.c. - (pkgdata_MODULES): Added configfile.mod. - (configfile_mod_SOURCES): New variable. - (configfile_mod_CFLAGS): Likewise. - * util/grub-emu.c (main): Call grub_configfile_init and - grub_configfile_fini. - * include/grub/normal.h [GRUB_UTIL] (grub_configfile_init): New - prototype. - [GRUB_UTIL] (grub_configfile_fini): Likewise. - -2005-02-27 Yoshinori K. Okuji - - * normal/arg.c (grub_arg_show_help): Do not show the bug report - address. - - * commands/help.c (grub_cmd_help): Do not print newlines after - the last command in print_command_help. - -2005-02-27 Yoshinori K. Okuji - - * commands/default.h: New file. - * commands/timeout.h: Likewise. - * normal/context.c: Likewise. - - * util/misc.c: Do not include sys/times.h. - Include sys/time.h and grub/machine/time.h. - (grub_get_rtc): Rewritten with gettimeofday. - - * util/grub-emu.c (main): Call grub_default_init and - grub_timeout_init before grub_normal_init, and call - grub_timeout_fini and grub_default_fini after grub_main. - - * util/console.c (grub_ncurses_checkkey): Return the read - character or -1. - - * normal/menu.c (run_menu): Set MENU->TIMEOUT to -1 once it - timeouts. - - * normal/main.c (read_config_file): Push MENU. If this fails, - print an error and wait for a user input. - Print an error only if GRUB_ERRNO is not GRUB_ERR_NONE. - If a menu is empty or an error occurs, pop MENU. - (grub_normal_execute): Pop and free MENU after grub_menu_run - returns. - - * kern/loader.c (grub_loader_boot): Call grub_machine_fini. - - * include/grub/powerpc/ieee1275/time.h [GRUB_UTIL]: Do not - include time.h. - [GRUB_UTIL] (GRUB_TICKS_PER_SECOND): Use the same definition as - without GRUB_UTIL. - * include/grub/i386/pc/time.h [GRUB_UTIL]: Do not include - time.h. - [GRUB_UTIL] (GRUB_TICKS_PER_SECOND): Use the same definition as - without GRUB_UTIL. - - * include/grub/normal.h (struct grub_menu_list): New struct. - (grub_menu_list_t): New type. - (struct grub_context): New struct. - (grub_context_t): New type. - (grub_register_command): Got rid of EXPORT_FUNC. - (grub_unregister_command): Likewise. - (grub_context_get): New prototype. - (grub_context_get_current_menu): Likewise. - (grub_context_push_menu): Likewise. - (grub_context_pop_menu): Likewise. - [GRUB_UTIL] (grub_default_init): Likewise. - [GRUB_UTIL] (grub_default_fini): Likewise. - [GRUB_UTIL] (grub_timeout_init): Likewise. - [GRUB_UTIL] (grub_timeout_fini): Likewise. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Added commands/default.c, - commands/timeout.c and normal/context.c. - (pkgdata_MODULES): Added default.mod and timeout.mod. - (normal_mod_SOURCES): Added normal/context.c. - (default_mod_SOURCES): New variable. - (default_mod_CFLAGS): Likewise. - (timeout_mod_SOURCES): Likewise. - (timeout_mod_CFLAGS): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Copied from - conf/i386-pc.rmk. - (pkgdata_MODULES): Added default.mod and timeout.mod. - (normal_mod_SOURCES): Added normal/context.c. - (default_mod_SOURCES): New variable. - (default_mod_CFLAGS): Likewise. - (timeout_mod_SOURCES): Likewise. - (timeout_mod_CFLAGS): Likewise. - - * Makefile.in (all-local): Added $(MKFILES). - -2005-02-21 Vincent Pelletier - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add `partmap/sun.c'. - (grub_emu_SOURCES): Likewise. - (pkgdata_MODULES): Add `sun.mod'. - (sun_mod_SOURCES, sun_mod_CFLAGS): New variables. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add - `partmap/sun.c'. - (pkgdata_MODULES): Add `sun.mod'. - (sun_mod_SOURCES, sun_mod_CFLAGS): New variables. - * include/grub/partition.h (grub_sun_partition_map_init): New - prototype. - (grub_sun_partition_map_fini): Likewise. - * partmap/sun.c: New file. - * util/grub-emu.c (main): Initialize and de-initialize the sun - partitionmap support. - -2005-02-19 Yoshinori K. Okuji - - This implements an Emacs-like menu entry editor. - - * normal/menu_entry.c: New file. - - * util/console.c (grub_ncurses_putchar): Translate some Unicode - characters to ASCII. - (saved_char): New variable. - (grub_ncurses_checkkey): Rewritten completely. - (grub_ncurses_getkey): Likewise. - (grub_ncurses_init): Call raw instead of cbreak. - - * normal/menu.c (print_entry): Do not put a space. - (init_page): Renamed to ... - (grub_menu_init_page): ... this. All callers changed. - (edit_menu_entry): Removed. - (run_menu): Call grub_menu_entry_run instead of edit_menu_entry. - - * normal/cmdline.c (grub_cmdline_run): Call grub_setcursor. - - * kern/misc.c (grub_vprintf): Call grub_refresh. - - * normal/menu.c (DISP_LEFT): Renamed to ... - * include/grub/term.h (GRUB_TERM_DISP_LEFT): ... this. - * normal/menu.c (DISP_UP): Renamed to ... - * include/grub/term.h (GRUB_TERM_DISP_UP): ... this. - * normal/menu.c (DISP_RIGHT): Renamed to ... - * include/grub/term.h (GRUB_TERM_DISP_RIGHT): ... this. - * normal/menu.c (DISP_DOWN): Renamed to ... - * include/grub/term.h (GRUB_TERM_DISP_DOWN): ... this. - * normal/menu.c (DISP_HLINE): Renamed to ... - * include/grub/term.h (GRUB_TERM_DISP_HLINE): ... this. - * normal/menu.c (DISP_VLINE): Renamed to ... - * include/grub/term.h (GRUB_TERM_DISP_VLINE): ... this. - * normal/menu.c (DISP_UL): Renamed to ... - * include/grub/term.h (GRUB_TERM_DISP_UL): ... this. - * normal/menu.c (DISP_UR): Renamed to ... - * include/grub/term.h (GRUB_TERM_DISP_UR): ... this. - * normal/menu.c (DISP_LL): Renamed to ... - * include/grub/term.h (GRUB_TERM_DISP_LL): ... this. - * normal/menu.c (DISP_LR): Renamed to ... - * include/grub/term.h (GRUB_TERM_DISP_LR): ... this. - * normal/menu.c (TERM_WIDTH): Renamed to ... - * include/grub/term.h (GRUB_TERM_WIDTH): ... this. - * normal/menu.c (TERM_HEIGHT): Renamed to ... - * include/grub/term.h (GRUB_TERM_HEIGHT): ... this. - * normal/menu.c (TERM_INFO_HEIGHT): Renamed to ... - * include/grub/term.h (GRUB_TERM_INFO_HEIGHT): ... this. - * normal/menu.c (TERM_MARGIN): Renamed to ... - * include/grub/term.h (GRUB_TERM_MARGIN): ... this. - * normal/menu.c (TERM_SCROLL_WIDTH): Renamed to ... - * include/grub/term.h (GRUB_TERM_SCROLL_WIDTH): ... this. - * normal/menu.c (TERM_TOP_BORDER_Y): Renamed to ... - * include/grub/term.h (GRUB_TERM_TOP_BORDER_Y): ... this. - * normal/menu.c (TERM_LEFT_BORDER_X): Renamed to ... - * include/grub/term.h (GRUB_TERM_LEFT_BORDER_X): ... this. - * normal/menu.c (TERM_BORDER_WIDTH): Renamed to ... - * include/grub/term.h (GRUB_TERM_BORDER_WIDTH): ... this. - * normal/menu.c (TERM_MESSAGE_HEIGHT): Renamed to ... - * include/grub/term.h (GRUB_TERM_MESSAGE_HEIGHT): ... this. - * normal/menu.c (TERM_BORDER_HEIGHT): Renamed to ... - * include/grub/term.h (GRUB_TERM_BORDER_HEIGHT): ... this. - * normal/menu.c (TERM_NUM_ENTRIES): Renamed to ... - * include/grub/term.h (GRUB_TERM_NUM_ENTRIES): ... this. - * normal/menu.c (TERM_FIRST_ENTRY_Y): Renamed to ... - * include/grub/term.h (GRUB_TERM_FIRST_ENTRY_Y): ... this. - * normal/menu.c (TERM_ENTRY_WIDTH): Renamed to ... - * include/grub/term.h (GRUB_TERM_ENTRY_WIDTH): ... this. - * normal/menu.c (TERM_CURSOR_X): Renamed to ... - * include/grub/term.h (GRUB_TERM_CURSOR_X): ... this. - All callers changed. - - * include/grub/normal.h: New prototype. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Added - normal/menu_entry.c. - (normal_mod_SOURCES): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Likewise. - (normal_mod_SOURCES): Likewise. - -2005-02-15 Yoshinori K. Okuji - - * include/grub/normal.h (grub_halt_init): New prototype. - (grub_halt_fini): Likewise. - (grub_reboot_init): Likewise. - (grub_reboot_fini): Likewise. - - * util/grub-emu.c: Include signal.h. - (main_env): New global variable. - (grub_machine_init): Ignore SIGINT. Otherwise grub-emu cannot - catch C-c. - (grub_machine_fini): New function. - (main): Call grub_halt_init and grub_reboot_init before - grub_main, and grub_reboot_fini and grub_halt_fini after it. - Call setjmp with MAIN_ENV to go back afterwards. - Call grub_machine_fini right before return. - - * include/grub/util/misc.h: Include setjmp.h. - (main_env): New prototype. - - * include/grub/kernel.h (grub_machine_fini): New prototype. - * include/grub/i386/pc/biosdisk.h (grub_biosdisk_fini): Likewise. - * include/grub/i386/pc/console.h (grub_console_fini): Likewise. - - * disk/i386/pc/biosdisk.c (grub_biosdisk_fini): New function. - * kern/i386/pc/init.c (grub_machine_fini): Likewise. - * term/i386/pc/console.c (grub_console_fini): Likewise. - - * util/i386/pc/misc.c: New file. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Added - util/i386/pc/misc.c, commands/i386/pc/halt.c and - commands/i386/pc/reboot.c. - -2005-02-14 Guillem Jover - - * include/grub/dl.h (grub_dl_check_header): New prototype. - (grub_arch_dl_check_header): Change return type to grub_err_t, - remove size parameter and export function. Update all callers. - * kern/dl.c (grub_dl_check_header): New function. - (grub_dl_load_core): Use `grub_dl_check_header' instead of - `grub_arch_dl_check_header'. Check ELF type. Check if sections - are inside the core. - * kern/i386/dl.c (grub_arch_dl_check_header): Remove arch - independent ELF header checks. - * kern/powerpc/dl.c (grub_arch_dl_check_header): Likewise. - * loader/i386/pc/multiboot.c (grub_rescue_cmd_multiboot): Use - `grub_dl_check_header' instead of explicit checks. Check for the - ELF type. - * loader/powerpc/ieee1275/linux.c (grub_rescue_cmd_linux): Use - `grub_dl_check_header' instead of explicit checks. Remove arch - specific ELF header checks. - - * util/grub-emu.c (grub_arch_dl_check_header): Remove the - argument SIZE. - -2005-02-13 Hollis Blanchard - - * conf/powerpc-ieee1275.rmk (pkgdata_MODULES): Add ls.mod. - * include/grub/powerpc/libgcc.h (__mulsf3): New prototype. - -2005-02-12 Hollis Blanchard - - * kern/partition.c (grub_partition_probe): Clear `grub_errno' and - return 0 if `grub_errno' is GRUB_ERR_BAD_PART_TABLE. - (part_map_iterate): Clear `grub_errno' and return 0 if - `partmap->iterate' returns GRUB_ERR_BAD_PART_TABLE. - * partmap/amiga.c (amiga_partition_map_iterate): Return - GRUB_ERR_BAD_PART_TABLE if no partition map magic is found. - * partmap/apple.c (apple_partition_map_iterate): Likewise. - -2005-02-01 Guillem Jover - - * loader/i386/pc/multiboot_normal.c (GRUB_MOD_INIT): Fix module - help info. - -2005-01-31 Marco Gerards - - * include/grub/powerpc/ieee1275/loader.h (grub_load_linux): - Removed prototype. - (grub_rescue_cmd_linux): New prototype. - (grub_rescue_cmd_initrd): Likewise. - * powerpc/ieee1275/linux.c (grub_linux_boot): Remove struct - `bi_rec'. - (grub_linux_release_mem): Release the memory for the initrd. - (grub_load_linux): Renamed from this... - (grub_rescue_cmd_linux): ...To this. Changed all callers. - Changed `entry' not to be static. Loop over memory regions to - find another one when the default fails. - (grub_rescue_cmd_initrd): New function. - (grub_linux_init): Remove function. - (grub_linux_fini): Likewise. - (GRUB_MOD_INIT): Register `initrd'. - (GRUB_MOD_FINI): Unregister `initrd'. - * powerpc/ieee1275/linux_normal.c (grub_linux_normal_init): - Function removed. - (grub_linux_normal_fini): Likewise. - (GRUB_MOD_INIT): Register `initrd'. - (GRUB_MOD_FINI): Unregister `initrd'. - -2005-01-31 Marco Gerards - - * commands/help.c: New file. - * normal/arg.c (show_help): Renamed to... - (grub_arg_show_help): ... this. - * commands/i386/pc/halt.c: New file. - * commands/i386/pc/reboot.c: Likewise. - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `commands/help.c'. - (pkgdata_MODULES): Add `reboot.mod', `halt.mod' and `help.mod'. - (help_mod_SOURCES, help_mod_CFLAGS, reboot_mod_SOURCES) - (reboot_mod_CFLAGS, halt_mod_SOURCES, halt_mod_CFLAGS): New - variables. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add - `commands/help.c'. - (pkgdata_MODULES): Add `help.mod'. - (help_mod_SOURCES, help_mod_CFLAGS): New variables. - * grub/i386/pc/init.h (grub_reboot): New prototype. - (grub_halt): Likewise. - * include/grub/normal.h (grub_arg_show_help): New prototype. - (grub_help_init): Likewise. - (grub_help_fini): Likewise. - * util/grub-emu.c (main): Initialize and deinitialize the help - command. - - * normal/cmdline.c (grub_cmdline_get): Doc fix. - - * normal/command.c (grub_command_init): Fixed the description of - the `set' and `unset' commands. - -2005-01-31 Marco Gerards - - * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_interpret): New - function. - * commands/ieee1275/halt.c: New file. - * commands/ieee1275/reboot.c: Likewise. - * commands/ieee1275/suspend.c (grub_cmd_suspend): Use - `__attribute__ ((unused))'. Some GCS related fixed. - (grub_suspend_init) [GRUB_UTIL]: Function removed. - (grub_suspend_fini): Likewise. - * conf/powerpc-ieee1275.rmk (pkgdata_MODULES): Add `reboot.mod' - and `halt.mod'. - (reboot_mod_SOURCES, reboot_mod_CFLAGS, halt_mod_SOURCES) - (halt_mod_CFLAGS): New variables. - * include/grub/powerpc/ieee1275/ieee1275.h - (grub_ieee1275_interpret): New prototype. - -2005-01-29 Yoshinori K. Okuji - - * include/grub/misc.h (memmove): New prototype. - (memcpy): Likewise. - -2005-01-22 Hollis Blanchard - - * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_open): Don't initialize - `devpath' to 0. Use `name' instead of `devpath' with `grub_strndup'. - -2005-01-22 Marco Gerards - - * kern/misc.c (grub_strndup): Function rewritten. - -2005-01-22 Vincent Pelletier - - * normal/menu.c (TERM_WIDTH): Macro redefined. - (TERM_TOP_BORDER_Y): Likewise. - (draw_border): Replaced while-loop by a for-loop. Make the number - of lines consistent with the number of lines displayed in - print_entries. Added a margin below the rectangle. - (print_entry): Make the entry fit in the rectangle. - (print_entries): Display the scroll arrows next to the right - border. - -2005-01-21 Marco Gerards - - * fs/minix.c (grub_minix_find_file): Reserve more space for - `fpath' so the \0 can be stored. Use `grub_strcpy' instead of - `grub_strncpy' to copy `path' into it. - -2005-01-21 Marco Gerards - - Add the loopback device, a device via which files can be accessed - as devices. - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add `disk/loopback.c'. - (pkgdata_MODULES): Add loopback.mod. - (loopback_mod_SOURCES): New variable. - (loopback_mod_CFLAGS): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add - `disk/loopback.c'. - (pkgdata_MODULES): Add loopback.mod. - (loopback_mod_SOURCES): New variable. - (loopback_mod_CFLAGS): Likewise. - * disk/loopback.c: new file. - * include/grub/normal.h (grub_loop_init): New prototype. - (grub_loop_fini): New prototype. - * util/grub-emu.c (main): Initialize and de-initialize loopback - support. - * include/grub/disk.h (grub_disk_dev_id): Add - `GRUB_DISK_DEVICE_LOOPBACK_ID'. - -2005-01-20 Hollis Blanchard - - * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_enter): New - function. - * conf/powerpc-ieee1275.rmk (pkgdata_MODULES): Add suspend.mod. - (suspend_mod_SOURCES): New variable. - (suspend_mod_CFLAGS): Likewise. - * include/grub/powerpc/ieee1275/ieee1275.h (grub_ieee1275_enter): - New prototype. - * commands/ieee1275/suspend.c: New file. - -2005-01-20 Timothy Baldwin - - * include/grub/dl.h (GRUB_MOD_INIT): Changed `__attribute__ - ((unused))' to `__attribute__ ((used))'. - (GRUB_MOD_FINI): Likewise. - * kern/dl.c (grub_dl_load_file): Fix null pointer dereference. - * genmk.rb (PModule): Assign space to common symbols when linking - modules. - -2005-01-20 Marco Gerards - - * include/grub/mm.h (grub_mm_init_region): Change the type of the - `unsigned' arguments to `grub_size_t'. - (grub_malloc): Likewise. - (grub_realloc): Likewise. - (grub_memalign): Likewise. - * kern/i386/dl.c (grub_arch_dl_check_header): Likewise. - * kern/powerpc/dl.c (grub_arch_dl_check_header): Likewise. - * util/misc.c (grub_malloc): Likewise. - (grub_realloc): Likewise. - * kern/mm.c (get_header_from_pointer): Change the casts to - `unsigned' into a cast to `grub_size_t'. - - * fs/fshelp.c (grub_fshelp_find_file): The `oldnode' should always - point to `currnode' when `currnode' is changed. - - * util/grub-emu.c (main): Initialize `progname'. Reported by Nico - Schottelius . - -2005-01-09 Hollis Blanchard - - * util/powerpc/ieee1275/grub-mkimage.c: Include . - (note_path): Remove variable. - (GRUB_IEEE1275_NOTE_NAME): New macro. - (GRUB_IEEE1275_NOTE_TYPE): Likewise. - (grub_ieee1275_note_hdr): New structure. - (grub_ieee1275_note_desc): Likewise. - (grub_ieee1275_note): Likewise. - (load_note): Remove `dir' argument. All callers updated. Remove - `note_img' and `path'. Do not load a file from `note_path'. - Initialize a struct grub_ieee1275_note and write that to `out'. - Use GRUB_IEEE1275_MODULE_BASE instead of MODULE_BASE. - -2005-01-05 Marco Gerards - - * util/misc.c (grub_util_read_image): Revert last change. It - called `grub_util_read_at', which seeks from the beginning of the - file. - -2005-01-04 Hollis Blanchard - - * TODO: Add note about endianness in grub-mkimage. - * boot/powerpc/ieee1275/crt0.S (note): Remove unused .note - section. - * conf/powerpc-ieee1275.rmk (bin_UTILITIES): Add grub-mkimage. - (grub_mkimage_SOURCES): New target. - * include/grub/kernel.h (grub_start_addr): Remove variable. - (grub_end_addr): Likewise. - (grub_total_module_size): Likewise. - (grub_kernel_image_size): Likewise. - (GRUB_MODULE_MAGIC): New constant. - (grub_module_info): New structure. - (grub_arch_modules_addr): New prototype. - (grub_get_end_addr): Remove prototype. - * include/grub/i386/pc/kernel.h (grub_end_addr): New prototype. - * include/grub/powerpc/ieee1275/kernel.h: New file. - * include/grub/util/misc.h (grub_util_get_fp_size): New - prototype. - (grub_util_read_at): Likewise. - (grub_util_write_image_at): Likewise. - * kern/main.c (grub_get_end_addr): Remove function. - (grub_load_modules): Call grub_arch_modules_addr instead of using - grub_end_addr. Look for a grub_module_info struct in memory. Use - the grub_module_info fields instead of calling grub_get_end_addr - as loop conditions. Move grub_add_unused_region code here. - (grub_add_unused_region): Remove function. - * kern/i386/pc/init.c: Include grub/cache.h. - (grub_machine_init): Remove call to grub_get_end_addr. Remove - one call to add_mem_region. - (grub_arch_modules_addr): New function. - * kern/powerpc/ieee1275/init.c (grub_end_addr): Remove variable. - (grub_total_module_size): Likewise. - Include grub/machine/kernel.h. - (grub_arch_modules_addr): New function. - * util/grub-emu.c (grub_end_addr): Remove variable. - (grub_total_module_size): Likewise. - (grub_arch_modules_addr): New function. - * util/misc.c: Include unistd.h. - (grub_util_get_fp_size): New function. - (grub_util_read_at): Likewise. - (grub_util_write_image_at): Likewise. - (grub_util_read_image): Call grub_util_read_at. - (grub_util_write_image): Call grub_util_write_image_at. - * util/i386/pc/grub-mkimage.c (generate_image): Allocate - additional memory in kernel_img for a struct grub_module_info. - Fill in that grub_module_info. - * util/powerpc/ieee1275/grub-mkimage.c: New file. - -2005-01-03 Hollis Blanchard - - * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_milliseconds): - New function. - * include/grub/powerpc/ieee1275/ieee1275.h - (grub_ieee1275_milliseconds): New prototype. - * include/grub/powerpc/ieee1275/time.h (GRUB_TICKS_PER_SECOND): - Change to 1000. - * kern/powerpc/ieee1275/init.c (grub_get_rtc): Call - grub_ieee1275_milliseconds. - -2005-01-03 Hollis Blanchard - - * boot/powerpc/ieee1275/cmain.c (grub_ieee1275_realmode): New - variable. - (find_options): New function. - (cmain): Call find_options. - * include/grub/powerpc/ieee1275/ieee1275.h - (grub_ieee1275_realmode): New extern variable. - * kern/powerpc/ieee1275/openfw.c (grub_claimmap): Only call - grub_map if grub_ieee1275_realmode is false. - -2004-12-29 Marco Gerards - - * normal/cmdline.c (grub_cmdline_get): Redone logic so no empty - lines are inserted and make it work like readline. Reported by - Vincent Pelletier . - -2004-12-28 Marco Gerards - - * boot/powerpc/ieee1275/crt0.S (_start): Don't set up the stack. - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCE): Remove - `kern/powerpc/cache.S'. - -2004-12-27 Marco Gerards - - * genmk.rb: Handle the `Program' class in the main loop. Written - by Johan Rydberg . - (Program): New class. - (programs): New variable. - * boot/powerpc/ieee1275/cmain.c: Include - instead of "grub/machine/ieee1275.h". Include - instead of "grub/kernel.h". Include . - (help_arch): Function removed. - * conf/powerpc-ieee1275.rmk (grubof_HEADERS): Add - `powerpc/libgcc.h' and `loader.h'. - (pkgdata_PROGRAMS): New variable. - (sbin_UTILITIES): Variable removed. - (grub_emu_SOURCES): Added kern/powerpc/cache.S. - (grubof_SOURCES): Variable re-defined so it only includes the - core functionality. - (grubof_CFLAGS): Remove `-DGRUBOF'. - (pkgdata_MODULES, fshelp_mod_SOURCES, fshelp_mod_CFLAGS, - (fat_mod_SOURCES, fat_mod_CFLAGS, ext2_mod_SOURCES) - (ext2_mod_CFLAGS, ufs_mod_SOURCES, ufs_mod_CFLAGS) - (minix_mod_SOURCES, minix_mod_CFLAGS, hfs_mod_SOURCES) - (hfs_mod_CFLAGS, jfs_mod_SOURCES, jfs_mod_CFLAGS) - (iso9660_mod_SOURCES, iso9660_mod_CFLAGS, _linux_mod_SOURCES) - (_linux_mod_CFLAGS, linux_mod_SOURCES, linux_mod_CFLAGS) - (normal_mod_SOURCES, normal_mod_CFLAGS, normal_mod_ASFLAGS) - (hello_mod_SOURCES, hello_mod_CFLAGS, boot_mod_SOURCES) - (boot_mod_CFLAGS, terminal_mod_SOURCES, terminal_mod_CFLAGS) - (ls_mod_SOURCES, ls_mod_CFLAGS, cmp_mod_SOURCES, cmp_mod_CFLAGS) - (cat_mod_SOURCES, cat_mod_CFLAGS, font_mod_SOURCES) - (font_mod_CFLAGS, amiga_mod_SOURCES, amiga_mod_CFLAGS) - (apple_mod_SOURCES, apple_mod_CFLAGS, pc_mod_SOURCES) - (pc_mod_CFLAGS): New variables. - * disk/powerpc/ieee1275/ofdisk.c: Include . - (grub_ofdisk_iterate): Add a prototype for `dev_iterate'. - * include/grub/dl.h (grub_arch_dl_sync_caches): New prototype. - * include/grub/loader.h (grub_os_area_addr, grub_os_area_size): - Moved from here... - * include/grub/i386/pc/init.h (grub_os_area_addr) - (rub_os_area_size): ... to here. - * include/grub/powerpc/ieee1275/ieee1275.h - (grub_ieee1275_entry_fn): Export symbol. - * include/grub/powerpc/ieee1275/init.h: New file. - * include/grub/powerpc/libgcc.h: Likewise. - * include/grub/cache.h: Likewise. - * kern/powerpc/cache.S: Likewise. Written by Hollis Blanchard - . - * kern/dl.c: Include . - (grub_dl_flush_cache): New function. - (grub_dl_load_core): Call `grub_dl_flush_cache' to flush the cache - for this module. - * kern/powerpc/ieee1275/init.c (grub_ofdisk_init) - (grub_console_init): Removed prototypes. - (grub_machine_init): Don't initialize the modules anymore. - * kern/powerpc/ieee1275/openfw.c (grub_map): Make the function - static. - * include/grub/powerpc/types.h (GRUB_HOST_WORDS_LITTLEENDIAN): - Macro undef removed. - (GRUB_HOST_WORDS_BIGENDIAN): New macro. - * kern/powerpc/dl.c (grub_arch_dl_relocate_symbols): Add - relocation `R_PPC_REL32'. Return an error when the relocation is - unknown. - * Makefile.in (DATA): Add `$(pkgdata_PROGRAMS)'. - * kern/i386/pc/init.c (grub_arch_sync_caches): New function. - * util/misc.c (grub_arch_sync_caches): Likewise. - -2004-12-19 Marco Gerards - - * conf/powerpc-ieee1275.rmk (MOSTLYCLEANFILES): Remove - `symlist.c', add `grubof_symlist.c'. - (symlist.c): Variable removed. - (grubof_HEADERS): Variable added. - (grubof_symlist.c): New target. - (kernel_syms.lst): Use `grubof_HEADERS' instead of - `kernel_img_HEADERS'. - (grubof_SOURCES): Add `kern/powerpc/dl.c' and `grubof_symlist.c'. - * kern/powerpc/dl.c: New file. - * kern/powerpc/ieee1275/init.c (grub_arch_dl_check_header): - Function removed. - (grub_arch_dl_relocate_symbols): Likewise. - (grub_register_exported_symbols): Likewise. - -2004-12-13 Marco Gerards - - * fs/ext2.c (grub_ext2_open): Don't use data after freeing it. - (grub_ext2_dir): Likewise. Don't return in case of an error, jump - to fail instead. Reported by Vincent Pelletier - . - - * fs/fshelp.c (grub_fshelp_find_file): Don't free `oldnode' when - it is not allocated. Reported by Vincent Pelletier - . - - * normal/cmdline.c (grub_tab_complete): Add a blank line to the - output so the output looks better. - -2004-12-04 Marco Gerards - - Modulize the partition map support and add support for the amiga - partition map. - - * commands/ls.c: Include instead of - . - * kern/disk.c: Likewise. - * kern/rescue.c: Likewise. - * loader/i386/pc/chainloader.c: Likewise. - * normal/cmdline.c: Likewise. - * kern/powerpc/ieee1275/init.c: Likewise. - (grub_machine_init): Call `grub_pc_partition_map_init', - `grub_amiga_partition_map_init' and - `grub_apple_partition_map_init'. - * conf/i386-pc.rmk (kernel_img_SOURCES): Remove - `disk/i386/pc/partition.c'. Add `kern/partition.c'. - (kernel_img_HEADERS): Remove `machine/partition.h'. Add - `partition.h' and `pc_partition.h'. - (grub_setup_SOURCES): Remove - `disk/i386/pc/partition.c'. Add `kern/partition.c', - `partmap/amiga.c', `partmap/apple.c' and `partmap/pc.c'. - (grub_emu_SOURCES): Likewise. - (pkgdata_MODULES): Add `amiga.mod', `apple.mod' and `pc.mod'. - (amiga_mod_SOURCES, amiga_mod_CFLAGS, apple_mod_SOURCES) - (apple_mod_CFLAGS, pc_mod_SOURCES, pc_mod_CFLAGS): New variables. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Remove - `disk/powerpc/ieee1275/partition.c'. Add `kern/partition.c', - `partmap/amiga.c', `partmap/apple.c' and `partmap/pc.c'. - (grubof_SOURCES): Likewise. - * disk/i386/pc/partition.c: File removed. - * disk/powerpc/ieee1275/partition.c: Likewise. - * include/grub/powerpc/ieee1275/partition.h: Likewise. - * include/grub/i386/pc/partition.h: Likewise. - * kern/partition.c: New file. - * partmap/amiga.c: Likewise. - * partmap/apple.c: Likewise. - * partmap/pc.c: Likewise. - * include/grub/partition.h: Likewise.. - * include/grub/pc_partition.h: Likewise. - * util/grub-emu.c: Include instead of - . - (main): Call `grub_pc_partition_map_init', - `grub_amiga_partition_map_init' and - `grub_apple_partition_map_init' and deinitialize afterwards. - * util/i386/pc/biosdisk.c: Include `#include - ' and `include ' instead of - `'. - * util/i386/pc/grub-setup.c: Likewise. - * util/i386/pc/biosdisk.c: Likewise. - (grub_util_biosdisk_get_grub_dev): Only access the PC specific - partition information in case of a PC partition. - * util/i386/pc/grub-setup.c: Include `#include - ' and `include ' instead of - `'. - (setup): Only access the PC specific partition information in case - of a PC partition. - -2004-11-17 Hollis Blanchard - - * kern/powerpc/ieee1275/init.c (grub_setjmp): Remove function. - (grub_longjmp): Likewise. - * include/grub/powerpc/setjmp.h (grub_jmp_buf): Set array size to - 20. - * normal/powerpc/setjmp.S: New file. - * conf/powerpc-ieee1275.rmk (grubof_SOURCES): Add - `normal/powerpc/setjmp.S'. - (grubof_CFLAGS): Add `-DGRUBOF'. - * include/grub/setjmp.h [GRUB_UTIL]: Changed condition to - [GRUB_UTIL && !GRUBOF]. - -2004-11-16 Marco Gerards - - * kern/powerpc/ieee1275/openfw.c (grub_devalias_iterate): Skip any - property named `name'. Correctly handle the error returned by - `grub_ieee1275_finddevice' if a device can not be opened. - -2004-11-02 Hollis Blanchard - - * term/powerpc/ieee1275/ofconsole.c (grub_ofconsole_readkey): Test - `actual' for negativity. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Remove - kern/fshelp.c. - -2004-11-01 Marco Gerards - - * term/i386/pc/vga.c (VGA_HEIGHT): Changed to 350. - (PAGE_OFFSET): New macro. - (CRTC_ADDR_PORT): Likewise. - (CRTC_DATA_PORT): Likewise. - (START_ADDR_HIGH_REGISTER): Likewise. - (START_ADDR_LOW_REGISTER): Likewise. - (GRAPHICS_ADDR_PORT): Likewise. - (GRAPHICS_DATA_PORT): Likewise. - (READ_MAP_REGISTER): Likewise. - (INPUT_STATUS1_REGISTER): Likewise. - (INPUT_STATUS1_VERTR_BIT): Likewise. - (page): New variable. - (wait_vretrace): New function. - (set_read_map): Likewise. - (set_start_address): Likewise. - (grub_vga_init): Use mode 0x10 instead of mode 0x12. Switch to - the right page. - (check_vga_mem): Take the page into account. - (write_char): Likewise. - (write_cursor): Likewise. - (scroll_up): Likewise. Copy the page to the page that is not - shown and switch between both pages. - (grub_vga_putchar): Fix off by one error. - (grub_vga_cls): Wait for the vertical retrace. Take the page into - account. - -2004-11-01 Marco Gerards - - Add support for iso9660 (including rockridge). - - * conf/i386-pc.rmk (grub_emu_SOURCES): Add fs/iso9660.c. - (iso9660_mod_SOURCES): New variable. - (iso9660_mod_CFLAGS): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add fs/iso9660.c. - * include/grub/fs.h (grub_iso9660_init): New prototype. - * util/grub-emu.c (main): Call `grub_iso9660_init'. - * fs/iso9660.c: New file. - - * include/grub/misc.h (grub_strncat): New prototype. - * kern/misc.c (grub_strncat): New function. - - * fs/hfs.c (grub_hfs_mount): Translate the error - `GRUB_ERR_OUT_OF_RANGE' to `GRUB_ERR_BAD_FS'. - * fs/jfs.c (grub_jfs_mount): Likewise. - * fs/ufs.c (grub_ufs_mount): Likewise. - -2004-10-28 Hollis Blanchard - - * boot/powerpc/ieee1275/cmain.c (cmain): Remove asm statements - which initialized BAT registers. - * boot/powerpc/ieee1275/ieee1275.c (IEEE1275_CALL_ENTRY_FN, - grub_ieee1275_common_hdr, INIT_IEEE1275_COMMON): - Move from here... - * include/grub/powerpc/ieee1275/ieee1275.h (IEEE1275_CALL_ENTRY_FN, - grub_ieee1275_common_hdr, INIT_IEEE1275_COMMON): - ... to here. - * kern/powerpc/ieee1275/openfw.c (grub_map): New function. - (grub_mapclaim): Likewise. - * loader/powerpc/ieee1275/linux.c (grub_load_linux): Use - grub_mapclaim instead of grub_ieee1275_claim. Assign linux_addr by - hand. - -2004-10-19 Hollis Blanchard - - * conf/powerpc-ieee1275.rmk (COMMON_ASFLAGS): Remove -fno-builtin. - (COMMON_CFLAGS): Remove -fno-builtin and -D__ASSEMBLY__. Add - -ffreestanding and -msoft-float. - -2004-10-15 Hollis Blanchard - - * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_open): Do not - append ":0" to devpath if the GRUB_IEEE1275_NO_PARTITION_0 flag is - set in grub_ieee1275_flags. - -2004-10-14 Hollis Blanchard - - * include/grub/powerpc/ieee1275/ieee1275.h (abort): Add function - prototype. - * kern/powerpc/ieee1275/init.c (grub_machine_init): Call - grub_console_init first. - Change the memory range used for grub_ieee1275_claim and - grub_mm_init_region. - Print an error message if the claim fails. - Include . - -2004-10-13 Hollis Blanchard - - * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_iterate): - Call grub_children_iterate for device nodes of type `scsi', - `ide', or `ata'. - (grub_ofdisk_open): Remove manual device alias resolution. - Fix memory leak when device cannot be opened. - * include/grub/powerpc/ieee1275/ieee1275.h - (grub_children_iterate): New prototype. - * kern/powerpc/ieee1275/openfw.c (grub_children_iterate): - New function. - * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_get_property): - Return -1 if args.size was -1. - -2004-10-11 Hollis Blanchard - - * boot/powerpc/ieee1275/cmain.c (grub_ieee1275_flags): New global. - (cmain): Accept 3 parameters. Test for 0xdeadbeef, indicating Old - World Macintosh. If Old Wold, set flag in grub_ieee1275_flags; claim - Open Firmware's memory for it; claim memory from _start to _end. - * boot/powerpc/ieee1275/crt0.S (__bss_start): New extern. - (_end): New extern. - (_start): Zero BSS from __bss_start to _end. - * include/grub/powerpc/ieee1275/ieee1275.h (grub_ieee1275_flags): - New extern. - (GRUB_IEEE1275_NO_PARTITION_0): New #define. - -2004-10-11 Hollis Blanchard - - * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_claim): Return - -1 if args.base was -1. - -2004-10-08 Hollis Blanchard - - * term/powerpc/ieee1275/ieee1275.c (grub_ofconsole_cls): Use an ANSI - escape sequence instead of a literal ^L. Also call - grub_ofconsole_gotoxy. - -2004-10-03 Hollis Blanchard - - * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_claim): change - void * arguments to grub_addr_t. All callers updated. Also make - the `result' argument optional. - (grub_ieee1275_release): change void * arguments to grub_addr_t. - All callers updated. - -2004-09-22 Hollis Blanchard - - * commands/ls.c (grub_ls_list_files): Use the string following the - initial ')', if present, as the filesystem path. - * kern/rescue.c (grub_rescue_cmd_ls): Likewise. - - * conf/powerpc-ieee1275.rmk (grubof_SOURCES): List crt0.S first. - -2004-09-18 Yoshinori K. Okuji - - Make the source code of the menu interface more readable. - - * normal/menu.c: Include grub/mm.h. - (TERM_WIDTH): New macro. - (TERM_HEIGHT): Likewise. - (TERM_INFO_HEIGHT): Likewise. - (TERM_MARGIN): Likewise. - (TERM_SCROLL_WIDTH): Likewise. - (TERM_TOP_BORDER_Y): Likewise. - (TERM_LEFT_BORDER_X): Likewise. - (TERM_BORDER_WIDTH): Likewise. - (TERM_MESSAGE_HEIGHT): Likewise. - (TERM_BORDER_HEIGHT): Likewise. - (TERM_NUM_ENTRIES): Likewise. - (TERM_FIRST_ENTRY_Y): Likewise. - (TERM_ENTRY_WIDTH): Likewise. - (TERM_CURSOR_X): Likewise. - (draw_border): Use macros instead of magic numbers. - (print_entry): Likewise. - (print_entries): Likewise. - (run_menu): Likewise. Also, handle the key 'e'. - (run_menu_entry): Ignore empty command lines. - (print_message): Added a new argument EDIT. If EDIT is true, - print a different message. - (init_page): Likewise. - (edit_menu_entry): New function. Not implemented yet. - -2004-09-17 Marco Gerards - - Add `linux.mod' and `multiboot.mod' so linux and multiboot kernels - can be loaded from normal mode. - - * conf/i386-pc.rmk (pkgdata_MODULES): Add `linux.mod' and - `multiboot.mod'. - (linux_mod_SOURCES, linux_mod_CFLAGS, multiboot_mod_SOURCES) - (multiboot_mod_CFLAGS): New variables. - * loader/i386/pc/linux_normal.c: New file. - * loader/i386/pc/multiboot_normal.c: Likewise. - - * loader/i386/pc/linux.c (grub_rescue_cmd_initrd): Don't use the - attribute `unused'. - - * fs/ext2.c (grub_ext2_iterate_dir): Fix typos in inode type. Use - `fdiro' to read the mode information from instead of `diro'. - - * fs/fshelp.c (grub_fshelp_find_file): Set type to foundtype after - looking up a symlink. - - * include/grub/normal.h (GRUB_COMMAND_FLAG_NO_ARG_PARSE): New - macro. - * normal/command.c (grub_command_execute): Don't parse the - arguments when `GRUB_COMMAND_FLAG_NO_ARG_PARSE' is set in the - flags of the command. - - * normal/menu.c (grub_menu_run): Fix typo. - -2004-09-14 Hollis Blanchard - - * kern/powerpc/ieee1275/init.c (abort): Trap into Open Firmware. - - * term/powerpc/ieee1275/ofconsole.c (grub_ofconsole_gotoxy): Use - `y + 1' instead of `y - 1'. - - * conf/powerpc-ieee1275.rmk (grubof_LDFLAGS): Add `-N' and `-S'. - -2004-09-14 Yoshinori K. Okuji - - From Hollis Blanchard : - * kern/misc.c (memmove): New alias for grub_memmove. - (memcmp): New alias for grub_memcmp. - (memset): New alias for grub_memset. - * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_get_property): - Change "int handle" to "grub_ieee1275_phandle_t handle". - * include/grub/powerpc/ieee1275/ieee1275.h - (grub_ieee1275_get_property): Likewise. - -2004-09-12 Tomas Ebenlendr - - Added normal mode command `chainloader' as module chain.mod, which - depends on normal.mod and _chain.mod. - - * conf/i386-pc.rmk (pkgdata_MODULES): Add `chain.mod'. - (chain_mod_SOURCES, chain_mod_CFLAGS): Variables added. - * include/grub/i386/pc/loader.h (grub_rescue_cmd_chainloader): - Deleted prototype. - * loader/i386/pc/chainloader.c (grub_rescue_cmd_chainloader): All - but arguments parsing moved to ... - (grub_chainloader_cmd): ... here. New function. - * include/grub/i386/pc/chainloader.h: New file. - * loader/i386/pc/chainloader_normal.c: Likewise. - -2004-09-11 Marco Gerards - - * conf/i386-pc.rmk (kernel_img_SOURCES): Added kern/fshelp.c. - (grub_mkimage_LDFLAGS): Likewise. - (grub_emu_SOURCES): Likewise. - (kernel_img_HEADERS): Added fshelp.h. - * fs/ext2.c: Include . - (FILETYPE_REG): New macro. - (FILETYPE_INO_REG): Likewise. - (grub_ext_sblock): Renamed to `grub_ext2_sblock'. - Changed all users. - (ext2_block_group): Renamed to `grub_ext2_block_group'. Changed - all users. - (grub_fshelp_node): New struct. - (grub_ext2_data): Added member `diropen'. Changed member `inode' - to a pointer. - (grub_ext2_get_file_block): Removed function. - (grub_ext2_read_block): New function. - (grub_ext2_read_file): Replaced parameter `data' by `node'. - This function was written. - (grub_ext2_mount): Read the root inode. Create a diropen struct. - (grub_ext2_find_file): Removed function. - (grub_ext2_read_symlink): New function. - (grub_ext2_iterate_dir): Likewise. - (grub_ext2_open): Rewritten. - (grub_ext2_dir): Rewritten. - * include/grub/fshelp.h: New file. - * fs/fshelp.c: Likewise. - -2004-09-10 Yoshinori K. Okuji - - * normal/menu.c: Include grub/loader.h and grub/machine/time.h. - (print_message): Add a missing newline. - (run_menu): Added timeout support. - (run_menu_entry): New local function. - (grub_menu_run): Added support for booting. - - * kern/loader.c (grub_loader_is_loaded): New function. - - * include/grub/powerpc/ieee1275/time.h: Include grub/symbol.h. - (grub_get_rtc): Exported. - - * include/grub/i386/pc/time.h: Include grub/symbol.h. - (grub_get_rtc): Exported. - - * include/grub/normal.h (struct grub_command_list): Remove - constant from the member `command'. - - * include/grub/loader.h (grub_loader_is_loaded): Declared. - - * include/grub/err.h (GRUB_ERR_INVALID_COMMAND): New constant. - - * conf/i386-pc.rmk (kernel_img_HEADERS): Added machine/time.h. - -2004-08-28 Marco Gerards - - Add support for the JFS filesystem. - - * fs/jfs.c: New file. - * include/grub/fs.h (grub_jfs_init): New prototype. - (grub_jfs_fini): New prototype. - * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/jfs.c. - (grub_emu_SOURCES): Likewise. - (pkgdata_MODULES): Add jfs.mod. - (jfs_mod_SOURCES): New variable. - (jfs_mod_CFLAGS): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add fs.jfs.c. - (grubof_SOURCES): Likewise. - * util/grub-emu.c (main): Initialize and deinitialize JFS support. - - * fs/fat.c (grub_fat_find_dir): Convert the filename little - endian to the host endian. - (grub_fat_utf16_to_utf8): Move function from there... - * kern/misc.c (grub_utf16_to_utf8): ...to here. Do not convert - the endianness of the source string anymore. - * include/grub/misc.h (grub_utf16_to_utf8): New prototype. - -2004-08-24 Marco Gerards - - * commands/boot.c (grub_boot_init) [GRUB_UTIL]: Make conditional. - (grub_boot_fini) [GRUB_UTIL]: Likewise. - (GRUB_MOD_INIT) [!GRUB_UTIL]: Likewise. - (GRUB_MOD_FINI) [!GRUB_UTIL]: Likewise. - - * fs/hfs.c (grub_hfs_find_node): Add a prototype for `node_found'. - (grub_hfs_iterate_dir): Make the function static. Add prototypes - for `node_found' and `it_dir'. - (grub_hfs_dir): Add prototype for `dir_hook'. - - * fs/minix.c (grub_minix_get_file_block): Add prototype for - `grub_get_indir'. Rename `indir' in two blocks to `indir16' - and `indir32' to silence a gcc warning. - - * include/grub/fs.h (grub_hfs_init): New prototype. - (grub_hfs_fini): Likewise. - - -2004-08-21 Yoshinori K. Okuji - - Each disk device has its own id now. This is useful to make use - of multiple disk devices. - - * include/grub/disk.h (grub_disk_dev_id): New enum. - (GRUB_DISK_DEVICE_BIOSDISK_ID): New constant. - (GRUB_DISK_DEVICE_OFDISK_ID): Likewise. - - * disk/i386/pc/biosdisk.c (grub_biosdisk_dev): Specify - GRUB_DISK_DEVICE_BIOSDISK_ID as an id. - - * disk/powerpc/ieee1275/ofdisk.c (grub_ofdisk_dev): Specify - GRUB_DISK_DEVICE_OFDISK_ID as an id. - - * util/i386/pc/biosdisk.c (grub_util_biosdisk_dev): Specify - GRUB_DISK_DEVICE_BIOSDISK_ID as an id. - - * include/grub/disk.h (struct grub_disk_dev): Added a new member - "id" which is used by the cache manager. - - * normal/main.c (grub_normal_init_page): Use "GNU GRUB" instead - of just "GRUB". - -2004-08-18 Marco Gerards - - * fs/hfs.c: New file. - * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/hfs.c. - (grub_emu_SOURCES): Likewise. - (pkgdata_MODULES): Add hfs.mod. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add fs/hfs.c. - (grubof_SOURCES): Likewise. - * util/grub-emu.c (main): Initialize and deinitialize HFS support. - - * include/grub/misc.h (grub_strncasecmp): Add prototype. - * kern/misc.c (grub_strncasecmp): Add function. - -2004-08-14 Marco Gerards - - * include/grub/arg.h (GRUB_ARG_OPTION_OPTIONAL): Surround macro - with parentheses. - - * fs/ext2.c (FILETYPE_UNKNOWN): New macro. - (grub_ext2_dir): In case the directory entry type is unknown, read - it from the inode. - -2004-08-02 Peter Bruin - - * loader/powerpc/ieee1275/linux.c (grub_linux_init): Pass - grub_load_linux instead of grub_rescue_cmd_linux as second - argument of grub_rescue_register_command. - - * Makefile.in (RMKFILES): Add conf/powerpc-ieee1275.rmk. - -2004-07-27 Marco Gerards - - * boot/powerpc/ieee1275/ieee1275.c (grub_ieee1275_release): New - function. - * commands/boot.c: Remove the check for `GRUB_UTIL'. - * conf/powerpc-ieee1275.rmk (grubof_SOURCES): Add - `loader/powerpc/ieee1275/linux.c', - `loader/powerpc/ieee1275/linux_normal.c' and `commands/boot.c'. - * include/grub/powerpc/ieee1275/ieee1275.h - (grub_ieee1275_release): New prototype. - * include/grub/powerpc/ieee1275/loader.h: Rewritten. - * kern/powerpc/ieee1275/init.c (grub_machine_init): Initialize - normal, boot, linux and linux_normal. - * loader/powerpc/ieee1275/linux.c: New file. - * loader/powerpc/ieee1275/linux_normal.c: Likewise. - -2004-07-12 Marco Gerards - - * normal/arg.c (grub_arg_parse): Correct error handling after - reallocating the argumentlist (check if `argl' is not null instead - of checking if `args' is not null). - * kern/mm.c (grub_realloc): Return the same pointer when using the - same region, instead of returning the header address. - -2004-07-11 Marco Gerards - - * disk/powerpc/ieee1275/partition.c (grub_partition_iterate): Skip - one block instead of two when looking for the initial partition. - (grub_partition_probe): Initialize the local variable `p' with 0. - Use base 10 for the grub_strtoul call. - * kern/misc.c (grub_strncpy): Fix off by one bug. Eliminated the - need for one local variable. - (grub_strtoul): Don't add the new value to `num', instead of that - just assign it. - -2004-07-11 Marco Gerards - - * conf/i386-pc.rmk (pkgdata_IMAGE): Add pxeboot.img. - (pxeboot_img_SOURCES): New variable. - (pxeboot_img_ASFLAGS): Likewise. - (pxeboot_img_LDFLAGS): Likewise. - * boot/i386/pc/pxeboot.S: New file. Based on pxeloader.S from - GRUB Legacy and boot.S. Adopted for GRUB 2 by lode leroy - . - -2004-06-27 Tomas Ebenlendr - - * kern/rescue.c (grub_enter_rescue_mode): Don't continue when - there was no input. - -2004-06-27 Tomas Ebenlendr - - * normal/cmdline.c (grub_set_history): Fix off by one bug. Fixed - the history buffer logic. - -2004-06-27 Tomas Ebenlendr - - * fs/ext2.c (FILETYPE_INO_MASK, FILETYPE_INO_DIRECTORY) - (FILETYPE_INO_SYMLINK): New macros. - (grub_ext2_find_file): Check if the node is a directory using the - inode stat information instead of using the filetype in the - dirent. Exclude the first character of an absolute symlink. - (grub_ext2_dir): Mask out the filetype part of the mode member of - the inode. - -2004-05-24 Marco Gerards - - Add support for UFS version 1 and 2. Add support for the minix - filesystem version 1 and 2, both the variants with 14 and 30 long - filenames. - - * conf/i386-pc.rmk (grub_setup_SOURCES): Add fs/ufs.c and - fs/minix.c. - (grub_emu_SOURCES): Likewise. - (pkgdata_MODULES): Add ufs.mod and minix.mod. - (ufs_mod_SOURCES): New variable. - (ufs_mod_CFLAGS): Likewise. - (minix_mod_SOURCES): Likewise. - (minix_mod_CFLAGS): Likewise. - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add fs/ufs.c and - fs/minix.c. - (grubof_SOURCES): Likewise. - * fs/ufs.c: New file. - * fs/minix.c: New file. - * include/grub/fs.h (grub_ufs_init): New prototype. - (grub_ufs_fini): Likewise. - (grub_minix_init): Likewise. - (grub_minix_fini): Likewise. - * util/grub-emu.c (main): Initialize and deinitialize UFS and - minix fs. - -2004-04-30 Jeroen Dekkers - - * conf/powerpc-ieee1275.rmk (grub_emu_SOURCES): Add normal/arg.c, - commands/ls.c, commands/terminal.c, commands/boot.c, - commands/cmp.c and commands/cat.c. - (grubof_LDFLAGS): Add -nostdlib -static-libgcc -lgcc. - - * kern/powerpc/ieee1275/init.c: Include "grub/env.h" instead of - "env.h" - -2004-04-04 Yoshinori K. Okuji - - All symbols prefixed with PUPA_ and pupa_ are renamed to GRUB_ - and grub_, respectively. Because the conversion is trivial and - mechanical, I omit the details here. Please refer to the CVS - if you need more information. - -2004-04-04 Yoshinori K. Okuji - - * include/pupa: Renamed to ... - * include/grub: ... this. - * util/i386/pc/pupa-mkimage.c: Renamed to ... - * util/i386/pc/grub-mkimage.c: ... this. - * util/i386/pc/pupa-setup.c: Renamed to ... - * util/i386/pc/grub-setup.c: ... this. - * util/pupa-emu.c: Renamed to ... - * util/grub-emu.c: ... this. - -2004-03-29 Marco Gerards - - Add support for the newworld apple macintosh (PPC). This has been - tested on the powerbook 2000 only. It only adds support for - generic ieee1275 functions, console and disk support. This should - be easy to port to other architectures with support for Open - Firmware. - - * configure.ac: Accept the powerpc as host_cpu. In the case of - the powerpc cpu set the host_vendor to ieee1275. Make sure the i386 - specific tests are only executed while building for the i386. - Inverse test for crosscompile. - * genmk.rb (Utility): Allow assembler files. - * normal/cmdline.c (pupa_tab_complete): Reset pupa_errno. - * conf/powerpc-ieee1275.rmk: New file. - * disk/powerpc/ieee1275/ofdisk.c: Likewise. - * disk/powerpc/ieee1275/partition.c: Likewise. - * include/pupa/powerpc/ieee1275/biosdisk.h: Likewise. - * include/pupa/powerpc/ieee1275/console.h: Likewise. - * include/pupa/powerpc/ieee1275/partition.h: Likewise. - * include/pupa/powerpc/ieee1275/time.h: Likewise. - * include/pupa/powerpc/ieee1275/util/biosdisk.h: Likewise. - * include/pupa/powerpc/ieee1275/multiboot.h: Likewise. - * include/pupa/powerpc/ieee1275/loader.h - * include/pupa/powerpc/setjmp.h: Likewise. - * include/pupa/powerpc/types.h: Likewise. - * kern/powerpc/ieee1275/init.c: Likewise. - * kern/powerpc/ieee1275/openfw.c: Likewise. - * term/powerpc/ieee1275/ofconsole.c: Likewise. - - These files were written by Johan Rydberg - (jrydberg@night.trouble.net) and I only modified them slightly. - - * boot/powerpc/ieee1275/cmain.c: New file. - * boot/powerpc/ieee1275/crt0.S: Likewise. - * boot/powerpc/ieee1275/ieee1275.c: Likewise. - * include/pupa/powerpc/ieee1275/ieee1275.h: Likewise. - -2004-03-14 Jeroen Dekkers - - * Makefile.in: Update copyright. - * genmodsrc.sh: Likewise. - * gensymlist.sh: Likewise. - * term/i386/pc/vga.c: Indent correctly. - - * util/i386/pc/pupa-mkimage.c (usage): Use PACKAGE_BUGREPORT as - bugreporting address. - * util/i386/pc/pupa-setup.c (usage): Likewise, - (main): Call pupa_ext2_init and pupa_ext2_fini. - - * fs/fat.c (log2): Renamed to ... - (fat_log2): ... this. - All callers changed. - * kern/misc.c (memcpy): Alias to pupa_memmove. - * loader/i386/pc/multiboot.c (pupa_rescue_cmd_multiboot): Fix - lvalue cast. - * util/console.c (pupa_ncurses_fini): Return 0. - - * util/i386/pc/biosdisk.c (pupa_util_biosdisk_open)[__linux__]: - Move fail label here. - [__GNU__]: Don't warn when using stat. - (open_device)[!__linux__]: Check if FD < 0 instead of !FD. - (pupa_util_biosdisk_get_pupa_dev)[__GNU__]: Change type of N to - long int. Use strtol instead of strtoul. - -2004-03-14 Marco Gerards - - * commands/boot.c: New file. - * commands/cat.c: Likewise. - * commands/cmp.c: Likewise. - * commands/ls.c: Likewise. - * commands/terminal.c: Likewise. - * normal/command.c: Include and . - (pupa_register_command): Changed interface to match the new - argument parser. - (pupa_command_execute): Changed (almost rewritten) so it uses - pupa_split_command. Added support for setting variables using the - syntax `foo=bar'. - (rescue_command): Changed to work with the new argument parser. - (terminal_command): Moved from here to commands/terminal.c. - (set_command): New function. - (unset_command): New function. - (insmod_command): New function. - (rmmod_command): New function. - (lsmod_command): New function. - (pupa_command_init): Don't initialize the command terminal - anymore. Initialize the commands set, unset, insmod, rmmod and - lsmod. - * conf/i386-pc.rmk (kernel_img_SOURCES): Add kern/env.c. - (kernel_img_HEADERS): Add arg.h and env.h. - (pupa_mkimage_LDFLAGS): Add kern/env.c. - (pupa_emu_SOURCES): Add kern/env.c, commands/ls.c, - commands/terminal.c commands/boot.c commands/cmp.c commands/cat.c, - normal/arg.c. - (pkgdata_MODULES): Add ls.mod, boot.mod, cmp.mod, cat.mod and - terminal.mod. - (normal_mod_SOURCES): Add normal/arg.c and normal/arg.c. - (boot_mod_SOURCES): New variable. - (terminal_mod_SOURCES): Likewise. - (ls_mod_SOURCES): Likewise. - (cmp_mod_SOURCES): Likewise. - (cat_mod_SOURCES): Likewise. - - * normal/arg.c: New file. - * kern/env.c: Likewise. - * include/pupa/arg.h: Likewise. - * include/pupa/env.h: Likewise. - * font/manager.c (font_command): Changed to match argument parsing - interface changes. - (PUPA_MOD_INIT): Likewise. - * hello/hello.c (pupa_cmd_hello): Likewise. - (PUPA_MOD_INIT): Likewise. - * include/pupa/disk.h: Include . - (pupa_print_partinfo): New prototype. - * include/pupa/dl.h (pupa_dl_set_prefix): Prototype removed. - (pupa_dl_get_prefix): Likewise. - * include/pupa/misc.h: Include . - (pupa_isgraph): New prototype. - (pupa_isdigit): Likewise. - (pupa_split_cmdline): Likewise. - * include/pupa/normal.h: Include . - (pupa_command): Changed the prototype of the member `func' to - match the argument parsing interface. Added member `options'. - (pupa_register_command): Updated to match function. - (pupa_arg_parse): New prototype. - (pupa_hello_init) [PUPA_UTIL]: New prototype. - (pupa_hello_fini) [PUPA_UTIL]: Likewise. - (pupa_ls_init) [PUPA_UTIL]: Likewise. - (pupa_ls_fini) [PUPA_UTIL]: Likewise. - (pupa_cat_init) [PUPA_UTIL]: Likewise. - (pupa_cat_fini) [PUPA_UTIL]: Likewise. - (pupa_boot_init) [PUPA_UTIL]: Likewise. - (pupa_boot_fini) [PUPA_UTIL]: Likewise. - (pupa_cmp_init) [PUPA_UTIL]: Likewise. - (pupa_cmp_fini) [PUPA_UTIL]: Likewise. - (pupa_terminal_init) [PUPA_UTIL]: Likewise. - (pupa_terminal_fini) [PUPA_UTIL]: Likewise. - * kern/disk.c: Include . - (pupa_print_partinfo): New function. - * kern/dl.c: Include . - (pupa_dl_dir): Variable removed. - (pupa_dl_load): Use the environment variable `prefix' instead of - the variable pupa_dl_dir. - (pupa_dl_set_prefix): Function removed. - (pupa_dl_get_prefix): Likewise. - * kern/i386/pc/init.c: Include . - (pupa_machine_init): Use the environment variable `prefix' instead of - using pupa_dl_set_prefix to set the prefix. - * kern/main.c: Include . - (pupa_set_root_dev): Use the environment variable `prefix' instead of - using pupa_dl_get_prefix to get the prefix. - * kern/misc.c: Include . - (pupa_isdigit): New function. - (pupa_isgraph): Likewise. - (pupa_ftoa): Likewise. - (pupa_vsprintf): Added support for printing values of the type - `double'. Make it possible to format variable output when using - formatting like `%1.2%f'. - (pupa_split_cmdline): New function. - * kern/rescue.c: Include . - (next_word): Removed function. - (pupa_rescue_cmd_prefix): Likewise. - (pupa_rescue_cmd_set): New function. - (pupa_rescue_cmd_unset): New function. - (pupa_enter_rescue_mode): Use the `pupa_split_cmdline' function to - split the command line instead of splitting it here. Added - support for setting variables using the syntax `foo=bar'. Don't - initialize the prefix command anymore. Initialized the set and - unset commands. - * normal/cmdline.c: Include . - (pupa_tab_complete): Added prototypes for print_simple_completion, - print_partition_completion, add_completion, iterate_commands, - iterate_dev, iterate_part and iterate_dir. Moved code to print - partition information from here to kern/disk.c. - (pupa_cmdline_run): Don't check if the function exists anymore. - * normal/main.c: Include . - (pupa_rescue_cmd_normal): Use the environment variable `prefix' - instead of using pupa_dl_get_prefix to get the prefix. - * term/i386/pc/vga.c: Include . - (check_vga_mem): Cast pointers to `void *' to silence a gcc - warning. - (pupa_vga_putchar) [! DEBUG_VGA]: Removed for this case. - (pupa_vga_setcolor): Declare unused variables with `__attribute__ - ((unused))' to silence a gcc warning. - (pupa_vga_setcolor): Likewise. - (debug_command): Changed to match argument parsing - interface changes. - * util/pupa-emu.c: Include . - (options): Added 0's for unused fields to silence a gcc warning. - (argp): Likewise. - (main): Use the environment variable `prefix' instead of using - pupa_dl_set_prefix to set the prefix. Initialize the commands ls, - boot, cmp, cat and terminal. Finish the commands boot, cmp, cat - and terminal. - - * util/i386/pc/getroot.c: Include . - * util/misc.c: Include . - (pupa_malloc): Rewritten so errors are correctly reported. - (pupa_realloc): Likewise. - (pupa_memalign): Likewise. - (pupa_mm_init_region): Declare unused variables with - `__attribute__ ((unused))' to silence a gcc warning. - * normal/i386/setjmp.S: Remove tab at the end of the file to - silence a gcc warning. - * loader/i386/pc/linux.c (pupa_rescue_cmd_initrd): Declare unused - variables with `__attribute__ ((unused))' to silence a gcc - warning. - * loader/i386/pc/multiboot.c (pupa_multiboot_unload): Make the - local variable i unsigned to silence a gcc warning. - - * kern/term.c: Include . - (pupa_more_lines): New variable. - (pupa_more): Likewise. - (pupa_putcode): When the pager is active pause at the end of every - screen. - (pupa_set_more): New function. - * include/pupa/term.h (pupa_set_more): New prototype. - - -2004-03-07 Yoshinori K. Okuji - - Now this project is GRUB 2 rather than PUPA. The location of - the CVS repository was moved to GRUB's. - - * configure.ac: Use bug-grub as the reporting address. - Use GRUB instead of PUPA. - Change the version number to 1.90. - -2004-02-24 Yoshinori K. Okuji - - * genkernsyms.sh: Updated copyright information. - * genmk.rb: Likewise. - * genmodsrc.sh: Likewise. - * gensymlist.sh: Likewise. - * boot/i386/pc/boot.S: Likewise. - * boot/i386/pc/diskboot.S: Likewise. - * disk/i386/pc/biosdisk.c: Likewise. - * disk/i386/pc/partition.c: Likewise. - * font/manager.c: Likewise. - * fs/ext2.c: Likewise. - * fs/fat.c: Likewise. - * include/pupa/boot.h: Likewise. - * include/pupa/device.h: Likewise. - * include/pupa/disk.h: Likewise. - * include/pupa/dl.h: Likewise. - * include/pupa/elf.h: Likewise. - * include/pupa/err.h: Likewise. - * include/pupa/file.h: Likewise. - * include/pupa/font.h: Likewise. - * include/pupa/fs.h: Likewise. - * include/pupa/kernel.h: Likewise. - * include/pupa/loader.h: Likewise. - * include/pupa/misc.h: Likewise. - * include/pupa/mm.h: Likewise. - * include/pupa/net.h: Likewise. - * include/pupa/normal.h: Likewise. - * include/pupa/rescue.h: Likewise. - * include/pupa/setjmp.h: Likewise. - * include/pupa/symbol.h: Likewise. - * include/pupa/term.h: Likewise. - * include/pupa/types.h: Likewise. - * include/pupa/i386/setjmp.h: Likewise. - * include/pupa/i386/types.h: Likewise. - * include/pupa/i386/pc/biosdisk.h: Likewise. - * include/pupa/i386/pc/boot.h: Likewise. - * include/pupa/i386/pc/console.h: Likewise. - * include/pupa/i386/pc/init.h: Likewise. - * include/pupa/i386/pc/kernel.h: Likewise. - * include/pupa/i386/pc/linux.h: Likewise. - * include/pupa/i386/pc/loader.h: Likewise. - * include/pupa/i386/pc/memory.h: Likewise. - * include/pupa/i386/pc/multiboot.h: Likewise. - * include/pupa/i386/pc/partition.h: Likewise. - * include/pupa/i386/pc/time.h: Likewise. - * include/pupa/i386/pc/vga.h: Likewise. - * include/pupa/i386/pc/util/biosdisk.h: Likewise. - * include/pupa/util/getroot.h: Likewise. - * include/pupa/util/misc.h: Likewise. - * include/pupa/util/resolve.h: Likewise. - * kern/device.c: Likewise. - * kern/disk.c: Likewise. - * kern/dl.c: Likewise. - * kern/err.c: Likewise. - * kern/file.c: Likewise. - * kern/fs.c: Likewise. - * kern/loader.c: Likewise. - * kern/main.c: Likewise. - * kern/misc.c: Likewise. - * kern/mm.c: Likewise. - * kern/rescue.c: Likewise. - * kern/term.c: Likewise. - * kern/i386/dl.c: Likewise. - * kern/i386/pc/init.c: Likewise. - * kern/i386/pc/lzo1x.S: Likewise. - * kern/i386/pc/startup.S: Likewise. - * loader/i386/pc/chainloader.c: Likewise. - * loader/i386/pc/linux.c: Likewise. - * loader/i386/pc/multiboot.c: Likewise. - * normal/cmdline.c: Likewise. - * normal/command.c: Likewise. - * normal/main.c: Likewise. - * normal/menu.c: Likewise. - * normal/i386/setjmp.S: Likewise. - * term/i386/pc/console.c: Likewise. - * term/i386/pc/vga.c: Likewise. - * util/console.c: Likewise. - * util/genmoddep.c: Likewise. - * util/misc.c: Likewise. - * util/pupa-emu.c: Likewise. - * util/resolve.c: Likewise. - * util/unifont2pff.rb: Likewise. - * util/i386/pc/biosdisk.c: Likewise. - * util/i386/pc/getroot.c: Likewise. - * util/i386/pc/pupa-mkimage.c: Likewise. - * util/i386/pc/pupa-setup.c: Likewise. - -2004-02-15 Jeroen Dekkers - - * fs/ext2.c (pupa_ext2_read_file): Correct the value of BLOCKEND - when it is EXT2_BLOCK_SIZE (data). New argument READ_HOOK, all - callers changed. Set DATA->DISK->READ_HOOK to READ_HOOK before - reading and reset it after reading. - (pupa_ext2_close): Return PUPA_ERR_NONE. - - * include/pupa/i386/pc/linux.h (PUPA_LINUX_INITRD_MAX_ADDRESS): - Correct value. - (struct linux_kernel_header): Add kernel_version and - initrd_addr_max. - * loader/i386/pc/linux.c (pupa_rescue_cmd_linux): Check whether - pupa_file_read succeeds. - (pupa_rescue_cmd_initrd): Implement. - -2003-12-03 Marco Gerards - - * fs/ext2.c (pupa_ext2_label): New function. - (pupa_ext2_fs): Added label. - * fs/fat.c (pupa_fat_label): New function. - (pupa_fat_fs): Added label. - * include/pupa/fs.h (struct pupa_fs): Added prototype label. - - * kern/misc.c (pupa_strndup): New function. - * include/pupa/misc.h (pupa_strndup): New prototype. - - * include/pupa/normal.h: Include . - (pupa_set_history): New prototype. - (pupa_iterate_commands): New prototype. - * normal/cmdline.c: Include , - , . - (hist_size): New variable. - (hist_lines): Likewise. - (hist_end): Likewise. - (hist_used): Likewise. - (pupa_set_history): New function. - (pupa_history_get): Likewise. - (pupa_history_add): Likewise. - (pupa_history_replace): Likewise. - (pupa_tab_complete): Likewise. - (pupa_cmdline_run): Added tab completion and history buffer. Tab - completion shows partitionnames while completing partitions, this - feature was suggested by Jeff Bailey. - * normal/command.c (pupa_iterate_commands): New function. - * normal/main.c (PUPA_DEFAULT_HISTORY_SIZE): New macro. - (pupa_normal_init): Initialize history buffer. - (PUPA_MOD_INIT): Likewise. - (pupa_normal_fini): Free the history buffer. - (PUPA_MOD_FINI): Likewise. - - * util/console.c (pupa_ncurses_getkey): Accept 127 as backspace - key. - - * aclocal.m4 (pupa_I386_CHECK_REGPARM_BUG): New DEFUN. - * configure.ac [i386]: Check for regparam bug. - (NESTED_FUNC_ATTR) [! i386]: Defined. - -2003-11-17 Marco Gerards - - * conf/i386-pc.rmk (sbin_UTILITIES): Added pupa-emu. - (pupa_setup_SOURCES): Added util/i386/pc/getroot.c. - (pupa_emu_SOURCES): New variable. - (pupa_emu_LDFLAGS): Likewise. - * include/pupa/fs.h (pupa_ext2_init) [PUPA_UTIL]: New prototype. - (pupa_ext2_fini) [PUPA_UTIL]: Likewise. - * include/pupa/normal.h (pupa_normal_init) [PUPA_UTIL]: Likewise. - (pupa_normal_fini) [PUPA_UTIL]: Likewise. - * include/pupa/setjmp.h [PUPA_UTIL]: Include . - (pupa_jmp_buf): New typedef. - (pupa_setjmp) [PUPA_UTIL]: New macro. - (pupa_longjmp) [PUPA_UTIL]: Likewise. - * include/pupa/term.h (struct pupa_term): New member `refresh'. - (pupa_refresh): New prototype. - * include/pupa/util/getroot.h: New file. - * kern/misc.c (pupa_vsprintf): Refresh the screen after updating - it. - * kern/rescue.c (pupa_rescue_get_command_line): Likewise. - (pupa_rescue_cmd_cat): Likewise. - (pupa_rescue_cmd_ls): Likewise. - (pupa_rescue_cmd_testload): Likewise. - (pupa_rescue_cmd_lsmod): Likewise. - * normal/cmdline.c (pupa_cmdline_get): Likewise. - * normal/menu.c (run_menu): Likewise. - * kern/term.c (pupa_cls): Likewise. - (pupa_refresh): New function. - * normal/normal.c (pupa_normal_init) [PUPA_UTIL]: New function. - (pupa_normal_fini) [PUPA_UTIL]: Likewise. - * util/console.c: New file. - - * util/i386/pc/getroot.c: New file. - * util/i386/pc/pupa-setup.c: Include . - (pupa_putchar): New function. - (pupa_refresh): Likewise. - (xgetcwd): Function moved to ... - (strip_extra_slashes): Likewise. - (get_prefix): Likewise. - * util/i386/pc/getroot.c: ... here. - (find_root_device): Function moved and renamed to... - * util/i386/pc/getroot.c (pupa_find_root_device): ... here. - Changed all callers. - * util/i386/pc/pupa-setup.c (guess_root_device): Function moved - and renamed to... - * util/i386/pc/getroot.c (pupa_guess_root_device): ... here. - Changed all callers. - * util/misc.c (pupa_memalign): New function. - (pupa_mm_init_region): Likewise. - (pupa_register_exported_symbols): Likewise. - (pupa_putchar): Function removed. - * util/pupa-emu.c: New file. - -2003-11-16 Jeroen Dekkers - - * conf/i386-pc.rmk (pkgdata_MODULES): Add _multiboot.mod. - (_multiboot_mod_SOURCES): New variable. - (_multiboot_mod_CFLAGS): Likewise. - * loader/i386/pc/multiboot.c: New file. - * include/pupa/i386/pc/multiboot.h: Likewise. - * kern/i386/pc/startup.S: Include pupa/machine/multiboot.h. - (pupa_multiboot_real_boot): New function. - * include/pupa/i386/pc/loader.h: Include pupa/machine/multiboot.h. - (pupa_multiboot_real_boot): New prototype. - (pupa_rescue_cmd_multiboot): Likewise - (pupa_rescue_cmd_module): Likewise. - - * kern/loader.c (pupa_loader_set): Continue when - pupa_loader_unload_func() fails. - (pupa_loader_unset): New function. - * include/pupa/loader.h (pupa_loader_unset): New prototype. - - * kern/misc.c (pupa_stpcpy): New function. - * include/pupa/misc.h (pupa_stpcpy): New prototype. - -2003-11-12 Marco Gerards - - * disk/i386/pc/biosdisk.c (pupa_biosdisk_open): Correctly check - for available extensions. - - * include/pupa/i386/pc/time.h: New file. - * kern/disk.c: Include . - (PUPA_CACHE_TIMEOUT): New macro. - (pupa_last_time): New variable. - (pupa_disk_open): Flush the cache when there was a timeout. - (pupa_disk_close): Reset the timer. - * kern/i386/pc/startup.S (pupa_get_rtc): Renamed from - pupa_currticks. - * util/misc.c: Include - (pupa_get_rtc): New function. - -2003-11-09 Jeroen Dekkers - - * fs/ext2.c (struct pupa_ext2_inode): Declare struct datablocks - as blocks. - (pupa_ext2_get_file_block): Use blocks member. - - * fs/ext2.c (pupa_ext2_read_file): Only set skipfirst for the - first block. Return -1 instead of pupa_errno on error. - -2003-10-27 Marco Gerards - - * README: In the pupa-mkimage example use _chain instead of chain - and ext2 instead of fat. - * TODO: Replace ext2fs with jfs as an example. Add an item for - adding journal playback for ext2fs. - * conf/i386-pc.rmk (pupa_setup_SOURCES): Added fs/ext2.c. - (pkgdata_MODULES): Added ext2.mod. - (ext2_mod_SOURCES): New variable. - (ext2_mod_CFLAGS): Likewise. - * include/pupa/err.h (pupa_err_t): Added PUPA_ERR_SYMLINK_LOOP. - * include/pupa/misc.h (pupa_strncpy): New prototype. - (pupa_strcat): Likewise. - (pupa_strncmp): Likewise. - * kern/misc.c (pupa_strcat): Enable function. - (pupa_strncpy): New function. - (pupa_strncmp): Likewise. - * fs/ext2.c: New file. - - * kern/disk.c (pupa_disk_read): Set pupa_errno to PUPA_ERR_NONE - when the read failed before retrying. - * util/i386/pc/biosdisk.c (_LARGEFILE_SOURCE): Removed. - (_FILE_OFFSET_BITS): Likewise. - * configure.ac: Added AC_SYS_LARGEFILE. - -2003-09-25 Yoshinori K. Okuji - - * genmk.rb (PModule#rule): Make sure to get only symbol names - from the output of nm. - Reported by Robert Millan . - -2003-09-25 Yoshinori K. Okuji - - I forgot to check in these changes for a long time. This adds - incomplete support for VGA console, and this is still very - buggy. Also, a lot of consideration is required for I18N, - UNICODE, and VGA font issues. Therefore, assume that this is - such that "better than nothing". - - * font/manager.c: New file. - * include/pupa/font.h: Likewise. - * include/pupa/i386/pc/vga.h: Likewise. - * term/i386/pc/vga.c: Likewise. - * util/unifont2pff.rb: Likewise. - - * conf/i386-pc.rmk (kernel_img_HEADERS): Added machine/vga.h. - (pkgdata_MODULES): Added vga.mod and font.mod. - (vga_mod_SOURCES): New variables. - (vga_mod_CFLAGS): Likewise. - (font_mod_SOURCES): Likewise. - (font_mod_CFLAGS): Likewise. - - * include/pupa/err.h (PUPA_ERR_BAD_FONT): New constant. - - * include/pupa/term.h: Include pupa/err.h. - (struct pupa_term): Added init and fini. - Changed the argument of putchar to pupa_uint32_t. - - * include/pupa/i386/pc/console.h: Include pupa/symbol.h. - (pupa_console_real_putchar): New prototype. - (pupa_console_putchar): Removed. - (pupa_console_checkkey): Exported. - (pupa_console_getkey): Likewise. - - * kern/misc.c (pupa_vsprintf): Add support for UNICODE - characters. - - * kern/term.c (pupa_term_set_current): Rewritten. - (pupa_putchar): Likewise. - (pupa_putcode): New function. - - * kern/i386/pc/startup.S (pupa_console_putchar): Renamed to ... - (pupa_console_real_putchar): ... this. - (pupa_vga_set_mode): New function. - (pupa_vga_get_font): Likewise. - - * normal/command.c: Include pupa/term.h. - (terminal_command): New function. - (pupa_command_init): Register the command "terminal". - - * normal/menu.c (DISP_LEFT): Changed to a UNICODE value. - (DISP_UP): Likewise. - (DISP_RIGHT): Likewise. - (DISP_DOWN): Likewise. - (DISP_HLINE): Likewise. - (DISP_VLINE): Likewise. - (DISP_UL): Likewise. - (DISP_UR): Likewise. - (DISP_LL): Likewise. - (DISP_LR): Likewise. - - * term/i386/pc/console.c (pupa_console_putchar): New function. - -2003-02-08 NIIBE Yutaka - - * util/resolve.c (pupa_util_resolve_dependencies): BUG - FIX. Reverse the path_list. - - * include/pupa/normal.h: Export pupa_register_command and - pupa_unregister_command. - - * hello/hello.c (pupa_cmd_hello): New module. - * conf/i386-pc.rmk: Added hello.mod. - -2003-01-31 Yoshinori K. Okuji - - * kern/i386/pc/lzo1x.S: New file. - - * util/i386/pc/pupa-mkimage.c: Include lzo1x.h. - (compress_kernel): New variable. - (generate_image): Heavily modified to support compressing a - large part of the core image. - - * util/misc.c (pupa_util_read_image): Fix a file descriptor - leak. - (pupa_util_load_image): New function. - - * kern/i386/pc/startup.S: Include pupa/machine/kernel.h. - (pupa_compressed_size): New variable. - (codestart): Enable Gate A20 here. - Decompress the compressed part of the core image. - Rearrange the code to put functions and variables which are - required for initialization in the non-compressed part. - Include lzo1x.S. - - * kern/i386/pc/init.c (pupa_machine_init): Don't enable Gate A20 - here. - - * include/pupa/util/misc.h (pupa_util_write_image): Declared. - - * include/pupa/i386/pc/kernel.h - (PUPA_KERNEL_MACHINE_COMPRESSED_SIZE): New macro. - (PUPA_KERNEL_MACHINE_INSTALL_DOS_PART): Increased by 4. - (PUPA_KERNEL_MACHINE_INSTALL_BSD_PART): Likewise. - (PUPA_KERNEL_MACHINE_PREFIX): Likewise. - (PUPA_KERNEL_MACHINE_RAW_SIZE): New macro. - - * conf/i386-pc.rmk (pupa_mkimage_LDFLAGS): New variable. - - * genmk.rb (Image#rule): Put LDFLAGS at the end of a line. - (Utility#rule): Likewise. - - * configure.ac: Check if LZO is available. - -2003-01-20 Yoshinori K. Okuji - - * include/pupa/normal.h: New file. - * include/pupa/setjmp.h: Likewise. - * include/pupa/i386/setjmp.h: Likewise. - * normal/cmdline.c: Likewise. - * normal/command.c: Likewise. - * normal/main.c: Likewise. - * normal/menu.c: Likewise. - * normal/i386/setjmp.S: Likewise. - - * loader/i386/pc/linux.c (pupa_rescue_cmd_linux): Made global. - (pupa_rescue_cmd_initrd): Likewise. - - * loader/i386/pc/chainloader.c (pupa_rescue_cmd_chainloader): - Likewise. - - * kern/i386/pc/startup.S (translation_table): New variable. - (translate_keycode): New function. - (pupa_console_getkey): Call translate_keycode. - - * kern/rescue.c (attempt_normal_mode): New function. - (pupa_enter_rescue_mode): Attempt to execute the normal mode. If - it failed, print a message. - - * kern/mm.c (pupa_real_malloc): Print more information when a - free magic is broken. - (pupa_free): If the first free header is not free actually, set - it to P. - - * kern/main.c (pupa_load_normal_mode): Just load the module - "normal". - (pupa_main): Don't print the message - "Entering into rescue mode..." here. - - * include/pupa/i386/pc/loader.h (pupa_rescue_cmd_initrd): - Declared. - (pupa_rescue_cmd_initrd): Likewise. - (pupa_rescue_cmd_initrd): Likewise. - - * include/pupa/symbol.h (FUNCTION): Specify the type. - (VARIABLE): Likewise. - - * include/pupa/err.h (pupa_err_t): Added - PUPA_ERR_UNKNOWN_COMMAND. - - * include/pupa/dl.h (pupa_dl_set_prefix): Exported. - (pupa_dl_get_prefix): Likewise. - - * conf/i386-pc.rmk (pkgdata_MODULES): Added normal.mod. - Added _chain.mod and _linux.mod instead of chain.mod and - linux.mod. - (chain_mod_SOURCES): Renamed to ... - (_chain_mod_SOURCES): ... this. - (chain_mod_CFLAGS): Renamed to ... - (_chain_mod_CFLAGS): ... this. - (linux_mod_SOURCES): Renamed to ... - (_linux_mod_SOURCES): ... this. - (linux_mod_CFLAGS): Renamed to ... - (_linux_mod_CFLAGS): ... this. - (normal_mod_SOURCES): New variable. - (normal_mod_CFLAGS): Likewise. - (normal_mod_ASFLAGS): Likewise. - -2003-01-18 Yoshinori K. Okuji - - * kern/rescue.c (pupa_rescue_cmd_rmmod): Call pupa_dl_unload, if - possible. - - * kern/dl.c (pupa_dl_ref): Refer depending modules - recursively. - (pupa_dl_unref): Unrefer depending modules recursively. - Don't call pupa_dl_unload implicitly, because PUPA can crash if - a module is unloaded before one depending on that module is - unloaded. - (pupa_dl_unload): Unload depending modules explicitly, - if possible. - -2003-01-17 Yoshinori K. Okuji - - * include/pupa/i386/pc/linux.h: New file. - * loader/i386/pc/linux.c: Likewise. - - * loader/i386/pc/chainloader.c (pupa_chainloader_boot_sector): - Removed. - (pupa_chainloader_unload): Return PUPA_ERR_NONE. - (pupa_rescue_cmd_chainloader): Read the image to 0x7C00 instead - of PUPA_CHAINLOADER_BOOT_SECTOR. - - * kern/i386/pc/startup.S: Include pupa/machine/linux.h. - (pupa_linux_prot_size): New variable. - (pupa_linux_tmp_addr): Likewise. - (pupa_linux_real_addr): Likewise. - (pupa_linux_boot_zimage): New function. - (pupa_linux_boot_bzimage): Likewise. - - * kern/i386/pc/init.c (struct mem_region): New structure. - (MAX_REGIONS): New macro. - (mem_regions): New variable. - (num_regions): Likewise. - (pupa_os_area_addr): Likewise. - (pupa_os_area_size): Likewise. - (pupa_lower_mem): Likewise. - (pupa_upper_mem): Likewise. - (add_mem_region): New function. - (compact_mem_regions): Likewise. - (pupa_machine_init): Set PUPA_LOWER_MEM and PUPA_UPPER_MEM to - the size of the conventional memory and that of so-called upper - memory (before the first memory hole). - Instead of adding each found region to free memory, use - add_mem_region and add them after removing overlaps. - Also, add only 1/4 of the upper memory to free memory. The rest - is used for loading OS images. Maybe this is ad hoc, but this - makes it much easier to relocate OS images when booting. - - * kern/rescue.c (pupa_rescue_cmd_module): Removed. - (pupa_enter_rescue_mode): Don't register initrd and module. - - * kern/mm.c: Include pupa/dl.h. - - * kern/main.c: Include pupa/file.h and pupa/device.h. - - * kern/loader.c (pupa_loader_load_module_func): Removed. - (pupa_loader_load_module): Likewise. - - * kern/dl.c (pupa_dl_load): Use the suffix ``.mod'' instead of - ``.o''. - - * include/pupa/i386/pc/loader.h (pupa_linux_prot_size): Declared. - (pupa_linux_tmp_addr): Likewise. - (pupa_linux_real_addr): Likewise. - (pupa_linux_boot_zimage): Likewise. - (pupa_linux_boot_bzimage): Likewise. - - * include/pupa/i386/pc/init.h (pupa_lower_mem): Declared. - (pupa_upper_mem): Likewise. - (pupa_gate_a20): Don't export, because turning off Gate A20 in a - module is too dangerous. - - * include/pupa/loader.h (pupa_os_area_addr): Declared. - (pupa_os_area_size): Likewise. - (pupa_loader_set): Remove the first argument. Loader doesn't - manage modules or initrd any longer. - (pupa_loader_load_module): Removed. - - * conf/i386-pc.rmk (pkgdata_MODULES): Added linux.mod. - (linux_mod_SOURCES): New variable. - (linux_mod_CFLAGS): Likewise. - -2003-01-07 Yoshinori K. Okuji - - * util/i386/pc/pupa-setup.c (setup): Convert the endianness of - the length of a blocklist correctly. - - * util/i386/pc/biosdisk.c (pupa_util_biosdisk_open) [__linux__]: - Use ioctl only if the OS file is a block device. - (pupa_util_biosdisk_open): Don't use ST.ST_BLOCKS, because it is - not very useful for normal files. - - * kern/main.c (pupa_set_root_dev): New function. - (pupa_load_normal_mode): Likewise. - (pupa_main): Call those above. - - * include/pupa/types.h (pupa_swap_bytes16): Cast the result to - pupa_uint16_t. - - * include/pupa/kernel.h (pupa_enter_normal_mode): Removed. - -2003-01-06 Yoshinori K. Okuji - - * util/i386/pc/pupa-setup.c: Include pupa/machine/kernel.h. - (setup): Configure the installed partition information and the - dl prefix. - - * loader/i386/pc/chainloader.c (my_mod): New variable. - (pupa_chainloader_unload): New function. - (pupa_rescue_cmd_chainloader): Refer itself. - (PUPA_MOD_INIT): Save its own module in MY_MOD. - - * kern/i386/pc/startup.S (install_partition): Removed. - (version_string): Likewise. - (config_file): Likewise. - (pupa_install_dos_part): New variable. - (pupa_install_bsd_part): Likewise. - (pupa_prefix): Likewise. - (pupa_chainloader_real_boot): Call pupa_dl_unload_all. - - * kern/i386/pc/init.c: Include pupa/machine/kernel.h, pupa/dl.h - and pupa/misc.h. - (make_install_device): New function. - (pupa_machine_init): Set the dl prefix. - - * kern/rescue.c: Include pupa/rescue.h and pupa/dl.h. - (buf): Renamed to ... - (linebuf): ... this. - (pupa_rescue_cmd_prefix): New function. - (pupa_rescue_cmd_insmod): Likewise. - (pupa_rescue_cmd_rmmod): Likewise. - (pupa_rescue_cmd_lsmod): Likewise. - (pupa_enter_rescue_mode): Register new commands: prefix, insmod, - rmmod and lsmod. - - * kern/mm.c (pupa_memalign): If failed even after invalidating - disk caches, unload unneeded modules and retry. - - * kern/misc.c (pupa_memmove): New function. - (pupa_memcpy): Removed. - (pupa_strcpy): New function. - (pupa_itoa): Made static. - - * kern/dl.c (pupa_dl_iterate): New function. - (pupa_dl_ref): Likewise. - (pupa_dl_unref): Likewise. - (pupa_dl_unload): Return if succeeded or not. - (pupa_dl_unload_unneeded): New function. - (pupa_dl_unload_all): Likewise. - (pupa_dl_init): Renamed to ... - (pupa_dl_set_prefix): ... this. - (pupa_dl_get_prefix): New function. - - * include/pupa/i386/pc/kernel.h: Include pupa/types.h. - (PUPA_KERNEL_MACHINE_INSTALL_DOS_PART): New macro. - (PUPA_KERNEL_MACHINE_INSTALL_BSD_PART): Likewise. - (PUPA_KERNEL_MACHINE_PREFIX): Likewise. - (pupa_install_dos_part): Declared. - (pupa_install_bsd_part): Likewise. - (pupa_prefix): Likewise. - (pupa_boot_drive): Likewise. - - * include/pupa/types.h: Fix a typo. - - * include/pupa/misc.h (pupa_memcpy): New macro. Just an alias to - pupa_memmove. - (pupa_memmove): Declared. - (pupa_strcpy): Likewise. - - * include/pupa/dl.h (PUPA_MOD_INIT): Change the prototype. Now - pupa_mod_init takes one argument, its own module. - (pupa_dl_unload_unneeded): Declared. - (pupa_dl_unload_all): Likewise. - (pupa_dl_ref): Likewise. - (pupa_dl_unref): Likewise. - (pupa_dl_iterate): Likewise. - (pupa_dl_init): Renamed to ... - (pupa_dl_set_prefix): ... this. - (pupa_dl_get_prefix): Declared. - - * fs/fat.c [!PUPA_UTIL] (my_mod): New variable. - (pupa_fat_dir) [!PUPA_UTIL]: Prevent the fat module from being - unloaded. - (pupa_fat_open) [!PUPA_UTIL]: Refer itself if succeeded. - (pupa_fat_close) [!PUPA_UTIL]: Unrefer itself. - - * configure.ac (tmp_CFLAGS): Added -Wshadow, -Wpointer-arith, - -Wmissing-prototypes, -Wundef and -Wstrict-prototypes. - -2003-01-03 Yoshinori K. Okuji - - * util/i386/pc/pupa-setup.c (setup): Define the internal - function find_first_partition_start at the top level, because GCC - 3.0.x cannot compile internal functions in deeper scopes - correctly. - (find_root_device): Use lstat instead of stat. - Don't follow symbolic links. - Fix the path-constructing code. - - * util/i386/pc/biosdisk.c [__linux__] (BLKFLSBUF): New macro. - (pupa_util_biosdisk_open) [__linux__]: Get the size of a device - by a BLKGETSIZE ioctl first, because block devices don't fill - the member st_mode of the structure stat on Linux. - [__linux__] (linux_find_partition): Use a temporary buffer - REAL_DEV for the working space. Copy it to DEV before returning. - (open_device) [__linux__]: Call ioctl with BLKFLSBUF to make the - buffer cache consistent. - (get_os_disk) [__linux__]: Use the length 5 instead of 4 for - strncmp. The previous value was merely wrong. - (pupa_util_biosdisk_get_pupa_dev): Use stat instead of lstat. - - * fs/fat.c (pupa_fat_read_data): Shift 4 instead of 12 when the - FAT size is 12. The previous value was merely wrong. - - * kern/main.c (pupa_main): Don't split the starting message from - newlines. - - * kern/term.c (pupa_putchar): Put CR after LF instead of before - LF, because BIOS goes crazy about character attributes in this - case. - -2003-01-03 Yoshinori K. Okuji - - * include/i386/pc/util/biosdisk.h: New file. - * util/i386/pc/biosdisk.c: Likewise. - * util/i386/pc/pupa-setup.c: Likewise. - - * Makefile.in (INCLUDE_DISTFILES): Added - include/pupa/i386/pc/util/biosdisk.h. - (UTIL_DISTFILES): Added biosdisk.c and pupa-setup.c under the - directory util/i386/pc. - (install-local): Added a rule for sbin_UTILITIES. - (uninstall): Likewise. - - * util/i386/pc/pupa-mkimage.c (usage): Fix a typo in the doc. - - * util/misc.c (xrealloc): New function. - (pupa_malloc): Likewise. - (pupa_free): Likewise. - (pupa_realloc): Likewise. - (pupa_stop): Likewise. - (pupa_putchar): Likewise. - - * kern/disk.c (pupa_disk_read): Prevent L from underflowing. - - * include/pupa/util/misc.h (xrealloc): Declared. - - * include/pupa/i386/pc/boot.h (PUPA_BOOT_MACHINE_BPB_START): New - macro. - (PUPA_BOOT_MACHINE_BPBEND): Renamed to ... - (PUPA_BOOT_MACHINE_BPB_END): ... this. - - * include/pupa/fs.h [PUPA_UTIL] (pupa_fat_init): Declared. - [PUPA_UTIL] (pupa_fat_fini): Likewise. - - * fs/fat.c [PUPA_UTIL] (pupa_fat_init): Defined. Maybe a better - way should be implemented. - [PUPA_UTIL] (pupa_fat_fini): Likewise. - - * disk/i386/pc/biosdisk.c (pupa_biosdisk_call_hook): Increase - the size of NAME for safety. - (pupa_biosdisk_iterate): Search hard disks to 0x90 instead of - 0x88. - - * conf/i386-pc.rmk (sbin_UTILITIES): New variable. - (pupa_setup_SOURCES): Likewise. - - * genmk.rb (Utility#rule): Add $(BUILD_CFLAGS) into the rules. - -2002-12-28 Yoshinori K. Okuji - - * kern/i386/pc/startup.S (push_get_mmap_entry): Revert to a - bunch of pushl's from pusha, because this destroys the return - value. - -2002-12-28 Yoshinori K. Okuji - - Use -mrtd and -mregparm=3 to reduce the generated code sizes. - This means that any missing prototypes could be fatal. Also, you - must take care when writing assembly code. See the comments at - the beginning of startup.S, for more details. - - * kern/i386/pc/startup.S (pupa_halt): Modified for the new - compilation mechanism. - (pupa_chainloader_real_boot): Likewise. - (pupa_biosdisk_rw_int13_extensions): Likewise. - (pupa_biosdisk_rw_standard): Likewise. - (pupa_biosdisk_check_int13_extensions): Likewise. - (pupa_biosdisk_get_diskinfo_int13_extensions): Likewise. - (pupa_biosdisk_get_diskinfo_standard): Likewise. - (pupa_get_memsize): Likewise. - (pupa_get_mmap_entry): Likewise. - (pupa_console_putchar): Likewise. - (pupa_console_setcursor): Likewise. - (pupa_getrtsecs): Use pushl instead of push. - - * kern/i386/pc/init.c (pupa_machine_init): Use the scratch - memory instead of the stack for a mmap entry, because some - BIOSes may ignore the maximum size and overflow. - - * conf/i386-pc.rmk (COMMON_CFLAGS): Added -mrtd and -mregparm=3. - - * genmk.rb (PModule#rule): Compile automatically generated - sources with module-specific CFLAGS as well as other sources. - -2002-12-27 Yoshinori K. Okuji - - * configure.ac: Check ld. - Replace CFLAGS and CPPFLAGS with BUILD_CFLAGS and BUILD_CPPFLAGS - respectively, before checking endianness and sizes. - - * Makefile.in (LD): New variable. - -2002-12-27 Yoshinori K. Okuji - - * Makefile.in (BUILD_CC): CC -> BUILD_CC. - -2002-12-27 Yoshinori K. Okuji - - * Changelog: New file. - diff --git a/INSTALL b/INSTALL index e325fa2b2..724584c57 100644 --- a/INSTALL +++ b/INSTALL @@ -4,6 +4,10 @@ This is the GRUB. Welcome. This file contains instructions for compiling and installing the GRUB. +Where this document refers to packages names, they are named according to the +Debian 11 package repositories. These packages can be found by searching +https://packages.debian.org/. + The Requirements ================ @@ -11,40 +15,95 @@ GRUB depends on some software packages installed into your system. If you don't have any of them, please obtain and install them before configuring the GRUB. -* GCC 4.1.3 or later +* GCC 5.1.0 or later + Experimental support for clang 8.0.0 or later (results in much bigger binaries) + for i386, x86_64, arm (including thumb), arm64, mips(el), powerpc, sparc64 * GNU Make * GNU Bison 2.3 or later -* GNU gettext 0.17 or later +* GNU gettext * GNU binutils 2.9.1.0.23 or later * Flex 2.5.35 or later +* pkg-config +* GNU patch * Other standard GNU/Unix tools +* a libc with large file support (e.g. glibc 2.1 or later) On GNU/Linux, you also need: * libdevmapper 1.02.34 or later (recommended) -To build grub-emu, you need: +For optional grub-emu features, you need: -* ncurses -* libusb (recommended) * SDL (recommended) +* libpciaccess (optional) To build GRUB's graphical terminal (gfxterm), you need: -* FreeType 2 or later +* FreeType 2.1.5 or later * GNU Unifont +To build grub-mkfont the unicode fonts are required (xfonts-unifont package +on Debian). + If you use a development snapshot or want to hack on GRUB you may need the following. -* Python 2.5.2 or later -* Autoconf 2.60 or later -* Automake 1.10.1 or later -* Autogen 5.10 or later +* Python 3 (NOTE: python 2.6 should still work, but it's not tested) +* Autoconf 2.64 or later +* Automake 1.14 or later + +Your distro may package cross-compiling toolchains such as the following +incomplete list on Debian: gcc-aarch64-linux-gnu, gcc-arm-linux-gnueabihf, +gcc-mips-linux-gnu, gcc-mipsel-linux-gnu, gcc-powerpc64-linux-gnu, +gcc-riscv64-linux-gnu, gcc-sparc64-linux-gnu, mingw-w64 and mingw-w64-tools. + +More cross compiling toolchains can be found at the following trusted sites: + +* https://mirrors.kernel.org/pub/tools/crosstool/ +* https://toolchains.bootlin.com/ Prerequisites for make-check: -* qemu, specifically the binary 'qemu-system-i386' +* qemu, specifically the binary "qemu-system-ARCH" where ARCH is the + architecture GRUB has been built for; the "qemu-system" package on Debian + will install all needed qemu architectures +* OVMF, for EFI platforms (packages ovmf, ovmf-ia32, qemu-efi-arm, and + qemu-efi-aarch64) +* OpenBIOS, for ieee1275 platforms (packages openbios-ppc and openbios-sparc) +* xorriso 1.2.9 or later, for grub-mkrescue and grub-shell +* wamerican, for grub-fs-tester +* mtools, FAT tools for EFI platforms +* xfonts-unifont, for the functional tests +* swtpm-tools and tpm2-tools, for TPM2 key protector tests + +* If running a Linux kernel the following modules must be loaded: + - fuse, loop + - btrfs, erofs, ext4, f2fs, fat, hfs, hfsplus, jfs, mac-roman, minix, nilfs2, + reiserfs, udf, xfs + - On newer kernels, the exfat kernel modules may be used instead of the + exfat FUSE filesystem +* The following are Debian named packages required mostly for the full + suite of filesystem testing (but some are needed by other tests as well): + - btrfs-progs, dosfstools, e2fsprogs, erofs-utils, exfatprogs, exfat-fuse, + f2fs-tools, genromfs, hfsprogs, jfsutils, nilfs-tools, ntfs-3g, + reiserfsprogs, squashfs-tools, reiserfsprogs, udftools, xfsprogs, zfs-fuse + - exfat-fuse, if not using the exfat kernel module + - gzip, lzop, xz-utils + - attr, cpio, g++, gawk, parted, recode, tar, util-linux + +Note that `make check' will run and many tests may complete successfully +with only a subset of these prerequisites. However, some tests may be +skipped or fail due to missing prerequisites. + +To build the documentation you'll need: +* texinfo, for the info and html documentation +* texlive, for building the dvi and pdf documentation (optional) + +To use the gdb_grub GDB script you'll need: +* readelf (binutils package) +* objdump (binutils package) +* GNU Debugger > 7, built with python support (gdb package) +* Python >= 3.5 (python3 package) Configuring the GRUB ==================== @@ -75,9 +134,17 @@ Building the GRUB The simplest way to compile this package is: - 1. `cd' to the directory containing the package's source code. If - you don't use a release tarball you have to type `./autogen.sh'. - Type `./configure' to configure the package for your system. + 1. `cd' to the directory containing the package's source code. + + 2. Skip this and following step if you use release tarball and proceed to + step 4. If you want translations type `./linguas.sh'. + + 3. Type `./bootstrap'. + + The autogen.sh (called by bootstrap) uses python. By default autodetect + it, but it can be overridden by setting the PYTHON variable. + + 4. Type `./configure' to configure the package for your system. If you're using `csh' on an old version of System V, you might need to type `sh ./configure' instead to prevent `csh' from trying to execute `configure' itself. @@ -85,15 +152,19 @@ The simplest way to compile this package is: Running `configure' takes awhile. While running, it prints some messages telling which features it is checking for. - 2. Type `make' to compile the package. + 6. Type `make' to compile the package. - 3. Optionally, type `make check' to run any self-tests that come with - the package. + 7. Optionally, type `make check' to run any self-tests that come with + the package. Note that many of the tests require root privileges in + order to run. - 4. Type `make install' to install the programs and any data files and + 8. Type `make install' to install the programs and any data files and documentation. - 5. You can remove the program binaries and object files from the + 9. Type `make html' or `make pdf' to generate the html or pdf + documentation. Note, these are not built by default. + + 10. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is @@ -102,6 +173,108 @@ The simplest way to compile this package is: all sorts of other programs in order to regenerate files that came with the distribution. +Cross-compiling the GRUB +======================== + +GRUB defines 3 platforms: + + - "Build" is the one which build systems runs on. + - "Host" is where you execute GRUB utils. + - "Target" is where GRUB itself runs. + +For grub-emu host and target must be the same but may differ from build. + +If build and host are different make check isn't available. + +If build and host are different man pages are not generated. + +As an example imagine you have a build system running on FreeBSD on sparc +which prepares packages for developers running amd64 GNU/Linux laptop and +they need to make images for ARM board running U-boot. In this case: + +build=sparc64-freebsd +host=amd64-linux-gnu +target=arm-uboot + +For this example the configure line might look like (more details below) +(some options are optional and included here for completeness but some rarely +used options are omitted): + + ./configure --build=sparc64-freebsd --host=x86_64-linux-gnu \ + --target=arm-linux-gnueabihf --with-platform=efi \ + BUILD_CC=gcc BUILD_PKG_CONFIG=pkg-config \ + HOST_CC=x86_64-linux-gnu-gcc HOST_CFLAGS='-g -O2' \ + PKG_CONFIG=x86_64-linux-gnu-pkg-config TARGET_CC=arm-linux-gnueabihf-gcc \ + TARGET_CFLAGS='-Os -march=armv8.3-a' TARGET_CCASFLAGS='-march=armv8.3-a' \ + TARGET_OBJCOPY=arm-linux-gnueabihf-objcopy \ + TARGET_STRIP=arm-linux-gnueabihf-strip TARGET_NM=arm-linux-gnueabihf-nm \ + TARGET_RANLIB=arm-linux-gnueabihf-ranlib LEX=flex + +Note, that the autoconf 2.65 manual states that when using the --host argument +to configure, the --build argument should be specified as well. Not sending +--build, enters a compatibility mode that will be removed in the future. + +Normally, for building a GRUB on amd64 with tools to run on amd64 to +generate images to run on ARM, using your Linux distribution's +packaged cross compiler, the following would suffice: + + ./configure --target=arm-linux-gnueabihf --with-platform=efi + +You need to use following options to specify tools and platforms. For minimum +version look at prerequisites. All tools not mentioned in this section under +corresponding platform are not needed for the platform in question. + + - For build + 1. --build= to autoconf name of build. + 2. BUILD_CC= to gcc able to compile for build. This is used, for + example, to compile build-gentrigtables which is then run to + generate sin and cos tables. + 3. BUILD_CFLAGS= for C options for build. + 4. BUILD_CPPFLAGS= for C preprocessor options for build. + 5. BUILD_LDFLAGS= for linker options for build. + 6. BUILD_PKG_CONFIG= for pkg-config for build (optional). + + - For host + 1. --host= to autoconf name of host. + 2. CC= for gcc able to compile for host. + 3. CFLAGS= for C options for host. + 4. HOST_CC= for gcc able to compile for host. + 5. HOST_CFLAGS= for C options for host. + 6. HOST_CPPFLAGS= for C preprocessor options for host. + 7. HOST_LDFLAGS= for linker options for host. + 8. PKG_CONFIG= for pkg-config for host (optional). + 9. Libdevmapper if any must be in standard linker folders (-ldevmapper) (optional). + 10. Libfuse if any must be in standard linker folders (-lfuse) (optional). + 11. Libzfs if any must be in standard linker folders (-lzfs) (optional). + 12. Liblzma if any must be in standard linker folders (-llzma) (optional). + Note: The HOST_* variables override not prefixed variables. + + - For target + 1. --target= to autoconf cpu name of target. + 2. --with-platform to choose firmware. + 3. TARGET_CC= for gcc able to compile for target. + 4. TARGET_CFLAGS= for C options for target. + 5. TARGET_CPPFLAGS= for C preprocessor options for target. + 6. TARGET_CCASFLAGS= for assembler options for target. + 7. TARGET_LDFLAGS= for linker options for target. + 8. TARGET_OBJCOPY= for objcopy for target. + 9. TARGET_STRIP= for strip for target. + 10. TARGET_NM= for nm for target. + 11. TARGET_RANLIB= for ranlib for target. + Note: If the TARGET_* variables are not specified then they will default + to be the same as the host variables. If host variables are not + specified then the TARGET_* variables will default to be the same + as not prefixed variables. + + - Additionally for emu, for host and target. + 1. SDL is looked for in standard linker directories (-lSDL) (optional) + 2. libpciaccess is looked for in standard linker directories (-lpciaccess) (optional) + + - Platform-agnostic tools and data. + 1. make is the tool you execute after ./configure. + 2. Bison is specified in YACC= variable + 3. Flex is specified in LEX= variable + 4. GNU unifont and Djvu sans are looked for in standard directories. Compiling For Multiple Architectures ==================================== diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 000000000..45e870c78 --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1,35 @@ +List of current GRUB maintainers and some basic information about the project +============================================================================= + +Here is the list of current GRUB maintainers: + - Daniel Kiper and , + - Alex Burmashev , + - Vladimir 'phcoder' Serbinenko . + +The maintainers drive and overlook the GRUB development. + +If you found a security vulnerability in the GRUB please check the SECURITY +file to get more information how to properly report this kind of bugs to +the maintainers. + +The GRUB development happens on the grub-devel mailing list [1]. The latest +GRUB source code is available at Savannah git repository [2]. + +Users can ask for help on the help-grub mailing list [3]. + + +List of past GRUB maintainers and people who strongly contributed to the project +================================================================================ + +Here is the list, sorted alphabetically, of past GRUB maintainers and people who +strongly contributed to the project: + - Andrei Borzenkov, + - Bryan Ford, + - Erich Stefan Boleyn, + - Gordon Matzigkeit, + - Yoshinori K. Okuji. + + +[1] https://lists.gnu.org/mailman/listinfo/grub-devel +[2] https://git.savannah.gnu.org/gitweb/?p=grub.git&view=view+git+repository +[3] https://lists.gnu.org/mailman/listinfo/help-grub diff --git a/Makefile.am b/Makefile.am index db9e930ff..43635d5ff 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,11 @@ AUTOMAKE_OPTIONS = subdir-objects -Wno-portability DEPDIR = .deps-util -SUBDIRS = grub-core/gnulib . grub-core po docs util/bash-completion.d +SUBDIRS = grub-core/lib/gnulib . +if COND_real_platform +SUBDIRS += grub-core +endif +SUBDIRS += po docs util/bash-completion.d include $(top_srcdir)/conf/Makefile.common include $(top_srcdir)/conf/Makefile.extra-dist @@ -20,6 +24,15 @@ CCASFLAGS_PROGRAM += $(CCASFLAGS_GNULIB) include $(srcdir)/Makefile.util.am +check_SCRIPTS = $(check_SCRIPTS_native) $(check_SCRIPTS_nonnative) +check_PROGRAMS = $(check_PROGRAMS_native) $(check_PROGRAMS_nonnative) +TESTS = $(check_SCRIPTS) $(check_PROGRAMS) + +check-native: + $(MAKE) TESTS="$(check_PROGRAMS_native) $(check_SCRIPTS_native)" check +check-nonnative: + $(MAKE) TESTS="$(check_PROGRAMS_nonnative) $(check_SCRIPTS_nonnative)" check + # XXX Use Automake's LEX & YACC support grub_script.tab.h: $(top_srcdir)/grub-core/script/parser.y $(YACC) -d -p grub_script_yy -b grub_script $(top_srcdir)/grub-core/script/parser.y @@ -33,13 +46,13 @@ grub_script.yy.c: grub_script.yy.h CLEANFILES += grub_script.yy.c grub_script.yy.h # For libgrub.a -libgrub.pp: grub_script.tab.h grub_script.yy.h $(libgrubmods_a_SOURCES) $(libgrubkern_a_SOURCES) +libgrub.pp: config-util.h grub_script.tab.h grub_script.yy.h $(libgrubmods_a_SOURCES) $(libgrubkern_a_SOURCES) $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libgrubmods_a_CPPFLAGS) $(libgrubkern_a_CPPFLAGS) $(CPPFLAGS) \ -D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1) CLEANFILES += libgrub.pp libgrub_a_init.lst: libgrub.pp - cat $< | grep '@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1) + cat $< | grep '^@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1) CLEANFILES += libgrub_a_init.lst libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh @@ -47,189 +60,210 @@ libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh CLEANFILES += libgrub_a_init.c # For grub-fstest -grub_fstest.pp: $(grub_fstest_SOURCES) +grub_fstest.pp: config-util.h $(grub_fstest_SOURCES) $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(grub_fstest_CPPFLAGS) $(CPPFLAGS) \ -D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1) CLEANFILES += grub_fstest.pp grub_fstest_init.lst: libgrub.pp grub_fstest.pp - cat $^ | grep '@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1) + cat $^ | grep '^@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1) CLEANFILES += grub_fstest_init.lst grub_fstest_init.c: grub_fstest_init.lst $(top_srcdir)/geninit.sh sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1) CLEANFILES += grub_fstest_init.c -if COND_GRUB_MKFONT if COND_HAVE_FONT_SOURCE pkgdata_DATA += unicode.pf2 ascii.pf2 euro.pf2 ascii.h widthspec.h endif -endif starfield_theme_files = $(srcdir)/themes/starfield/blob_w.png $(srcdir)/themes/starfield/boot_menu_c.png $(srcdir)/themes/starfield/boot_menu_e.png $(srcdir)/themes/starfield/boot_menu_ne.png $(srcdir)/themes/starfield/boot_menu_n.png $(srcdir)/themes/starfield/boot_menu_nw.png $(srcdir)/themes/starfield/boot_menu_se.png $(srcdir)/themes/starfield/boot_menu_s.png $(srcdir)/themes/starfield/boot_menu_sw.png $(srcdir)/themes/starfield/boot_menu_w.png $(srcdir)/themes/starfield/slider_c.png $(srcdir)/themes/starfield/slider_n.png $(srcdir)/themes/starfield/slider_s.png $(srcdir)/themes/starfield/starfield.png $(srcdir)/themes/starfield/terminal_box_c.png $(srcdir)/themes/starfield/terminal_box_e.png $(srcdir)/themes/starfield/terminal_box_ne.png $(srcdir)/themes/starfield/terminal_box_n.png $(srcdir)/themes/starfield/terminal_box_nw.png $(srcdir)/themes/starfield/terminal_box_se.png $(srcdir)/themes/starfield/terminal_box_s.png $(srcdir)/themes/starfield/terminal_box_sw.png $(srcdir)/themes/starfield/terminal_box_w.png $(srcdir)/themes/starfield/theme.txt $(srcdir)/themes/starfield/README $(srcdir)/themes/starfield/COPYING.CC-BY-SA-3.0 +build-grub-mkfont$(BUILD_EXEEXT): util/grub-mkfont.c grub-core/unidata.c grub-core/kern/emu/misc.c util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-mkfont\" $^ $(BUILD_FREETYPE_CFLAGS) $(BUILD_FREETYPE_LIBS) +CLEANFILES += build-grub-mkfont$(BUILD_EXEEXT) + +garbage-gen$(BUILD_EXEEXT): util/garbage-gen.c + $(BUILD_CC) -o $@ $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $^ +CLEANFILES += garbage-gen$(BUILD_EXEEXT) +EXTRA_DIST += util/garbage-gen.c + +build-grub-gen-asciih$(BUILD_EXEEXT): util/grub-gen-asciih.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(BUILD_FREETYPE_CFLAGS) $(BUILD_FREETYPE_LIBS) -Wall -Werror +CLEANFILES += build-grub-gen-asciih$(BUILD_EXEEXT) + +build-grub-gen-widthspec$(BUILD_EXEEXT): util/grub-gen-widthspec.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_MKFONT=1 -DGRUB_BUILD=1 -DGRUB_UTIL=1 $^ $(BUILD_FREETYPE_CFLAGS) $(BUILD_FREETYPE_LIBS) -Wall -Werror +CLEANFILES += build-grub-gen-widthspec$(BUILD_EXEEXT) + if COND_STARFIELD starfield_DATA = dejavu_10.pf2 dejavu_12.pf2 dejavu_bold_14.pf2 dejavu_14.pf2 dejavu_16.pf2 $(starfield_theme_files) -dejavu_10.pf2: $(DJVU_FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -s 10 -o $@ $(DJVU_FONT_SOURCE) -dejavu_12.pf2: $(DJVU_FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -s 12 -o $@ $(DJVU_FONT_SOURCE) -dejavu_14.pf2: $(DJVU_FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -s 14 -o $@ $(DJVU_FONT_SOURCE) -dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -b -s 14 -o $@ $(DJVU_FONT_SOURCE) -dejavu_16.pf2: $(DJVU_FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -s 16 -o $@ $(DJVU_FONT_SOURCE) +dejavu_10.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) + ./build-grub-mkfont$(BUILD_EXEEXT) -s 10 -o $@ $(DJVU_FONT_SOURCE) +CLEANFILES += dejavu_10.pf2 +dejavu_12.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) + ./build-grub-mkfont$(BUILD_EXEEXT) -s 12 -o $@ $(DJVU_FONT_SOURCE) +CLEANFILES += dejavu_12.pf2 +dejavu_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) + ./build-grub-mkfont$(BUILD_EXEEXT) -s 14 -o $@ $(DJVU_FONT_SOURCE) +CLEANFILES += dejavu_14.pf2 +dejavu_bold_14.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) + ./build-grub-mkfont$(BUILD_EXEEXT) -b -s 14 -o $@ $(DJVU_FONT_SOURCE) +CLEANFILES += dejavu_bold_14.pf2 +dejavu_16.pf2: $(DJVU_FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) + ./build-grub-mkfont$(BUILD_EXEEXT) -s 16 -o $@ $(DJVU_FONT_SOURCE) +CLEANFILES += dejavu_16.pf2 else -starfield_DATA = +starfield_DATA = endif EXTRA_DIST += $(starfield_theme_files) EXTRA_DIST += $(srcdir)/themes/starfield/src/slider_s.xcf $(srcdir)/themes/starfield/src/slider_n.xcf $(srcdir)/themes/starfield/src/slider_c.xcf $(srcdir)/themes/starfield/src/blob_nw.xcf $(srcdir)/themes/starfield/src/bootmenu/center.xcf $(srcdir)/themes/starfield/src/bootmenu/corner.xcf $(srcdir)/themes/starfield/src/bootmenu/side.xcf $(srcdir)/themes/starfield/src/terminalbox/side.xcf $(srcdir)/themes/starfield/src/terminalbox/corner.xcf $(srcdir)/themes/starfield/src/terminalbox/center.xcf -unicode.pf2: $(FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) +unicode.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) + ./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) || (rm -f $@; exit 1) CLEANFILES += unicode.pf2 # Arrows and lines are needed to draw the menu, so always include them UNICODE_ARROWS=0x2190-0x2193 UNICODE_LINES=0x2501-0x251B -ascii.pf2: $(FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) +ascii.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) + ./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1) CLEANFILES += ascii.pf2 -euro.pf2: $(FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) +euro.pf2: $(FONT_SOURCE) build-grub-mkfont$(BUILD_EXEEXT) + ./build-grub-mkfont$(BUILD_EXEEXT) -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) || (rm -f $@; exit 1) CLEANFILES += euro.pf2 -ascii.bitmaps: $(FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont --ascii-bitmaps -o $@ $(FONT_SOURCE) -CLEANFILES += ascii.bitmaps +ascii.h: $(FONT_SOURCE) build-grub-gen-asciih$(BUILD_EXEEXT) + ./build-grub-gen-asciih$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1) +CLEANFILES += ascii.h -ascii.h: ascii.bitmaps grub-bin2h - $(builddir)/grub-bin2h ascii_bitmaps < $< > $@ -CLEANFILES += ascii.h $(top_builddir)/grub-core/include/ascii.h - -widthspec.bin: $(FONT_SOURCE) grub-mkfont - $(builddir)/grub-mkfont --width-spec -o $@ $(FONT_SOURCE) -CLEANFILES += widthspec.bin - -widthspec.h: widthspec.bin grub-bin2h - $(builddir)/grub-bin2h widthspec < $< > $@ +widthspec.h: $(FONT_SOURCE) build-grub-gen-widthspec$(BUILD_EXEEXT) + ./build-grub-gen-widthspec$(BUILD_EXEEXT) $(FONT_SOURCE) $@ || (rm -f $@; exit 1) CLEANFILES += widthspec.h # Install config.h into platformdir -platform_HEADERS = config.h +nodist_platform_HEADERS = config.h pkgdata_DATA += grub-mkconfig_lib +if COND_real_platform + if COND_i386_coreboot QEMU32=qemu-system-i386 +MINIMUM_CPU_LINUX=pentium2 endif if COND_i386_multiboot QEMU32=qemu-system-i386 +MINIMUM_CPU_LINUX=pentium2 endif if COND_i386_ieee1275 QEMU32=qemu-system-i386 +MINIMUM_CPU_LINUX=pentium2 endif if COND_i386_qemu QEMU32=qemu-system-i386 +MINIMUM_CPU_LINUX=pentium2 endif if COND_i386_pc QEMU32=qemu-system-i386 +MINIMUM_CPU_LINUX=pentium2 endif if COND_i386_efi QEMU32=qemu-system-i386 +MINIMUM_CPU_LINUX=pentium2 endif if COND_x86_64_efi QEMU32=qemu-system-x86_64 +MINIMUM_CPU_LINUX=core2duo endif -linux.init.x86_64: $(srcdir)/grub-core/tests/boot/linux.init-x86_64.S - $(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" +linux.init.x86_64: $(srcdir)/grub-core/tests/boot/linux.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -static -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -linux.init.i386: $(srcdir)/grub-core/tests/boot/linux.init-i386.S - $(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" +linux.init.i386: $(srcdir)/grub-core/tests/boot/linux.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -static -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" linux.init.mips: $(srcdir)/grub-core/tests/boot/linux.init-mips.S - $(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" + $(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" linux.init.ppc: $(srcdir)/grub-core/tests/boot/linux.init-ppc.S - $(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" + $(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" linux.init.mipsel: $(srcdir)/grub-core/tests/boot/linux.init-mips.S - $(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" + $(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" linux.init.loongson: $(srcdir)/grub-core/tests/boot/linux.init-mips.S - $(TARGET_CC) -o $@ $< -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -DREBOOT=1 + $(TARGET_CC) -o $@ $< -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -DREBOOT=1 -multiboot.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S - $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -DTARGET_MULTIBOOT=1 -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include +multiboot.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -static -ffreestanding -nostdlib -nostdinc -DTARGET_MULTIBOOT=1 -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -kfreebsd.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S - $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include +kfreebsd.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -static -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include kfreebsd.aout: kfreebsd.elf - $(OBJCOPY) -O a.out-i386-linux $< $@ -R .note.gnu.build-id -R .note.gnu.gold-version + $(TARGET_OBJCOPY) -O a.out-i386-linux $< $@ -j .text -pc-chainloader.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S - $(TARGET_CC) -o $@ $< -DTARGET_CHAINLOADER=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x7c00 -m32 +pc-chainloader.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -static -DTARGET_CHAINLOADER=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x7c00 -m32 pc-chainloader.bin: pc-chainloader.elf - $(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; + $(TARGET_OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; -ntldr.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S - $(TARGET_CC) -o $@ $< -DTARGET_NTLDR=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0 -m32 +ntldr.elf: $(srcdir)/grub-core/tests/boot/kernel-8086.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -DTARGET_NTLDR=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -static -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0 -m32 ntldr.bin: ntldr.elf - $(OBJCOPY) -O binary --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; + $(TARGET_OBJCOPY) -O binary --strip-unneeded -j .text $< $@; -multiboot2.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S - $(TARGET_CC) -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -DTARGET_MULTIBOOT2=1 +multiboot2.elf: $(srcdir)/grub-core/tests/boot/kernel-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -static -o $@ $< -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -ffreestanding -nostdlib -nostdinc -Wl,--build-id=none -Wl,-N -Wl,-Ttext,0x100000 -m32 -I$(srcdir)/include -DTARGET_MULTIBOOT2=1 -kfreebsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kfreebsd.init-x86_64.S - $(TARGET_CC) -o $@ $< -m64 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@ +kfreebsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kfreebsd.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -m64 -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@ -kfreebsd.init.i386: $(srcdir)/grub-core/tests/boot/kfreebsd.init-i386.S - $(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@ +kfreebsd.init.i386: $(srcdir)/grub-core/tests/boot/kfreebsd.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -m32 -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" && freebsd-brandelf -t FreeBSD $@ -knetbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S - $(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DTARGET_NETBSD=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" +knetbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -m32 -static -nostdlib -nostdinc -DTARGET_NETBSD=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -kopenbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S - $(TARGET_CC) -o $@ $< -m32 -nostdlib -nostdinc -DTARGET_OPENBSD=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" +kopenbsd.init.i386: $(srcdir)/grub-core/tests/boot/kbsd.init-i386.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -m32 -static -nostdlib -nostdinc -DTARGET_OPENBSD=1 -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -knetbsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kbsd.init-x86_64.S - $(TARGET_CC) -o $@ $< -m64 -DTARGET_NETBSD=1 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" +knetbsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kbsd.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -m64 -DTARGET_NETBSD=1 -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" -kopenbsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kbsd.init-x86_64.S - $(TARGET_CC) -o $@ $< -m64 -DTARGET_OPENBSD=1 -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" +kopenbsd.init.x86_64: $(srcdir)/grub-core/tests/boot/kbsd.init-x86_64.S $(srcdir)/grub-core/tests/boot/qemu-shutdown-x86.S + $(TARGET_CC) -o $@ $< -m64 -DTARGET_OPENBSD=1 -static -nostdlib -nostdinc -DSUCCESSFUL_BOOT_STRING=\"$(SUCCESSFUL_BOOT_STRING)\" linux-initramfs.mips: linux.init.mips Makefile - TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR linux-initramfs.ppc: linux.init.ppc Makefile - TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR linux-initramfs.mipsel: linux.init.mipsel Makefile - TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR linux-initramfs.loongson: linux.init.loongson Makefile - TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR linux-initramfs.i386: linux.init.i386 Makefile - TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR linux-initramfs.x86_64: linux.init.x86_64 Makefile - TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR + TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && cp $< $$TDIR/init && (cd $$TDIR && echo ./init | cpio -R 0:0 --quiet --dereference -o -H newc) | gzip > $@ && rm -rf $$TDIR kfreebsd-mfsroot.i386.img: kfreebsd.init.i386 Makefile TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -t ffs -s 30m -f 1000 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR @@ -244,7 +278,7 @@ kopenbsd.image.x86_64: kopenbsd.init.x86_64 $(srcdir)/grub-core/tests/boot/kopen TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 128k -f 10 -o minfree=0,version=1 $@ $$TDIR && bsdlabel -f -R $@ $(srcdir)/grub-core/tests/boot/kopenbsdlabel.txt && rm -rf $$TDIR || rm -f $@ knetbsd.miniroot-image.i386.img: knetbsd.image.i386 $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386 - $(OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386 $@ + $(TARGET_OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.i386 $@ kfreebsd-mfsroot.x86_64.img: kfreebsd.init.x86_64 Makefile TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -t ffs -s 30m -f 1000 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR @@ -253,7 +287,7 @@ knetbsd.image.x86_64: knetbsd.init.x86_64 $(srcdir)/grub-core/tests/boot/kbsd.sp TDIR=`mktemp -d "$${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` && mkdir $$TDIR/dev && mkdir $$TDIR/sbin && cp $< $$TDIR/sbin/init && makefs -F $(srcdir)/grub-core/tests/boot/kbsd.spec.txt -t ffs -s 64k -f 10 -o minfree=0,version=1 $@ $$TDIR && rm -rf $$TDIR knetbsd.miniroot-image.x86_64.img: knetbsd.image.x86_64 $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 - $(OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 $@ + $(TARGET_OBJCOPY) --add-section=miniroot=$< $(GRUB_PAYLOADS_DIR)/knetbsd.miniroot.x86_64 $@ CLEANFILES += linux.init.i386 kfreebsd.init.i386 linux.init.x86_64 linux-initramfs.i386 linux-initramfs.x86_64 @@ -261,100 +295,107 @@ kfreebsd-mfsroot.i386.gz: kfreebsd-mfsroot.i386.img gzip < $< > $@ bootcheck-kfreebsd-i386: kfreebsd-mfsroot.i386.gz $(GRUB_PAYLOADS_DIR)/kfreebsd.i386 $(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/mfsroot.gz=kfreebsd-mfsroot.i386.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.i386 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/mfsroot.gz=kfreebsd-mfsroot.i386.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.i386 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.i386 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null kfreebsd-mfsroot.x86_64.gz: kfreebsd-mfsroot.x86_64.img gzip < $< > $@ bootcheck-kfreebsd-x86_64: kfreebsd-mfsroot.x86_64.gz $(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 $(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=qemu-system-x86_64 --files=/mfsroot.gz=kfreebsd-mfsroot.x86_64.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/mfsroot.gz=kfreebsd-mfsroot.x86_64.gz --files=/kfreebsd=$(GRUB_PAYLOADS_DIR)/kfreebsd.x86_64 --files=/kfreebsd_env=$(GRUB_PAYLOADS_DIR)/kfreebsd_env.x86_64 $(srcdir)/grub-core/tests/boot/kfreebsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null knetbsd.miniroot-image.i386.gz: knetbsd.miniroot-image.i386.img gzip < $< > $@ bootcheck-knetbsd-i386: knetbsd.miniroot-image.i386.gz $(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/miniroot.gz=knetbsd.miniroot-image.i386.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/miniroot.gz=knetbsd.miniroot-image.i386.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.i386 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-kopenbsd-i386: kopenbsd.image.i386 $(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/ramdisk=kopenbsd.image.i386 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/ramdisk=kopenbsd.image.i386 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.i386 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-kopenbsd-x86_64: kopenbsd.image.x86_64 $(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=qemu-system-x86_64 --files=/ramdisk=kopenbsd.image.x86_64 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/ramdisk=kopenbsd.image.x86_64 --files=/kopenbsd=$(GRUB_PAYLOADS_DIR)/kopenbsd.x86_64 $(srcdir)/grub-core/tests/boot/kopenbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null knetbsd.miniroot-image.x86_64.gz: knetbsd.miniroot-image.x86_64.img gzip < $< > $@ bootcheck-knetbsd-x86_64: knetbsd.miniroot-image.x86_64.gz $(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=qemu-system-x86_64 --files=/miniroot.gz=knetbsd.miniroot-image.x86_64.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/miniroot.gz=knetbsd.miniroot-image.x86_64.gz --files=/knetbsd=$(GRUB_PAYLOADS_DIR)/knetbsd.x86_64 $(srcdir)/grub-core/tests/boot/knetbsd.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg --qemu-opts="-cpu $(MINIMUM_CPU_LINUX)" | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-mips: linux-initramfs.mips $(GRUB_PAYLOADS_DIR)/linux.mips $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --files=/initrd=linux-initramfs.mips --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.mips $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.mips --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.mips $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-ppc: linux-initramfs.ppc $(GRUB_PAYLOADS_DIR)/linux.ppc $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --files=/initrd=linux-initramfs.ppc --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.ppc $(srcdir)/grub-core/tests/boot/linux-ppc.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.ppc --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.ppc $(srcdir)/grub-core/tests/boot/linux-ppc.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-mipsel: linux-initramfs.mipsel $(GRUB_PAYLOADS_DIR)/linux.mipsel $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --files=/initrd=linux-initramfs.mipsel --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.mipsel $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.mipsel --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.mipsel $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux-loongson: linux-initramfs.loongson $(GRUB_PAYLOADS_DIR)/linux.loongson $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --files=/initrd=linux-initramfs.loongson --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.loongson $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --files=/initrd=linux-initramfs.loongson --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.loongson $(srcdir)/grub-core/tests/boot/linux.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux16-i386: linux-initramfs.i386 $(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/initrd=linux-initramfs.i386 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.i386 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-linux16-x86_64: linux-initramfs.x86_64 $(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=qemu-system-x86_64 --files=/initrd=linux-initramfs.x86_64 --files=/linux=$(GRUB_PAYLOADS_DIR)/linux.x86_64 $(srcdir)/grub-core/tests/boot/linux16.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-multiboot: multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/multiboot.elf=multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/multiboot.elf=multiboot.elf $(srcdir)/grub-core/tests/boot/multiboot.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-multiboot2: multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/multiboot2.elf=multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/multiboot2.elf=multiboot2.elf $(srcdir)/grub-core/tests/boot/multiboot2.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-kfreebsd-aout: kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/kfreebsd.aout=kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/kfreebsd.aout=kfreebsd.aout $(srcdir)/grub-core/tests/boot/kfreebsd-aout.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-pc-chainloader: pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/pc-chainloader.bin=pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/pc-chainloader.bin=pc-chainloader.bin $(srcdir)/grub-core/tests/boot/pc-chainloader.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null bootcheck-ntldr: ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg grub-shell - timeout -s KILL $(BOOTCHECK_TIMEOUT) ./grub-shell --qemu=$(QEMU32) --files=/ntldr.bin=ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null + ./grub-shell --timeout=$(BOOTCHECK_TIMEOUT) --qemu=$(QEMU32) --files=/ntldr.bin=ntldr.bin $(srcdir)/grub-core/tests/boot/ntldr.cfg | grep $(SUCCESSFUL_BOOT_STRING) > /dev/null if COND_i386_efi -BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 +# NetBSD has no support for finding ACPI on EFI +BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 endif if COND_x86_64_efi -BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 +# NetBSD has no support for finding ACPI on EFI +BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 endif if COND_i386_multiboot -# Freebsd crashes because memory at 0-0x1000 is occupied and requires ACPI -BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 +# *BSD requires ACPI +BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 +endif + + +if COND_i386_qemu +# *BSD requires ACPI +BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 endif if COND_i386_coreboot -# 64-bit NetBSD crashes because memory at 0-0x1000 is occupied -# Freebsd crashes because memory at 0-0x1000 is occupied and requires ACPI -BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 +BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 endif -if COND_i386_qemu -# Freebsd crashes because memory at 0-0x1000 is occupied and requires ACPI -BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 +if COND_i386_ieee1275 +# *BSD requires ACPI +#legacy protocol (linux16) makes early BIOS calls. +BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 endif if COND_i386_pc #pc chainloader by definition is only for i386-pc #ntldr and bootmgr require BIOS. -#legacy protocol makes early BIOS calls. -# NetBSD crashes early on non-BIOS +#legacy protocol (linux16) makes early BIOS calls. +# 32-bit NetBSD crashes early on non-BIOS BOOTCHECKS = bootcheck-kfreebsd-aout bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 bootcheck-multiboot bootcheck-multiboot2 bootcheck-linux-i386 bootcheck-linux-x86_64 bootcheck-knetbsd-x86_64 bootcheck-kfreebsd-x86_64 bootcheck-kfreebsd-i386 bootcheck-pc-chainloader bootcheck-ntldr bootcheck-linux16-i386 bootcheck-linux16-x86_64 bootcheck-knetbsd-i386 endif @@ -377,12 +418,10 @@ if COND_powerpc_ieee1275 BOOTCHECKS = bootcheck-linux-ppc endif -EXTRA_DIST += grub-core/tests/boot/kbsd.init-i386.S grub-core/tests/boot/kbsd.init-x86_64.S grub-core/tests/boot/kbsd.spec.txt grub-core/tests/boot/kernel-8086.S grub-core/tests/boot/kernel-i386.S grub-core/tests/boot/kfreebsd-aout.cfg grub-core/tests/boot/kfreebsd.cfg grub-core/tests/boot/kfreebsd.init-i386.S grub-core/tests/boot/kfreebsd.init-x86_64.S grub-core/tests/boot/knetbsd.cfg grub-core/tests/boot/kopenbsd.cfg grub-core/tests/boot/kopenbsdlabel.txt grub-core/tests/boot/linux16.cfg grub-core/tests/boot/linux.cfg grub-core/tests/boot/linux.init-i386.S grub-core/tests/boot/linux.init-x86_64.S grub-core/tests/boot/multiboot2.cfg grub-core/tests/boot/multiboot.cfg grub-core/tests/boot/ntldr.cfg grub-core/tests/boot/pc-chainloader.cfg - .PHONY: bootcheck-linux-i386 bootcheck-linux-x86_64 \ bootcheck-kfreebsd-i386 bootcheck-kfreebsd-x86_64 \ bootcheck-knetbsd-i386 bootcheck-knetbsd-x86_64 \ - bootcheck-linux-mips + bootcheck-linux-mips FORCE # Randomly generated SUCCESSFUL_BOOT_STRING=3e49994fd5d82b7c9298d672d774080d @@ -390,3 +429,66 @@ SUCCESSFUL_BOOT_STRING=3e49994fd5d82b7c9298d672d774080d BOOTCHECK_TIMEOUT=180 bootcheck: $(BOOTCHECKS) + +if COND_i386_coreboot +FS_PAYLOAD_MODULES ?= $(shell cat grub-core/fs.lst) +default_payload.elf: grub-mkstandalone grub-mkimage FORCE + test -f $@ && rm $@ || true + pkgdatadir=. ./grub-mkstandalone --grub-mkimage=./grub-mkimage -O i386-coreboot -o $@ --modules='ahci pata ehci uhci ohci usb_keyboard usbms part_msdos ext2 fat at_keyboard part_gpt usbserial_usbdebug cbfs' --install-modules='ls linux search configfile normal cbtime cbls memrw iorw minicmd lsmmap lspci halt reboot hexdump pcidump regexp setpci lsacpi chain test serial multiboot cbmemc linux16 gzio echo help syslinuxcfg xnu $(FS_PAYLOAD_MODULES) password_pbkdf2 $(EXTRA_PAYLOAD_MODULES)' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=$(srcdir)/coreboot.cfg +endif + +endif + +EXTRA_DIST += grub-core/tests/boot/kbsd.init-i386.S grub-core/tests/boot/kbsd.init-x86_64.S grub-core/tests/boot/kbsd.spec.txt grub-core/tests/boot/kernel-8086.S grub-core/tests/boot/kernel-i386.S grub-core/tests/boot/kfreebsd-aout.cfg grub-core/tests/boot/kfreebsd.cfg grub-core/tests/boot/kfreebsd.init-i386.S grub-core/tests/boot/kfreebsd.init-x86_64.S grub-core/tests/boot/knetbsd.cfg grub-core/tests/boot/kopenbsd.cfg grub-core/tests/boot/kopenbsdlabel.txt grub-core/tests/boot/linux16.cfg grub-core/tests/boot/linux.cfg grub-core/tests/boot/linux.init-i386.S grub-core/tests/boot/linux.init-mips.S grub-core/tests/boot/linux.init-ppc.S grub-core/tests/boot/linux.init-x86_64.S grub-core/tests/boot/linux-ppc.cfg grub-core/tests/boot/multiboot2.cfg grub-core/tests/boot/multiboot.cfg grub-core/tests/boot/ntldr.cfg grub-core/tests/boot/pc-chainloader.cfg grub-core/tests/boot/qemu-shutdown-x86.S + +windowsdir=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows +windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA) + test -d $(windowsdir) && rm -rf $(windowsdir) || true + test -d $(windowsdir) || mkdir $(windowsdir) + $(MAKE) -C po $(AM_MAKEFLAGS) windowsdir + $(MAKE) -C grub-core $(AM_MAKEFLAGS) windowsdir + test -d $(windowsdir)/themes || mkdir $(windowsdir)/themes + test -d $(windowsdir)/themes/starfield || mkdir $(windowsdir)/themes/starfield + for x in $(PROGRAMS); do \ + if [ x$(STRIP) != x ]; then $(STRIP) $$x -o $(windowsdir)/$$x; \ + else cp -fp $$x $(windowsdir)/$$x; fi; \ + done + for x in $(pkgdata_DATA); do \ + cp -fp $$x $(windowsdir)/$$x; \ + done + for x in $(starfield_DATA); do \ + cp -fp $$x $(windowsdir)/themes/starfield/$$(basename $$x); \ + done + for x in $(GRUB_WINDOWS_EXTRA_DIST); do \ + cp -fp $$x $(windowsdir); \ + done + +windowszip=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows.zip +windowszip: windowsdir + test -f $(windowszip) && rm $(windowszip) || true + zip -r $(windowszip) $(windowsdir) + rm -rf $(windowsdir) + +EXTRA_DIST += linguas.sh + +changelog_start_date = 2015-01-23 +gitlog_to_changelog = $(top_srcdir)/build-aux/gitlog-to-changelog + +ChangeLog: FORCE + if test -d $(top_srcdir)/.git; then \ + $(gitlog_to_changelog) --srcdir=$(top_srcdir) --since=$(changelog_start_date) > '$@.tmp'; \ + rm -f '$@'; mv '$@.tmp' '$@'; \ + else \ + touch $@; \ + fi + +syslinux_test: $(top_builddir)/config.status tests/syslinux/ubuntu10.04_grub.cfg + +# Mimic simplify_filename from grub-core/lib/syslinux_parse.c, so that we +# can predict its behaviour in tests. We have to pre-substitute this before +# calling config.status, as config.status offers no reliable way to hook in +# a command between setting ac_abs_top_srcdir and emitting output files. +tests/syslinux/ubuntu10.04_grub.cfg: $(top_builddir)/config.status tests/syslinux/ubuntu10.04_grub.cfg.in + simplified_abs_top_srcdir=`echo "$(abs_top_srcdir)" | sed 's,//,/,g; s,/\./,/,g; :loop; s,/[^/][^/]*/\.\.\(/\|$$\),\1,; t loop'`; \ + sed "s,@simplified_abs_top_srcdir@,$$simplified_abs_top_srcdir,g" $(srcdir)/tests/syslinux/ubuntu10.04_grub.cfg.in | $(top_builddir)/config.status --file=$@:- +CLEANFILES += tests/syslinux/ubuntu10.04_grub.cfg diff --git a/Makefile.util.def b/Makefile.util.def index b80187c81..038253b37 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -3,15 +3,29 @@ AutoGen definitions Makefile.tpl; library = { name = libgrubkern.a; cflags = '$(CFLAGS_GNULIB)'; - cppflags = '$(CPPFLAGS_GNULIB)'; + cppflags = '$(CPPFLAGS_GNULIB) -I$(srcdir)/grub-core/lib/json'; common = util/misc.c; common = grub-core/kern/command.c; common = grub-core/kern/device.c; common = grub-core/kern/disk.c; + common = grub-core/lib/disk.c; common = util/getroot.c; - common = util/raid.c; + common = grub-core/osdep/unix/getroot.c; + common = grub-core/osdep/getroot.c; + common = grub-core/osdep/devmapper/getroot.c; + common = grub-core/osdep/relpath.c; + extra_dist = grub-core/kern/disk_common.c; + extra_dist = grub-core/osdep/unix/relpath.c; + extra_dist = grub-core/osdep/aros/relpath.c; + extra_dist = grub-core/osdep/windows/relpath.c; common = grub-core/kern/emu/hostdisk.c; + common = grub-core/osdep/devmapper/hostdisk.c; + common = grub-core/osdep/hostdisk.c; + common = grub-core/osdep/unix/hostdisk.c; + common = grub-core/osdep/exec.c; + common = grub-core/osdep/sleep.c; + common = grub-core/osdep/password.c; common = grub-core/kern/emu/misc.c; common = grub-core/kern/emu/mm.c; common = grub-core/kern/env.c; @@ -22,8 +36,11 @@ library = { common = grub-core/kern/misc.c; common = grub-core/kern/partition.c; common = grub-core/lib/crypto.c; + common = grub-core/lib/json/json.c; common = grub-core/disk/luks.c; + common = grub-core/disk/luks2.c; common = grub-core/disk/geli.c; + common = grub-core/disk/key_protector.c; common = grub-core/disk/cryptodisk.c; common = grub-core/disk/AFSplitter.c; common = grub-core/lib/pbkdf2.c; @@ -32,12 +49,15 @@ library = { common = grub-core/disk/ldm.c; common = grub-core/disk/diskfilter.c; common = grub-core/partmap/gpt.c; + common = grub-core/partmap/msdos.c; + common = grub-core/fs/proc.c; + common = grub-core/fs/archelp.c; }; library = { name = libgrubmods.a; - cflags = '$(CFLAGS_POSIX) -Wno-undef -Wno-error=missing-noreturn'; - cppflags = '-I$(top_srcdir)/grub-core/lib/minilzo -I$(srcdir)/grub-core/lib/xzembed -DMINILZO_HAVE_CONFIG_H'; + cflags = '-fno-builtin -Wno-undef -Wno-unused-but-set-variable'; + cppflags = '-I$(srcdir)/grub-core/lib/minilzo -I$(srcdir)/grub-core/lib/xzembed -I$(srcdir)/grub-core/lib/zstd -DMINILZO_HAVE_CONFIG_H'; common_nodist = grub_script.tab.c; common_nodist = grub_script.yy.c; @@ -46,6 +66,7 @@ library = { common_nodist = grub_script.tab.h; common = grub-core/commands/blocklist.c; + common = grub-core/commands/macbless.c; common = grub-core/commands/xnu_uuid.c; common = grub-core/commands/testload.c; common = grub-core/commands/ls.c; @@ -57,20 +78,36 @@ library = { common = grub-core/disk/mdraid1x_linux.c; common = grub-core/disk/raid5_recover.c; common = grub-core/disk/raid6_recover.c; + common = grub-core/font/font.c; + common = grub-core/gfxmenu/font.c; + common = grub-core/normal/charset.c; + common = grub-core/video/fb/fbblit.c; + common = grub-core/video/fb/fbutil.c; + common = grub-core/video/fb/fbfill.c; + common = grub-core/video/fb/video_fb.c; + common = grub-core/video/video.c; + common = grub-core/video/capture.c; + common = grub-core/video/colors.c; + common = grub-core/unidata.c; + common = grub-core/io/bufio.c; common = grub-core/fs/affs.c; common = grub-core/fs/afs.c; common = grub-core/fs/bfs.c; common = grub-core/fs/btrfs.c; + common = grub-core/fs/cbfs.c; common = grub-core/fs/cpio.c; common = grub-core/fs/cpio_be.c; common = grub-core/fs/odc.c; common = grub-core/fs/newc.c; + common = grub-core/fs/erofs.c; common = grub-core/fs/ext2.c; common = grub-core/fs/fat.c; common = grub-core/fs/exfat.c; + common = grub-core/fs/f2fs.c; common = grub-core/fs/fshelp.c; common = grub-core/fs/hfs.c; common = grub-core/fs/hfsplus.c; + common = grub-core/fs/hfspluscomp.c; common = grub-core/fs/iso9660.c; common = grub-core/fs/jfs.c; common = grub-core/fs/minix.c; @@ -90,11 +127,13 @@ library = { common = grub-core/fs/udf.c; common = grub-core/fs/ufs2.c; common = grub-core/fs/ufs.c; + common = grub-core/fs/ufs_be.c; common = grub-core/fs/xfs.c; common = grub-core/fs/zfs/zfscrypt.c; common = grub-core/fs/zfs/zfs.c; common = grub-core/fs/zfs/zfsinfo.c; common = grub-core/fs/zfs/zfs_lzjb.c; + common = grub-core/fs/zfs/zfs_lz4.c; common = grub-core/fs/zfs/zfs_sha256.c; common = grub-core/fs/zfs/zfs_fletcher.c; common = grub-core/lib/envblk.c; @@ -104,40 +143,42 @@ library = { common = grub-core/lib/crc.c; common = grub-core/lib/adler32.c; common = grub-core/lib/crc64.c; - common = grub-core/normal/datetime.c; + common = grub-core/lib/datetime.c; common = grub-core/normal/misc.c; common = grub-core/partmap/acorn.c; common = grub-core/partmap/amiga.c; common = grub-core/partmap/apple.c; - common = grub-core/partmap/msdos.c; common = grub-core/partmap/sun.c; common = grub-core/partmap/plan.c; common = grub-core/partmap/dvh.c; common = grub-core/partmap/sunpc.c; common = grub-core/partmap/bsdlabel.c; + common = grub-core/partmap/dfly.c; common = grub-core/script/function.c; common = grub-core/script/lexer.c; common = grub-core/script/main.c; common = grub-core/script/script.c; common = grub-core/script/argv.c; common = grub-core/io/gzio.c; + common = grub-core/io/xzio.c; common = grub-core/io/lzopio.c; common = grub-core/kern/ia64/dl_helper.c; + common = grub-core/kern/arm/dl_helper.c; + common = grub-core/kern/arm64/dl_helper.c; + common = grub-core/kern/loongarch64/dl_helper.c; common = grub-core/lib/minilzo/minilzo.c; common = grub-core/lib/xzembed/xz_dec_bcj.c; common = grub-core/lib/xzembed/xz_dec_lzma2.c; common = grub-core/lib/xzembed/xz_dec_stream.c; -}; - -program = { - name = grub-bin2h; - common = util/bin2h.c; - ldadd = libgrubmods.a; - ldadd = libgrubgcry.a; - ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER)'; - installdir = noinst; + common = grub-core/lib/zstd/debug.c; + common = grub-core/lib/zstd/entropy_common.c; + common = grub-core/lib/zstd/error_private.c; + common = grub-core/lib/zstd/fse_decompress.c; + common = grub-core/lib/zstd/huf_decompress.c; + common = grub-core/lib/zstd/module.c; + common = grub-core/lib/zstd/xxhash.c; + common = grub-core/lib/zstd/zstd_common.c; + common = grub-core/lib/zstd/zstd_decompress.c; }; program = { @@ -145,18 +186,52 @@ program = { mansection = 1; common = util/grub-mkimage.c; + common = util/mkimage.c; + common = util/grub-mkimage32.c; + common = util/grub-mkimage64.c; common = util/resolve.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + common = grub-core/osdep/config.c; + extra_dist = grub-core/osdep/aros/config.c; + extra_dist = grub-core/osdep/windows/config.c; + extra_dist = grub-core/osdep/unix/config.c; + common = util/config.c; extra_dist = util/grub-mkimagexx.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBLZMA)'; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - cppflags = '-DGRUB_PKGLIBDIR=\"$(pkglibdir)\"'; +}; + +program = { + name = grub-protect; + mansection = 1; + + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + common = grub-core/lib/tss2/buffer.c; + common = grub-core/lib/tss2/tss2_mu.c; + common = grub-core/lib/tss2/tpm2_cmd.c; + common = grub-core/commands/tpm2_key_protector/args.c; + common = grub-core/commands/tpm2_key_protector/tpm2key_asn1_tab.c; + common = util/grub-protect.c; + common = util/probe.c; + + cflags = '-I$(srcdir)/grub-core/lib/tss2 -I$(srcdir)/grub-core/commands/tpm2_key_protector'; + + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBTASN1)'; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + + condition = COND_GRUB_PROTECT; }; program = { @@ -165,11 +240,12 @@ program = { common = util/grub-mkrelpath.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -179,11 +255,12 @@ program = { common = util/grub-script-check.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -192,11 +269,24 @@ program = { mansection = 1; common = util/grub-editenv.c; + common = util/editenv.c; + common = util/grub-install-common.c; + common = grub-core/osdep/init.c; + common = grub-core/osdep/compress.c; + extra_dist = grub-core/osdep/unix/compress.c; + extra_dist = grub-core/osdep/basic/compress.c; + common = util/mkimage.c; + common = util/grub-mkimage32.c; + common = util/grub-mkimage64.c; + common = grub-core/osdep/config.c; + common = util/config.c; + common = util/resolve.c; + ldadd = '$(LIBLZMA)'; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -206,34 +296,21 @@ program = { common = util/grub-mkpasswd-pbkdf2.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/random.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - cflags = '$(CFLAGS_GCRY)'; - cppflags = '$(CPPFLAGS_GCRY)'; }; program = { name = grub-macho2img; mansection = 1; common = util/grub-macho2img.c; - condition = COND_APPLE_CC; -}; - -program = { - name = grub-pe2elf; - mansection = 1; - common = util/grub-pe2elf.c; - - ldadd = libgrubmods.a; - ldadd = libgrubgcry.a; - ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL)'; - condition = COND_GRUB_PE2ELF; + condition = COND_APPLE_LINKER; }; program = { @@ -243,14 +320,12 @@ program = { common = util/grub-fstest.c; common = grub-core/kern/emu/hostfs.c; common = grub-core/disk/host.c; - - cflags = '$(CFLAGS_GCRY)'; - cppflags = '$(CPPFLAGS_GCRY)'; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -261,12 +336,15 @@ program = { common = util/grub-mount.c; common = grub-core/kern/emu/hostfs.c; common = grub-core/disk/host.c; + common = grub-core/osdep/init.c; + + cflags = '$(FUSE_CFLAGS)'; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) -lfuse'; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM) $(FUSE_LIBS)'; condition = COND_GRUB_MOUNT; }; @@ -274,16 +352,17 @@ program = { name = grub-mkfont; mansection = 1; common = util/grub-mkfont.c; - common = grub-core/unidata.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; - cflags = '$(freetype_cflags)'; + cflags = '$(FREETYPE_CFLAGS)'; + cppflags = '-DGRUB_MKFONT=1'; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(freetype_libs)'; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(FREETYPE_LIBS)'; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; condition = COND_GRUB_MKFONT; }; @@ -293,13 +372,15 @@ program = { installdir = sbin; mansection = 8; common = util/grub-probe.c; - common = util/ieee1275/ofpath.c; + common = util/probe.c; + common = grub-core/osdep/ofpath.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -308,16 +389,22 @@ program = { installdir = sbin; mansection = 8; common = util/grub-setup.c; - common = util/lvm.c; + common = util/setup_bios.c; + extra_dist = util/setup.c; common = grub-core/kern/emu/argp_common.c; common = grub-core/lib/reed_solomon.c; + common = grub-core/osdep/blocklist.c; + extra_dist = grub-core/osdep/generic/blocklist.c; + extra_dist = grub-core/osdep/linux/blocklist.c; + extra_dist = grub-core/osdep/windows/blocklist.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubkern.a; ldadd = libgrubgcry.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - cppflags = '-DGRUB_SETUP_BIOS=1'; + cppflags = '-DGRUB_SETUP_FUNC=grub_util_bios_setup'; }; program = { @@ -325,17 +412,19 @@ program = { installdir = sbin; mansection = 8; common = util/grub-setup.c; - common = util/lvm.c; + common = util/setup_sparc.c; common = grub-core/kern/emu/argp_common.c; common = grub-core/lib/reed_solomon.c; - common = util/ieee1275/ofpath.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/blocklist.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubkern.a; ldadd = libgrubgcry.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; - cppflags = '-DGRUB_SETUP_SPARC64=1'; + cppflags = '-DGRUB_SETUP_FUNC=grub_util_sparc_setup'; }; program = { @@ -343,13 +432,14 @@ program = { installdir = sbin; mansection = 8; common = util/ieee1275/grub-ofpathname.c; - common = util/ieee1275/ofpath.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBGEOM)'; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; program = { @@ -358,14 +448,30 @@ program = { common = util/grub-mklayout.c; common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; +program = { + name = grub-macbless; + installdir = sbin; + mansection = 8; + common = util/grub-macbless.c; + common = grub-core/osdep/init.c; + common = grub-core/kern/emu/argp_common.c; + + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +}; + data = { common = util/grub.d/README; installdir = grubconf; @@ -433,12 +539,24 @@ script = { condition = COND_HOST_LINUX; }; +script = { + name = '25_bli'; + common = util/grub.d/25_bli.in; + installdir = grubconf; +}; + script = { name = '30_os-prober'; common = util/grub.d/30_os-prober.in; installdir = grubconf; }; +script = { + name = '30_uefi-firmware'; + common = util/grub.d/30_uefi-firmware.in; + installdir = grubconf; +}; + script = { name = '40_custom'; common = util/grub.d/40_custom.in; @@ -451,47 +569,168 @@ script = { installdir = grubconf; }; -script = { +program = { mansection = 1; name = grub-mkrescue; - x86 = util/grub-mkrescue.in; - mips_qemu_mips = util/grub-mkrescue.in; - mips_loongson = util/grub-mkrescue.in; - ia64_efi = util/grub-mkrescue.in; - powerpc_ieee1275 = util/powerpc/ieee1275/grub-mkrescue.in; - enable = i386_pc; - enable = i386_efi; - enable = x86_64_efi; - enable = i386_qemu; - enable = i386_multiboot; - enable = i386_coreboot; - enable = mips_qemu_mips; - enable = mips_loongson; - enable = ia64_efi; - enable = powerpc_ieee1275; + + common = util/grub-mkrescue.c; + common = util/render-label.c; + common = util/glue-efi.c; + common = util/mkimage.c; + common = util/grub-mkimage32.c; + common = util/grub-mkimage64.c; + common = util/grub-install-common.c; + common = util/setup_bios.c; + common = util/setup_sparc.c; + common = grub-core/lib/reed_solomon.c; + common = grub-core/osdep/random.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/platform.c; + common = grub-core/osdep/platform_unix.c; + common = grub-core/osdep/compress.c; + extra_dist = grub-core/osdep/unix/compress.c; + extra_dist = grub-core/osdep/basic/compress.c; + common = util/editenv.c; + common = grub-core/osdep/blocklist.c; + common = grub-core/osdep/config.c; + common = util/config.c; + + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + + common = util/resolve.c; + + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + + ldadd = '$(LIBLZMA)'; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + + condition = COND_HAVE_EXEC; }; -script = { +program = { mansection = 1; name = grub-mkstandalone; - common = util/grub-mkstandalone.in; + common = util/grub-mkstandalone.c; + + common = util/render-label.c; + common = util/glue-efi.c; + common = util/mkimage.c; + common = util/grub-mkimage32.c; + common = util/grub-mkimage64.c; + common = util/grub-install-common.c; + common = util/setup_bios.c; + common = util/setup_sparc.c; + common = grub-core/lib/reed_solomon.c; + common = grub-core/osdep/random.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/platform.c; + common = grub-core/osdep/platform_unix.c; + extra_dist = grub-core/osdep/linux/platform.c; + extra_dist = grub-core/osdep/windows/platform.c; + extra_dist = grub-core/osdep/basic/platform.c; + extra_dist = grub-core/osdep/basic/no_platform.c; + extra_dist = grub-core/osdep/unix/platform.c; + common = grub-core/osdep/compress.c; + common = util/editenv.c; + common = grub-core/osdep/blocklist.c; + common = grub-core/osdep/config.c; + common = util/config.c; + + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + + common = util/resolve.c; + + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + + ldadd = '$(LIBLZMA)'; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; -script = { +program = { mansection = 8; installdir = sbin; name = grub-install; - common = util/grub-install.in; - enable = noemu; + common = util/grub-install.c; + common = util/probe.c; + common = util/mkimage.c; + common = util/grub-mkimage32.c; + common = util/grub-mkimage64.c; + common = util/grub-install-common.c; + common = util/setup_bios.c; + common = util/setup_sparc.c; + common = grub-core/lib/reed_solomon.c; + common = grub-core/osdep/random.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/platform.c; + common = grub-core/osdep/platform_unix.c; + common = grub-core/osdep/compress.c; + common = util/editenv.c; + common = grub-core/osdep/blocklist.c; + common = grub-core/osdep/config.c; + common = util/config.c; + common = util/render-label.c; + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + + common = util/resolve.c; + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + + ldadd = '$(LIBLZMA)'; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; -script = { - mansection = 8; - installdir = sbin; +program = { + mansection = 1; + installdir = bin; name = grub-mknetdir; - common = util/grub-mknetdir.in; + common = util/grub-mknetdir.c; + + common = util/mkimage.c; + common = util/grub-mkimage32.c; + common = util/grub-mkimage64.c; + common = util/grub-install-common.c; + common = util/setup_bios.c; + common = util/setup_sparc.c; + common = grub-core/lib/reed_solomon.c; + common = grub-core/osdep/random.c; + common = grub-core/osdep/ofpath.c; + common = grub-core/osdep/platform.c; + common = grub-core/osdep/platform_unix.c; + common = grub-core/osdep/compress.c; + common = util/editenv.c; + common = grub-core/osdep/blocklist.c; + common = grub-core/osdep/config.c; + common = util/config.c; + + common = util/resolve.c; + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + + ldadd = '$(LIBLZMA)'; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; script = { @@ -540,169 +779,525 @@ script = { }; script = { - testcase; + name = grub-shell-luks-tester; + common = tests/util/grub-shell-luks-tester.in; + installdir = noinst; +}; + +script = { + name = grub-fs-tester; + common = tests/util/grub-fs-tester.in; + installdir = noinst; + dependencies = 'garbage-gen$(BUILD_EXEEXT)'; +}; + +script = { + testcase = native; + name = erofs_test; + common = tests/erofs_test.in; +}; + +script = { + testcase = native; + name = ext234_test; + common = tests/ext234_test.in; +}; + +script = { + testcase = native; + name = squashfs_test; + common = tests/squashfs_test.in; +}; + +script = { + testcase = native; + name = iso9660_test; + common = tests/iso9660_test.in; +}; + +script = { + testcase = native; + name = hfsplus_test; + common = tests/hfsplus_test.in; +}; + +script = { + testcase = native; + name = ntfs_test; + common = tests/ntfs_test.in; +}; + +script = { + testcase = native; + name = reiserfs_test; + common = tests/reiserfs_test.in; +}; + +script = { + testcase = native; + name = fat_test; + common = tests/fat_test.in; +}; + +script = { + testcase = native; + name = minixfs_test; + common = tests/minixfs_test.in; +}; + +script = { + testcase = native; + name = xfs_test; + common = tests/xfs_test.in; +}; + +script = { + testcase = native; + name = f2fs_test; + common = tests/f2fs_test.in; +}; + +script = { + testcase = native; + name = nilfs2_test; + common = tests/nilfs2_test.in; +}; + +script = { + testcase = native; + name = romfs_test; + common = tests/romfs_test.in; +}; + +script = { + testcase = native; + name = exfat_test; + common = tests/exfat_test.in; +}; + +script = { + testcase = native; + name = tar_test; + common = tests/tar_test.in; +}; + +script = { + testcase = native; + name = udf_test; + common = tests/udf_test.in; +}; + +script = { + testcase = native; + name = hfs_test; + common = tests/hfs_test.in; +}; + +script = { + testcase = native; + name = jfs_test; + common = tests/jfs_test.in; +}; + +script = { + testcase = native; + name = btrfs_test; + common = tests/btrfs_test.in; +}; + +script = { + testcase = native; + name = zfs_test; + common = tests/zfs_test.in; +}; + +script = { + testcase = native; + name = cpio_test; + common = tests/cpio_test.in; +}; + +script = { + testcase = native; name = example_scripted_test; common = tests/example_scripted_test.in; }; script = { - testcase; + testcase = native; + name = gettext_strings_test; + common = tests/gettext_strings_test.in; + extra_dist = po/exclude.pot; +}; + +script = { + testcase = nonnative; + name = pata_test; + common = tests/pata_test.in; +}; + +script = { + testcase = nonnative; + name = ahci_test; + common = tests/ahci_test.in; +}; + +script = { + testcase = nonnative; + name = uhci_test; + common = tests/uhci_test.in; +}; + +script = { + testcase = nonnative; + name = ohci_test; + common = tests/ohci_test.in; +}; + +script = { + testcase = nonnative; + name = ehci_test; + common = tests/ehci_test.in; +}; + +script = { + testcase = nonnative; name = example_grub_script_test; common = tests/example_grub_script_test.in; }; script = { - testcase; + testcase = nonnative; + name = grub_script_eval; + common = tests/grub_script_eval.in; +}; + +script = { + testcase = nonnative; + name = grub_script_test; + common = tests/grub_script_test.in; +}; + +script = { + testcase = nonnative; name = grub_script_echo1; common = tests/grub_script_echo1.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_leading_whitespace; common = tests/grub_script_leading_whitespace.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_echo_keywords; common = tests/grub_script_echo_keywords.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_vars1; common = tests/grub_script_vars1.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_for1; common = tests/grub_script_for1.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_while1; common = tests/grub_script_while1.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_if; common = tests/grub_script_if.in; }; script = { - testcase; + testcase = native; name = grub_script_blanklines; common = tests/grub_script_blanklines.in; }; script = { - testcase; + testcase = native; name = grub_script_final_semicolon; common = tests/grub_script_final_semicolon.in; }; script = { - testcase; + testcase = native; name = grub_script_dollar; common = tests/grub_script_dollar.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_comments; common = tests/grub_script_comments.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_functions; common = tests/grub_script_functions.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_break; common = tests/grub_script_break.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_continue; common = tests/grub_script_continue.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_shift; common = tests/grub_script_shift.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_blockarg; common = tests/grub_script_blockarg.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_setparams; common = tests/grub_script_setparams.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_return; common = tests/grub_script_return.in; }; script = { - testcase; + testcase = nonnative; + name = grub_cmd_cryptomount; + common = tests/grub_cmd_cryptomount.in; +}; + +script = { + testcase = nonnative; name = grub_cmd_regexp; common = tests/grub_cmd_regexp.in; }; script = { - testcase; + testcase = nonnative; + name = grub_cmd_date; + common = tests/grub_cmd_date.in; +}; + +script = { + testcase = nonnative; + name = grub_cmd_set_date; + common = tests/grub_cmd_set_date.in; +}; + +script = { + testcase = nonnative; + name = grub_cmd_sleep; + common = tests/grub_cmd_sleep.in; +}; + +script = { + testcase = nonnative; name = grub_script_expansion; common = tests/grub_script_expansion.in; }; script = { - testcase; + testcase = nonnative; name = grub_script_not; common = tests/grub_script_not.in; }; script = { - testcase; + testcase = native; + name = grub_script_no_commands; + common = tests/grub_script_no_commands.in; +}; + +script = { + testcase = nonnative; name = partmap_test; common = tests/partmap_test.in; }; script = { - testcase; + testcase = nonnative; + name = hddboot_test; + common = tests/hddboot_test.in; +}; + +script = { + testcase = nonnative; + name = fddboot_test; + common = tests/fddboot_test.in; +}; + +script = { + testcase = nonnative; + name = cdboot_test; + common = tests/cdboot_test.in; +}; + +script = { + testcase = nonnative; + name = netboot_test; + common = tests/netboot_test.in; +}; + +script = { + testcase = nonnative; + name = serial_test; + common = tests/serial_test.in; +}; + +script = { + testcase = nonnative; + name = pseries_test; + common = tests/pseries_test.in; +}; + +script = { + testcase = nonnative; + name = core_compress_test; + common = tests/core_compress_test.in; +}; + +script = { + testcase = nonnative; + name = xzcompress_test; + common = tests/xzcompress_test.in; +}; + +script = { + testcase = nonnative; + name = gzcompress_test; + common = tests/gzcompress_test.in; +}; + +script = { + testcase = nonnative; + name = lzocompress_test; + common = tests/lzocompress_test.in; +}; + +script = { + testcase = nonnative; name = grub_cmd_echo; common = tests/grub_cmd_echo.in; }; script = { - testcase; + testcase = nonnative; + name = help_test; + common = tests/help_test.in; +}; + +script = { + testcase = nonnative; name = grub_script_gettext; common = tests/grub_script_gettext.in; }; script = { - testcase; + testcase = nonnative; + name = grub_script_escape_comma; + common = tests/grub_script_escape_comma.in; +}; + +script = { + testcase = nonnative; name = grub_script_strcmp; common = tests/grub_script_strcmp.in; }; +script = { + testcase = nonnative; + name = test_sha512sum; + common = tests/test_sha512sum.in; +}; + +script = { + testcase = nonnative; + name = test_unset; + common = tests/test_unset.in; +}; + +script = { + testcase = nonnative; + name = grub_func_test; + common = tests/grub_func_test.in; +}; + +script = { + testcase = nonnative; + name = grub_cmd_tr; + common = tests/grub_cmd_tr.in; +}; + +script = { + testcase = nonnative; + name = file_filter_test; + common = tests/file_filter_test.in; +}; + +script = { + testcase = nonnative; + name = grub_cmd_test; + common = tests/grub_cmd_test.in; +}; + +script = { + testcase = native; + name = syslinux_test; + common = tests/syslinux_test.in; +}; + +script = { + testcase = native; + name = luks1_test; + common = tests/luks1_test.in; +}; + +script = { + testcase = native; + name = luks2_test; + common = tests/luks2_test.in; +}; + +script = { + testcase = native; + name = asn1_test; + common = tests/asn1_test.in; +}; + +script = { + testcase = native; + name = tpm2_key_protector_test; + common = tests/tpm2_key_protector_test.in; +}; + program = { - testcase; + testcase = native; name = example_unit_test; common = tests/example_unit_test.c; common = tests/lib/unit_test.c; @@ -712,12 +1307,12 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; program = { - testcase; + testcase = native; name = printf_test; common = tests/printf_unit_test.c; common = tests/lib/unit_test.c; @@ -727,12 +1322,44 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; program = { - testcase; + testcase = native; + name = date_test; + common = tests/date_unit_test.c; + common = tests/lib/unit_test.c; + common = grub-core/kern/list.c; + common = grub-core/kern/misc.c; + common = grub-core/tests/lib/test.c; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +}; + +program = { + testcase = native; + name = priority_queue_unit_test; + common = tests/priority_queue_unit_test.cc; + common = tests/lib/unit_test.c; + common = grub-core/kern/list.c; + common = grub-core/kern/misc.c; + common = grub-core/tests/lib/test.c; + common = grub-core/lib/priority_queue.c; + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + condition = COND_HAVE_CXX; +}; + +program = { + testcase = native; name = cmp_test; common = tests/cmp_unit_test.c; common = tests/lib/unit_test.c; @@ -742,7 +1369,7 @@ program = { ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; @@ -752,10 +1379,92 @@ program = { common = util/grub-menulst2cfg.c; common = grub-core/lib/legacy_parse.c; common = grub-core/lib/i386/pc/vesa_modes_table.c; + common = grub-core/osdep/init.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +}; + +program = { + name = grub-syslinux2cfg; + mansection = 1; + common = util/grub-syslinux2cfg.c; + common = grub-core/lib/syslinux_parse.c; + common = grub-core/lib/getline.c; + common = grub-core/osdep/init.c; + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + common = grub-core/kern/emu/argp_common.c; + + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +}; + +program = { + name = grub-glue-efi; + mansection = 1; + + common = util/grub-glue-efi.c; + common = util/glue-efi.c; + common = grub-core/kern/emu/argp_common.c; + common = grub-core/osdep/init.c; + + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +}; + +program = { + name = grub-render-label; + mansection = 1; + + common = util/grub-render-label.c; + common = util/render-label.c; + common = grub-core/kern/emu/argp_common.c; + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + common = grub-core/osdep/init.c; + + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; +}; + +program = { + name = grub-file; + mansection = 1; + + common = util/grub-file.c; + common = util/render-label.c; + common = grub-core/commands/file.c; + common = grub-core/commands/file32.c; + common = grub-core/commands/file64.c; + common = grub-core/loader/i386/xen_file.c; + common = grub-core/loader/i386/xen_file32.c; + common = grub-core/loader/i386/xen_file64.c; + common = grub-core/io/offset.c; + common = grub-core/kern/elf.c; + common = grub-core/loader/lzss.c; + common = grub-core/loader/macho.c; + common = grub-core/loader/macho32.c; + common = grub-core/loader/macho64.c; + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; + common = grub-core/osdep/init.c; + + ldadd = libgrubmods.a; + ldadd = libgrubgcry.a; + ldadd = libgrubkern.a; + ldadd = grub-core/lib/gnulib/libgnu.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; }; diff --git a/NEWS b/NEWS index f9b06ab48..310130962 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,237 @@ +New in 2.12: + +* GCC 13 support. +* clang 14 support. +* binutils 2.38 support. +* Unification of EFI Linux kernel loader across architectures. +* Transition to EFI Linux kernel stub loader for x86 architecture. +* Initial support for Boot Loader Interface. +* Support for dynamic GRUB runtime memory addition using firmware calls. +* PCI and MMIO UARTs support. +* SDL2 support. +* LoongArch support. +* TPM driver fixes. +* Many filesystems fixes. +* Many CVE and Coverity fixes. +* Debugging support improvements. +* Tests improvements. +* Documentation improvements. +* ...and tons of other fixes and cleanups... + +New in 2.06: + +* GCC 10 support. +* clang 10 support. +* SBAT support. +* LUKS2 support. +* Drop small MBR gap support. +* Xen Security Modules (XSM/FLASK) support. +* The lockdown mechanism similar to the Linux kernel one. +* Disable the os-prober by default. +* Many backports of GRUB distros specific patches. +* BootHole and BootHole2 fixes. +* ...and tons of other fixes and cleanups... + +New in 2.04: + +* GCC 8 and 9 support. +* Gnulib integration overhaul. +* RISC-V support. +* Xen PVH support. +* Native UEFI secure boot support. +* UEFI TPM driver. +* New IEEE 1275 obdisk driver. +* Btrfs RAID 5 and RIAD 6 support. +* PARTUUID support. +* VLAN support. +* Native DHCP support. +* Many ARM and ARM64 fixes. +* Many SPARC fixes. +* Many IEEE 1275 fixes. +* ...and tons of other fixes and cleanups... + +New in 2.02: + +* New/improved filesystem and disk support: + * Big-endian UFS1. + * Experimental 64-bit ext2 support. + * Various fixes for non-512-byte sector devices. + * New `proc' filesystem framework, used by LUKS disks. + * Fix DM-RAID partition handling. + * New `nativedisk' command to switch from firmware to native disk drivers. + * Compressed HFS+. + * DragonFly BSD labels. + * CBFS (coreboot). + * Handle partitioned LVM properly. + * Use LVM UUIDs whenever possible. + * GPT PReP. + * New `progress' module that shows progress information while reading + files. + * ZFS features support. + * ZFS LZ4 support. + * XFS V5 format support. + * LVM RAID1 support. + +* New/improved terminal and video support: + * Monochrome text (matching `hercules' in GRUB Legacy). + * Morse code output using system speaker. + * `spkmodem' output (simple data protocol using system speaker). + * Handle Japanese special keys. + * coreboot framebuffer. + * Serial on ARC. + * Native vt100 handling for grub-emu, replacing the use of the curses + library. + * New gfxmenu options for terminal window positioning, theme background + image handling, and scrollbar padding, plus `item_pixmap_style' and + `highlight_overlay'. + * Support several more image types (paletted and greyscale). + +* Boot protocol improvements: + * Support Apple FAT binaries on non-Apple platforms. + * Improve FreeDOS direct loading support compatibility. + * Enable `linux16' on all x86 platforms, not just BIOS. + * New TrueCrypt ISO loader. + * multiboot2 boot-services EFI specification. + * multiboot2 EFI memory map specification. + * multiboot2 full-file specfication. + +* New/improved network support: + * New variables `net_default_*' containing properties of the default + interface. + * Autoload `http' and `tftp' modules if necessary. + * Improve TFTP robustness. + * Parse `nd' disk names in GRUB Legacy configuration files. + * Issue separate DNS queries for IPv4 and IPv6. + * Support IPv6 Router Advertisement to configure default router. + * New variable net__next_server containing next server + from BOOTP reply. + +* Coreboot improvements: + * CBFS support both in on-disk images (loopback) and flash. + * Ability to launch another payload from flash or disk + * Coreboot framebuffer + * CBMEMC support (both logging and inspecting logs) + * Command for inspecting coreboot timestamps (`coreboot_boottime'). + * Command for inspecting coreboot tables (`lscoreboot'). + * New target default_payload.elf. + * Increased maximal core size. + * Prefer pmtimer for TSC calibration. + +* New/improved platform support: + * New `efifwsetup' and `lsefi' commands on EFI platforms. + * New `cmosdump' and `cmosset' commands on platforms with CMOS support. + * New command `pcidump' for PCI platforms. + * Improve opcode parsing in ACPI halt implementation. + * Use the TSC as a possible time source on i386-ieee1275. + * Merge PowerPC grub-mkrescue implementation with the common one. + * Support grub-mkrescue on i386-ieee1275, sparc64, bootinfo machines such + as pSeries, and mips-arc. + * Make grub-mkrescue better support Apple Intel Macs on CD. + * Enable GRUB Legacy configuration file parsing on EFI. + * Support halt for Loongson 2E. + * ARM U-Boot and EFI ports. + * Reorganise platform-dependent code in utilities to avoid #ifdef mess. + * AROS and Haiku support for userspace utilities. + * Xen PV port. + * Fix EFI stack alignment. + * ARM64 EFI port. + * On Linux, read partition start offsets from sysfs if possible. + * New grub-macbless utility, and better integration with Mac firmware in + grub-install. + * Support Yeeloong 3A. + * Add `cpuid --pae' option to detect Physical Address Extension on x86. + * Support for USB debug dongles. + * Support for *-emu on all platforms (previously only i386/x86_64 worked). + * Support *-emu on Windows. + * New platform `none' which builds only user level utilities. This is now + default if target CPU is not supported. + * Support for booting little-endian Linux kernel on powerpc. + * Support network boot with Oracle sun4v vnet devices. + * Added SAS disks to the IEEE 1275 Open Firmware device list. + * Try multiple methods for TSC (timestamp counter) calibration - PIT, pmtimer, + EFI Stall. If everything fails, use hardcoded frequency 800MHz. + * Support Hyper-V Gen2 platforms which lack PIT for TSC calibration. + * Map UEFI Persistent Memory to E820 persistent memory. + * New Xen loader on ARM64. + * Respect alignment requirement for block device IO buffers on EFI. + +* Security: + * Add optional facility to enforce that all files read by the core image + from disk have a valid detached digital signature. + +* Performance: + * Avoid costly division operations in many places. + * New boot time analysis framework (`./configure --enable-boot-time'). + * Initialise USB ports in parallel. + * New `testspeed' command to test file read speed. + * Speed-up gfxterm by storing intermediate results in more compact format. + * Lazy LVM/mdraid scan. + * Disk hints. + +* Scripting: + * New `eval' and `tr' commands. + * grub-script-check fails on scripts containing no commands. + +* Installation and other utility improvements: + * Add option to compress files on installation or image creation. + * Using grub-reboot no longer requires setting `GRUB_DEFAULT=saved'. + * Support probing EFI System Partition (requires os-prober >= 1.58). + * Fix inconsistent use of `GRUB_CRYPTODISK_ENABLE' and + `GRUB_ENABLE_CRYPTODISK'; the latter is now used consistently. + * grub-mount handles symbolic links to directories. + * Support disabling submenus with `GRUB_DISABLE_SUBMENU' configuration key + for grub-mkconfig. + * grub-install, grub-mknetdir, grub-mkrescue, and grub-mkstandalone + rewritten in C. They should now work in supported non-Unix-like + environments. + * Native mingw support. + * Ability to install on EFI under windows. + * Reorganise timeout handling using new `timeout_style' environment + variable and `GRUB_TIMEOUT_STYLE' configuration key for grub-mkconfig. + Menu hotkeys pressed during a hidden timeout now boot the corresponding + menu entry immediately. + * New `file' command and grub-file utility to check file types. + * New syslinux configuration file parser. + * Set menu entry class to primary OS name returned by os-prober to display + OS specific icon. + * On Linux x86 detect EFI word size in grub-install and automatically select + correct platform (x86_64-efi or i386-efi) to install. Requires Linux kernel + 4.0 or higher. + +* Build system: + * Remove all uses of nested functions; GRUB no longer requires an + executable stack. + * Fix documentation build with Texinfo >= 5.1. + * More robust and documented cross-compiling support. + * Partial clang support for some platforms (experimental). + * Partial mingw64 x86_64-efi compile support (highly experimental). + * Partial mingw32 i386-* (other than already present i386-pc) + compile support (highly experimental). + * Support for grub-mkpasswd on Windows. + * Eliminate the use of AutoGen. This allowed some performance + improvements to the build system. + * Remove variable length arrays. + * OpenBSD compile and tools support (NetBSD and FreeBSD were already supported). + * Fix build with FreeType >= 2.5.1. + * Make gentpl.py compatible with Python 3. It now requires at least + Python 2.6. + * modinfo.sh contains build information now. + * Added many new tests to improve robustness. + * Target is built without libgcc now. Necessary builtins are reimplemented + directly. This removes requirement for target-specific runtime on build + system. + * emu libusb support removed (was broken and unmaintained). + * powerpc64le compile support. + * Use fixed timestamp when generating GRUB image for reproducible builds. + * Verify at build time that modules contain only supported relocations and their + structure matches what boot-time module loader expects. + * Do not require fonts on powerpc-ieee1275. + +* Revision control moved to git. + New in 2.00: -* Appearence: +* Appearance: * Official theme for gfxmenu (starfield) * Menu is organised with submenus. * Better default video mode selection using EDID. @@ -24,7 +255,6 @@ New in 2.00: * IEEE1275 serial. * EFI serial. * Network stack for BIOS, IEEE1275, EMU and EFI, including TFTP, HTTP and DNS. - * VBE on coreboot support. * New filesystem, filters and disks formats: * DVH partition map. @@ -48,7 +278,7 @@ New in 2.00: * multidevice, mirrored and raidz(2,3) ZFS support. * RAID LVM (internal RAIDing) support. * ZFS crypto support. - * ZLE and GZIP on ZFS support. + * ZLE, LZ4 and GZIP on ZFS support. * Support ZFS up to 33. * HFS string is now treated like mac-roman and not UTF-8 * HFS mtime support. diff --git a/README b/README index b30a4b68b..49ce15ea3 100644 --- a/README +++ b/README @@ -7,13 +7,17 @@ See the file NEWS for a description of recent changes to GRUB 2. See the file INSTALL for instructions on how to build and install the GRUB 2 data and program files. +See the file MAINTAINERS for information about the GRUB maintainers, etc. + +If you found a security vulnerability in the GRUB please check the SECURITY +file to get more information how to properly report this kind of bugs to +the maintainers. + Please visit the official web page of GRUB 2, for more information. The URL is . More extensive documentation is available in the Info manual, accessible using 'info grub' after building and installing GRUB 2. -Please look at the GRUB Wiki for testing -procedures. There are a number of important user-visible differences from the first version of GRUB, now known as GRUB Legacy. For a summary, please diff --git a/SECURITY b/SECURITY new file mode 100644 index 000000000..1c3e8ef36 --- /dev/null +++ b/SECURITY @@ -0,0 +1,60 @@ +Security Policy +=============== + +To report a vulnerability see "Reporting a Vulnerability" below. + + +Security Incident Policy +======================== + +Security bug reports are treated with special attention and are handled +differently from normal bugs. In particular, security sensitive bugs are not +handled in public but in private. Information about the bug and access to it +is restricted to people in the security group, the individual engineers that +work on fixing it, and any other person who needs to be involved for organisational +reasons. The process is handled by the security team, which decides on the people +involved in order to fix the issue. It is also guaranteed that the person reporting +the issue has visibility into the process of fixing it. Any security issue gets +prioritized according to its security rating. The issue is opened up to the public +in coordination with the release schedule and the reporter. + + +Disclosure Policy +================= + +Everyone involved in the handling of a security issue - including the reporter - +is required to adhere to the following policy. Any information related to +a security issue must be treated as confidential and only shared with trusted +partners if necessary, for example to coordinate a release or manage exposure +of clients to the issue. No information must be disclosed to the public before +the embargo ends. The embargo time is agreed upon by all involved parties. It +should be as short as possible without putting any users at risk. + + +Supported Versions +================== + +Only the most recent version of the GRUB is supported. + + +Reporting a Vulnerability +========================= + +The security report should be encrypted with the PGP keys and sent to ALL email +addresses listed below. Every vulnerability report will be assessed within +72 hours of receiving it. If the outcome of the assessment is that the report +describes a security issue, the report will be transferred into an issue on the +internal vulnerability project for further processing. The reporter is updated +on each step of the process. + +While there's currently no bug bounty program we appreciate every report. + +* Contact: Daniel Kiper and + Daniel Kiper +* PGP Key Fingerprint: BE5C 2320 9ACD DACE B20D B0A2 8C81 89F1 988C 2166 + +* Contact: Alex Burmashev +* PGP Key Fingerprint: 50A4 EC06 EF7E B84D 67E0 3BB6 2AE2 C87E 28EF 2E6E + +* Contact: Vladimir 'phcoder' Serbinenko +* PGP Key Fingerprint: E53D 497F 3FA4 2AD8 C9B4 D1E8 35A9 3B74 E82E 4209 diff --git a/TODO b/TODO index 6ec1521cd..a9b6d3523 100644 --- a/TODO +++ b/TODO @@ -7,7 +7,3 @@ glance. So write to first. For bug tracking, refer to: http://savannah.gnu.org/bugs/?group=grub - -Our wiki also lists some areas that need work: - - http://grub.enbug.org/ diff --git a/acinclude.m4 b/acinclude.m4 index 0eb2e2a17..fa7840f09 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -19,6 +19,8 @@ AC_DEFUN([grub_PROG_TARGET_CC], AC_CACHE_VAL(grub_cv_prog_target_cc, [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ asm (".globl start; start:"); +void __main (void); +void __main (void) {} int main (void); ]], [[]])], [grub_cv_prog_target_cc=yes], @@ -74,7 +76,7 @@ AC_MSG_RESULT([$grub_cv_asm_uscore]) dnl Some versions of `objcopy -O binary' vary their output depending dnl on the link address. AC_DEFUN([grub_PROG_OBJCOPY_ABSOLUTE], -[AC_MSG_CHECKING([whether ${OBJCOPY} works for absolute addresses]) +[AC_MSG_CHECKING([whether ${TARGET_OBJCOPY} works for absolute addresses]) AC_CACHE_VAL(grub_cv_prog_objcopy_absolute, [cat > conftest.c <<\EOF void cmain (void); @@ -91,13 +93,13 @@ else fi grub_cv_prog_objcopy_absolute=yes for link_addr in 0x2000 0x8000 0x7C00; do - if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -nostdlib ${TARGET_IMG_LDFLAGS_AC} ${TARGET_IMG_BASE_LDOPT},$link_addr conftest.o -o conftest.exec]); then : + if AC_TRY_COMMAND([${CC-cc} ${TARGET_CFLAGS} ${TARGET_LDFLAGS} -nostdlib ${TARGET_IMG_LDFLAGS_AC} ${TARGET_IMG_BASE_LDOPT},$link_addr conftest.o -o conftest.exec]); then : else AC_MSG_ERROR([${CC-cc} cannot link at address $link_addr]) fi - if AC_TRY_COMMAND([${OBJCOPY-objcopy} --only-section=.text -O binary conftest.exec conftest]); then : + if AC_TRY_COMMAND([${TARGET_OBJCOPY-objcopy} --only-section=.text -O binary conftest.exec conftest]); then : else - AC_MSG_ERROR([${OBJCOPY-objcopy} cannot create binary files]) + AC_MSG_ERROR([${TARGET_OBJCOPY-objcopy} cannot create binary files]) fi if test ! -f conftest.old || AC_TRY_COMMAND([cmp -s conftest.old conftest]); then mv -f conftest conftest.old @@ -134,110 +136,78 @@ if test "x$grub_cv_prog_ld_build_id_none" = xyes; then fi ]) - -dnl Mass confusion! -dnl Older versions of GAS interpret `.code16' to mean ``generate 32-bit -dnl instructions, but implicitly insert addr32 and data32 bytes so -dnl that the code works in real mode''. -dnl -dnl Newer versions of GAS interpret `.code16' to mean ``generate 16-bit -dnl instructions,'' which seems right. This requires the programmer -dnl to explicitly insert addr32 and data32 instructions when they want -dnl them. -dnl -dnl We only support the newer versions, because the old versions cause -dnl major pain, by requiring manual assembly to get 16-bit instructions into -dnl asm files. -AC_DEFUN([grub_I386_ASM_ADDR32], -[AC_REQUIRE([AC_PROG_CC]) -AC_REQUIRE([grub_I386_ASM_PREFIX_REQUIREMENT]) -AC_MSG_CHECKING([for .code16 addr32 assembler support]) -AC_CACHE_VAL(grub_cv_i386_asm_addr32, -[cat > conftest.s.in <<\EOF - .code16 -l1: @ADDR32@ movb %al, l1 -EOF - -if test "x$grub_cv_i386_asm_prefix_requirement" = xyes; then - sed -e s/@ADDR32@/addr32/ < conftest.s.in > conftest.s +dnl Check nm +AC_DEFUN([grub_PROG_NM_WORKS], +[AC_MSG_CHECKING([whether nm works]) +AC_CACHE_VAL(grub_cv_prog_nm_works, +[ +nm_works_tmp_dir="$(mktemp -d "./confXXXXXX")" +AC_LANG_CONFTEST([AC_LANG_PROGRAM([[]], [[]])]) +$TARGET_CC $TARGET_CFLAGS -c conftest.c -o "$nm_works_tmp_dir/ef" +if $TARGET_NM "$nm_works_tmp_dir/ef" > /dev/null; then + grub_cv_prog_nm_works=yes else - sed -e s/@ADDR32@/addr32\;/ < conftest.s.in > conftest.s + grub_cv_prog_nm_minus_p=no fi +rm "$nm_works_tmp_dir/ef" +rmdir "$nm_works_tmp_dir" +]) +AC_MSG_RESULT([$grub_cv_prog_nm_works]) -if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then - grub_cv_i386_asm_addr32=yes -else - grub_cv_i386_asm_addr32=no -fi - -rm -f conftest*]) - -AC_MSG_RESULT([$grub_cv_i386_asm_addr32])]) - -dnl check if our compiler is apple cc -dnl because it requires numerous workarounds -AC_DEFUN([grub_apple_cc], -[AC_REQUIRE([AC_PROG_CC]) -AC_MSG_CHECKING([whether our compiler is apple cc]) -AC_CACHE_VAL(grub_cv_apple_cc, -[if $CC -v 2>&1 | grep "Apple Inc." > /dev/null; then - grub_cv_apple_cc=yes -else - grub_cv_apple_cc=no +if test "x$grub_cv_prog_nm_works" != xyes; then + AC_MSG_ERROR([nm does not work]) fi ]) -AC_MSG_RESULT([$grub_cv_apple_cc])]) - -dnl check if our target compiler is apple cc -dnl because it requires numerous workarounds -AC_DEFUN([grub_apple_target_cc], -[AC_REQUIRE([AC_PROG_CC]) -AC_MSG_CHECKING([whether our target compiler is apple cc]) -AC_CACHE_VAL(grub_cv_apple_target_cc, -[if $CC -v 2>&1 | grep "Apple Inc." > /dev/null; then - grub_cv_apple_target_cc=yes +dnl Supply -P to nm +AC_DEFUN([grub_PROG_NM_MINUS_P], +[AC_MSG_CHECKING([whether nm accepts -P]) +AC_CACHE_VAL(grub_cv_prog_nm_minus_p, +[ +nm_minus_p_tmp_dir="$(mktemp -d "./confXXXXXX")" +AC_LANG_CONFTEST([AC_LANG_PROGRAM([[]], [[]])]) +$TARGET_CC $TARGET_CFLAGS -c conftest.c -o "$nm_minus_p_tmp_dir/ef" +if $TARGET_NM -P "$nm_minus_p_tmp_dir/ef" 2>&1 > /dev/null; then + grub_cv_prog_nm_minus_p=yes else - grub_cv_apple_target_cc=no + grub_cv_prog_nm_minus_p=no +fi +rm "$nm_minus_p_tmp_dir/ef" +rmdir "$nm_minus_p_tmp_dir" +]) +AC_MSG_RESULT([$grub_cv_prog_nm_minus_p]) + +if test "x$grub_cv_prog_nm_minus_p" = xyes; then + TARGET_NMFLAGS_MINUS_P="-P" +else + TARGET_NMFLAGS_MINUS_P= fi ]) -AC_MSG_RESULT([$grub_cv_apple_target_cc])]) - - -dnl Later versions of GAS requires that addr32 and data32 prefixes -dnl appear in the same lines as the instructions they modify, while -dnl earlier versions requires that they appear in separate lines. -AC_DEFUN([grub_I386_ASM_PREFIX_REQUIREMENT], -[AC_REQUIRE([AC_PROG_CC]) -AC_MSG_CHECKING(dnl -[whether addr32 must be in the same line as the instruction]) -AC_CACHE_VAL(grub_cv_i386_asm_prefix_requirement, -[cat > conftest.s <<\EOF - .code16 -l1: addr32 movb %al, l1 -EOF - -if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -c conftest.s]) && test -s conftest.o; then - grub_cv_i386_asm_prefix_requirement=yes +dnl Supply --defined-only to nm +AC_DEFUN([grub_PROG_NM_DEFINED_ONLY], +[AC_MSG_CHECKING([whether nm accepts --defined-only]) +AC_CACHE_VAL(grub_cv_prog_nm_defined_only, +[ +nm_defined_only_tmp_dir="$(mktemp -d "./confXXXXXX")" +AC_LANG_CONFTEST([AC_LANG_PROGRAM([[]], [[]])]) +$TARGET_CC $TARGET_CFLAGS -c conftest.c -o "$nm_defined_only_tmp_dir/ef" +if $TARGET_NM --defined-only "$nm_defined_only_tmp_dir/ef" 2>&1 > /dev/null; then + grub_cv_prog_nm_defined_only=yes else - grub_cv_i386_asm_prefix_requirement=no + grub_cv_prog_nm_defined_only=no fi +rm "$nm_defined_only_tmp_dir/ef" +rmdir "$nm_defined_only_tmp_dir" +]) +AC_MSG_RESULT([$grub_cv_prog_nm_defined_only]) -rm -f conftest*]) - -if test "x$grub_cv_i386_asm_prefix_requirement" = xyes; then - grub_tmp_addr32="addr32" - grub_tmp_data32="data32" +if test "x$grub_cv_prog_nm_defined_only" = xyes; then + TARGET_NMFLAGS_DEFINED_ONLY=--defined-only else - grub_tmp_addr32="addr32;" - grub_tmp_data32="data32;" + TARGET_NMFLAGS_DEFINED_ONLY= fi - -ADDR32=$grub_tmp_addr32 -DATA32=$grub_tmp_data32 - -AC_MSG_RESULT([$grub_cv_i386_asm_prefix_requirement])]) +]) dnl Check what symbol is defined as a bss start symbol. @@ -246,7 +216,12 @@ AC_DEFUN([grub_CHECK_BSS_START_SYMBOL], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([if __bss_start is defined by the compiler]) AC_CACHE_VAL(grub_cv_check_uscore_uscore_bss_start_symbol, -[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +asm (".globl start; start:"); +void __main (void); +void __main (void) {} +int main (void); +]], [[asm ("incl __bss_start")]])], [grub_cv_check_uscore_uscore_bss_start_symbol=yes], [grub_cv_check_uscore_uscore_bss_start_symbol=no])]) @@ -255,7 +230,11 @@ AC_MSG_RESULT([$grub_cv_check_uscore_uscore_bss_start_symbol]) AC_MSG_CHECKING([if edata is defined by the compiler]) AC_CACHE_VAL(grub_cv_check_edata_symbol, -[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +asm (".globl start; start:"); +void __main (void); +void __main (void) {} +int main (void);]], [[asm ("incl edata")]])], [grub_cv_check_edata_symbol=yes], [grub_cv_check_edata_symbol=no])]) @@ -264,7 +243,11 @@ AC_MSG_RESULT([$grub_cv_check_edata_symbol]) AC_MSG_CHECKING([if _edata is defined by the compiler]) AC_CACHE_VAL(grub_cv_check_uscore_edata_symbol, -[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +asm (".globl start; start:"); +void __main (void); +void __main (void) {} +int main (void);]], [[asm ("incl _edata")]])], [grub_cv_check_uscore_edata_symbol=yes], [grub_cv_check_uscore_edata_symbol=no])]) @@ -288,7 +271,11 @@ AC_DEFUN([grub_CHECK_END_SYMBOL], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([if end is defined by the compiler]) AC_CACHE_VAL(grub_cv_check_end_symbol, -[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +asm (".globl start; start:"); +void __main (void); +void __main (void) {} +int main (void);]], [[asm ("incl end")]])], [grub_cv_check_end_symbol=yes], [grub_cv_check_end_symbol=no])]) @@ -297,7 +284,11 @@ AC_MSG_RESULT([$grub_cv_check_end_symbol]) AC_MSG_CHECKING([if _end is defined by the compiler]) AC_CACHE_VAL(grub_cv_check_uscore_end_symbol, -[AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], +[AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +asm (".globl start; start:"); +void __main (void); +void __main (void) {} +int main (void);]], [[asm ("incl _end")]])], [grub_cv_check_uscore_end_symbol=yes], [grub_cv_check_uscore_end_symbol=no])]) @@ -313,36 +304,10 @@ else fi ]) -dnl Check if the C compiler generates calls to `__enable_execute_stack()'. -AC_DEFUN([grub_CHECK_ENABLE_EXECUTE_STACK],[ -AC_MSG_CHECKING([whether `$CC' generates calls to `__enable_execute_stack()']) -AC_LANG_CONFTEST([AC_LANG_SOURCE([[ -void f (int (*p) (void)); -void g (int i) -{ - int nestedfunc (void) { return i; } - f (nestedfunc); -} -]])]) -if AC_TRY_COMMAND([${CC-cc} ${CFLAGS} -S conftest.c]) && test -s conftest.s; then - true -else - AC_MSG_ERROR([${CC-cc} failed to produce assembly code]) -fi -if grep __enable_execute_stack conftest.s >/dev/null 2>&1; then - NEED_ENABLE_EXECUTE_STACK=1 - AC_MSG_RESULT([yes]) -else - NEED_ENABLE_EXECUTE_STACK=0 - AC_MSG_RESULT([no]) -fi -rm -f conftest* -]) - -dnl Check if the C compiler supports `-fstack-protector'. +dnl Check if the C compiler supports the stack protector AC_DEFUN([grub_CHECK_STACK_PROTECTOR],[ -[# Smashing stack protector. +[# Stack smashing protector. ssp_possible=yes] AC_MSG_CHECKING([whether `$CC' accepts `-fstack-protector']) # Is this a reliable test case? @@ -359,6 +324,40 @@ else ssp_possible=no] AC_MSG_RESULT([no]) [fi] +[# Strong stack smashing protector. +ssp_strong_possible=yes] +AC_MSG_CHECKING([whether `$CC' accepts `-fstack-protector-strong']) +# Is this a reliable test case? +AC_LANG_CONFTEST([AC_LANG_SOURCE([[ +void foo (void) { volatile char a[8]; a[3]; } +]])]) +[# `$CC -c -o ...' might not be portable. But, oh, well... Is calling +# `ac_compile' like this correct, after all? +if eval "$ac_compile -S -fstack-protector-strong -o conftest.s" 2> /dev/null; then] + AC_MSG_RESULT([yes]) + [# Should we clear up other files as well, having called `AC_LANG_CONFTEST'? + rm -f conftest.s +else + ssp_strong_possible=no] + AC_MSG_RESULT([no]) +[fi] +[# Global stack smashing protector. +ssp_global_possible=yes] +AC_MSG_CHECKING([whether `$CC' accepts `-mstack-protector-guard=global']) +# Is this a reliable test case? +AC_LANG_CONFTEST([AC_LANG_SOURCE([[ +void foo (void) { volatile char a[8]; a[3]; } +]])]) +[# `$CC -c -o ...' might not be portable. But, oh, well... Is calling +# `ac_compile' like this correct, after all? +if eval "$ac_compile -S -fstack-protector -mstack-protector-guard=global -o conftest.s" 2> /dev/null; then] + AC_MSG_RESULT([yes]) + [# Should we clear up other files as well, having called `AC_LANG_CONFTEST'? + rm -f conftest.s +else + ssp_global_possible=no] + AC_MSG_RESULT([no]) +[fi] ]) dnl Check if the C compiler supports `-mstack-arg-probe' (Cygwin). @@ -369,7 +368,7 @@ AC_MSG_CHECKING([whether `$CC' accepts `-mstack-arg-probe']) AC_LANG_CONFTEST([AC_LANG_SOURCE([[ void foo (void) { volatile char a[8]; a[3]; } ]])]) -[if eval "$ac_compile -S -mstack-arg-probe -o conftest.s" 2> /dev/null; then] +[if eval "$ac_compile -S -mstack-arg-probe -Werror -o conftest.s" 2> /dev/null; then] AC_MSG_RESULT([yes]) [# Should we clear up other files as well, having called `AC_LANG_CONFTEST'? rm -f conftest.s @@ -379,15 +378,15 @@ else [fi] ]) -dnl Check if ln can handle directories properly (mingw). +dnl Check if ln -s can handle directories properly (mingw). AC_DEFUN([grub_CHECK_LINK_DIR],[ -AC_MSG_CHECKING([whether ln can handle directories properly]) +AC_MSG_CHECKING([whether ln -s can handle directories properly]) [mkdir testdir 2>/dev/null case $srcdir in [\\/$]* | ?:[\\/]* ) reldir=$srcdir/include/grub/util ;; *) reldir=../$srcdir/include/grub/util ;; esac -if ln -s $reldir testdir/util 2>/dev/null ; then] +if ln -s $reldir testdir/util 2>/dev/null && rm -f testdir/util 2>/dev/null ; then] AC_MSG_RESULT([yes]) [link_dir=yes else @@ -425,6 +424,58 @@ else [fi] ]) +AC_DEFUN([grub_CHECK_LINK_PIE],[ +[# Position independent executable. +link_nopie_needed=no] +AC_MSG_CHECKING([whether linker needs disabling of PIE to work]) +AC_LANG_CONFTEST([AC_LANG_SOURCE([[]])]) + +[if eval "$ac_compile -Wl,-r -nostdlib -Werror -o conftest.o" 2> /dev/null; then] + AC_MSG_RESULT([no]) + [# Should we clear up other files as well, having called `AC_LANG_CONFTEST'? + rm -f conftest.o +else + link_nopie_needed=yes] + AC_MSG_RESULT([yes]) +[fi] +]) + + +dnl Check if the Linker supports `-no-pie'. +AC_DEFUN([grub_CHECK_NO_PIE], +[AC_MSG_CHECKING([whether linker accepts -no-pie]) +AC_CACHE_VAL(grub_cv_cc_ld_no_pie, +[save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS -no-pie -nostdlib -Werror" +AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_ld_no_pie=yes], + [grub_cv_cc_ld_no_pie=no]) +LDFLAGS="$save_LDFLAGS" +]) +AC_MSG_RESULT([$grub_cv_cc_ld_no_pie]) +nopie_possible=no +if test "x$grub_cv_cc_ld_no_pie" = xyes ; then + nopie_possible=yes +fi +]) + +AC_DEFUN([grub_CHECK_NO_PIE_ONEWORD], +[AC_MSG_CHECKING([whether linker accepts -nopie]) +AC_CACHE_VAL(grub_cv_cc_ld_no_pie_oneword, +[save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS -nopie -nostdlib -Werror" +AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_ld_no_pie_oneword=yes], + [grub_cv_cc_ld_no_pie_oneword=no]) +LDFLAGS="$save_LDFLAGS" +]) +AC_MSG_RESULT([$grub_cv_cc_ld_no_pie_oneword]) +nopie_oneword_possible=no +if test "x$grub_cv_cc_ld_no_pie_oneword" = xyes ; then + nopie_oneword_possible=yes +fi +]) + dnl Check if the C compiler supports `-fPIC'. AC_DEFUN([grub_CHECK_PIC],[ [# Position independent executable. @@ -452,3 +503,9 @@ else AC_MSG_RESULT([no]) [fi] ]) + +dnl Create an output variable with the transformed name of a GRUB utility +dnl program. +AC_DEFUN([grub_TRANSFORM],[dnl +AC_SUBST(AS_TR_SH([$1]), [`AS_ECHO([$1]) | sed "$program_transform_name"`])dnl +]) diff --git a/asm-tests/arm.S b/asm-tests/arm.S new file mode 100644 index 000000000..97c2546bf --- /dev/null +++ b/asm-tests/arm.S @@ -0,0 +1,20 @@ +/* on arm clang doesn't support .arch directive */ + + .text + .syntax unified + +#if !defined (__thumb2__) + .arch armv7a + .arm +#else + .arch armv7 + .thumb +#endif + mcr p15, 0, r11, c7, c14, 2 + + /* clang restricts access to dsb/isb despite .arch */ + dsb + isb + + + diff --git a/asm-tests/i386-pc.S b/asm-tests/i386-pc.S new file mode 100644 index 000000000..d037744f9 --- /dev/null +++ b/asm-tests/i386-pc.S @@ -0,0 +1,18 @@ +/* on x86 old clang doesn't support .code16 + newer clang supports it but creates 6-byte jumps instead of 3-byte ones + which makes us go over boot sector size. + Starting with 3.9 clang emits 3-byte jumps but still creates 8-bytes movl + instead of 5-bytes, so code overflows into data. */ + + .code16 + jmp far + .org 4 + jmp nearer + .org 6 + movl nearer, %ebx + .org 11 + .space 100 +nearer: + .space 200 +far: + .byte 0 diff --git a/asm-tests/i386.S b/asm-tests/i386.S new file mode 100644 index 000000000..30adc4fe2 --- /dev/null +++ b/asm-tests/i386.S @@ -0,0 +1,4 @@ +/* on x86 old clang doesn't support .code16 */ + + .code16 + movb %al, %bl diff --git a/asm-tests/mips.S b/asm-tests/mips.S new file mode 100644 index 000000000..1312d47d5 --- /dev/null +++ b/asm-tests/mips.S @@ -0,0 +1,11 @@ +/* on mips clang doesn't support privilegied instructions, doubleword store/load + and crashes with hand-written assembly + */ + + .set mips3 + sync + ld $t2, 0($t1) + +a: + addiu $t1, $s0, (b - a) +b: nop diff --git a/asm-tests/powerpc.S b/asm-tests/powerpc.S new file mode 100644 index 000000000..396a6cce9 --- /dev/null +++ b/asm-tests/powerpc.S @@ -0,0 +1,8 @@ +/* clang <= 3.3 doesn't handle most of ppc assembly, not even inline assembly + used by gcrypt */ +/* Cache invalidation loop is a fair test. */ + li 5, 0 +1: icbi 5, 3 + addi 5, 5, 32 + cmpw 5, 4 + blt 1b diff --git a/asm-tests/sparc64.S b/asm-tests/sparc64.S new file mode 100644 index 000000000..03c5fe02a --- /dev/null +++ b/asm-tests/sparc64.S @@ -0,0 +1,9 @@ + .text +1: + /* A small list of examples of what clang doesn't support. */ + clr %o0 + lduw [%o4 + 4], %o4 + and %o6, ~0xff, %o6 + stw %o5, [%o3] + bne,pt %icc, 1b + nop diff --git a/autogen.sh b/autogen.sh index db719cd1d..ebd614792 100755 --- a/autogen.sh +++ b/autogen.sh @@ -2,22 +2,89 @@ set -e -export LC_CTYPE=C +if [ ! -e grub-core/lib/gnulib/stdlib.in.h ]; then + echo "Gnulib not yet bootstrapped; run ./bootstrap instead." >&2 + exit 1 +fi + +# Detect python +if [ -z "$PYTHON" ]; then + for i in python3 python3.10 python; do + if command -v "$i" > /dev/null 2>&1; then + PYTHON="$i" + echo "Using $PYTHON..." + break + fi + done + + if [ -z "$PYTHON" ]; then + echo "python not found." >&2 + exit 1 + fi +fi + export LC_COLLATE=C unset LC_ALL -autogen --version >/dev/null || exit 1 +find . -iname '*.[ch]' ! -ipath './grub-core/lib/libgcrypt-grub/*' ! -ipath './build-aux/*' ! -ipath './grub-core/lib/libgcrypt/src/misc.c' ! -ipath './grub-core/lib/libgcrypt/src/global.c' ! -ipath './grub-core/lib/libgcrypt/src/secmem.c' ! -ipath './util/grub-gen-widthspec.c' ! -ipath './util/grub-gen-asciih.c' ! -ipath './gnulib/*' ! -ipath './grub-core/lib/gnulib/*' |sort > po/POTFILES.in +find util -iname '*.in' ! -name Makefile.in |sort > po/POTFILES-shell.in echo "Importing unicode..." -python util/import_unicode.py unicode/UnicodeData.txt unicode/BidiMirroring.txt unicode/ArabicShaping.txt grub-core/unidata.c +${PYTHON} util/import_unicode.py unicode/UnicodeData.txt unicode/BidiMirroring.txt unicode/ArabicShaping.txt grub-core/unidata.c echo "Importing libgcrypt..." -python util/import_gcry.py grub-core/lib/libgcrypt/ grub-core +${PYTHON} util/import_gcry.py grub-core/lib/libgcrypt/ grub-core +sed -n -f util/import_gcrypth.sed < grub-core/lib/libgcrypt/src/gcrypt.h.in > include/grub/gcrypt/gcrypt.h +if [ -f include/grub/gcrypt/g10lib.h ]; then + rm include/grub/gcrypt/g10lib.h +fi +if [ -d grub-core/lib/libgcrypt-grub/mpi/generic ]; then + rm -rf grub-core/lib/libgcrypt-grub/mpi/generic +fi +cp grub-core/lib/libgcrypt-grub/src/g10lib.h include/grub/gcrypt/g10lib.h +cp -R grub-core/lib/libgcrypt/mpi/generic grub-core/lib/libgcrypt-grub/mpi/generic -echo "Creating Makefile.tpl..." -python gentpl.py | sed -e '/^$/{N;/^\n$/D;}' > Makefile.tpl +for x in mpi-asm-defs.h mpih-add1.c mpih-sub1.c mpih-mul1.c mpih-mul2.c mpih-mul3.c mpih-lshift.c mpih-rshift.c; do + if [ -h grub-core/lib/libgcrypt-grub/mpi/"$x" ] || [ -f grub-core/lib/libgcrypt-grub/mpi/"$x" ]; then + rm grub-core/lib/libgcrypt-grub/mpi/"$x" + fi + cp grub-core/lib/libgcrypt-grub/mpi/generic/"$x" grub-core/lib/libgcrypt-grub/mpi/"$x" +done -echo "Running autogen..." +echo "Importing libtasn1..." +if [ -d grub-core/lib/libtasn1-grub ]; then + rm -rf grub-core/lib/libtasn1-grub +fi + +mkdir -p grub-core/lib/libtasn1-grub/lib +cp grub-core/lib/libtasn1/lib/*.[ch] grub-core/lib/libtasn1-grub/lib +cp grub-core/lib/libtasn1/libtasn1.h grub-core/lib/libtasn1-grub/ + +if [ -d grub-core/tests/asn1/tests ]; then + rm -rf grub-core/tests/asn1/tests +fi + +mkdir grub-core/tests/asn1/tests +cp grub-core/lib/libtasn1/tests/*.[ch] grub-core/tests/asn1/tests + +for patch in \ + 0001-libtasn1-disable-code-not-needed-in-grub.patch \ + 0002-libtasn1-replace-strcat-with-strcpy-in-_asn1_str_cat.patch \ + 0003-libtasn1-replace-strcat-with-_asn1_str_cat.patch \ + 0004-libtasn1-adjust-the-header-paths-in-libtasn1.h.patch \ + 0005-libtasn1-Use-grub_divmod64-for-division.patch \ + 0006-libtasn1-fix-the-potential-buffer-overrun.patch \ + 0007-asn1_test-include-asn1_test.h-only.patch \ + 0008-asn1_test-rename-the-main-functions-to-the-test-name.patch \ + 0009-asn1_test-return-either-0-or-1-to-reflect-the-result.patch \ + 0010-asn1_test-remove-verbose-and-the-unnecessary-printf.patch \ + 0011-asn1_test-print-the-error-messages-with-grub_printf.patch \ + 0012-asn1_test-use-the-grub-specific-functions-and-types.patch \ + 0013-asn1_test-enable-the-testcase-only-when-GRUB_LONG_MA.patch ; do + patch -p1 -i grub-core/lib/libtasn1-patches/$patch +done + +echo "Generating Automake input..." # Automake doesn't like including files from a path outside the project. rm -f contrib grub-core/contrib @@ -41,8 +108,8 @@ for extra in contrib/*/Makefile.core.def; do fi done -cat $UTIL_DEFS | autogen -T Makefile.tpl | sed -e '/^$/{N;/^\n$/D;}' > Makefile.util.am -cat $CORE_DEFS | autogen -T Makefile.tpl | sed -e '/^$/{N;/^\n$/D;}' > grub-core/Makefile.core.am +${PYTHON} gentpl.py $UTIL_DEFS > Makefile.util.am +${PYTHON} gentpl.py $CORE_DEFS > grub-core/Makefile.core.am for extra in contrib/*/Makefile.common; do if test -e "$extra"; then @@ -66,6 +133,17 @@ done echo "Saving timestamps..." echo timestamp > stamp-h.in -echo "Running autoreconf..." -autoreconf -vi +if [ -z "$FROM_BOOTSTRAP" ]; then + # Unaided autoreconf is likely to install older versions of many files + # than the ones provided by Gnulib, but in most cases this won't matter + # very much. This mode is provided so that you can run ./autogen.sh to + # regenerate the GRUB build system in an unpacked release tarball (perhaps + # after patching it), even on systems that don't have access to + # gnulib.git. + echo "Running autoreconf..." + cp -a INSTALL INSTALL.grub + autoreconf -vif + mv INSTALL.grub INSTALL +fi + exit 0 diff --git a/bootstrap b/bootstrap new file mode 100755 index 000000000..dc2238f4a --- /dev/null +++ b/bootstrap @@ -0,0 +1,1118 @@ +#! /bin/sh +# Print a version string. +scriptversion=2022-01-26.05; # UTC + +# Bootstrap this package from checked-out sources. + +# Copyright (C) 2003-2022 Free Software Foundation, 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 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Originally written by Paul Eggert. The canonical version of this +# script is maintained as build-aux/bootstrap in gnulib, however, to +# be useful to your project, you should place a copy of it under +# version control in the top-level directory of your project. The +# intent is that all customization can be done with a bootstrap.conf +# file also maintained in your version control; gnulib comes with a +# template build-aux/bootstrap.conf to get you started. + +# Please report bugs or propose patches to bug-gnulib@gnu.org. + +nl=' +' + +# Ensure file names are sorted consistently across platforms. +LC_ALL=C +export LC_ALL + +# Ensure that CDPATH is not set. Otherwise, the output from cd +# would cause trouble in at least one use below. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +local_gl_dir=gl + +# Honor $PERL, but work even if there is none. +PERL="${PERL-perl}" + +me=$0 + +default_gnulib_url=https://git.savannah.gnu.org/git/gnulib.git + +usage() { + cat <&2 +} + +# warn_ WORD1... +warn_ () +{ + # If IFS does not start with ' ', set it and emit the warning in a subshell. + case $IFS in + ' '*) warnf_ '%s\n' "$*";; + *) (IFS=' '; warn_ "$@");; + esac +} + +# die WORD1... +die() { warn_ "$@"; exit 1; } + +# Configuration. + +# Name of the Makefile.am +gnulib_mk=gnulib.mk + +# List of gnulib modules needed. +gnulib_modules= + +# Any gnulib files needed that are not in modules. +gnulib_files= + +: ${AUTOPOINT=autopoint} +: ${AUTORECONF=autoreconf} + +# A function to be called for each unrecognized option. Returns 0 if +# the option in $1 has been processed by the function. Returns 1 if +# the option has not been processed by the function. Override it via +# your own definition in bootstrap.conf + +bootstrap_option_hook() { return 1; } + +# A function to be called in order to print the --help information +# corresponding to user-defined command-line options. + +bootstrap_print_option_usage_hook() { :; } + +# A function to be called right after gnulib-tool is run. +# Override it via your own definition in bootstrap.conf. +bootstrap_post_import_hook() { :; } + +# A function to be called after everything else in this script. +# Override it via your own definition in bootstrap.conf. +bootstrap_epilogue() { :; } + +# The command to download all .po files for a specified domain into a +# specified directory. Fill in the first %s with the destination +# directory and the second with the domain name. +po_download_command_format=\ +"wget --mirror --level=1 -nd -nv -A.po -P '%s' \ + https://translationproject.org/latest/%s/" + +# Prefer a non-empty tarname (4th argument of AC_INIT if given), else +# fall back to the package name (1st argument with munging). +extract_package_name=' + /^AC_INIT(\[*/{ + s/// + /^[^,]*,[^,]*,[^,]*,[ []*\([^][ ,)]\)/{ + s//\1/ + s/[],)].*// + p + q + } + s/[],)].*// + s/^GNU // + y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + s/[^abcdefghijklmnopqrstuvwxyz0123456789_]/-/g + p + } +' +package=$(${AUTOCONF:-autoconf} --trace AC_INIT:\$4 configure.ac 2>/dev/null) +if test -z "$package"; then + package=$(sed -n "$extract_package_name" configure.ac) \ + || die 'cannot find package name in configure.ac' +fi +gnulib_name=lib$package + +build_aux=build-aux +source_base=lib +m4_base=m4 +doc_base=doc +tests_base=tests +gnulib_extra_files=" + build-aux/install-sh + build-aux/mdate-sh + build-aux/texinfo.tex + build-aux/depcomp + build-aux/config.guess + build-aux/config.sub + doc/INSTALL +" + +# Additional gnulib-tool options to use. Use "\newline" to break lines. +gnulib_tool_option_extras= + +# Other locale categories that need message catalogs. +EXTRA_LOCALE_CATEGORIES= + +# Additional xgettext options to use. Use "\\\newline" to break lines. +XGETTEXT_OPTIONS='\\\ + --flag=_:1:pass-c-format\\\ + --flag=N_:1:pass-c-format\\\ + --flag=error:3:c-format --flag=error_at_line:5:c-format\\\ +' + +# Package bug report address and copyright holder for gettext files +COPYRIGHT_HOLDER='Free Software Foundation, Inc.' +MSGID_BUGS_ADDRESS=bug-$package@gnu.org + +# Files we don't want to import. +excluded_files= + +# File that should exist in the top directory of a checked out hierarchy, +# but not in a distribution tarball. +checkout_only_file=README-hacking + +# Whether to use copies instead of symlinks. +copy=false + +# Set this to '.cvsignore .gitignore' in bootstrap.conf if you want +# those files to be generated in directories like lib/, m4/, and po/. +# Or set it to 'auto' to make this script select which to use based +# on which version control system (if any) is used in the source directory. +vc_ignore=auto + +# Set this to true in bootstrap.conf to enable --bootstrap-sync by +# default. +bootstrap_sync=false + +# Use git to update gnulib sources +use_git=true + +check_exists() { + if test "$1" = "--verbose"; then + ($2 --version /dev/null 2>&1 + if test $? -ge 126; then + # If not found, run with diagnostics as one may be + # presented with env variables to set to find the right version + ($2 --version /dev/null 2>&1 + fi + + test $? -lt 126 +} + +# find_tool ENVVAR NAMES... +# ------------------------- +# Search for a required program. Use the value of ENVVAR, if set, +# otherwise find the first of the NAMES that can be run. +# If found, set ENVVAR to the program name, die otherwise. +# +# FIXME: code duplication, see also gnu-web-doc-update. +find_tool () +{ + find_tool_envvar=$1 + shift + find_tool_names=$@ + eval "find_tool_res=\$$find_tool_envvar" + if test x"$find_tool_res" = x; then + for i; do + if check_exists $i; then + find_tool_res=$i + break + fi + done + fi + if test x"$find_tool_res" = x; then + warn_ "one of these is required: $find_tool_names;" + die "alternatively set $find_tool_envvar to a compatible tool" + fi + eval "$find_tool_envvar=\$find_tool_res" + eval "export $find_tool_envvar" +} + +# Strip blank and comment lines to leave significant entries. +gitignore_entries() { + sed '/^#/d; /^$/d' "$@" +} + +# If $STR is not already on a line by itself in $FILE, insert it at the start. +# Entries are inserted at the start of the ignore list to ensure existing +# entries starting with ! are not overridden. Such entries support +# whitelisting exceptions after a more generic blacklist pattern. +insert_if_absent() { + file=$1 + str=$2 + test -f $file || touch $file + test -r $file || die "Error: failed to read ignore file: $file" + duplicate_entries=$(gitignore_entries $file | sort | uniq -d) + if [ "$duplicate_entries" ] ; then + die "Error: Duplicate entries in $file: " $duplicate_entries + fi + linesold=$(gitignore_entries $file | wc -l) + linesnew=$( { echo "$str"; cat $file; } | gitignore_entries | sort -u | wc -l) + if [ $linesold != $linesnew ] ; then + { echo "$str" | cat - $file > $file.bak && mv $file.bak $file; } \ + || die "insert_if_absent $file $str: failed" + fi +} + +# Adjust $PATTERN for $VC_IGNORE_FILE and insert it with +# insert_if_absent. +insert_vc_ignore() { + vc_ignore_file="$1" + pattern="$2" + case $vc_ignore_file in + *.gitignore) + # A .gitignore entry that does not start with '/' applies + # recursively to subdirectories, so prepend '/' to every + # .gitignore entry. + pattern=$(echo "$pattern" | sed s,^,/,);; + esac + insert_if_absent "$vc_ignore_file" "$pattern" +} + +symlink_to_dir() +{ + src=$1/$2 + dst=${3-$2} + + test -f "$src" && { + + # If the destination directory doesn't exist, create it. + # This is required at least for "lib/uniwidth/cjk.h". + dst_dir=$(dirname "$dst") + if ! test -d "$dst_dir"; then + mkdir -p "$dst_dir" + + # If we've just created a directory like lib/uniwidth, + # tell version control system(s) it's ignorable. + # FIXME: for now, this does only one level + parent=$(dirname "$dst_dir") + for dot_ig in x $vc_ignore; do + test $dot_ig = x && continue + ig=$parent/$dot_ig + insert_vc_ignore $ig "${dst_dir##*/}" + done + fi + + if $copy; then + { + test ! -h "$dst" || { + echo "$me: rm -f $dst" && + rm -f "$dst" + } + } && + test -f "$dst" && + cmp -s "$src" "$dst" || { + echo "$me: cp -fp $src $dst" && + cp -fp "$src" "$dst" + } + else + # Leave any existing symlink alone, if it already points to the source, + # so that broken build tools that care about symlink times + # aren't confused into doing unnecessary builds. Conversely, if the + # existing symlink's timestamp is older than the source, make it afresh, + # so that broken tools aren't confused into skipping needed builds. See + # . + test -h "$dst" && + src_ls=$(ls -diL "$src" 2>/dev/null) && set $src_ls && src_i=$1 && + dst_ls=$(ls -diL "$dst" 2>/dev/null) && set $dst_ls && dst_i=$1 && + test "$src_i" = "$dst_i" && + both_ls=$(ls -dt "$src" "$dst") && + test "X$both_ls" = "X$dst$nl$src" || { + dot_dots= + case $src in + /*) ;; + *) + case /$dst/ in + *//* | */../* | */./* | /*/*/*/*/*/) + die "invalid symlink calculation: $src -> $dst";; + /*/*/*/*/) dot_dots=../../../;; + /*/*/*/) dot_dots=../../;; + /*/*/) dot_dots=../;; + esac;; + esac + + echo "$me: ln -fs $dot_dots$src $dst" && + ln -fs "$dot_dots$src" "$dst" + } + fi + } +} + +# Override the default configuration, if necessary. +# Make sure that bootstrap.conf is sourced from the current directory +# if we were invoked as "sh bootstrap". +case "$0" in + */*) test -r "$0.conf" && . "$0.conf" ;; + *) test -r "$0.conf" && . ./"$0.conf" ;; +esac + +if test "$vc_ignore" = auto; then + vc_ignore= + test -d .git && vc_ignore=.gitignore + test -d CVS && vc_ignore="$vc_ignore .cvsignore" +fi + +if test x"$gnulib_modules$gnulib_files$gnulib_extra_files" = x; then + use_gnulib=false +else + use_gnulib=true +fi + +# Translate configuration into internal form. + +# Parse options. + +for option +do + case $option in + --help) + usage + exit;; + --version) + set -e + echo "bootstrap $scriptversion" + echo "$copyright" + exit 0 + ;; + --gnulib-srcdir=*) + GNULIB_SRCDIR=${option#--gnulib-srcdir=};; + --skip-po) + SKIP_PO=t;; + --force) + checkout_only_file=;; + --copy) + copy=true;; + --bootstrap-sync) + bootstrap_sync=true;; + --no-bootstrap-sync) + bootstrap_sync=false;; + --no-git) + use_git=false;; + *) + bootstrap_option_hook $option || die "$option: unknown option";; + esac +done + +$use_git || test -d "$GNULIB_SRCDIR" \ + || die "Error: --no-git requires --gnulib-srcdir" + +if test -n "$checkout_only_file" && test ! -r "$checkout_only_file"; then + die "Bootstrapping from a non-checked-out distribution is risky." +fi + +# Die if there is no AC_CONFIG_AUX_DIR($build_aux) line in configure.ac. +found_aux_dir=no +grep '^[ ]*AC_CONFIG_AUX_DIR(\['"$build_aux"'\])' configure.ac \ + >/dev/null && found_aux_dir=yes +grep '^[ ]*AC_CONFIG_AUX_DIR('"$build_aux"')' configure.ac \ + >/dev/null && found_aux_dir=yes +test $found_aux_dir = yes \ + || die "configure.ac lacks 'AC_CONFIG_AUX_DIR([$build_aux])'; add it" + +# If $build_aux doesn't exist, create it now, otherwise some bits +# below will malfunction. If creating it, also mark it as ignored. +if test ! -d $build_aux; then + mkdir $build_aux + for dot_ig in x $vc_ignore; do + test $dot_ig = x && continue + insert_vc_ignore $dot_ig $build_aux + done +fi + +# Note this deviates from the version comparison in automake +# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a +# but this should suffice as we won't be specifying old +# version formats or redundant trailing .0 in bootstrap.conf. +# If we did want full compatibility then we should probably +# use m4_version_compare from autoconf. +sort_ver() { # sort -V is not generally available + ver1="$1" + ver2="$2" + + # split on '.' and compare each component + i=1 + while : ; do + p1=$(echo "$ver1" | cut -d. -f$i) + p2=$(echo "$ver2" | cut -d. -f$i) + if [ ! "$p1" ]; then + echo "$1 $2" + break + elif [ ! "$p2" ]; then + echo "$2 $1" + break + elif [ ! "$p1" = "$p2" ]; then + if [ "$p1" -gt "$p2" ] 2>/dev/null; then # numeric comparison + echo "$2 $1" + elif [ "$p2" -gt "$p1" ] 2>/dev/null; then # numeric comparison + echo "$1 $2" + else # numeric, then lexicographic comparison + lp=$(printf "$p1\n$p2\n" | LANG=C sort -n | tail -n1) + if [ "$lp" = "$p2" ]; then + echo "$1 $2" + else + echo "$2 $1" + fi + fi + break + fi + i=$(($i+1)) + done +} + +get_version_sed=' +# Move version to start of line. +s/.*[v ]\([0-9]\)/\1/ + +# Skip lines that do not start with version. +/^[0-9]/!d + +# Remove characters after the version. +s/[^.a-z0-9-].*// + +# The first component must be digits only. +s/^\([0-9]*\)[a-z-].*/\1/ + +#the following essentially does s/5.005/5.5/ +s/\.0*\([1-9]\)/.\1/g +p +q' + +get_version() { + app=$1 + + $app --version >/dev/null 2>&1 || { $app --version; return 1; } + + $app --version 2>&1 | sed -n "$get_version_sed" +} + +check_versions() { + ret=0 + + while read app req_ver; do + # We only need libtoolize from the libtool package. + if test "$app" = libtool; then + app=libtoolize + fi + # Exempt git if --no-git is in effect. + if test "$app" = git; then + $use_git || continue + fi + # Honor $APP variables ($TAR, $AUTOCONF, etc.) + appvar=$(echo $app | LC_ALL=C tr '[a-z]-' '[A-Z]_') + test "$appvar" = TAR && appvar=AMTAR + case $appvar in + GZIP) ;; # Do not use $GZIP: it contains gzip options. + PERL::*) ;; # Keep perl modules as-is + *) eval "app=\${$appvar-$app}" ;; + esac + + # Handle the still-experimental Automake-NG programs specially. + # They remain named as the mainstream Automake programs ("automake", + # and "aclocal") to avoid gratuitous incompatibilities with + # pre-existing usages (by, say, autoreconf, or custom autogen.sh + # scripts), but correctly identify themselves (as being part of + # "GNU automake-ng") when asked their version. + case $app in + automake-ng|aclocal-ng) + app=${app%-ng} + ($app --version | grep '(GNU automake-ng)') >/dev/null 2>&1 || { + warn_ "Error: '$app' not found or not from Automake-NG" + ret=1 + continue + } ;; + # Another check is for perl modules. These can be written as + # e.g. perl::XML::XPath in case of XML::XPath module, etc. + perl::*) + # Extract module name + app="${app#perl::}" + if ! $PERL -m"$app" -e 'exit 0' >/dev/null 2>&1; then + warn_ "Error: perl module '$app' not found" + ret=1 + fi + continue + ;; + esac + if [ "$req_ver" = "-" ]; then + # Merely require app to exist; not all prereq apps are well-behaved + # so we have to rely on $? rather than get_version. + if ! check_exists --verbose $app; then + warn_ "Error: '$app' not found" + ret=1 + fi + else + # Require app to produce a new enough version string. + inst_ver=$(get_version $app) + if [ ! "$inst_ver" ]; then + warn_ "Error: '$app' not found" + ret=1 + else + latest_ver=$(sort_ver $req_ver $inst_ver | cut -d' ' -f2) + if [ ! "$latest_ver" = "$inst_ver" ]; then + warnf_ '%s\n' \ + "Error: '$app' version == $inst_ver is too old" \ + " '$app' version >= $req_ver is required" + ret=1 + fi + fi + fi + done + + return $ret +} + +print_versions() { + echo "Program Min_version" + echo "----------------------" + printf %s "$buildreq" + echo "----------------------" + # can't depend on column -t +} + +# Find sha1sum, named gsha1sum on MacPorts, shasum on Mac OS X 10.6. +# Also find the compatible sha1 utility on the BSDs +if test x"$SKIP_PO" = x; then + find_tool SHA1SUM sha1sum gsha1sum shasum sha1 +fi + +use_libtool=0 +# We'd like to use grep -E, to see if any of LT_INIT, +# AC_PROG_LIBTOOL, AM_PROG_LIBTOOL is used in configure.ac, +# but that's not portable enough (e.g., for Solaris). +grep '^[ ]*A[CM]_PROG_LIBTOOL' configure.ac >/dev/null \ + && use_libtool=1 +grep '^[ ]*LT_INIT' configure.ac >/dev/null \ + && use_libtool=1 +if test $use_libtool = 1; then + find_tool LIBTOOLIZE glibtoolize libtoolize +fi + +# gnulib-tool requires at least automake and autoconf. +# If either is not listed, add it (with minimum version) as a prerequisite. +case $buildreq in + *automake*) ;; + *) buildreq="automake 1.9 +$buildreq" ;; +esac +case $buildreq in + *autoconf*) ;; + *) buildreq="autoconf 2.59 +$buildreq" ;; +esac + +# When we can deduce that gnulib-tool will require patch, +# and when patch is not already listed as a prerequisite, add it, too. +if test -d "$local_gl_dir" \ + && ! find "$local_gl_dir" -name '*.diff' -exec false {} +; then + case $buildreq in + *patch*) ;; + *) buildreq="patch - +$buildreq" ;; + esac +fi + +if ! printf "$buildreq" | check_versions; then + echo >&2 + if test -f README-prereq; then + die "See README-prereq for how to get the prerequisite programs" + else + die "Please install the prerequisite programs" + fi +fi + +# Warn the user if autom4te appears to be broken; this causes known +# issues with at least gettext 0.18.3. +probe=$(echo 'm4_quote([hi])' | autom4te -l M4sugar -t 'm4_quote:$%' -) +if test "x$probe" != xhi; then + warn_ "WARNING: your autom4te wrapper eats stdin;" + warn_ "if bootstrap fails, consider upgrading your autotools" +fi + +echo "$0: Bootstrapping from checked-out $package sources..." + +# See if we can use gnulib's git-merge-changelog merge driver. +if $use_git && test -d .git && check_exists git; then + if git config merge.merge-changelog.driver >/dev/null ; then + : + elif check_exists git-merge-changelog; then + echo "$0: initializing git-merge-changelog driver" + git config merge.merge-changelog.name 'GNU-style ChangeLog merge driver' + git config merge.merge-changelog.driver 'git-merge-changelog %O %A %B' + else + echo "$0: consider installing git-merge-changelog from gnulib" + fi +fi + + +cleanup_gnulib() { + status=$? + rm -fr "$gnulib_path" + exit $status +} + +git_modules_config () { + test -f .gitmodules && git config --file .gitmodules "$@" +} + +if $use_gnulib; then + if $use_git; then + gnulib_path=$(git_modules_config submodule.gnulib.path) + test -z "$gnulib_path" && gnulib_path=gnulib + fi + + # Get gnulib files. Populate $GNULIB_SRCDIR, possibly updating a + # submodule, for use in the rest of the script. + + case ${GNULIB_SRCDIR--} in + -) + # Note that $use_git is necessarily true in this case. + if git_modules_config submodule.gnulib.url >/dev/null; then + echo "$0: getting gnulib files..." + git submodule init -- "$gnulib_path" || exit $? + git submodule update -- "$gnulib_path" || exit $? + + elif [ ! -d "$gnulib_path" ]; then + echo "$0: getting gnulib files..." + + trap cleanup_gnulib 1 2 13 15 + + shallow= + if test -z "$GNULIB_REVISION"; then + git clone -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2' + git clone $shallow ${GNULIB_URL:-$default_gnulib_url} "$gnulib_path" \ + || cleanup_gnulib + else + git fetch -h 2>&1 | grep -- --depth > /dev/null && shallow='--depth 2' + mkdir -p "$gnulib_path" + # Only want a shallow checkout of $GNULIB_REVISION, but git does not + # support cloning by commit hash. So attempt a shallow fetch by commit + # hash to minimize the amount of data downloaded and changes needed to + # be processed, which can drastically reduce download and processing + # time for checkout. If the fetch by commit fails, a shallow fetch can + # not be performed because we do not know what the depth of the commit + # is without fetching all commits. So fallback to fetching all commits. + git -C "$gnulib_path" init + git -C "$gnulib_path" remote add origin ${GNULIB_URL:-$default_gnulib_url} + git -C "$gnulib_path" fetch $shallow origin "$GNULIB_REVISION" \ + || git -C "$gnulib_path" fetch origin \ + || cleanup_gnulib + git -C "$gnulib_path" reset --hard FETCH_HEAD + fi + + trap - 1 2 13 15 + fi + GNULIB_SRCDIR=$gnulib_path + ;; + *) + # Use GNULIB_SRCDIR directly or as a reference. + if $use_git && test -d "$GNULIB_SRCDIR"/.git && \ + git_modules_config submodule.gnulib.url >/dev/null; then + echo "$0: getting gnulib files..." + if git submodule -h|grep -- --reference > /dev/null; then + # Prefer the one-liner available in git 1.6.4 or newer. + git submodule update --init --reference "$GNULIB_SRCDIR" \ + "$gnulib_path" || exit $? + else + # This fallback allows at least git 1.5.5. + if test -f "$gnulib_path"/gnulib-tool; then + # Since file already exists, assume submodule init already complete. + git submodule update -- "$gnulib_path" || exit $? + else + # Older git can't clone into an empty directory. + rmdir "$gnulib_path" 2>/dev/null + git clone --reference "$GNULIB_SRCDIR" \ + "$(git_modules_config submodule.gnulib.url)" "$gnulib_path" \ + && git submodule init -- "$gnulib_path" \ + && git submodule update -- "$gnulib_path" \ + || exit $? + fi + fi + GNULIB_SRCDIR=$gnulib_path + fi + ;; + esac + + if test -d "$GNULIB_SRCDIR"/.git && test -n "$GNULIB_REVISION" \ + && ! git_modules_config submodule.gnulib.url >/dev/null; then + (cd "$GNULIB_SRCDIR" && git checkout "$GNULIB_REVISION") || cleanup_gnulib + fi + + # $GNULIB_SRCDIR now points to the version of gnulib to use, and + # we no longer need to use git or $gnulib_path below here. + + if $bootstrap_sync; then + cmp -s "$0" "$GNULIB_SRCDIR/build-aux/bootstrap" || { + echo "$0: updating bootstrap and restarting..." + case $(sh -c 'echo "$1"' -- a) in + a) ignored=--;; + *) ignored=ignored;; + esac + exec sh -c \ + 'cp "$1" "$2" && shift && exec "${CONFIG_SHELL-/bin/sh}" "$@"' \ + $ignored "$GNULIB_SRCDIR/build-aux/bootstrap" \ + "$0" "$@" --no-bootstrap-sync + } + fi + + gnulib_tool=$GNULIB_SRCDIR/gnulib-tool + <$gnulib_tool || exit $? +fi + +# Get translations. + +download_po_files() { + subdir=$1 + domain=$2 + echo "$me: getting translations into $subdir for $domain..." + cmd=$(printf "$po_download_command_format" "$subdir" "$domain") + eval "$cmd" +} + +# Mirror .po files to $po_dir/.reference and copy only the new +# or modified ones into $po_dir. Also update $po_dir/LINGUAS. +# Note po files that exist locally only are left in $po_dir but will +# not be included in LINGUAS and hence will not be distributed. +update_po_files() { + # Directory containing primary .po files. + # Overwrite them only when we're sure a .po file is new. + po_dir=$1 + domain=$2 + + # Mirror *.po files into this dir. + # Usually contains *.s1 checksum files. + ref_po_dir="$po_dir/.reference" + + test -d $ref_po_dir || mkdir $ref_po_dir || return + download_po_files $ref_po_dir $domain \ + && ls "$ref_po_dir"/*.po 2>/dev/null | + sed 's|.*/||; s|\.po$||' > "$po_dir/LINGUAS" || return + + langs=$(cd $ref_po_dir && echo *.po | sed 's/\.po//g') + test "$langs" = '*' && langs=x + for po in $langs; do + case $po in x) continue;; esac + new_po="$ref_po_dir/$po.po" + cksum_file="$ref_po_dir/$po.s1" + if ! test -f "$cksum_file" || + ! test -f "$po_dir/$po.po" || + ! $SHA1SUM -c "$cksum_file" < "$new_po" > /dev/null 2>&1; then + echo "$me: updated $po_dir/$po.po..." + cp "$new_po" "$po_dir/$po.po" \ + && $SHA1SUM < "$new_po" > "$cksum_file" || return + fi + done +} + +case $SKIP_PO in +'') + if test -d po; then + update_po_files po $package || exit + fi + + if test -d runtime-po; then + update_po_files runtime-po $package-runtime || exit + fi;; +esac + +version_controlled_file() { + parent=$1 + file=$2 + if test -d .git; then + git rm -n "$file" > /dev/null 2>&1 + elif test -d .svn; then + svn log -r HEAD "$file" > /dev/null 2>&1 + elif test -d CVS; then + grep -F "/${file##*/}/" "$parent/CVS/Entries" 2>/dev/null | + grep '^/[^/]*/[0-9]' > /dev/null + else + warn_ "no version control for $file?" + false + fi +} + +# NOTE: we have to be careful to run both autopoint and libtoolize +# before gnulib-tool, since gnulib-tool is likely to provide newer +# versions of files "installed" by these two programs. +# Then, *after* gnulib-tool (see below), we have to be careful to +# run autoreconf in such a way that it does not run either of these +# two just-pre-run programs. + +# Import from gettext. +with_gettext=yes +grep '^[ ]*AM_GNU_GETTEXT_VERSION(' configure.ac >/dev/null || \ + with_gettext=no + +if test $with_gettext = yes || test $use_libtool = 1; then + + tempbase=.bootstrap$$ + trap "rm -f $tempbase.0 $tempbase.1" 1 2 13 15 + + > $tempbase.0 > $tempbase.1 && + find . ! -type d -print | sort > $tempbase.0 || exit + + if test $with_gettext = yes; then + # Released autopoint has the tendency to install macros that have been + # obsoleted in current gnulib, so run this before gnulib-tool. + echo "$0: $AUTOPOINT --force" + $AUTOPOINT --force || exit + fi + + # Autoreconf runs aclocal before libtoolize, which causes spurious + # warnings if the initial aclocal is confused by the libtoolized + # (or worse out-of-date) macro directory. + # libtoolize 1.9b added the --install option; but we support back + # to libtoolize 1.5.22, where the install action was default. + if test $use_libtool = 1; then + install= + case $($LIBTOOLIZE --help) in + *--install*) install=--install ;; + esac + echo "running: $LIBTOOLIZE $install --copy" + $LIBTOOLIZE $install --copy + fi + + find . ! -type d -print | sort >$tempbase.1 + old_IFS=$IFS + IFS=$nl + for file in $(comm -13 $tempbase.0 $tempbase.1); do + IFS=$old_IFS + parent=${file%/*} + version_controlled_file "$parent" "$file" || { + for dot_ig in x $vc_ignore; do + test $dot_ig = x && continue + ig=$parent/$dot_ig + insert_vc_ignore "$ig" "${file##*/}" + done + } + done + IFS=$old_IFS + + rm -f $tempbase.0 $tempbase.1 + trap - 1 2 13 15 +fi + +# Import from gnulib. + +if $use_gnulib; then + gnulib_tool_options="\ + --no-changelog\ + --aux-dir=$build_aux\ + --doc-base=$doc_base\ + --lib=$gnulib_name\ + --m4-base=$m4_base/\ + --source-base=$source_base/\ + --tests-base=$tests_base\ + --local-dir=$local_gl_dir\ + $gnulib_tool_option_extras\ + " + if test $use_libtool = 1; then + case "$gnulib_tool_options " in + *' --libtool '*) ;; + *) gnulib_tool_options="$gnulib_tool_options --libtool" ;; + esac + fi + echo "$0: $gnulib_tool $gnulib_tool_options --import ..." + $gnulib_tool $gnulib_tool_options --import $gnulib_modules \ + || die "gnulib-tool failed" + + for file in $gnulib_files; do + symlink_to_dir "$GNULIB_SRCDIR" $file \ + || die "failed to symlink $file" + done +fi + +bootstrap_post_import_hook \ + || die "bootstrap_post_import_hook failed" + +# Don't proceed if there are uninitialized submodules. In particular, +# the next step will remove dangling links, which might be links into +# uninitialized submodules. +# +# Uninitialized submodules are listed with an initial dash. +if $use_git && git submodule | grep '^-' >/dev/null; then + die "some git submodules are not initialized. " \ + "Run 'git submodule update --init' and bootstrap again." +fi + +# Remove any dangling symlink matching "*.m4" or "*.[ch]" in some +# gnulib-populated directories. Such .m4 files would cause aclocal to fail. +# The following requires GNU find 4.2.3 or newer. Considering the usual +# portability constraints of this script, that may seem a very demanding +# requirement, but it should be ok. Ignore any failure, which is fine, +# since this is only a convenience to help developers avoid the relatively +# unusual case in which a symlinked-to .m4 file is git-removed from gnulib +# between successive runs of this script. +find "$m4_base" "$source_base" \ + -depth \( -name '*.m4' -o -name '*.[ch]' \) \ + -type l -xtype l -delete > /dev/null 2>&1 + +# Invoke autoreconf with --force --install to ensure upgrades of tools +# such as ylwrap. +AUTORECONFFLAGS="--verbose --install --force -I $m4_base $ACLOCAL_FLAGS" + +# Some systems (RHEL 5) are using ancient autotools, for which the +# --no-recursive option had not been invented. Detect that lack and +# omit the option when it's not supported. FIXME in 2017: remove this +# hack when RHEL 5 autotools are updated, or when they become irrelevant. +case $($AUTORECONF --help) in + *--no-recursive*) AUTORECONFFLAGS="$AUTORECONFFLAGS --no-recursive";; +esac + +# Tell autoreconf not to invoke autopoint or libtoolize; they were run above. +echo "running: AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS" +AUTOPOINT=true LIBTOOLIZE=true $AUTORECONF $AUTORECONFFLAGS \ + || die "autoreconf failed" + +# Get some extra files from gnulib, overriding existing files. +for file in $gnulib_extra_files; do + case $file in + */INSTALL) dst=INSTALL;; + build-aux/*) dst=$build_aux/${file#build-aux/};; + *) dst=$file;; + esac + symlink_to_dir "$GNULIB_SRCDIR" $file $dst \ + || die "failed to symlink $file" +done + +if test $with_gettext = yes; then + # Create gettext configuration. + echo "$0: Creating po/Makevars from po/Makevars.template ..." + rm -f po/Makevars + sed ' + /^EXTRA_LOCALE_CATEGORIES *=/s/=.*/= '"$EXTRA_LOCALE_CATEGORIES"'/ + /^COPYRIGHT_HOLDER *=/s/=.*/= '"$COPYRIGHT_HOLDER"'/ + /^MSGID_BUGS_ADDRESS *=/s|=.*|= '"$MSGID_BUGS_ADDRESS"'| + /^XGETTEXT_OPTIONS *=/{ + s/$/ \\/ + a\ + '"$XGETTEXT_OPTIONS"' $${end_of_xgettext_options+} + } + ' po/Makevars.template >po/Makevars \ + || die 'cannot generate po/Makevars' + + # If the 'gettext' module is in use, grab the latest Makefile.in.in. + # If only the 'gettext-h' module is in use, assume autopoint already + # put the correct version of this file into place. + case $gnulib_modules in + *gettext-h*) ;; + *gettext*) + cp $GNULIB_SRCDIR/build-aux/po/Makefile.in.in po/Makefile.in.in \ + || die "cannot create po/Makefile.in.in" + ;; + esac + + if test -d runtime-po; then + # Similarly for runtime-po/Makevars, but not quite the same. + rm -f runtime-po/Makevars + sed ' + /^DOMAIN *=.*/s/=.*/= '"$package"'-runtime/ + /^subdir *=.*/s/=.*/= runtime-po/ + /^MSGID_BUGS_ADDRESS *=/s/=.*/= bug-'"$package"'@gnu.org/ + /^XGETTEXT_OPTIONS *=/{ + s/$/ \\/ + a\ + '"$XGETTEXT_OPTIONS_RUNTIME"' $${end_of_xgettext_options+} + } + ' po/Makevars.template >runtime-po/Makevars \ + || die 'cannot generate runtime-po/Makevars' + + # Copy identical files from po to runtime-po. + (cd po && cp -p Makefile.in.in *-quot *.header *.sed *.sin ../runtime-po) + fi +fi + +bootstrap_epilogue + +echo "$0: done. Now you can run './configure'." + +# Local Variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/bootstrap.conf b/bootstrap.conf new file mode 100644 index 000000000..7a7813d28 --- /dev/null +++ b/bootstrap.conf @@ -0,0 +1,103 @@ +# Bootstrap configuration. + +# Copyright (C) 2006-2022 Free Software Foundation, 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 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +GNULIB_REVISION=9f48fb992a3d7e96610c4ce8be969cff2d61a01b + +# gnulib modules used by this package. +# mbswidth is used by fix-width.diff's changes to argp rather than directly. +gnulib_modules=" + argp + base64 + error + fnmatch + getdelim + getline + gettext-h + gitlog-to-changelog + mbswidth + progname + realloc-gnu + regex + save-cwd + stdbool +" + +gnulib_tool_option_extras="\ + --no-conditional-dependencies \ + --no-vc-files \ +" + +gnulib_name=libgnu +source_base=grub-core/lib/gnulib +gnulib_extra_files=" + build-aux/install-sh + build-aux/mdate-sh + build-aux/texinfo.tex + build-aux/depcomp + build-aux/config.guess + build-aux/config.sub +" + +# Additional xgettext options to use. Use "\\\newline" to break lines. +XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\ + --from-code=UTF-8\\\ +' + +checkout_only_file= +copy=true +vc_ignore= + +SKIP_PO=t + +# Build prerequisites +buildreq="\ +autoconf 2.64 +automake 1.14 +gettext - +git 1.5.5 +patch - +tar - +" + +# bootstrap doesn't give us a reasonable way to stop Automake from +# overwriting this, so we just copy our version aside and put it back later. +cp -a INSTALL INSTALL.grub + +bootstrap_post_import_hook () { + set -e + + # Instead of patching our gnulib and therefore maintaining a fork, submit + # changes to gnulib and update the hash above when they've merged. Do not + # add new patches here. + patch -d grub-core/lib/gnulib -p2 < grub-core/lib/gnulib-patches/fix-width.patch + + for patchname in \ + 0001-Support-POTFILES-shell \ + 0002-Handle-gettext_printf-shell-function \ + 0003-Make-msgfmt-output-in-little-endian \ + 0004-Use-SHELL-rather-than-bin-sh; do + patch -d po -p3 \ + < "po/gettext-patches/$patchname.patch" + done + FROM_BOOTSTRAP=1 ./autogen.sh + set +e # bootstrap expects this +} + +bootstrap_epilogue () { + mv INSTALL.grub INSTALL +} diff --git a/build-aux/arg-nonnull.h b/build-aux/arg-nonnull.h deleted file mode 100644 index 7e3e2db82..000000000 --- a/build-aux/arg-nonnull.h +++ /dev/null @@ -1,26 +0,0 @@ -/* A C macro for declaring that specific arguments must not be NULL. - Copyright (C) 2009, 2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* _GL_ARG_NONNULL((n,...,m)) tells the compiler and static analyzer tools - that the values passed as arguments n, ..., m must be non-NULL pointers. - n = 1 stands for the first argument, n = 2 for the second argument etc. */ -#ifndef _GL_ARG_NONNULL -# if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ > 3 -# define _GL_ARG_NONNULL(params) __attribute__ ((__nonnull__ params)) -# else -# define _GL_ARG_NONNULL(params) -# endif -#endif diff --git a/build-aux/c++defs.h b/build-aux/c++defs.h deleted file mode 100644 index 0c2fad7a2..000000000 --- a/build-aux/c++defs.h +++ /dev/null @@ -1,271 +0,0 @@ -/* C++ compatible function declaration macros. - Copyright (C) 2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef _GL_CXXDEFS_H -#define _GL_CXXDEFS_H - -/* The three most frequent use cases of these macros are: - - * For providing a substitute for a function that is missing on some - platforms, but is declared and works fine on the platforms on which - it exists: - - #if @GNULIB_FOO@ - # if !@HAVE_FOO@ - _GL_FUNCDECL_SYS (foo, ...); - # endif - _GL_CXXALIAS_SYS (foo, ...); - _GL_CXXALIASWARN (foo); - #elif defined GNULIB_POSIXCHECK - ... - #endif - - * For providing a replacement for a function that exists on all platforms, - but is broken/insufficient and needs to be replaced on some platforms: - - #if @GNULIB_FOO@ - # if @REPLACE_FOO@ - # if !(defined __cplusplus && defined GNULIB_NAMESPACE) - # undef foo - # define foo rpl_foo - # endif - _GL_FUNCDECL_RPL (foo, ...); - _GL_CXXALIAS_RPL (foo, ...); - # else - _GL_CXXALIAS_SYS (foo, ...); - # endif - _GL_CXXALIASWARN (foo); - #elif defined GNULIB_POSIXCHECK - ... - #endif - - * For providing a replacement for a function that exists on some platforms - but is broken/insufficient and needs to be replaced on some of them and - is additionally either missing or undeclared on some other platforms: - - #if @GNULIB_FOO@ - # if @REPLACE_FOO@ - # if !(defined __cplusplus && defined GNULIB_NAMESPACE) - # undef foo - # define foo rpl_foo - # endif - _GL_FUNCDECL_RPL (foo, ...); - _GL_CXXALIAS_RPL (foo, ...); - # else - # if !@HAVE_FOO@ or if !@HAVE_DECL_FOO@ - _GL_FUNCDECL_SYS (foo, ...); - # endif - _GL_CXXALIAS_SYS (foo, ...); - # endif - _GL_CXXALIASWARN (foo); - #elif defined GNULIB_POSIXCHECK - ... - #endif -*/ - -/* _GL_EXTERN_C declaration; - performs the declaration with C linkage. */ -#if defined __cplusplus -# define _GL_EXTERN_C extern "C" -#else -# define _GL_EXTERN_C extern -#endif - -/* _GL_FUNCDECL_RPL (func, rettype, parameters_and_attributes); - declares a replacement function, named rpl_func, with the given prototype, - consisting of return type, parameters, and attributes. - Example: - _GL_FUNCDECL_RPL (open, int, (const char *filename, int flags, ...) - _GL_ARG_NONNULL ((1))); - */ -#define _GL_FUNCDECL_RPL(func,rettype,parameters_and_attributes) \ - _GL_FUNCDECL_RPL_1 (rpl_##func, rettype, parameters_and_attributes) -#define _GL_FUNCDECL_RPL_1(rpl_func,rettype,parameters_and_attributes) \ - _GL_EXTERN_C rettype rpl_func parameters_and_attributes - -/* _GL_FUNCDECL_SYS (func, rettype, parameters_and_attributes); - declares the system function, named func, with the given prototype, - consisting of return type, parameters, and attributes. - Example: - _GL_FUNCDECL_SYS (open, int, (const char *filename, int flags, ...) - _GL_ARG_NONNULL ((1))); - */ -#define _GL_FUNCDECL_SYS(func,rettype,parameters_and_attributes) \ - _GL_EXTERN_C rettype func parameters_and_attributes - -/* _GL_CXXALIAS_RPL (func, rettype, parameters); - declares a C++ alias called GNULIB_NAMESPACE::func - that redirects to rpl_func, if GNULIB_NAMESPACE is defined. - Example: - _GL_CXXALIAS_RPL (open, int, (const char *filename, int flags, ...)); - */ -#define _GL_CXXALIAS_RPL(func,rettype,parameters) \ - _GL_CXXALIAS_RPL_1 (func, rpl_##func, rettype, parameters) -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ - namespace GNULIB_NAMESPACE \ - { \ - rettype (*const func) parameters = ::rpl_func; \ - } \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#else -# define _GL_CXXALIAS_RPL_1(func,rpl_func,rettype,parameters) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIAS_RPL_CAST_1 (func, rpl_func, rettype, parameters); - is like _GL_CXXALIAS_RPL_1 (func, rpl_func, rettype, parameters); - except that the C function rpl_func may have a slightly different - declaration. A cast is used to silence the "invalid conversion" error - that would otherwise occur. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ - namespace GNULIB_NAMESPACE \ - { \ - rettype (*const func) parameters = \ - reinterpret_cast(::rpl_func); \ - } \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#else -# define _GL_CXXALIAS_RPL_CAST_1(func,rpl_func,rettype,parameters) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIAS_SYS (func, rettype, parameters); - declares a C++ alias called GNULIB_NAMESPACE::func - that redirects to the system provided function func, if GNULIB_NAMESPACE - is defined. - Example: - _GL_CXXALIAS_SYS (open, int, (const char *filename, int flags, ...)); - */ -#if defined __cplusplus && defined GNULIB_NAMESPACE - /* If we were to write - rettype (*const func) parameters = ::func; - like above in _GL_CXXALIAS_RPL_1, the compiler could optimize calls - better (remove an indirection through a 'static' pointer variable), - but then the _GL_CXXALIASWARN macro below would cause a warning not only - for uses of ::func but also for uses of GNULIB_NAMESPACE::func. */ -# define _GL_CXXALIAS_SYS(func,rettype,parameters) \ - namespace GNULIB_NAMESPACE \ - { \ - static rettype (*func) parameters = ::func; \ - } \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#else -# define _GL_CXXALIAS_SYS(func,rettype,parameters) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIAS_SYS_CAST (func, rettype, parameters); - is like _GL_CXXALIAS_SYS (func, rettype, parameters); - except that the C function func may have a slightly different declaration. - A cast is used to silence the "invalid conversion" error that would - otherwise occur. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ - namespace GNULIB_NAMESPACE \ - { \ - static rettype (*func) parameters = \ - reinterpret_cast(::func); \ - } \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#else -# define _GL_CXXALIAS_SYS_CAST(func,rettype,parameters) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIAS_SYS_CAST2 (func, rettype, parameters, rettype2, parameters2); - is like _GL_CXXALIAS_SYS (func, rettype, parameters); - except that the C function is picked among a set of overloaded functions, - namely the one with rettype2 and parameters2. Two consecutive casts - are used to silence the "cannot find a match" and "invalid conversion" - errors that would otherwise occur. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE - /* The outer cast must be a reinterpret_cast. - The inner cast: When the function is defined as a set of overloaded - functions, it works as a static_cast<>, choosing the designated variant. - When the function is defined as a single variant, it works as a - reinterpret_cast<>. The parenthesized cast syntax works both ways. */ -# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ - namespace GNULIB_NAMESPACE \ - { \ - static rettype (*func) parameters = \ - reinterpret_cast( \ - (rettype2(*)parameters2)(::func)); \ - } \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#else -# define _GL_CXXALIAS_SYS_CAST2(func,rettype,parameters,rettype2,parameters2) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIASWARN (func); - causes a warning to be emitted when ::func is used but not when - GNULIB_NAMESPACE::func is used. func must be defined without overloaded - variants. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_CXXALIASWARN(func) \ - _GL_CXXALIASWARN_1 (func, GNULIB_NAMESPACE) -# define _GL_CXXALIASWARN_1(func,namespace) \ - _GL_CXXALIASWARN_2 (func, namespace) -/* To work around GCC bug , - we enable the warning only when not optimizing. */ -# if !__OPTIMIZE__ -# define _GL_CXXALIASWARN_2(func,namespace) \ - _GL_WARN_ON_USE (func, \ - "The symbol ::" #func " refers to the system function. " \ - "Use " #namespace "::" #func " instead.") -# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING -# define _GL_CXXALIASWARN_2(func,namespace) \ - extern __typeof__ (func) func -# else -# define _GL_CXXALIASWARN_2(func,namespace) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -# endif -#else -# define _GL_CXXALIASWARN(func) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -/* _GL_CXXALIASWARN1 (func, rettype, parameters_and_attributes); - causes a warning to be emitted when the given overloaded variant of ::func - is used but not when GNULIB_NAMESPACE::func is used. */ -#if defined __cplusplus && defined GNULIB_NAMESPACE -# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ - _GL_CXXALIASWARN1_1 (func, rettype, parameters_and_attributes, \ - GNULIB_NAMESPACE) -# define _GL_CXXALIASWARN1_1(func,rettype,parameters_and_attributes,namespace) \ - _GL_CXXALIASWARN1_2 (func, rettype, parameters_and_attributes, namespace) -/* To work around GCC bug , - we enable the warning only when not optimizing. */ -# if !__OPTIMIZE__ -# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ - _GL_WARN_ON_USE_CXX (func, rettype, parameters_and_attributes, \ - "The symbol ::" #func " refers to the system function. " \ - "Use " #namespace "::" #func " instead.") -# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING -# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ - extern __typeof__ (func) func -# else -# define _GL_CXXALIASWARN1_2(func,rettype,parameters_and_attributes,namespace) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -# endif -#else -# define _GL_CXXALIASWARN1(func,rettype,parameters_and_attributes) \ - _GL_EXTERN_C int _gl_cxxalias_dummy -#endif - -#endif /* _GL_CXXDEFS_H */ diff --git a/build-aux/config.rpath b/build-aux/config.rpath deleted file mode 100755 index c492a93b6..000000000 --- a/build-aux/config.rpath +++ /dev/null @@ -1,614 +0,0 @@ -#! /bin/sh -# Output a system dependent set of variables, describing how to set the -# run time search path of shared libraries in an executable. -# -# Copyright 1996-2006 Free Software Foundation, Inc. -# Taken from GNU libtool, 2001 -# Originally by Gordon Matzigkeit , 1996 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# The first argument passed to this file is the canonical host specification, -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM -# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld -# should be set by the caller. -# -# The set of defined variables is at the end of this script. - -# Known limitations: -# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer -# than 256 bytes, otherwise the compiler driver will dump core. The only -# known workaround is to choose shorter directory names for the build -# directory and/or the installation directory. - -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a -shrext=.so - -host="$1" -host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` - -# Code taken from libtool.m4's _LT_CC_BASENAME. - -for cc_temp in $CC""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` - -# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC. - -wl= -if test "$GCC" = yes; then - wl='-Wl,' -else - case "$host_os" in - aix*) - wl='-Wl,' - ;; - darwin*) - case $cc_basename in - xlc*) - wl='-Wl,' - ;; - esac - ;; - mingw* | pw32* | os2*) - ;; - hpux9* | hpux10* | hpux11*) - wl='-Wl,' - ;; - irix5* | irix6* | nonstopux*) - wl='-Wl,' - ;; - newsos6) - ;; - linux*) - case $cc_basename in - icc* | ecc*) - wl='-Wl,' - ;; - pgcc | pgf77 | pgf90) - wl='-Wl,' - ;; - ccc*) - wl='-Wl,' - ;; - como) - wl='-lopt=' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - wl='-Wl,' - ;; - esac - ;; - esac - ;; - osf3* | osf4* | osf5*) - wl='-Wl,' - ;; - sco3.2v5*) - ;; - solaris*) - wl='-Wl,' - ;; - sunos4*) - wl='-Qoption ld ' - ;; - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - wl='-Wl,' - ;; - sysv4*MP*) - ;; - unicos*) - wl='-Wl,' - ;; - uts4*) - ;; - esac -fi - -# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS. - -hardcode_libdir_flag_spec= -hardcode_libdir_separator= -hardcode_direct=no -hardcode_minus_L=no - -case "$host_os" in - cygwin* | mingw* | pw32*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; -esac - -ld_shlibs=yes -if test "$with_gnu_ld" = yes; then - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - # Unlike libtool, we use -rpath here, not --rpath, since the documented - # option of GNU ld is called -rpath, not --rpath. - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - case "$host_os" in - aix3* | aix4* | aix5*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - ld_shlibs=no - fi - ;; - amigaos*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # Samuel A. Falvo II reports - # that the semantics of dynamic libraries on AmigaOS, at least up - # to version 4, is to share data among multiple programs linked - # with the same dynamic library. Since this doesn't match the - # behavior of shared libraries on other platforms, we cannot use - # them. - ld_shlibs=no - ;; - beos*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - : - else - ld_shlibs=no - fi - ;; - cygwin* | mingw* | pw32*) - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec='-L$libdir' - if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then - : - else - ld_shlibs=no - fi - ;; - interix3*) - hardcode_direct=no - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - linux*) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - : - else - ld_shlibs=no - fi - ;; - netbsd*) - ;; - solaris*) - if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then - ld_shlibs=no - elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - : - else - ld_shlibs=no - fi - ;; - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) - ld_shlibs=no - ;; - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' - else - ld_shlibs=no - fi - ;; - esac - ;; - sunos4*) - hardcode_direct=yes - ;; - *) - if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then - : - else - ld_shlibs=no - fi - ;; - esac - if test "$ld_shlibs" = no; then - hardcode_libdir_flag_spec= - fi -else - case "$host_os" in - aix3*) - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - hardcode_minus_L=yes - if test "$GCC" = yes; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - hardcode_direct=unsupported - fi - ;; - aix4* | aix5*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - else - aix_use_runtimelinking=no - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[23]|aix4.[23].*|aix5*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - fi - hardcode_direct=yes - hardcode_libdir_separator=':' - if test "$GCC" = yes; then - case $host_os in aix4.[012]|aix4.[012].*) - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && \ - strings "$collect2name" | grep resolve_lib_name >/dev/null - then - # We have reworked collect2 - hardcode_direct=yes - else - # We have old collect2 - hardcode_direct=unsupported - hardcode_minus_L=yes - hardcode_libdir_flag_spec='-L$libdir' - hardcode_libdir_separator= - fi - ;; - esac - fi - # Begin _LT_AC_SYS_LIBPATH_AIX. - echo 'int main () { return 0; }' > conftest.c - ${CC} ${LDFLAGS} conftest.c -o conftest - aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` - if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } -}'` - fi - if test -z "$aix_libpath"; then - aix_libpath="/usr/lib:/lib" - fi - rm -f conftest.c conftest - # End _LT_AC_SYS_LIBPATH_AIX. - if test "$aix_use_runtimelinking" = yes; then - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' - else - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - fi - fi - ;; - amigaos*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - # see comment about different semantics on the GNU ld section - ld_shlibs=no - ;; - bsdi[45]*) - ;; - cygwin* | mingw* | pw32*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - hardcode_libdir_flag_spec=' ' - libext=lib - ;; - darwin* | rhapsody*) - hardcode_direct=no - if test "$GCC" = yes ; then - : - else - case $cc_basename in - xlc*) - ;; - *) - ld_shlibs=no - ;; - esac - fi - ;; - dgux*) - hardcode_libdir_flag_spec='-L$libdir' - ;; - freebsd1*) - ld_shlibs=no - ;; - freebsd2.2*) - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - ;; - freebsd2*) - hardcode_direct=yes - hardcode_minus_L=yes - ;; - freebsd* | kfreebsd*-gnu | dragonfly*) - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - ;; - hpux9*) - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - ;; - hpux10*) - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - hardcode_direct=yes - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - fi - ;; - hpux11*) - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_separator=: - case $host_cpu in - hppa*64*|ia64*) - hardcode_direct=no - ;; - *) - hardcode_direct=yes - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - hardcode_minus_L=yes - ;; - esac - fi - ;; - irix5* | irix6* | nonstopux*) - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - netbsd*) - hardcode_libdir_flag_spec='-R$libdir' - hardcode_direct=yes - ;; - newsos6) - hardcode_direct=yes - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - openbsd*) - hardcode_direct=yes - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - else - case "$host_os" in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac - fi - ;; - os2*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_minus_L=yes - ;; - osf3*) - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - hardcode_libdir_separator=: - ;; - osf4* | osf5*) - if test "$GCC" = yes; then - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - else - # Both cc and cxx compiler support -rpath directly - hardcode_libdir_flag_spec='-rpath $libdir' - fi - hardcode_libdir_separator=: - ;; - solaris*) - hardcode_libdir_flag_spec='-R$libdir' - ;; - sunos4*) - hardcode_libdir_flag_spec='-L$libdir' - hardcode_direct=yes - hardcode_minus_L=yes - ;; - sysv4) - case $host_vendor in - sni) - hardcode_direct=yes # is this really true??? - ;; - siemens) - hardcode_direct=no - ;; - motorola) - hardcode_direct=no #Motorola manual says yes, but my tests say they lie - ;; - esac - ;; - sysv4.3*) - ;; - sysv4*MP*) - if test -d /usr/nec; then - ld_shlibs=yes - fi - ;; - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7*) - ;; - sysv5* | sco3.2v5* | sco5v6*) - hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' - hardcode_libdir_separator=':' - ;; - uts4*) - hardcode_libdir_flag_spec='-L$libdir' - ;; - *) - ld_shlibs=no - ;; - esac -fi - -# Check dynamic linker characteristics -# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER. -libname_spec='lib$name' -case "$host_os" in - aix3*) - ;; - aix4* | aix5*) - ;; - amigaos*) - ;; - beos*) - ;; - bsdi[45]*) - ;; - cygwin* | mingw* | pw32*) - shrext=.dll - ;; - darwin* | rhapsody*) - shrext=.dylib - ;; - dgux*) - ;; - freebsd1*) - ;; - kfreebsd*-gnu) - ;; - freebsd* | dragonfly*) - ;; - gnu*) - ;; - hpux9* | hpux10* | hpux11*) - case $host_cpu in - ia64*) - shrext=.so - ;; - hppa*64*) - shrext=.sl - ;; - *) - shrext=.sl - ;; - esac - ;; - interix3*) - ;; - irix5* | irix6* | nonstopux*) - case "$host_os" in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; - *) libsuff= shlibsuff= ;; - esac - ;; - esac - ;; - linux*oldld* | linux*aout* | linux*coff*) - ;; - linux*) - ;; - knetbsd*-gnu) - ;; - netbsd*) - ;; - newsos6) - ;; - nto-qnx*) - ;; - openbsd*) - ;; - os2*) - libname_spec='$name' - shrext=.dll - ;; - osf3* | osf4* | osf5*) - ;; - solaris*) - ;; - sunos4*) - ;; - sysv4 | sysv4.3*) - ;; - sysv4*MP*) - ;; - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - ;; - uts4*) - ;; -esac - -sed_quote_subst='s/\(["`$\\]\)/\\\1/g' -escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` -shlibext=`echo "$shrext" | sed -e 's,^\.,,'` -escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` - -LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <. */ - -/* _GL_WARN_ON_USE (function, "literal string") issues a declaration - for FUNCTION which will then trigger a compiler warning containing - the text of "literal string" anywhere that function is called, if - supported by the compiler. If the compiler does not support this - feature, the macro expands to an unused extern declaration. - - This macro is useful for marking a function as a potential - portability trap, with the intent that "literal string" include - instructions on the replacement function that should be used - instead. However, one of the reasons that a function is a - portability trap is if it has the wrong signature. Declaring - FUNCTION with a different signature in C is a compilation error, so - this macro must use the same type as any existing declaration so - that programs that avoid the problematic FUNCTION do not fail to - compile merely because they included a header that poisoned the - function. But this implies that _GL_WARN_ON_USE is only safe to - use if FUNCTION is known to already have a declaration. Use of - this macro implies that there must not be any other macro hiding - the declaration of FUNCTION; but undefining FUNCTION first is part - of the poisoning process anyway (although for symbols that are - provided only via a macro, the result is a compilation error rather - than a warning containing "literal string"). Also note that in - C++, it is only safe to use if FUNCTION has no overloads. - - For an example, it is possible to poison 'getline' by: - - adding a call to gl_WARN_ON_USE_PREPARE([[#include ]], - [getline]) in configure.ac, which potentially defines - HAVE_RAW_DECL_GETLINE - - adding this code to a header that wraps the system : - #undef getline - #if HAVE_RAW_DECL_GETLINE - _GL_WARN_ON_USE (getline, "getline is required by POSIX 2008, but" - "not universally present; use the gnulib module getline"); - #endif - - It is not possible to directly poison global variables. But it is - possible to write a wrapper accessor function, and poison that - (less common usage, like &environ, will cause a compilation error - rather than issue the nice warning, but the end result of informing - the developer about their portability problem is still achieved): - #if HAVE_RAW_DECL_ENVIRON - static inline char ***rpl_environ (void) { return &environ; } - _GL_WARN_ON_USE (rpl_environ, "environ is not always properly declared"); - # undef environ - # define environ (*rpl_environ ()) - #endif - */ -#ifndef _GL_WARN_ON_USE - -# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) -/* A compiler attribute is available in gcc versions 4.3.0 and later. */ -# define _GL_WARN_ON_USE(function, message) \ -extern __typeof__ (function) function __attribute__ ((__warning__ (message))) -# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING -/* Verify the existence of the function. */ -# define _GL_WARN_ON_USE(function, message) \ -extern __typeof__ (function) function -# else /* Unsupported. */ -# define _GL_WARN_ON_USE(function, message) \ -_GL_WARN_EXTERN_C int _gl_warn_on_use -# endif -#endif - -/* _GL_WARN_ON_USE_CXX (function, rettype, parameters_and_attributes, "string") - is like _GL_WARN_ON_USE (function, "string"), except that the function is - declared with the given prototype, consisting of return type, parameters, - and attributes. - This variant is useful for overloaded functions in C++. _GL_WARN_ON_USE does - not work in this case. */ -#ifndef _GL_WARN_ON_USE_CXX -# if 4 < __GNUC__ || (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) -# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ -extern rettype function parameters_and_attributes \ - __attribute__ ((__warning__ (msg))) -# elif __GNUC__ >= 3 && GNULIB_STRICT_CHECKING -/* Verify the existence of the function. */ -# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ -extern rettype function parameters_and_attributes -# else /* Unsupported. */ -# define _GL_WARN_ON_USE_CXX(function,rettype,parameters_and_attributes,msg) \ -_GL_WARN_EXTERN_C int _gl_warn_on_use -# endif -#endif - -/* _GL_WARN_EXTERN_C declaration; - performs the declaration with C linkage. */ -#ifndef _GL_WARN_EXTERN_C -# if defined __cplusplus -# define _GL_WARN_EXTERN_C extern "C" -# else -# define _GL_WARN_EXTERN_C extern -# endif -#endif diff --git a/conf/Makefile.common b/conf/Makefile.common index b5615a14b..c60f55386 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -3,39 +3,25 @@ CFLAGS_PLATFORM= export LC_COLLATE := C -export LC_CTYPE := C unexport LC_ALL # Platform specific options -if COND_i386_pc - CFLAGS_PLATFORM += -mrtd -mregparm=3 -endif -if COND_i386_efi - LDFLAGS_PLATFORM = -Wl,-melf_i386 -endif -if COND_x86_64_efi - LDFLAGS_PLATFORM = -Wl,-melf_x86_64 -endif -if COND_i386_qemu - CFLAGS_PLATFORM += -mrtd -mregparm=3 -endif -if COND_i386_coreboot - CFLAGS_PLATFORM += -mrtd -mregparm=3 -endif -if COND_i386_ieee1275 - CFLAGS_PLATFORM += -mrtd -mregparm=3 -endif -if COND_mips_loongson - CFLAGS_PLATFORM += -mexplicit-relocs - CPPFLAGS_PLATFORM = -DUSE_ASCII_FAILBACK -endif -if COND_mips - CFLAGS_PLATFORM += -mflush-func=grub_cpu_flush_cache - CCASFLAGS_PLATFORM = -march=mips3 -endif if COND_sparc64_ieee1275 - CFLAGS_PLATFORM += -mno-app-regs - LDFLAGS_PLATFORM = -Wl,-melf64_sparc -mno-relax + LDFLAGS_PLATFORM = -Wl,-melf64_sparc +endif +if COND_arm +if !COND_emu + LDFLAGS_PLATFORM = -Wl,--wrap=__clear_cache +endif +endif +if COND_arm64 + CFLAGS_PLATFORM += -mcmodel=large +endif +if COND_powerpc_ieee1275 + CFLAGS_PLATFORM += -mcpu=powerpc +endif +if COND_HAVE_PCI + CFLAGS_PLATFORM += -DGRUB_HAS_PCI endif # Other options @@ -47,43 +33,30 @@ CPPFLAGS_DEFAULT += -I$(top_builddir) CPPFLAGS_DEFAULT += -I$(top_srcdir) CPPFLAGS_DEFAULT += -I$(top_srcdir)/include CPPFLAGS_DEFAULT += -I$(top_builddir)/include -CCASFLAGS_DEFAULT = -DASM_FILE=1 +CPPFLAGS_DEFAULT += -I$(top_srcdir)/grub-core/lib/libgcrypt-grub/src/ +CCASFLAGS_DEFAULT = $(CPPFLAGS_DEFAULT) -DASM_FILE=1 +BUILD_CPPFLAGS += $(CPPFLAGS_DEFAULT) -LDADD_KERNEL = - -if ! COND_i386_pc -if ! COND_i386_efi -if ! COND_i386_qemu -if ! COND_i386_coreboot -if ! COND_i386_multiboot -if ! COND_i386_ieee1275 -if ! COND_x86_64_efi -LDADD_KERNEL += -lgcc -endif -endif -endif -endif -endif -endif -endif - -CFLAGS_KERNEL = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding -LDFLAGS_KERNEL = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -static-libgcc -CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) +CFLAGS_KERNEL = $(CFLAGS_PLATFORM) -ffreestanding +LDFLAGS_KERNEL = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) +CPPFLAGS_KERNEL = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) -DGRUB_KERNEL=1 CCASFLAGS_KERNEL = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) -if COND_CYGWIN -STRIPFLAGS_KERNEL = -F elf32-i386 -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version +STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .drectve -R .note.gnu.gold-version -R .MIPS.abiflags -R .ARM.exidx +if !COND_emu +if COND_HAVE_ASM_USCORE + LDFLAGS_KERNEL += -Wl,--defsym=_malloc=_grub_malloc -Wl,--defsym=_free=_grub_free else -STRIPFLAGS_KERNEL = -R .rel.dyn -R .reginfo -R .note -R .comment -R .note.gnu.gold-version + LDFLAGS_KERNEL += -Wl,--defsym=malloc=grub_malloc -Wl,--defsym=free=grub_free +endif endif -CFLAGS_MODULE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -ffreestanding -LDFLAGS_MODULE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r,-d +CFLAGS_MODULE = $(CFLAGS_PLATFORM) -ffreestanding +LDFLAGS_MODULE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-r CPPFLAGS_MODULE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) CCASFLAGS_MODULE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) -CFLAGS_IMAGE = $(CFLAGS_CPU) $(CFLAGS_PLATFORM) -fno-builtin -LDFLAGS_IMAGE = $(LDFLAGS_CPU) $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-S +CFLAGS_IMAGE = $(CFLAGS_PLATFORM) -fno-builtin +LDFLAGS_IMAGE = $(LDFLAGS_PLATFORM) -nostdlib $(TARGET_LDFLAGS_OLDMAGIC) -Wl,-S CPPFLAGS_IMAGE = $(CPPFLAGS_CPU) $(CPPFLAGS_PLATFORM) CCASFLAGS_IMAGE = $(CCASFLAGS_CPU) $(CCASFLAGS_PLATFORM) @@ -102,15 +75,15 @@ grubconfdir = $(sysconfdir)/grub.d platformdir = $(pkglibdir)/$(target_cpu)-$(platform) starfielddir = $(pkgdatadir)/themes/starfield -CFLAGS_GCRY = -Wno-error -Wno-missing-field-initializers -CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap - -CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion -Wno-old-style-definition -Wno-unsafe-loop-optimizations -CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/gnulib -I$(top_srcdir)/grub-core/gnulib +CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter -Wno-redundant-decls -Wno-unreachable-code -Wno-conversion -Wno-error=attributes +CPPFLAGS_GNULIB = -I$(top_builddir)/grub-core/lib/gnulib -I$(top_srcdir)/grub-core/lib/gnulib CFLAGS_POSIX = -fno-builtin CPPFLAGS_POSIX = -I$(top_srcdir)/grub-core/lib/posix_wrap +CFLAGS_GCRY = -Wno-error -Wno-missing-field-initializers -Wno-redundant-decls -Wno-undef $(CFLAGS_POSIX) +CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap $(CPPFLAGS_POSIX) -D_GCRYPT_IN_LIBGCRYPT=1 -I$(top_srcdir)/include/grub/gcrypt + CPPFLAGS_EFIEMU = -I$(top_srcdir)/grub-core/efiemu/runtime # List file macros for recognizing /interesting/ modules @@ -121,11 +94,15 @@ CPPFLAGS_PARTTOOL_LIST = -Dgrub_parttool_register=PARTTOOL_LIST_MARKER CPPFLAGS_TERMINAL_LIST = '-Dgrub_term_register_input(...)=INPUT_TERMINAL_LIST_MARKER(__VA_ARGS__)' CPPFLAGS_TERMINAL_LIST += '-Dgrub_term_register_output(...)=OUTPUT_TERMINAL_LIST_MARKER(__VA_ARGS__)' CPPFLAGS_COMMAND_LIST = '-Dgrub_register_command(...)=COMMAND_LIST_MARKER(__VA_ARGS__)' +CPPFLAGS_COMMAND_LIST += '-Dgrub_register_command_lockdown(...)=COMMAND_LOCKDOWN_LIST_MARKER(__VA_ARGS__)' CPPFLAGS_COMMAND_LIST += '-Dgrub_register_extcmd(...)=EXTCOMMAND_LIST_MARKER(__VA_ARGS__)' +CPPFLAGS_COMMAND_LIST += '-Dgrub_register_extcmd_lockdown(...)=EXTCOMMAND_LOCKDOWN_LIST_MARKER(__VA_ARGS__)' CPPFLAGS_COMMAND_LIST += '-Dgrub_register_command_p1(...)=P1COMMAND_LIST_MARKER(__VA_ARGS__)' +CPPFLAGS_FDT_LIST := '-Dgrub_fdtbus_register(...)=FDT_DRIVER_LIST_MARKER(__VA_ARGS__)' CPPFLAGS_MARKER = $(CPPFLAGS_FS_LIST) $(CPPFLAGS_VIDEO_LIST) \ $(CPPFLAGS_PARTTOOL_LIST) $(CPPFLAGS_PARTMAP_LIST) \ - $(CPPFLAGS_TERMINAL_LIST) $(CPPFLAGS_COMMAND_LIST) + $(CPPFLAGS_TERMINAL_LIST) $(CPPFLAGS_COMMAND_LIST) \ + $(CPPFLAGS_FDT_LIST) # Define these variables to calm down automake @@ -134,45 +111,42 @@ MOD_FILES = MODULE_FILES = MARKER_FILES = KERNEL_HEADER_FILES = +EXTRA_DEPS = +bin_SCRIPTS = +bin_PROGRAMS = +check_SCRIPTS_native = +check_SCRIPTS_nonnative = +check_PROGRAMS_native = +check_PROGRAMS_nonnative = +dist_grubconf_DATA = +dist_noinst_DATA = +grubconf_SCRIPTS = man_MANS = noinst_DATA = -pkgdata_DATA = -bin_SCRIPTS = -sbin_SCRIPTS = -bin_PROGRAMS = -platform_DATA = -sbin_PROGRAMS = -check_SCRIPTS = -grubconf_DATA = -check_PROGRAMS = noinst_SCRIPTS = noinst_PROGRAMS = -grubconf_SCRIPTS = noinst_LIBRARIES = -dist_noinst_DATA = +pkgdata_DATA = +platform_DATA = platform_SCRIPTS = platform_PROGRAMS = +sbin_SCRIPTS = +sbin_PROGRAMS = -TESTS = EXTRA_DIST = CLEANFILES = BUILT_SOURCES = -# Rules for autogen definition files - -.PRECIOUS: $(top_srcdir)/Makefile.tpl -$(top_srcdir)/Makefile.tpl: $(top_srcdir)/gentpl.py - python $< | sed -e '/^$$/{N;/^\\n$$/D;}' > $@.new || (rm -f $@.new; exit 1) - mv $@.new $@ +# Rules for Automake input .PRECIOUS: $(top_srcdir)/Makefile.util.am -$(top_srcdir)/Makefile.util.am: $(top_srcdir)/Makefile.util.def $(top_srcdir)/Makefile.tpl - autogen -T $(top_srcdir)/Makefile.tpl $< | sed -e '/^$$/{N;/^\\n$$/D;}' > $@.new || (rm -f $@.new; exit 1) +$(top_srcdir)/Makefile.util.am: $(top_srcdir)/gentpl.py $(top_srcdir)/Makefile.util.def $(top_srcdir)/Makefile.utilgcry.def + $(PYTHON) $^ > $@.new || (rm -f $@.new; exit 1) mv $@.new $@ .PRECIOUS: $(top_srcdir)/grub-core/Makefile.core.am -$(top_srcdir)/grub-core/Makefile.core.am: $(top_srcdir)/grub-core/Makefile.core.def $(top_srcdir)/grub-core/Makefile.gcry.def $(top_srcdir)/Makefile.tpl - if [ "x$$GRUB_CONTRIB" != x ]; then echo "You need to run ./autogen.sh manually." >&2; exit 1; fi - autogen -T $(top_srcdir)/Makefile.tpl $(top_srcdir)/grub-core/Makefile.core.def $(top_srcdir)/grub-core/Makefile.gcry.def | sed -e '/^$$/{N;/^\\n$$/D;}' > $@.new || (rm -f $@.new; exit 1) +$(top_srcdir)/grub-core/Makefile.core.am: $(top_srcdir)/gentpl.py $(top_srcdir)/grub-core/Makefile.core.def $(top_srcdir)/grub-core/Makefile.gcry.def + if [ "x$$GRUB_CONTRIB" != x ]; then echo "You need to run ./bootstrap manually." >&2; exit 1; fi + $(PYTHON) $^ > $@.new || (rm -f $@.new; exit 1) mv $@.new $@ diff --git a/conf/Makefile.extra-dist b/conf/Makefile.extra-dist index c862206bc..d9e2b8cc7 100644 --- a/conf/Makefile.extra-dist +++ b/conf/Makefile.extra-dist @@ -2,23 +2,26 @@ EXTRA_DIST += autogen.sh EXTRA_DIST += geninit.sh EXTRA_DIST += gentpl.py -EXTRA_DIST += Makefile.tpl EXTRA_DIST += Makefile.util.def EXTRA_DIST += Makefile.utilgcry.def +EXTRA_DIST += asm-tests EXTRA_DIST += unicode EXTRA_DIST += util/import_gcry.py EXTRA_DIST += util/import_unicode.py EXTRA_DIST += docs/man +EXTRA_DIST += docs/autoiso.cfg EXTRA_DIST += docs/grub.cfg +EXTRA_DIST += docs/osdetect.cfg -EXTRA_DIST += conf/i386-pc-cygwin-img-ld.sc +EXTRA_DIST += conf/i386-cygwin-img-ld.sc EXTRA_DIST += grub-core/Makefile.core.def EXTRA_DIST += grub-core/Makefile.gcry.def +EXTRA_DIST += grub-core/extra_deps.lst EXTRA_DIST += grub-core/genmoddep.awk EXTRA_DIST += grub-core/genmod.sh.in EXTRA_DIST += grub-core/gensyminfo.sh.in @@ -26,16 +29,31 @@ EXTRA_DIST += grub-core/gensymlist.sh EXTRA_DIST += grub-core/genemuinit.sh EXTRA_DIST += grub-core/genemuinitheader.sh -EXTRA_DIST += grub-core/lib/libgcrypt/cipher +EXTRA_DIST += grub-core/lib/gnulib-patches/fix-width.patch + +EXTRA_DIST += grub-core/lib/libgcrypt +EXTRA_DIST += grub-core/lib/libgcrypt-grub/mpi/generic EXTRA_DIST += $(shell find $(top_srcdir)/include -name '*.h') EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/lib -name '*.h') -EXTRA_DIST += $(shell find $(top_srcdir)/grub-core/gnulib -name '*.h') EXTRA_DIST += grub-core/efiemu/runtime/config.h EXTRA_DIST += grub-core/lib/LzmaDec.c +EXTRA_DIST += grub-core/fs/cpio_common.c + EXTRA_DIST += BUGS EXTRA_DIST += util/i386/efi/grub-dumpdevtree +EXTRA_DIST += util/spkmodem-recv.c +EXTRA_DIST += util/import_gcrypth.sed +EXTRA_DIST += util/bin2h.c +EXTRA_DIST += util/grub-gen-asciih.c +EXTRA_DIST += util/grub-gen-widthspec.c +EXTRA_DIST += util/grub-module-verifier.c +EXTRA_DIST += util/grub-module-verifier32.c +EXTRA_DIST += util/grub-module-verifier64.c +EXTRA_DIST += util/grub-module-verifierXX.c +EXTRA_DIST += util/grub-pe2elf.c + EXTRA_DIST += m4/gnulib-cache.m4 EXTRA_DIST += m4/glibc2.m4 @@ -51,3 +69,85 @@ EXTRA_DIST += m4/printf-posix.m4 EXTRA_DIST += m4/threadlib.m4 EXTRA_DIST += m4/uintmax_t.m4 EXTRA_DIST += m4/visibility.m4 +EXTRA_DIST += m4/math_h.m4 + +EXTRA_DIST += grub-core/osdep/apple/hostdisk.c +EXTRA_DIST += grub-core/osdep/aros/hostdisk.c +EXTRA_DIST += grub-core/osdep/basic/hostdisk.c +EXTRA_DIST += grub-core/osdep/bsd/hostdisk.c +EXTRA_DIST += grub-core/osdep/freebsd/hostdisk.c +EXTRA_DIST += grub-core/osdep/hurd/hostdisk.c +EXTRA_DIST += grub-core/osdep/linux/hostdisk.c +EXTRA_DIST += grub-core/osdep/windows/hostdisk.c +EXTRA_DIST += grub-core/osdep/sun/hostdisk.c +EXTRA_DIST += grub-core/osdep/haiku/hostdisk.c + +EXTRA_DIST += grub-core/osdep/basic/init.c +EXTRA_DIST += grub-core/osdep/windows/init.c + +EXTRA_DIST += grub-core/osdep/apple/getroot.c +EXTRA_DIST += grub-core/osdep/aros/getroot.c +EXTRA_DIST += grub-core/osdep/basic/getroot.c +EXTRA_DIST += grub-core/osdep/bsd/getroot.c +EXTRA_DIST += grub-core/osdep/windows/getroot.c +EXTRA_DIST += grub-core/osdep/freebsd/getroot.c +EXTRA_DIST += grub-core/osdep/hurd/getroot.c +EXTRA_DIST += grub-core/osdep/linux/getroot.c +EXTRA_DIST += grub-core/osdep/sun/getroot.c +EXTRA_DIST += grub-core/osdep/haiku/getroot.c + +EXTRA_DIST += grub-core/osdep/basic/random.c +EXTRA_DIST += grub-core/osdep/basic/ofpath.c + +EXTRA_DIST += grub-core/osdep/unix/password.c +EXTRA_DIST += grub-core/osdep/unix/random.c +EXTRA_DIST += grub-core/osdep/unix/sleep.c + +EXTRA_DIST += grub-core/osdep/linux/ofpath.c + +EXTRA_DIST += grub-core/osdep/windows/password.c +EXTRA_DIST += grub-core/osdep/windows/random.c +EXTRA_DIST += grub-core/osdep/windows/sleep.c + +EXTRA_DIST += po/gettext-patches/0001-Support-POTFILES-shell.patch +EXTRA_DIST += po/gettext-patches/0002-Handle-gettext_printf-shell-function.patch +EXTRA_DIST += po/gettext-patches/0003-Make-msgfmt-output-in-little-endian.patch +EXTRA_DIST += po/gettext-patches/0004-Use-SHELL-rather-than-bin-sh.patch + +EXTRA_DIST += po/POTFILES-shell.in +EXTRA_DIST += po/README +EXTRA_DIST += po/Rules-translit +EXTRA_DIST += po/Rules-windowsdir +EXTRA_DIST += po/arabic.sed +EXTRA_DIST += po/cyrillic.sed +EXTRA_DIST += po/greek.sed +EXTRA_DIST += po/grub.d.sed +EXTRA_DIST += po/hebrew.sed + +EXTRA_DIST += tests/dfly-mbr-mbexample.mbr.img.gz +EXTRA_DIST += tests/dfly-mbr-mbexample.dfly.img.gz + +EXTRA_DIST += coreboot.cfg + +EXTRA_DIST += tests/file_filter/file +EXTRA_DIST += tests/file_filter/file.gz +EXTRA_DIST += tests/file_filter/file.gz.sig +EXTRA_DIST += tests/file_filter/file.lzop +EXTRA_DIST += tests/file_filter/file.lzop.sig +EXTRA_DIST += tests/file_filter/file.xz +EXTRA_DIST += tests/file_filter/file.xz.sig +EXTRA_DIST += tests/file_filter/keys +EXTRA_DIST += tests/file_filter/keys.pub +EXTRA_DIST += tests/file_filter/test.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/prompt.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/gfxboot.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/adtxt.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/isolinux.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/exithelp.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/txt.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/menu.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/stdmenu.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/dtmenu.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/po4a.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04/isolinux/rqtxt.cfg +EXTRA_DIST += tests/syslinux/ubuntu10.04_grub.cfg.in diff --git a/conf/i386-pc-cygwin-img-ld.sc b/conf/i386-cygwin-img-ld.sc similarity index 80% rename from conf/i386-pc-cygwin-img-ld.sc rename to conf/i386-cygwin-img-ld.sc index 90866c379..578da91b0 100644 --- a/conf/i386-pc-cygwin-img-ld.sc +++ b/conf/i386-cygwin-img-ld.sc @@ -5,6 +5,8 @@ SECTIONS .text : { start = . ; + _start = . ; + __start = . ; *(.text) etext = . ; } @@ -12,6 +14,8 @@ SECTIONS { __data_start__ = . ; *(.data) + /* Do not discard this section. */ + . = . ; __data_end__ = . ; __rdata_start__ = . ; *(.rdata) @@ -32,7 +36,11 @@ SECTIONS .edata : { *(.edata) + /* Do not discard this section. */ + . = . ; end = . ; + _end = . ; + __end = . ; } .stab : { diff --git a/config.h.in b/config.h.in index a7eaf1925..9b1d39971 100644 --- a/config.h.in +++ b/config.h.in @@ -5,52 +5,145 @@ #if defined(__PPC__) && !defined(__powerpc__) #define __powerpc__ 1 #endif -#if defined (GRUB_UTIL) || !defined (GRUB_MACHINE) -#include -#define NESTED_FUNC_ATTR -#else -/* Define if C symbols get an underscore after compilation. */ -#define HAVE_ASM_USCORE @HAVE_ASM_USCORE@ -/* Define it to \"addr32\" or \"addr32;\" to make GAS happy. */ -#define ADDR32 @ADDR32@ -/* Define it to \"data32\" or \"data32;\" to make GAS happy. */ -#define DATA32 @DATA32@ -/* Define it to one of __bss_start, edata and _edata. */ -#define BSS_START_SYMBOL @BSS_START_SYMBOL@ -/* Define it to either end or _end. */ -#define END_SYMBOL @END_SYMBOL@ -/* Name of package. */ -#define PACKAGE "@PACKAGE@" -/* Version number of package. */ -#define VERSION "@VERSION@" -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "@PACKAGE_STRING@" -/* Define to the version of this package. */ -#define PACKAGE_VERSION "@PACKAGE_VERSION@" -/* Define to the full name of this package. */ -#define PACKAGE_NAME "@PACKAGE_NAME@" -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" -/* Default boot directory name" */ -#define GRUB_BOOT_DIR_NAME "@bootdirname@" -/* Default grub directory name */ -#define GRUB_DIR_NAME "@grubdirname@" -/* Define to 1 if GCC generates calls to __enable_execute_stack(). */ -#define NEED_ENABLE_EXECUTE_STACK @NEED_ENABLE_EXECUTE_STACK@ -/* Define to 1 if GCC generates calls to __register_frame_info(). */ -#define NEED_REGISTER_FRAME_INFO @NEED_REGISTER_FRAME_INFO@ + +#define GCRYPT_NO_DEPRECATED 1 +#define HAVE_MEMMOVE 1 + +#if @MM_DEBUG@ +#define MM_DEBUG @MM_DEBUG@ +#endif + /* Define to 1 to enable disk cache statistics. */ #define DISK_CACHE_STATS @DISK_CACHE_STATS@ +#define BOOT_TIME_STATS @BOOT_TIME_STATS@ -#define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" -#define GRUB_PLATFORM "@GRUB_PLATFORM@" +/* We don't need those. */ +#define MINILZO_CFG_SKIP_LZO_PTR 1 +#define MINILZO_CFG_SKIP_LZO_UTIL 1 +#define MINILZO_CFG_SKIP_LZO_STRING 1 +#define MINILZO_CFG_SKIP_LZO_INIT 1 +#define MINILZO_CFG_SKIP_LZO1X_1_COMPRESS 1 +#define MINILZO_CFG_SKIP_LZO1X_DECOMPRESS 1 -#define RE_ENABLE_I18N 1 +#if defined (GRUB_BUILD) +# undef ENABLE_NLS +# define BUILD_SIZEOF_LONG @BUILD_SIZEOF_LONG@ +# define BUILD_SIZEOF_VOID_P @BUILD_SIZEOF_VOID_P@ +# if defined __APPLE__ +# if defined __BIG_ENDIAN__ +# define BUILD_WORDS_BIGENDIAN 1 +# else +# define BUILD_WORDS_BIGENDIAN 0 +# endif +# else /* !defined __APPLE__ */ +# define BUILD_WORDS_BIGENDIAN @BUILD_WORDS_BIGENDIAN@ +# endif /* !defined __APPLE__ */ +#elif defined (GRUB_UTIL) || !defined (GRUB_MACHINE) +# include +#else /* !defined GRUB_UTIL && defined GRUB_MACHINE */ +# define HAVE_FONT_SOURCE @HAVE_FONT_SOURCE@ +/* Define if C symbols get an underscore after compilation. */ +# define HAVE_ASM_USCORE @HAVE_ASM_USCORE@ +/* Define it to one of __bss_start, edata and _edata. */ +# define BSS_START_SYMBOL @BSS_START_SYMBOL@ +/* Define it to either end or _end. */ +# define END_SYMBOL @END_SYMBOL@ +/* Name of package. */ +# define PACKAGE "@PACKAGE@" +/* Version number of package. */ +# define VERSION "@VERSION@" +/* Define to the full name and version of this package. */ +# define PACKAGE_STRING "@PACKAGE_STRING@" +/* Define to the version of this package. */ +# define PACKAGE_VERSION "@PACKAGE_VERSION@" +/* Define to the full name of this package. */ +# define PACKAGE_NAME "@PACKAGE_NAME@" +/* Define to the address where bug reports for this package should be sent. */ +# define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@" -#if defined(__i386__) -#define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1))) -#else -#define NESTED_FUNC_ATTR -#endif +# define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" +# define GRUB_PLATFORM "@GRUB_PLATFORM@" + +# define GRUB_STACK_PROTECTOR_INIT @GRUB_STACK_PROTECTOR_INIT@ + +# define RE_ENABLE_I18N 1 + +# define _GNU_SOURCE 1 + +# ifndef _GL_INLINE_HEADER_BEGIN +/* + * gnulib gets configured against the host, not the target, and the rest of + * our buildsystem works around that. This is difficult to avoid as gnulib's + * detection requires a more capable system than our target. Instead, we + * reach in and set values appropriately - intentionally setting more than the + * bare minimum. If, when updating gnulib, something breaks, there's probably + * a change needed here or in grub-core/Makefile.core.def. + */ +# define SIZE_MAX ((size_t) -1) +# define _GL_ATTRIBUTE_ALLOC_SIZE(args) \ + __attribute__ ((__alloc_size__ args)) +# define _GL_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((__always_inline__)) +# define _GL_ATTRIBUTE_ARTIFICIAL __attribute__ ((__artificial__)) +# define _GL_ATTRIBUTE_COLD __attribute__ ((cold)) +# define _GL_ATTRIBUTE_CONST __attribute__ ((const)) +# define _GL_ATTRIBUTE_DEALLOC(f, i) __attribute ((__malloc__ (f, i))) +# define _GL_ATTRIBUTE_DEALLOC_FREE _GL_ATTRIBUTE_DEALLOC (free, 1) +# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__)) +# define _GL_ATTRIBUTE_ERROR(msg) __attribute__ ((__error__ (msg))) +# define _GL_ATTRIBUTE_EXTERNALLY_VISIBLE \ + __attribute__ ((externally_visible)) +# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) +# define _GL_ATTRIBUTE_LEAF __attribute__ ((__leaf__)) +# define _GL_ATTRIBUTE_MALLOC __attribute__ ((malloc)) +# define _GL_ATTRIBUTE_MAYBE_UNUSED _GL_ATTRIBUTE_UNUSED +# define _GL_ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__)) +# define _GL_ATTRIBUTE_NODISCARD __attribute__ ((__warn_unused_result__)) +# define _GL_ATTRIBUTE_NOINLINE __attribute__ ((__noinline__)) +# define _GL_ATTRIBUTE_NONNULL(args) __attribute__ ((__nonnull__ args)) +# define _GL_ATTRIBUTE_NONSTRING __attribute__ ((__nonstring__)) +# define _GL_ATTRIBUTE_PACKED __attribute__ ((__packed__)) +# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# define _GL_ATTRIBUTE_RETURNS_NONNULL \ + __attribute__ ((__returns_nonnull__)) +# define _GL_ATTRIBUTE_SENTINEL(pos) __attribute__ ((__sentinel__ pos)) +# define _GL_ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +# define _GL_ATTRIBUTE_WARNING(msg) __attribute__ ((__warning__ (msg))) +# define _GL_CMP(n1, n2) (((n1) > (n2)) - ((n1) < (n2))) +# define _GL_GNUC_PREREQ GNUC_PREREQ +# define _GL_INLINE inline +# define _GL_UNUSED_LABEL _GL_ATTRIBUTE_UNUSED + +/* We can't use __has_attribute for these because gcc-5.1 is too old for + * that. Everything above is present in that version, though. */ +# if __GNUC__ >= 7 +# define _GL_ATTRIBUTE_FALLTHROUGH __attribute__ ((fallthrough)) +# else +# define _GL_ATTRIBUTE_FALLTHROUGH /* empty */ +# endif + +# ifndef ASM_FILE +typedef __INT_FAST32_TYPE__ int_fast32_t; +typedef __UINT_FAST32_TYPE__ uint_fast32_t; +# endif + +/* Ensure ialloc nests static/non-static inline properly. */ +# define IALLOC_INLINE static inline + +/* + * gnulib uses these for blocking out warnings they can't/won't fix. gnulib + * also makes the decision about whether to provide a declaration for + * reallocarray() at compile-time, so this is a convenient place to override - + * it's used by the ialloc module, which is used by base64. + */ +# define _GL_INLINE_HEADER_BEGIN _Pragma ("GCC diagnostic push") \ + void * \ + reallocarray (void *ptr, unsigned int nmemb, unsigned int size); +# define _GL_INLINE_HEADER_END _Pragma ("GCC diagnostic pop") +# endif /* !_GL_INLINE_HEADER_BEGIN */ + +/* gnulib doesn't build cleanly with older compilers. */ +# if __GNUC__ < 11 +_Pragma ("GCC diagnostic ignored \"-Wtype-limits\"") +# endif #endif diff --git a/configure.ac b/configure.ac index 91b36d0a4..83e3ddf90 100644 --- a/configure.ac +++ b/configure.ac @@ -26,59 +26,103 @@ dnl This is necessary because the target type in autoconf does not dnl describe such a system very well. dnl dnl The current strategy is to use variables with no prefix (such as -dnl CC, CFLAGS, etc.) for the host type as well as the build type, -dnl because GRUB does not need to use those variables for the build -dnl type, so there is no conflict. Variables with the prefix "TARGET_" -dnl (such as TARGET_CC, TARGET_CFLAGS, etc.) are used for the target -dnl type. +dnl CC, CFLAGS, etc.) for the host and target type, variables with +dnl prefix "BUILD_" (such as BUILD_CC, BUILD_CFLAGS, etc.) for the +dnl build type, variables with prefix "HOST_" (such as HOST_CC, +dnl HOST_CFLAGS, etc.) for the host type and variables with the prefix +dnl "TARGET_" (such as TARGET_CC, TARGET_CFLAGS, etc.) are used for +dnl the target type. See INSTALL for full list of variables and +dnl description of the relationships between them. -AC_INIT([GRUB],[2.00],[bug-grub@gnu.org]) +AC_INIT([GRUB],[2.13],[bug-grub@gnu.org]) -AC_CONFIG_AUX_DIR([build-aux]) +AS_CASE(["$ERROR_PLATFORM_NOT_SUPPORT_SSP"], + [n | no | nO | N | No | NO], [ERROR_PLATFORM_NOT_SUPPORT_SSP=no], + [ERROR_PLATFORM_NOT_SUPPORT_SSP=yes]) # We don't want -g -O2 by default in CFLAGS : ${CFLAGS=""} -# Checks for host and target systems. -AC_CANONICAL_HOST -AC_CANONICAL_TARGET +AC_USE_SYSTEM_EXTENSIONS +AC_CONFIG_AUX_DIR([build-aux]) -AM_INIT_AUTOMAKE() -AC_PREREQ(2.60) +# Checks for build, host and target systems. +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +save_program_prefix="${program_prefix}" +AC_CANONICAL_TARGET +program_prefix="${save_program_prefix}" + +AM_INIT_AUTOMAKE([1.11]) +AC_PREREQ(2.64) AC_CONFIG_SRCDIR([include/grub/dl.h]) -AC_CONFIG_HEADER([config-util.h]) +AC_CONFIG_HEADERS([config-util.h]) + +# Explicitly check for pkg-config early on, since otherwise conditional +# calls are problematic. +PKG_PROG_PKG_CONFIG # Program name transformations AC_ARG_PROGRAM +grub_TRANSFORM([grub-bios-setup]) +grub_TRANSFORM([grub-editenv]) +grub_TRANSFORM([grub-install]) +grub_TRANSFORM([grub-mkconfig]) +grub_TRANSFORM([grub-mkfont]) +grub_TRANSFORM([grub-mkimage]) +grub_TRANSFORM([grub-glue-efi]) +grub_TRANSFORM([grub-mklayout]) +grub_TRANSFORM([grub-mkpasswd-pbkdf2]) +grub_TRANSFORM([grub-mkrelpath]) +grub_TRANSFORM([grub-mkrescue]) +grub_TRANSFORM([grub-probe]) +grub_TRANSFORM([grub-protect]) +grub_TRANSFORM([grub-reboot]) +grub_TRANSFORM([grub-script-check]) +grub_TRANSFORM([grub-set-default]) +grub_TRANSFORM([grub-sparc64-setup]) +grub_TRANSFORM([grub-render-label]) +grub_TRANSFORM([grub-file]) + +# Allow HOST_CC to override CC. +if test "x$HOST_CC" != x; then + CC=$HOST_CC +fi # Optimization flag. Allow user to override. if test "x$TARGET_CFLAGS" = x; then - TARGET_CFLAGS="$TARGET_CFLAGS -Os" + TARGET_CFLAGS=-Os fi +# Enable support for "restrict" keyword and other +# features from gnu99 C language standard. +BUILD_CFLAGS="-std=gnu99 -fno-common $BUILD_CFLAGS" +HOST_CFLAGS="-std=gnu99 -fno-common $HOST_CFLAGS" +TARGET_CFLAGS="-std=gnu99 -fno-common $TARGET_CFLAGS" + # Default HOST_CPPFLAGS HOST_CPPFLAGS="$HOST_CPPFLAGS -Wall -W" -HOST_CPPFLAGS="$HOST_CPPFLAGS -I\$(top_builddir)/include" HOST_CPPFLAGS="$HOST_CPPFLAGS -DGRUB_UTIL=1" -HOST_CPPFLAGS="$HOST_CPPFLAGS -DGRUB_LIBDIR=\\\"\$(pkglibdir)\\\"" -HOST_CPPFLAGS="$HOST_CPPFLAGS -DLOCALEDIR=\\\"\$(localedir)\\\"" TARGET_CPPFLAGS="$TARGET_CPPFLAGS -Wall -W" -TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_srcdir)/include" -TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_builddir)/include" case "$target_cpu" in i[[3456]]86) target_cpu=i386 ;; amd64) target_cpu=x86_64 ;; sparc) target_cpu=sparc64 ;; mipsel|mips64el) - target_cpu=mipsel; - machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPSEL=1"; + target_cpu=mipsel + machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPSEL=1" ;; mips|mips64) - target_cpu=mips; - machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPS=1"; + target_cpu=mips + machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_CPU_MIPS=1" ;; + arm*) target_cpu=arm ;; + aarch64*) target_cpu=arm64 ;; + loongarch64) target_cpu=loongarch64 ;; + riscv32*) target_cpu=riscv32 ;; + riscv64*) target_cpu=riscv64 ;; esac # Specify the platform (such as firmware). @@ -95,11 +139,20 @@ if test "x$with_platform" = x; then x86_64-*) platform=pc ;; powerpc-*) platform=ieee1275 ;; powerpc64-*) platform=ieee1275 ;; + powerpc64le-*) platform=ieee1275 ;; sparc64-*) platform=ieee1275 ;; mipsel-*) platform=loongson ;; mips-*) platform=arc ;; ia64-*) platform=efi ;; - *) AC_MSG_ERROR([unsupported CPU: "$target_cpu"]) ;; + arm-*) platform=uboot ;; + arm64-*) platform=efi ;; + loongarch64-*) platform=efi;; + riscv32-*) platform=efi ;; + riscv64-*) platform=efi ;; + *) + AC_MSG_WARN([unsupported CPU: "$target_cpu" - only building utilities]) + platform=none + ;; esac else platform="$with_platform" @@ -108,14 +161,20 @@ fi case "$target_cpu"-"$platform" in x86_64-efi) ;; x86_64-emu) ;; + x86_64-xen) ;; + x86_64-none) ;; x86_64-*) target_cpu=i386 ;; powerpc64-ieee1275) target_cpu=powerpc ;; + powerpc64le-ieee1275) target_cpu=powerpc ;; esac # Check if the platform is supported, make final adjustments. case "$target_cpu"-"$platform" in i386-efi) ;; x86_64-efi) ;; + i386-xen) ;; + i386-xen_pvh) ;; + x86_64-xen) ;; i386-pc) ;; i386-multiboot) ;; i386-coreboot) ;; @@ -128,22 +187,37 @@ case "$target_cpu"-"$platform" in mips-qemu_mips) ;; mips-qemu-mips) platform=qemu_mips;; mips-arc) ;; + mipsel-arc) ;; mipsel-qemu_mips) ;; mipsel-qemu-mips) platform=qemu_mips;; mipsel-yeeloong) platform=loongson ;; mipsel-fuloong) platform=loongson ;; mipsel-loongson) ;; + arm-uboot) ;; + arm-coreboot) ;; + arm-efi) ;; + arm64-efi) ;; + loongarch64-efi) ;; + riscv32-efi) ;; + riscv64-efi) ;; *-emu) ;; + *-none) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; esac -case "$target_cpu" in - i386 | powerpc) target_m32=1 ;; - x86_64 | sparc64) target_m64=1 ;; -esac +if test x$platform != xemu ; then + case "$target_cpu" in + i386 | powerpc) target_m32=1 ;; + x86_64 | sparc64) target_m64=1 ;; + esac +fi -case "$host_os" in - mingw32*) host_os=cygwin ;; +if test x"$target_cpu-$platform" = xsparc64-emu ; then + target_m64=1 +fi + +case "$target_os" in + windows* | mingw32*) target_os=cygwin ;; esac # This normalizes the names, and creates a new variable ("host_kernel") @@ -156,31 +230,54 @@ case "$host_os" in netbsd*) host_kernel=netbsd ;; solaris*) host_kernel=illumos ;; darwin*) host_kernel=xnu ;; - cygwin) host_kernel=windows ;; + cygwin | windows* | mingw32*) host_kernel=windows ;; +esac + +case "$host_os" in + cygwin) have_exec=y ;; + windows* | mingw32*) have_exec=n ;; + aros*) have_exec=n ;; + *) have_exec=y;; esac case "$platform" in coreboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_COREBOOT=1" ;; multiboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MULTIBOOT=1" ;; efi) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EFI=1" ;; + xen) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_XEN=1" ;; + xen_pvh) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_XEN_PVH=1" ;; ieee1275) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_IEEE1275=1" ;; + uboot) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_UBOOT=1" ;; qemu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_QEMU=1" ;; pc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_PCBIOS=1" ;; emu) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_EMU=1" ;; - loongson) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_LOONGSON=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; - qemu_mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; - arc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARC=1" ;; -esac -case "$target_cpu" in - mips |mipsel) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS=1" ;; - sparc64) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_SPARC64=1" ;; + loongson) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_LOONGSON=1" ;; + qemu_mips) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_MIPS_QEMU_MIPS=1" ;; + arc) machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE_ARC=1" ;; esac if test x${target_cpu} = xmipsel ; then machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo mips_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`" else - machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,` -DGRUB_TARGET_CPU_`echo ${target_cpu} | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`=1" + machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`" fi +case "${target_cpu}-$platform" in + mips-arc) + TARGET_LINK_ADDR=0x88200000 + TARGET_DECOMPRESSOR_LINK_ADDR=0x88100000 + ;; + mipsel-arc) + TARGET_LINK_ADDR=0x80700000 + TARGET_DECOMPRESSOR_LINK_ADDR=0x80600000 + ;; + mips*-qemu_mips | mips*-loongson) + TARGET_DECOMPRESSOR_LINK_ADDR=0x80100000 + ;; +esac + +AC_SUBST(TARGET_LINK_ADDR) +AC_SUBST(TARGET_DECOMPRESSOR_LINK_ADDR) + TARGET_CPPFLAGS="$TARGET_CPPFLAGS $machine_CPPFLAGS" AC_SUBST(host_cpu) @@ -211,7 +308,7 @@ fi AC_SUBST(bootdirname) AC_DEFINE_UNQUOTED(GRUB_BOOT_DIR_NAME, "$bootdirname", - [Default boot directory name]") + [Default boot directory name]) AC_ARG_WITH([grubdir], AS_HELP_STRING([--with-grubdir=DIR], @@ -239,27 +336,10 @@ if test "x$YACC" = x; then AC_MSG_ERROR([bison is not found]) fi -FONT_SOURCE= - -for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do - for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/unifont; do - if test -f "$dir/unifont.$ext"; then - FONT_SOURCE="$dir/unifont.$ext" - break 2 - fi - done -done - -if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips); then - AC_MSG_ERROR([qemu and loongson ports need unifont]) -fi - -AC_SUBST([FONT_SOURCE]) - AC_PROG_RANLIB AC_PROG_INSTALL AC_PROG_AWK -AC_PROG_LEX +AC_PROG_LEX([noyywrap]) AC_PROG_YACC AC_PROG_MAKE_SET AC_PROG_MKDIR_P @@ -268,7 +348,7 @@ AC_PROG_LN_S if test "x$LEX" = "x:"; then AC_MSG_ERROR([flex is not found]) else - version=`$LEX --version | $AWK '{ split($NF,x,"."); print x[[1]]*10000+x[[2]]*100+x[[3]]; }'` + version=`$LEX --version | $AWK '{ split($2,x,"."); print x[[1]]*10000+x[[2]]*100+x[[3]]; }'` if test -n "$version" -a "$version" -ge 20535; then : else @@ -285,26 +365,58 @@ AC_PATH_PROGS(MAKEINFO, makeinfo true) AC_PROG_CC gl_EARLY +AC_PROG_CXX AM_PROG_CC_C_O AM_PROG_AS +AM_PATH_PYTHON([2.6]) # Must be GCC. test "x$GCC" = xyes || AC_MSG_ERROR([GCC is required]) -AC_GNU_SOURCE +AC_CHECK_PROG(HAVE_CXX, $CXX, yes, no) + AM_GNU_GETTEXT([external]) +AM_GNU_GETTEXT_VERSION([0.18.3]) AC_SYS_LARGEFILE +PLATFORMS_PCI=" $(PYTHONPATH="${srcdir}" $PYTHON -c 'import gentpl; print(" ".join(gentpl.GROUPS[["pci"]]))') " +if test x"${PLATFORMS_PCI##* ${target_cpu}_${platform} *}" = x ; then + have_pci=y +fi + # Identify characteristics of the host architecture. +unset ac_cv_c_bigendian + +if test x"$target_cpu-$platform" = xsparc64-emu ; then + CFLAGS="$CFLAGS -m64" + HOST_CFLAGS="$HOST_CFLAGS -m64" +fi + +CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64" +HOST_CPPFLAGS="$HOST_CPPFLAGS -D_FILE_OFFSET_BITS=64" + AC_C_BIGENDIAN AC_CHECK_SIZEOF(void *) AC_CHECK_SIZEOF(long) -grub_apple_cc -if test x$grub_cv_apple_cc = xyes ; then - HOST_CPPFLAGS="$HOST_CPPFLAGS -fnested-functions" - HOST_LDFLAGS="$HOST_LDFLAGS -Wl,-allow_stack_execute" -fi +case "$host_os" in + cygwin | windows* | mingw32*) + HOST_CPPFLAGS="$HOST_CPPFLAGS -DUNICODE=1 -D_WIN32_WINNT=0x0500" + CPPFLAGS="$CPPFLAGS -DUNICODE=1 -D_WIN32_WINNT=0x0500" + AC_CHECK_SIZEOF(TCHAR,,[#include ]) + ;; +esac + +case "$host_os" in + cygwin | windows* | mingw32* | aros*) + ;; + *) + AC_CHECK_SIZEOF(off_t) + if test x"$ac_cv_sizeof_off_t" != x8 ; then + AC_CHECK_SIZEOF(off64_t) + test x"$ac_cv_sizeof_off64_t" = x8 || AC_MSG_ERROR([Large file support is required]) + fi;; +esac if test x$USE_NLS = xno; then HOST_CFLAGS="$HOST_CFLAGS -fno-builtin-gettext" @@ -317,8 +429,16 @@ else fi # Check for functions and headers. -AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getextmntent) -AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h limits.h) +AC_CHECK_FUNCS(posix_memalign memalign getextmntent atexit) +AC_CHECK_HEADERS(sys/param.h sys/mount.h sys/mnttab.h limits.h) + +# glibc 2.25 still includes sys/sysmacros.h in sys/types.h but emits deprecation +# warning which causes compilation failure later with -Werror. So use -Werror here +# as well to force proper sys/sysmacros.h detection. Used in include/grub/osdep/major.h. +SAVED_CFLAGS="$CFLAGS" +CFLAGS="$HOST_CFLAGS -Werror" +AC_HEADER_MAJOR +CFLAGS="$SAVED_CFLAGS" AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default #include @@ -342,16 +462,75 @@ AC_CHECK_HEADER([util.h], [ ]) AC_SUBST([LIBUTIL]) +AC_CACHE_CHECK([whether -Wtrampolines work], [grub_cv_host_cc_wtrampolines], [ + SAVED_CFLAGS="$CFLAGS" + CFLAGS="$HOST_CFLAGS -Wtrampolines -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +int va_arg_func (int fixed, va_list args);]], [[]])], + [grub_cv_host_cc_wtrampolines=yes], + [grub_cv_host_cc_wtrampolines=no]) + CFLAGS="$SAVED_CFLAGS" +]) + +if test x"$grub_host_cv_cc_wtrampolines" = xyes ; then + HOST_CFLAGS="$HOST_CFLAGS -Wtrampolines" +fi + # # Check for host and build compilers. # HOST_CC=$CC -AC_CHECK_PROGS(BUILD_CC, [gcc egcs cc], - [AC_MSG_ERROR([none of gcc, egcs and cc is found. set BUILD_CC manually.])]) +AC_CHECK_PROGS(BUILD_CC, [gcc egcs cc]) +test -z "$BUILD_CC" && AC_MSG_ERROR([none of gcc, egcs and cc is found. set BUILD_CC manually.]) +BUILD_CPP="$BUILD_CC -E" + +case "$build_os" in + haiku*) BUILD_LIBM= ;; + *) BUILD_LIBM=-lm ;; +esac + +dnl FIXME proper test seems to require too deep dive into Autoconf internals. +dnl For now just list known platforms that we support. + +case "$build_os" in + cygwin*|mingw32*|mingw64*) BUILD_EXEEXT=.exe ;; + *) BUILD_EXEEXT= ;; +esac +AC_SUBST(BUILD_EXEEXT) + +# In some build environments like termux /bin/sh is not a valid +# shebang. Use $SHELL instead if it's executable and /bin/sh isn't +BUILD_SHEBANG=/bin/sh +for she in /bin/sh "$SHELL"; do + if test -x "$she" ; then + BUILD_SHEBANG="$she" + fi +done +AC_SUBST(BUILD_SHEBANG) # For gnulib. gl_INIT +WARN_FLAGS="-Wall -W -Wshadow -Wpointer-arith -Wundef -Wchar-subscripts -Wcomment -Wdeprecated-declarations -Wdisabled-optimization -Wdiv-by-zero -Wfloat-equal -Wformat-extra-args -Wformat-security -Wformat-y2k -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wmain -Wmissing-braces -Wmissing-format-attribute -Wmultichar -Wparentheses -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wswitch -Wtrigraphs -Wunknown-pragmas -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wwrite-strings -Wnested-externs -Wstrict-prototypes" +EXTRA_WARN_FLAGS="-Wextra -Wattributes -Wendif-labels -Winit-self -Wint-to-pointer-cast -Winvalid-pch -Wmissing-field-initializers -Wnonnull -Woverflow -Wvla -Wpointer-to-int-cast -Wstrict-aliasing -Wvariadic-macros -Wvolatile-register-var -Wpointer-sign -Wmissing-include-dirs -Wmissing-prototypes -Wmissing-declarations -Wformat=2" + +HOST_CFLAGS="$HOST_CFLAGS $WARN_FLAGS -Wcast-align" + +AC_CACHE_CHECK([which extra warnings work], [grub_cv_cc_w_extra_flags], [ + SAVED_CFLAGS="$CFLAGS" + grub_cv_cc_w_extra_flags= + for x in $EXTRA_WARN_FLAGS; do + CFLAGS="$HOST_CFLAGS $x -Werror" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [flag=1], [flag=0]) + if test x$flag = x1 ; then + grub_cv_cc_w_extra_flags="$grub_cv_cc_w_extra_flags $x" + fi + done + CFLAGS="$SAVED_CFLAGS" +]) + +HOST_CFLAGS="$HOST_CFLAGS $grub_cv_cc_w_extra_flags" + # # Check for target programs. # @@ -363,22 +542,32 @@ if test "x$target_alias" != x && test "x$host_alias" != "x$target_alias"; then AC_CHECK_TOOLS(TARGET_CC, [gcc egcs cc], [AC_MSG_ERROR([none of gcc, egcs and cc is found. set TARGET_CC manually.])]) - AC_CHECK_TOOL(OBJCOPY, objcopy) - AC_CHECK_TOOL(STRIP, strip) - AC_CHECK_TOOL(NM, nm) + AC_CHECK_TOOL(TARGET_OBJCOPY, objcopy) + AC_CHECK_TOOL(TARGET_STRIP, strip) + AC_CHECK_TOOL(TARGET_NM, nm) + AC_CHECK_TOOL(TARGET_RANLIB, ranlib) ac_tool_prefix="$tmp_ac_tool_prefix" else if test "x$TARGET_CC" = x; then TARGET_CC=$CC fi - AC_CHECK_TOOL(OBJCOPY, objcopy) - AC_CHECK_TOOL(STRIP, strip) - AC_CHECK_TOOL(NM, nm) + AC_CHECK_TOOL(TARGET_OBJCOPY, objcopy) + AC_CHECK_TOOL(TARGET_STRIP, strip) + AC_CHECK_TOOL(TARGET_NM, nm) + AC_CHECK_TOOL(TARGET_RANLIB, ranlib) fi + AC_SUBST(HOST_CC) AC_SUBST(BUILD_CC) +AC_SUBST(BUILD_CFLAGS) +AC_SUBST(BUILD_CPPFLAGS) +AC_SUBST(BUILD_LDFLAGS) AC_SUBST(TARGET_CC) +AC_SUBST(TARGET_NM) +AC_SUBST(TARGET_RANLIB) +AC_SUBST(TARGET_STRIP) +AC_SUBST(TARGET_OBJCOPY) # Test the C compiler for the target environment. tmp_CC="$CC" @@ -392,152 +581,6 @@ CPPFLAGS="$TARGET_CPPFLAGS" LDFLAGS="$TARGET_LDFLAGS" LIBS="" -# debug flags. -WARN_FLAGS="-Wall -W -Wshadow -Wold-style-definition -Wpointer-arith -Wundef -Wextra -Waddress -Wattributes -Wcast-align -Wchar-subscripts -Wcomment -Wdeprecated-declarations -Wdisabled-optimization -Wdiv-by-zero -Wempty-body -Wendif-labels -Wfloat-equal -Wformat-extra-args -Wformat-security -Wformat-y2k -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Winit-self -Wint-to-pointer-cast -Winvalid-pch -Wmain -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-noreturn -Wmultichar -Wnonnull -Woverflow -Wparentheses -Wpointer-arith -Wpointer-to-int-cast -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wstrict-aliasing -Wswitch -Wtrigraphs -Wundef -Wunknown-pragmas -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings -Wnested-externs -Wstrict-prototypes -Wpointer-sign" -HOST_CFLAGS="$HOST_CFLAGS $WARN_FLAGS" -TARGET_CFLAGS="$TARGET_CFLAGS $WARN_FLAGS -g -Wredundant-decls -Wmissing-prototypes -Wmissing-declarations" -TARGET_CCASFLAGS="$TARGET_CCASFLAGS -g" - -# Force no alignment to save space on i386. -if test "x$target_cpu" = xi386; then - AC_CACHE_CHECK([whether -falign-loops works], [grub_cv_cc_falign_loop], [ - CFLAGS="$CFLAGS -falign-loops=1" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_falign_loop=yes], - [grub_cv_cc_falign_loop=no]) - ]) - - if test "x$grub_cv_cc_falign_loop" = xyes; then - TARGET_CFLAGS="$TARGET_CFLAGS -falign-jumps=1 -falign-loops=1 -falign-functions=1" - else - TARGET_CFLAGS="$TARGET_CFLAGS -malign-jumps=1 -malign-loops=1 -malign-functions=1" - fi - - # Some toolchains enable these features by default, but they need - # registers that aren't set up properly in GRUB. - TARGET_CFLAGS="$TARGET_CFLAGS -mno-mmx -mno-sse -mno-sse2 -mno-3dnow" -fi - -# By default, GCC 4.4 generates .eh_frame sections containing unwind -# information in some cases where it previously did not. GRUB doesn't need -# these and they just use up vital space. Restore the old compiler -# behaviour. -AC_CACHE_CHECK([whether -fno-dwarf2-cfi-asm works], [grub_cv_cc_fno_dwarf2_cfi_asm], [ - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fno-dwarf2-cfi-asm" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_fno_dwarf2_cfi_asm=yes], - [grub_cv_cc_fno_dwarf2_cfi_asm=no]) - CFLAGS="$SAVE_CFLAGS" -]) - -if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then - TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" -fi - -# By default, GCC 4.6 generates .eh_frame sections containing unwind -# information in some cases where it previously did not. GRUB doesn't need -# these and they just use up vital space. Restore the old compiler -# behaviour. -AC_CACHE_CHECK([whether -fno-asynchronous-unwind-tables works], [grub_cv_cc_fno_asynchronous_unwind_tables], [ - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -fno-dwarf2-cfi-asm" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_fno_asynchronous_unwind_tables=yes], - [grub_cv_cc_fno_asynchronous_unwind_tables=no]) - CFLAGS="$SAVE_CFLAGS" -]) - -if test "x$grub_cv_cc_fno_asynchronous_unwind_tables" = xyes; then - TARGET_CFLAGS="$TARGET_CFLAGS -fno-asynchronous-unwind-tables" -fi - -grub_apple_target_cc -if test x$grub_cv_apple_target_cc = xyes ; then - TARGET_CPPFLAGS="$TARGET_CPPFLAGS -fnested-functions" - - CFLAGS="$CFLAGS -fnested-functions" - TARGET_APPLE_CC=1 - AC_CHECK_PROG([OBJCONV], [objconv], [objconv], []) - if test "x$OBJCONV" = x ; then - AC_CHECK_PROG([OBJCONV], [objconv], [./objconv], [], [.]) - fi - if test "x$OBJCONV" = x ; then - AC_MSG_ERROR([objconv not found which is required when building with apple compiler]) - fi - TARGET_IMG_LDSCRIPT= - TARGET_IMG_CFLAGS="-static" - TARGET_IMG_LDFLAGS='-nostdlib -static -Wl,-preload -Wl,-segalign,20' - TARGET_IMG_LDFLAGS_AC='-nostdlib -static -Wl,-preload -Wl,-segalign,20' - TARGET_IMG_BASE_LDOPT="-Wl,-image_base" - TARGET_LDFLAGS_OLDMAGIC="" -else - TARGET_APPLE_CC=0 - TARGET_LDFLAGS_OLDMAGIC="-Wl,-N" -# Use linker script if present, otherwise use builtin -N script. -if test -f "${srcdir}/${grub_coredir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc"; then - TARGET_IMG_LDSCRIPT='$(top_srcdir)'"/${grub_coredir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc" - TARGET_IMG_LDFLAGS="-Wl,-T${TARGET_IMG_LDSCRIPT}" - TARGET_IMG_LDFLAGS_AC="-Wl,-T${srcdir}/${grub_coredir}/conf/${target_cpu}-${platform}-${host_os}-img-ld.sc" - TARGET_IMG_BASE_LDOPT="-Wl,-Ttext" -else - TARGET_IMG_LDSCRIPT= - TARGET_IMG_LDFLAGS='-Wl,-N' - TARGET_IMG_LDFLAGS_AC='-Wl,-N' - TARGET_IMG_BASE_LDOPT="-Wl,-Ttext" -fi -TARGET_IMG_CFLAGS= -fi - -AC_SUBST(TARGET_LDFLAGS_OLDMAGIC) - -# For platforms where ELF is not the default link format. -AC_MSG_CHECKING([for command to convert module to ELF format]) -case "${host_os}" in - cygwin) TARGET_OBJ2ELF='$(top_builddir)/grub-pe2elf'; -# FIXME: put proper test here - NEED_REGISTER_FRAME_INFO=1 - ;; - *) NEED_REGISTER_FRAME_INFO=0 ;; -esac -AC_MSG_RESULT([$TARGET_OBJ2ELF]) - - -AC_ARG_ENABLE([efiemu], - [AS_HELP_STRING([--enable-efiemu], - [build and install the efiemu runtimes (default=guessed)])]) -if test x"$enable_efiemu" = xno ; then - efiemu_excuse="explicitly disabled" -fi -if test x"$target_cpu" != xi386 ; then - efiemu_excuse="only available on i386" -fi -if test x"$platform" = xefi ; then - efiemu_excuse="not available on efi" -fi -if test x"$efiemu_excuse" = x ; then - AC_CACHE_CHECK([whether options required for efiemu work], grub_cv_cc_efiemu, [ - SAVED_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -m64 -mcmodel=large -mno-red-zone -nostdlib" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], - [grub_cv_cc_efiemu=yes], - [grub_cv_cc_efiemu=no]) - CFLAGS="$SAVED_CFLAGS" - ]) - if test x$grub_cv_cc_efiemu = xno; then - efiemu_excuse="cannot compile with -m64 -mcmodel=large -mno-red-zone -nostdlib" - fi -fi -if test x"$enable_efiemu" = xyes && test x"$efiemu_excuse" != x ; then - AC_MSG_ERROR([efiemu runtime was explicitly requested but can't be compiled]) -fi -if test x"$efiemu_excuse" = x ; then -enable_efiemu=yes -else -enable_efiemu=no -fi -AC_SUBST([enable_efiemu]) - if test "x$target_m32" = x1; then # Force 32-bit mode. TARGET_CFLAGS="$TARGET_CFLAGS -m32" @@ -556,24 +599,738 @@ if test "x$target_m64" = x1; then TARGET_MODULE_FORMAT="elf64" fi -if test "$target_cpu"-"$platform" = x86_64-efi; then +# debug flags. +TARGET_CFLAGS="$TARGET_CFLAGS $WARN_FLAGS -g -Wredundant-decls -Wmissing-prototypes -Wmissing-declarations" +TARGET_CCASFLAGS="$TARGET_CCASFLAGS -g" + +if test "x$target_cpu" != xi386 && test "x$target_cpu" != xx86_64; then +TARGET_CFLAGS="$TARGET_CFLAGS -Wcast-align" +fi + +TARGET_CC_VERSION="$(LC_ALL=C $TARGET_CC --version | head -n1)" + +AC_CACHE_CHECK([which extra warnings work], [grub_cv_target_cc_w_extra_flags], [ + LDFLAGS="$TARGET_LDFLAGS -nostdlib -static" + + grub_cv_target_cc_w_extra_flags= + for x in $EXTRA_WARN_FLAGS; do + CFLAGS="$TARGET_CFLAGS $x -Werror" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +asm (".globl start; start:"); +void __main (void); +void __main (void) {} +int main (void); +]], [[]])], [flag=1], [flag=0]) + if test x$flag = x1 ; then + grub_cv_target_cc_w_extra_flags="$grub_cv_target_cc_w_extra_flags $x" + fi + done +]) + +TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_w_extra_flags" + +AC_CACHE_CHECK([if compiling with clang], [grub_cv_cc_target_clang], +[ +CFLAGS="$TARGET_CFLAGS" +AC_COMPILE_IFELSE( +[AC_LANG_PROGRAM([], [[ +#ifdef __clang__ +#error "is clang" +#endif +]])], +[grub_cv_cc_target_clang=no], [grub_cv_cc_target_clang=yes])]) + +if test x$target_cpu = xpowerpc -o x$target_cpu = xmips; then + AC_CACHE_CHECK([for options to get big-endian compilation], grub_cv_target_cc_big_endian, [ + grub_cv_target_cc_big_endian=no + for cand in "-target $target_cpu -Wl,-EB" "-target $target_cpu" \ + "-target $target_cpu-linux-gnu -Wl,-EB" "-target $target_cpu-linux-gnu" \ + "-EB" "-mbig-endian"; do + if test x"$grub_cv_target_cc_big_endian" != xno ; then + break + fi + CFLAGS="$TARGET_CFLAGS $cand -Werror" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__ORDER_BIG_ENDIAN__ != __BYTE_ORDER__) +#error still little endian +#endif +asm (".globl start; start:"); +asm (".globl _start; _start:"); +asm (".globl __start; __start:"); +void __main (void); +void __main (void) {} +int main (void); +]], [[]])], + [grub_cv_target_cc_big_endian="$cand"], []) + done + ]) + + if test x"$grub_cv_target_cc_big_endian" = xno ; then + AC_MSG_ERROR([could not force big-endian]) + fi + + skip_linkflags="$(echo "$grub_cv_target_cc_big_endian"|sed 's@-Wl,-EB@@')" + + TARGET_CFLAGS="$TARGET_CFLAGS $skip_linkflags" + TARGET_CPPFLAGS="$TARGET_CPPFLAGS $skip_linkflags" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS $skip_linkflags" + TARGET_LDFLAGS="$TARGET_LDFLAGS $grub_cv_target_cc_big_endian" +elif test x$target_cpu = xmipsel; then + AC_CACHE_CHECK([for options to get little-endian compilation], grub_cv_target_cc_little_endian, [ + grub_cv_target_cc_little_endian=no + for cand in "-target $target_cpu -Wl,-EL" "-target $target_cpu" \ + "-target $target_cpu-linux-gnu -Wl,-EL" "-target $target_cpu-linux-gnu" \ + "-EL"; do + if test x"$grub_cv_target_cc_little_endian" != xno ; then + break + fi + CFLAGS="$TARGET_CFLAGS $cand -Werror" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && (__ORDER_BIG_ENDIAN__ == __BYTE_ORDER__) +#error still big endian +#endif +asm (".globl start; start:"); +asm (".globl _start; _start:"); +asm (".globl __start; __start:"); +void __main (void); +void __main (void) {} +int main (void); +]], [[]])], + [grub_cv_target_cc_little_endian="$cand"], []) + done + ]) + + if test x"$grub_cv_target_cc_little_endian" = xno ; then + AC_MSG_ERROR([could not force little-endian]) + fi + + skip_linkflags="$(echo "$grub_cv_target_cc_little_endian"|sed 's@-Wl,-EL@@')" + + TARGET_CFLAGS="$TARGET_CFLAGS $skip_linkflags" + TARGET_CPPFLAGS="$TARGET_CPPFLAGS $skip_linkflags" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS $skip_linkflags" + TARGET_LDFLAGS="$TARGET_LDFLAGS $grub_cv_target_cc_little_endian" +fi + +# GRUB code is N32-compliant but it's experimental and we would prefer to +# avoid having too much variety when it doesn't result in any real improvement. +# Moreover N64 isn't supported. +if test "x$target_cpu" = xmips || test "x$target_cpu" = xmipsel ; then + AC_CACHE_CHECK([for options to force MIPS o32 ABI], grub_cv_target_cc_mips_o32_abi, [ + grub_cv_target_cc_mips_o32_abi=no + for arg in "" "-mabi=32" "-target $target_cpu -mabi=32" ; do + if test x"$grub_cv_target_cc_mips_o32_abi" != xno ; then + break + fi + CFLAGS="$TARGET_CFLAGS $arg -Werror" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#if !defined(_ABIO32) || !defined(_MIPS_SIM) || (_MIPS_SIM != _ABIO32) +#error not o32 ABI +#endif +asm (".globl start; start:"); +asm (".globl _start; _start:"); +asm (".globl __start; __start:"); +void __main (void); +void __main (void) {} +int main (void); +]], [[]])], + [grub_cv_target_cc_mips_o32_abi="$arg"], []) + done + ]) + + if test x"$grub_cv_target_cc_mips_o32_abi" = xno ; then + AC_MSG_ERROR([could not force MIPS o32 ABI]) + fi + + TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_mips_o32_abi" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_target_cc_mips_o32_abi" +fi + +AC_CACHE_CHECK([for options to compile assembly], [grub_cv_cc_target_asm_compile], [ +test_program= +case "x$target_cpu-$platform" in + xmips-* | xmipsel-*) + test_program=mips + ;; + xi386-pc) + test_program=i386-pc + ;; + xi386-* | xx86_64-*) + test_program=i386 + ;; + xpowerpc-* | xsparc64-* | xarm-*) + test_program=$target_cpu + ;; +esac +if test x"$test_program" = x ; then + grub_cv_cc_target_asm_compile= +else + found=no + for arg in "" "-no-integrated-as"; do + cmdline="$TARGET_CC -c -o /dev/null $TARGET_CCASFLAGS $arg $TARGET_CPPFLAGS $srcdir/asm-tests/$test_program.S" + echo "Running $cmdline" >&AS_MESSAGE_LOG_FD + if $cmdline >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then + grub_cv_cc_target_asm_compile="$arg" + found=yes + break + fi + done + if test x"$found" = xno ; then + AC_MSG_ERROR([could not compile assembly]) + fi +fi +]) + +TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_cc_target_asm_compile" + +if test "x$target_cpu" = xi386 && test "x$platform" != xemu; then + TARGET_CFLAGS="$TARGET_CFLAGS -march=i386" +fi + +if test "x$grub_cv_cc_target_clang" = xno && test "x$target_cpu" = xi386 && test "x$platform" != xemu && test "x$platform" != xefi; then + TARGET_CFLAGS="$TARGET_CFLAGS -mrtd -mregparm=3" +fi + +# on mips redirect cache flushing function to non-existant one. +if test "x$target_cpu" = xmips || test "x$target_cpu" = xmipsel ; then + AC_CACHE_CHECK([whether -mflush-func=grub_red_herring works], [grub_cv_cc_mflush_func], [ + CFLAGS="$TARGET_CFLAGS -mflush-func=grub_red_herring -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_mflush_func=yes], + [grub_cv_cc_mflush_func=no]) + ]) + + if test "x$grub_cv_cc_mflush_func" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -mflush-func=grub_red_herring" + fi + + AC_CACHE_CHECK([whether -mno-gpopt works], [grub_cv_cc_mno_gpopt], [ + CFLAGS="$TARGET_CFLAGS -mno-gpopt -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_mno_gpopt=yes], + [grub_cv_cc_mno_gpopt=no]) + ]) + + if test "x$grub_cv_cc_mno_gpopt" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -mno-gpopt" + fi +fi + + +# Force no alignment to save space on i386. +if test "x$target_cpu" = xi386; then + TARGET_CFLAGS="$TARGET_CFLAGS -falign-functions=1" + + AC_CACHE_CHECK([whether -falign-loops works], [grub_cv_cc_falign_loop], [ + CFLAGS="$TARGET_CFLAGS -falign-loops=1 -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_falign_loop=yes], + [grub_cv_cc_falign_loop=no]) + ]) + + if test "x$grub_cv_cc_falign_loop" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -falign-loops=1" + fi + + AC_CACHE_CHECK([whether -falign-jumps works], [grub_cv_cc_falign_jumps], [ + CFLAGS="$TARGET_CFLAGS -falign-jumps=1 -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_falign_jumps=yes], + [grub_cv_cc_falign_jumps=no]) + ]) + + if test "x$grub_cv_cc_falign_jumps" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -falign-jumps=1" + fi +fi + +AC_CACHE_CHECK([whether -freg-struct-return works], [grub_cv_cc_freg_struct_return], [ + CFLAGS="$TARGET_CFLAGS -freg-struct-return -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_freg_struct_return=yes], + [grub_cv_cc_freg_struct_return=no]) +]) + +if test "x$grub_cv_cc_freg_struct_return" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -freg-struct-return" +fi + +if ( test "x$target_cpu" = xi386 || test "x$target_cpu" = xx86_64 ) && test "x$platform" != xemu; then + # Some toolchains enable these features by default, but they need + # registers that aren't set up properly in GRUB. + TARGET_CFLAGS="$TARGET_CFLAGS -mno-mmx -mno-sse -mno-sse2 -mno-sse3 -mno-3dnow" +fi + +if ( test "x$target_cpu" = xi386 || test "x$target_cpu" = xx86_64 ); then + AC_CACHE_CHECK([whether -Wa,-mx86-used-note works], [grub_cv_cc_mx86_used_note], [ + CFLAGS="$TARGET_CFLAGS -Wa,-mx86-used-note=no -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_mx86_used_note=yes], + [grub_cv_cc_mx86_used_note=no]) + ]) + + if test "x$grub_cv_cc_mx86_used_note" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -Wa,-mx86-used-note=no" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS -Wa,-mx86-used-note=no" + fi +fi + +if test "x$target_cpu" = xloongarch64; then + AC_CACHE_CHECK([whether _mno_explicit_relocs works], [grub_cv_cc_mno_explicit_relocs], [ + CFLAGS="$TARGET_CFLAGS -mno-explicit-relocs -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_mno_explicit_relocs=yes], + [grub_cv_cc_mno_explicit_relocs=no]) + ]) + if test "x$grub_cv_cc_mno_explicit_relocs" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -mno-explicit-relocs -fno-plt" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS -mno-explicit-relocs -fno-plt" + fi + + AC_CACHE_CHECK([for no-relax options], grub_cv_target_cc_mno_relax, [ + grub_cv_target_cc_mno_relax=no + for cand in "-mno-relax" "-Wa,-mno-relax"; do + if test x"$grub_cv_target_cc_mno_relax" != xno ; then + break + fi + CFLAGS="$TARGET_CFLAGS $cand -Werror" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + asm (".globl start; start:"); + void __main (void); + void __main (void) {} + int main (void); + ]], [[]])], [grub_cv_target_cc_mno_relax="$cand"], []) + done + ]) + CFLAGS="$TARGET_CFLAGS" + + if test x"$grub_cv_target_cc_mno_relax" != xno ; then + TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_mno_relax" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_target_cc_mno_relax" + fi + + TARGET_CFLAGS="$TARGET_CFLAGS -Wa,-mla-global-with-abs" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS -Wa,-mla-global-with-abs" +fi + +if test "x$target_cpu" = xriscv64 || test "x$target_cpu" = xriscv32; then + AC_CACHE_CHECK([for no-relax options], grub_cv_target_cc_mno_relax, [ + grub_cv_target_cc_mno_relax=no + for cand in "-mno-relax" "-Wa,-mno-relax"; do + if test x"$grub_cv_target_cc_mno_relax" != xno ; then + break + fi + CFLAGS="$TARGET_CFLAGS $cand -Werror" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + asm (".globl start; start:"); + void __main (void); + void __main (void) {} + int main (void); + ]], [[]])], [grub_cv_target_cc_mno_relax="$cand"], []) + done + ]) + + CFLAGS="$TARGET_CFLAGS" + + if test x"$grub_cv_target_cc_mno_relax" != xno ; then + TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_mno_relax" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_target_cc_mno_relax" + fi +fi + +# GRUB doesn't use float or doubles at all. Yet some toolchains may decide +# that floats are a good fit to run instead of what's written in the code. +# Given that floating point unit is disabled (if present to begin with) +# when GRUB is running which may result in various hard crashes. +if test x"$platform" != xemu ; then + AC_CACHE_CHECK([for options to get soft-float], grub_cv_target_cc_soft_float, [ + grub_cv_target_cc_soft_float=no + if test "x$target_cpu" = xarm64; then + CFLAGS="$TARGET_CFLAGS -mgeneral-regs-only -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_target_cc_soft_float="-mgeneral-regs-only"], []) + fi + if test "x$target_cpu" = xriscv32; then + CFLAGS="$TARGET_CFLAGS -march=rv32imac -mabi=ilp32 -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_target_cc_soft_float="-march=rv32imac -mabi=ilp32"], []) + # ISA spec version 20191213 factored out extensions Zicsr and Zifencei + CFLAGS="$TARGET_CFLAGS -march=rv32imac_zicsr_zifencei -mabi=ilp32 -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_target_cc_soft_float="-march=rv32imac_zicsr_zifencei -mabi=ilp32"], []) + fi + if test "x$target_cpu" = xriscv64; then + CFLAGS="$TARGET_CFLAGS -march=rv64imac -mabi=lp64 -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_target_cc_soft_float="-march=rv64imac -mabi=lp64"], []) + # ISA spec version 20191213 factored out extensions Zicsr and Zifencei + CFLAGS="$TARGET_CFLAGS -march=rv64imac_zicsr_zifencei -mabi=lp64 -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_target_cc_soft_float="-march=rv64imac_zicsr_zifencei -mabi=lp64"], []) + fi + if test "x$target_cpu" = xia64; then + CFLAGS="$TARGET_CFLAGS -mno-inline-float-divide -mno-inline-sqrt -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_target_cc_soft_float="-mno-inline-float-divide -mno-inline-sqrt"], []) + fi + if test "x$target_cpu" = xsh4; then + CFLAGS="$TARGET_CFLAGS -m4-nofpu -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_target_cc_soft_float="-m4-nofpu"], []) + fi + for cand in "-msoft-float -Xclang -msoft-float -Xclang -no-implicit-float" \ + "-Xclang -msoft-float -Xclang -no-implicit-float" \ + "-Xclang -msoft-float" "-msoft-float"; do + if test x"$grub_cv_target_cc_soft_float" != xno ; then + break + fi + CFLAGS="$TARGET_CFLAGS $cand -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_target_cc_soft_float="$cand"], []) + done + ]) + + if test x"$grub_cv_target_cc_soft_float" = xno ; then + AC_MSG_ERROR([could not force soft-float]) + fi + + case x"$grub_cv_target_cc_soft_float" in + x*"-Xclang"*) + # A trick so that clang doesn't see it on link stаge + TARGET_CPPFLAGS="$TARGET_CPPFLAGS $grub_cv_target_cc_soft_float" + ;; + *) + TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_soft_float" + ;; + esac + TARGET_CCASFLAGS="$TARGET_CCASFLAGS $grub_cv_target_cc_soft_float" + +fi + +if test x"$target_cpu" = xsparc64 ; then + AC_CACHE_CHECK([for options to reserve application registers], grub_cv_target_cc_mno_app_regs, [ + grub_cv_target_cc_mno_app_regs=no + for cand in "-mllvm -sparc-reserve-app-registers" \ + "-mno-app-regs"; do + if test x"$grub_cv_target_cc_mno_app_regs" != xno ; then + break + fi + CFLAGS="$TARGET_CFLAGS $cand -Werror" + CPPFLAGS="$TARGET_CPPFLAGS" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_target_cc_mno_app_regs="$cand"], []) + done + ]) + + if test x"$grub_cv_target_cc_mno_app_regs" = xno ; then + AC_MSG_ERROR([could not reserve application registers]) + fi + if test x"$grub_cv_target_cc_mno_app_regs" = x"-mllvm -sparc-reserve-app-registers" ; then + # A trick so that clang doesn't see it on link stаge + TARGET_CPPFLAGS="$TARGET_CPPFLAGS $grub_cv_target_cc_mno_app_regs" + else + TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_mno_app_regs" + fi + + AC_CACHE_CHECK([for no-relax options], grub_cv_target_cc_mno_relax, [ + grub_cv_target_cc_mno_relax=no + for cand in "-mno-relax" "-Wl,--no-relax"; do + if test x"$grub_cv_target_cc_mno_relax" != xno ; then + break + fi + LDFLAGS="$TARGET_LDFLAGS $cand -nostdlib -static" + CFLAGS="$TARGET_CFLAGS -Werror" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + asm (".globl start; start:"); + void __main (void); + void __main (void) {} + int main (void); + ]], [[]])], [grub_cv_target_cc_mno_relax="$cand"], []) + done + ]) + LDFLAGS="$TARGET_LDFLAGS" + CFLAGS="$TARGET_CFLAGS" + + if test x"$grub_cv_target_cc_mno_relax" = xno ; then + AC_MSG_ERROR([could not find no-relax options]) + fi + TARGET_LDFLAGS="$TARGET_LDFLAGS $grub_cv_target_cc_mno_relax" +fi + +# The backtrace module relies on frame pointers and the default optimization +# level, -Os, omits them. Make sure they are enabled. +AC_CACHE_CHECK([whether -fno-omit-frame-pointer works], [grub_cv_cc_fno_omit_frame_pointer], [ + CFLAGS="$TARGET_CFLAGS -fno-omit-frame-pointer" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_fno_omit_frame_pointer=yes], + [grub_cv_cc_fno_omit_frame_pointer=no]) +]) + +if test "x$grub_cv_cc_fno_omit_frame_pointer" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -fno-omit-frame-pointer" +fi + +# By default, GCC 4.4 generates .eh_frame sections containing unwind +# information in some cases where it previously did not. GRUB doesn't need +# these and they just use up vital space. Restore the old compiler +# behaviour. +AC_CACHE_CHECK([whether -fno-dwarf2-cfi-asm works], [grub_cv_cc_fno_dwarf2_cfi_asm], [ + CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_fno_dwarf2_cfi_asm=yes], + [grub_cv_cc_fno_dwarf2_cfi_asm=no]) +]) + +if test "x$grub_cv_cc_fno_dwarf2_cfi_asm" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -fno-dwarf2-cfi-asm" +fi + +if test x"$target_os" = xcygwin; then + AC_CACHE_CHECK([whether option -fno-reorder-functions works], grub_cv_cc_no_reorder_functions, [ + CFLAGS="$TARGET_CFLAGS -fno-reorder-functions" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_no_reorder_functions=yes], + [grub_cv_cc_no_reorder_functions=no]) + ]) +fi + +if test x"$target_os" = xcygwin && test "x$grub_cv_cc_no_reorder_functions" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -fno-reorder-functions" +fi + +AC_CACHE_CHECK([whether -mno-stack-arg-probe works], [grub_cv_cc_mno_stack_arg_probe], [ + CFLAGS="$TARGET_CFLAGS -mno-stack-arg-probe" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_mno_stack_arg_probe=yes], + [grub_cv_cc_mno_stack_arg_probe=no]) +]) + +if test "x$grub_cv_cc_mno_stack_arg_probe" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -mno-stack-arg-probe" +fi + + +# By default, GCC 4.6 generates .eh_frame sections containing unwind +# information in some cases where it previously did not. GRUB doesn't need +# these and they just use up vital space. Restore the old compiler +# behaviour. +AC_CACHE_CHECK([whether -fno-asynchronous-unwind-tables works], [grub_cv_cc_fno_asynchronous_unwind_tables], [ + CFLAGS="$TARGET_CFLAGS -fno-asynchronous-unwind-tables" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_fno_asynchronous_unwind_tables=yes], + [grub_cv_cc_fno_asynchronous_unwind_tables=no]) +]) + +if test "x$grub_cv_cc_fno_asynchronous_unwind_tables" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -fno-asynchronous-unwind-tables" +fi + +AC_CACHE_CHECK([whether -fno-unwind-tables works], [grub_cv_cc_fno_unwind_tables], [ + CFLAGS="$TARGET_CFLAGS -fno-unwind-tables" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_fno_unwind_tables=yes], + [grub_cv_cc_fno_unwind_tables=no]) +]) + +if test "x$grub_cv_cc_fno_unwind_tables" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -fno-unwind-tables" +fi + +# Do not generate .ident sections. +AC_CACHE_CHECK([whether -fno-ident works], [grub_cv_cc_fno_ident], [ + CFLAGS="$TARGET_CFLAGS -fno-ident" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_fno_ident=yes], + [grub_cv_cc_fno_ident=no]) +]) + +if test "x$grub_cv_cc_fno_ident" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -fno-ident" +fi + +CFLAGS="$TARGET_CFLAGS" + + +if test x"$platform" = xemu ; then + TARGET_OBJ2ELF= + grub_cv_target_cc_link_format= + case "$host_os" in + *darwin* | *mac*) + grub_cv_target_cc_link_format="-arch,${target_cpu}" + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,$grub_cv_target_cc_link_format" + ;; + *windows* | *cygwin* | *mingw*) + if test x${target_cpu} = xi386 ; then + grub_cv_target_cc_link_format=-mi386pe + TARGET_OBJ2ELF='./build-grub-pe2elf$(BUILD_EXEEXT)' + fi + if test x${target_cpu} = xx86_64 ; then + grub_cv_target_cc_link_format=-mi386pep + TARGET_OBJ2ELF='./build-grub-pep2elf$(BUILD_EXEEXT)' + fi + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,$grub_cv_target_cc_link_format" + ;; + esac +elif test x"$target_cpu" = xi386 || test x"$target_cpu" = xx86_64; then + AC_CACHE_CHECK([for target linking format], [grub_cv_target_cc_link_format], [ + grub_cv_target_cc_link_format=unknown + for format in -melf_${target_cpu} -melf_${target_cpu}_fbsd -melf_${target_cpu}_obsd -melf_${target_cpu}_haiku -mi386pe -mi386pep -arch,${target_cpu}; do + if test x${target_cpu} != xi386 && test x$format = x-mi386pe; then + continue + fi + if test x${target_cpu} != xx86_64 && test x$format = x-mi386pep; then + continue + fi + CFLAGS="$TARGET_CFLAGS" + LDFLAGS="$TARGET_LDFLAGS -Wl,$format -nostdlib -static" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + asm (".globl start; start:"); + asm (".globl _start; _start:"); + asm (".globl __start; __start:"); + void __main (void); + void __main (void) {} + ]], [[]])], [flag=1], [flag=0]) + if test x"$flag" = x1; then + grub_cv_target_cc_link_format="$format" + break + fi + done]) + if test x"$grub_cv_target_cc_link_format" = xunknown; then + AC_MSG_ERROR([no suitable link format found]) + fi + TARGET_LDFLAGS="$TARGET_LDFLAGS -Wl,$grub_cv_target_cc_link_format" + if test x"$grub_cv_target_cc_link_format" = x-mi386pe ; then + TARGET_OBJ2ELF='./build-grub-pe2elf$(BUILD_EXEEXT)' + fi + if test x"$grub_cv_target_cc_link_format" = x-mi386pep ; then + TARGET_OBJ2ELF='./build-grub-pep2elf$(BUILD_EXEEXT)' + fi +fi + +if test x$grub_cv_target_cc_link_format = x-arch,i386 || test x$grub_cv_target_cc_link_format = x-arch,x86_64; then + TARGET_APPLE_LINKER=1 + AC_CHECK_PROG([TARGET_OBJCONV], [objconv], [objconv], []) + if test "x$TARGET_OBJCONV" = x ; then + AC_CHECK_PROG([TARGET_OBJCONV], [objconv], [./objconv], [], [.]) + fi + if test "x$TARGET_OBJCONV" = x ; then + AC_MSG_ERROR([objconv not found which is required when building with apple compiler]) + fi + TARGET_IMG_LDSCRIPT= + TARGET_IMG_CFLAGS="-static" + TARGET_IMG_LDFLAGS='-nostdlib -static -Wl,-preload -Wl,-segalign,20' + TARGET_IMG_LDFLAGS_AC='-nostdlib -static -Wl,-preload -Wl,-segalign,20' + TARGET_IMG_BASE_LDOPT="-Wl,-image_base" + TARGET_LDFLAGS_OLDMAGIC="" +elif test x$grub_cv_target_cc_link_format = x-mi386pe || test x$grub_cv_target_cc_link_format = x-mi386pep ; then + TARGET_APPLE_LINKER=0 + TARGET_LDFLAGS_OLDMAGIC="-Wl,-N" + TARGET_IMG_LDSCRIPT='$(top_srcdir)'"/conf/i386-cygwin-img-ld.sc" + TARGET_IMG_LDFLAGS="-Wl,-T${TARGET_IMG_LDSCRIPT}" + TARGET_IMG_LDFLAGS_AC="-Wl,-T${srcdir}/conf/i386-cygwin-img-ld.sc" + TARGET_IMG_BASE_LDOPT="-Wl,-Ttext" + TARGET_IMG_CFLAGS= +else + TARGET_APPLE_LINKER=0 + TARGET_LDFLAGS_OLDMAGIC="-Wl,-N" + TARGET_IMG_LDSCRIPT= + TARGET_IMG_LDFLAGS='-Wl,-N' + TARGET_IMG_LDFLAGS_AC='-Wl,-N' + TARGET_IMG_BASE_LDOPT="-Wl,-Ttext" + TARGET_IMG_CFLAGS= +fi + +CFLAGS="$TARGET_CFLAGS" + +AC_ARG_ENABLE([efiemu], + [AS_HELP_STRING([--enable-efiemu], + [build and install the efiemu runtimes (default=guessed)])]) +if test x"$enable_efiemu" = xno ; then + efiemu_excuse="explicitly disabled" +fi + +if test x"$grub_cv_target_cc_link_format" = x-mi386pe || test x"$grub_cv_target_cc_link_format" = x-mi386pep ; then + efiemu_excuse="not available on cygwin" +fi +if test x"$target_cpu" != xi386 ; then + efiemu_excuse="only available on i386" +fi +if test x"$platform" = xefi ; then + efiemu_excuse="not available on efi" +fi + +if test x"$efiemu_excuse" = x ; then + AC_CACHE_CHECK([whether options required for efiemu work], grub_cv_cc_efiemu, [ + CFLAGS="-m64 -nostdlib -O2 -mcmodel=large -mno-red-zone" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_efiemu=yes], + [grub_cv_cc_efiemu=no]) + ]) + if test x$grub_cv_cc_efiemu = xno; then + efiemu_excuse="cannot compile with -m64 -mcmodel=large -mno-red-zone -nostdlib" + fi +fi +if test x"$efiemu_excuse" = x ; then + AC_CACHE_CHECK([for efiemu64 linking format], [grub_cv_target_cc_efiemu64_link_format], [ + grub_cv_target_cc_efiemu64_link_format=unknown + for format in -melf_x86_64 -melf_x86_64_fbsd -melf_x86_64_obsd -melf_x86_64_haiku -arch,x86_64; do + CFLAGS="-m64 -nostdlib -O2 -mcmodel=large -mno-red-zone" + LDFLAGS="-m64 -Wl,$format -nostdlib -static" + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ + asm (".globl start; start:"); + asm (".globl _start; _start:"); + asm (".globl __start; __start:"); + void __main (void); + void __main (void) {} + ]], [[]])], [flag=1], [flag=0]) + if test x"$flag" = x1; then + grub_cv_target_cc_efiemu64_link_format="$format" + break + fi + done]) + if test x"$grub_cv_target_cc_efiemu64_link_format" = xunknown; then + efiemu_excuse="no suitable link format for efiemu64 found" + else + EFIEMU64_LINK_FORMAT="-Wl,$grub_cv_target_cc_efiemu64_link_format" + fi +fi +if test x"$enable_efiemu" = xyes && test x"$efiemu_excuse" != x ; then + AC_MSG_ERROR([efiemu runtime was explicitly requested but can't be compiled ($efiemu_excuse)]) +fi +if test x"$efiemu_excuse" = x ; then +enable_efiemu=yes +else +enable_efiemu=no +fi +AC_SUBST([enable_efiemu]) +AC_SUBST([EFIEMU64_LINK_FORMAT]) + +CFLAGS="$TARGET_CFLAGS" + +AC_SUBST(TARGET_LDFLAGS_OLDMAGIC) + + +LDFLAGS="$TARGET_LDFLAGS" + +if test "$target_cpu" = x86_64 || test "$target_cpu" = sparc64 || test "$target_cpu" = riscv64 ; then # Use large model to support 4G memory AC_CACHE_CHECK([whether option -mcmodel=large works], grub_cv_cc_mcmodel, [ - SAVED_CFLAGS=$CFLAGS - CFLAGS="$CFLAGS -m64 -mcmodel=large" + CFLAGS="$TARGET_CFLAGS -mcmodel=large" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [grub_cv_cc_mcmodel=yes], [grub_cv_cc_mcmodel=no]) ]) - if test "x$grub_cv_cc_mcmodel" = xno; then - AC_MSG_ERROR([-mcmodel=large not supported. Upgrade your gcc.]) - else + if test "x$grub_cv_cc_mcmodel" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -mcmodel=large" + elif test "$target_cpu" = sparc64 || test "$target_cpu" = riscv64; then + TARGET_CFLAGS="$TARGET_CFLAGS -mcmodel=medany" fi +fi +if test "$target_cpu"-"$platform" = x86_64-efi; then # EFI writes to stack below %rsp, we must not use the red zone AC_CACHE_CHECK([whether option -mno-red-zone works], grub_cv_cc_no_red_zone, [ - CFLAGS="$CFLAGS -m64 -mno-red-zone" + CFLAGS="$TARGET_CFLAGS -mno-red-zone" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [grub_cv_cc_no_red_zone=yes], [grub_cv_cc_no_red_zone=no]) @@ -585,36 +1342,165 @@ if test "$target_cpu"-"$platform" = x86_64-efi; then TARGET_CFLAGS="$TARGET_CFLAGS -mno-red-zone" fi +if test "x$target_cpu" = xarm; then + AC_CACHE_CHECK([for options to disable movt and movw], grub_cv_target_cc_mno_movt, [ + grub_cv_target_cc_mno_movt=no + for cand in "-mno-movt" \ + "-mllvm -arm-use-movt=0" \ + "-mword-relocations"; do + if test x"$grub_cv_target_cc_mno_movt" != xno ; then + break + fi + CFLAGS="$TARGET_CFLAGS $cand -Werror" + CPPFLAGS="$TARGET_CPPFLAGS" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_target_cc_mno_movt="$cand"], []) + done + ]) + + if test x"$grub_cv_target_cc_mno_movt" != xno ; then + # A trick so that clang doesn't see it on link stage + TARGET_CPPFLAGS="$TARGET_CPPFLAGS $grub_cv_target_cc_mno_movt" + fi + AC_CACHE_CHECK([whether option -mthumb-interwork works], grub_cv_cc_mthumb_interwork, [ + CFLAGS="$TARGET_CFLAGS -mthumb-interwork -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_cc_mthumb_interwork=yes], + [grub_cv_cc_mthumb_interwork=no]) + ]) + if test "x$grub_cv_cc_mthumb_interwork" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -mthumb-interwork" + # Clang defaults to thumb interworking + elif test "x$grub_cv_cc_target_clang" = xno ; then + AC_MSG_ERROR([your compiler doesn't support -mthumb-interwork]) + fi +fi + +AC_CACHE_CHECK([whether option -Qn works], grub_cv_target_cc_qn, [ + CFLAGS="$TARGET_CFLAGS -Qn -Qunused-arguments -Werror" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], + [grub_cv_target_cc_qn=yes], + [grub_cv_target_cc_qn=no])]) +if test "x$grub_cv_target_cc_qn" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -Qn -Qunused-arguments" +fi + # # Compiler features. # -# Need __enable_execute_stack() for nested function trampolines? -grub_CHECK_ENABLE_EXECUTE_STACK +CFLAGS="$TARGET_CFLAGS" # Position independent executable. grub_CHECK_PIE +grub_CHECK_NO_PIE +grub_CHECK_NO_PIE_ONEWORD +grub_CHECK_LINK_PIE [# Need that, because some distributions ship compilers that include -# `-fPIE' in the default specs. +# `-fPIE' or '-fpie' and '-pie' in the default specs. if [ x"$pie_possible" = xyes ]; then - TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIE" + TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIE -fno-pie" + TARGET_CCASFLAGS="$TARGET_CCASFLAGS -fno-PIE -fno-pie" +fi + +if [ x"$link_nopie_needed" = xyes ] || [ x"$pie_possible" = xyes ]; then + if [ x"$nopie_possible" = xyes ]; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -no-pie" + fi + if [ x"$nopie_oneword_possible" = xyes ]; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -nopie" + fi fi] +CFLAGS="$TARGET_CFLAGS" +LDFLAGS="$TARGET_LDFLAGS" + # Position independent executable. grub_CHECK_PIC -[# Need that, because some distributions ship compilers that include -# `-fPIC' in the default specs. -if [ x"$pic_possible" = xyes ]; then - TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIC" +[# On most platforms we don't want PIC as it only makes relocations harder +# and code less efficient. On mips we want to have one got table per module +# and reload $gp in every function. +# GCC implements it using symbol __gnu_local_gp in non-PIC as well. +# However with clang we need PIC for this reloading to happen. +# With arm64 we need relocations that are in some way representable in +# PE as we need to support arm64-efi. Without -fPIC clang generates +# movk's which aren't representable. +# Since default varies across dictributions use either -fPIC or -fno-PIC +# explicitly. +if ( test x$target_cpu = xmips || test x$target_cpu = xmipsel || test x$target_cpu = xarm64 ) && test "x$grub_cv_cc_target_clang" = xyes ; then + TARGET_CFLAGS="$TARGET_CFLAGS -fPIC" +elif [ x"$pic_possible" = xyes ]; then + TARGET_CFLAGS="$TARGET_CFLAGS -fno-PIC" fi] -# Smashing stack protector. +CFLAGS="$TARGET_CFLAGS" + +# Stack smashing protector. grub_CHECK_STACK_PROTECTOR -# Need that, because some distributions ship compilers that include -# `-fstack-protector' in the default specs. -if test "x$ssp_possible" = xyes; then - TARGET_CFLAGS="$TARGET_CFLAGS -fno-stack-protector" +AC_ARG_ENABLE([stack-protector], + AS_HELP_STRING([--enable-stack-protector], + [enable the stack protector]), + [], + [enable_stack_protector=no]) +if test "x$enable_stack_protector" = xno; then + if test "x$ssp_possible" = xyes; then + # Need that, because some distributions ship compilers that include + # `-fstack-protector' in the default specs. + TARGET_CFLAGS="$TARGET_CFLAGS -fno-stack-protector" + fi +elif test "x$platform" != xefi; then + if test "$ERROR_PLATFORM_NOT_SUPPORT_SSP" = "yes"; then + AC_MSG_ERROR([--enable-stack-protector is only supported on EFI platforms]) + else + AC_MSG_WARN([--enable-stack-protector is only supported on EFI platforms]) + fi + enable_stack_protector=no +elif test "x$ssp_global_possible" != xyes; then + AC_MSG_ERROR([--enable-stack-protector is not supported (compiler doesn't support -mstack-protector-guard=global)]) +else + TARGET_CFLAGS="$TARGET_CFLAGS -mstack-protector-guard=global" + if test "x$enable_stack_protector" = xyes; then + if test "x$ssp_possible" != xyes; then + AC_MSG_ERROR([--enable-stack-protector is not supported (compiler doesn't support -fstack-protector)]) + fi + TARGET_CFLAGS="$TARGET_CFLAGS -fstack-protector" + elif test "x$enable_stack_protector" = xstrong; then + if test "x$ssp_strong_possible" != xyes; then + AC_MSG_ERROR([--enable-stack-protector=strong is not supported (compiler doesn't support -fstack-protector-strong)]) + fi + TARGET_CFLAGS="$TARGET_CFLAGS -fstack-protector-strong" + else + # Note, -fstack-protector-all requires that the protector is disabled for + # functions that appear in the call stack when the canary is initialized. + AC_MSG_ERROR([invalid value $enable_stack_protector for --enable-stack-protector]) + fi + TARGET_CPPFLAGS="$TARGET_CPPFLAGS -DGRUB_STACK_PROTECTOR=1" + + if test -n "$SOURCE_DATE_EPOCH"; then + GRUB_STACK_PROTECTOR_INIT="0x00f2b7e2$(printf "%x" "$SOURCE_DATE_EPOCH" | sed 's/.*\(........\)$/\1/')" + elif test -r /dev/urandom; then + # Generate the 8 byte stack protector canary at build time if /dev/urandom + # is able to be read. The first byte should be NUL to filter out string + # buffer overflow attacks. + GRUB_STACK_PROTECTOR_INIT="$($PYTHON -c 'import codecs; rf=open("/dev/urandom", "rb"); print("0x00"+codecs.encode(rf.read(7), "hex").decode("ascii"))')" + else + # Some hosts may not have a urandom, e.g. Windows, so use statically + # generated random bytes + GRUB_STACK_PROTECTOR_INIT="0x00f2b7e2f193b25c" + fi + + if test x"$target_m32" = x1 ; then + # Make sure that the canary default value is 24-bits by only using the + # lower 3 bytes on 32 bit systems. This allows the upper byte to be NUL + # to filter out string buffer overflow attacks. + GRUB_STACK_PROTECTOR_INIT="0x00$(echo "$GRUB_STACK_PROTECTOR_INIT" | sed 's/.*\(......\)$/\1/')" + fi + + AC_SUBST([GRUB_STACK_PROTECTOR_INIT]) fi + +CFLAGS="$TARGET_CFLAGS" + grub_CHECK_STACK_ARG_PROBE # Cygwin's GCC uses alloca() to probe the stackframe on static # stack allocations above some threshold. @@ -622,127 +1508,108 @@ if test x"$sap_possible" = xyes; then TARGET_CFLAGS="$TARGET_CFLAGS -mno-stack-arg-probe" fi -AC_ARG_ENABLE([werror], - [AS_HELP_STRING([--disable-werror], - [do not use -Werror when building GRUB])]) -if test x"$enable_werror" != xno ; then - TARGET_CFLAGS="$TARGET_CFLAGS -Werror" - HOST_CFLAGS="$HOST_CFLAGS -Werror" +CFLAGS="$TARGET_CFLAGS" + +# -mno-unaligned-access -mstrict-align +if test "$target_cpu" = arm; then + AC_CACHE_CHECK([for compile options to get strict alignment], [grub_cv_target_cc_strict_align], [ + grub_cv_target_cc_strict_align= + for arg in -mno-unaligned-access "-Xclang -mstrict-align" -mstrict-align; do + CFLAGS="$TARGET_CFLAGS $arg -Werror" + LDFLAGS="$TARGET_LDFLAGS" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])], [flag=1], [flag=0]) + if test x"$flag" = x1; then + grub_cv_target_cc_strict_align="$arg" + break + fi + done]) + + TARGET_CFLAGS="$TARGET_CFLAGS $grub_cv_target_cc_strict_align" + if test x"$grub_cv_target_cc_strict_align" = x"-Xclang -mstrict-align"; then + TARGET_LDFLAGS="$TARGET_LDFLAGS -Qunused-arguments" + fi + AC_CACHE_CHECK([if compiler generates unaligned accesses], [grub_cv_cc_target_emits_unaligned], + [CFLAGS="$TARGET_CFLAGS" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[ +#ifdef __ARM_FEATURE_UNALIGNED +#error "unaligned" +#endif + ]])], + [grub_cv_cc_target_emits_unaligned=no], [grub_cv_cc_target_emits_unaligned=yes])]) + if test x$grub_cv_cc_target_emits_unaligned = xyes; then + AC_MSG_ERROR([compiler generates unaligned accesses]) + fi fi -TARGET_CPP="$TARGET_CC -E" -TARGET_CCAS=$TARGET_CC - -GRUB_TARGET_CPU="${target_cpu}" -GRUB_PLATFORM="${platform}" - -AC_SUBST(GRUB_TARGET_CPU) -AC_SUBST(GRUB_PLATFORM) - -AC_SUBST(OBJCONV) -AC_SUBST(TARGET_CPP) -AC_SUBST(TARGET_CCAS) -AC_SUBST(TARGET_OBJ2ELF) -AC_SUBST(TARGET_APPLE_CC) -AC_SUBST(TARGET_MODULE_FORMAT) - -AC_SUBST(TARGET_CFLAGS) -AC_SUBST(TARGET_LDFLAGS) -AC_SUBST(TARGET_CPPFLAGS) -AC_SUBST(TARGET_CCASFLAGS) - -AC_SUBST(TARGET_IMG_LDSCRIPT) -AC_SUBST(TARGET_IMG_LDFLAGS) -AC_SUBST(TARGET_IMG_CFLAGS) -AC_SUBST(TARGET_IMG_BASE_LDOPT) - -AC_SUBST(HOST_CFLAGS) -AC_SUBST(HOST_LDFLAGS) -AC_SUBST(HOST_CPPFLAGS) -AC_SUBST(HOST_CCASFLAGS) - # Set them to their new values for the tests below. CC="$TARGET_CC" -if test "x$TARGET_APPLE_CC" = x1 ; then -CFLAGS="$TARGET_CFLAGS -nostdlib -Wno-error" -else -CFLAGS="$TARGET_CFLAGS -nostdlib -Wl,--defsym,___main=0x8100 -Wno-error" -fi CPPFLAGS="$TARGET_CPPFLAGS" -if test x$target_cpu = xi386 || test x$target_cpu = xx86_64 ; then -LIBS= -else -LIBS=-lgcc -fi - -grub_ASM_USCORE -if test x$grub_cv_asm_uscore = xyes; then -CFLAGS="$CFLAGS -Wl,--defsym,_abort=_main" -else -CFLAGS="$CFLAGS -Wl,--defsym,abort=main" -fi # Check for libgcc symbols -AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x __ia64_trampoline __udivsi3 __umoddi3 __udivdi3 __divsi3 __modsi3 __umodsi3 __moddi3 __divdi3 __ctzdi2 __ctzsi2) +if test x"$platform" = xemu; then +CFLAGS="$TARGET_CFLAGS -Wno-error" +AC_CHECK_FUNCS(__udivsi3 __umodsi3 __divsi3 __modsi3 __divdi3 __moddi3 __udivdi3 __umoddi3 __ctzdi2 __ctzsi2 __clzdi2 __aeabi_uidiv __aeabi_uidivmod __aeabi_idiv __aeabi_idivmod __aeabi_ulcmp __muldi3 __aeabi_lmul __aeabi_memcpy __aeabi_memcpy4 __aeabi_memcpy8 __aeabi_memclr __aeabi_memclr4 __aeabi_memclr8 __aeabi_memset __aeabi_lasr __aeabi_llsl __aeabi_llsr _restgpr_14_x __ucmpdi2 __ashldi3 __ashrdi3 __lshrdi3 __bswapsi2 __bswapdi2 __bzero __register_frame_info __deregister_frame_info ___chkstk_ms __chkstk_ms) +fi -if test "x$TARGET_APPLE_CC" = x1 ; then -CFLAGS="$TARGET_CFLAGS -nostdlib" +if test "x$TARGET_APPLE_LINKER" = x1 ; then +CFLAGS="$TARGET_CFLAGS -nostdlib -static" else -CFLAGS="$TARGET_CFLAGS -nostdlib -Wl,--defsym,___main=0x8100" +CFLAGS="$TARGET_CFLAGS -nostdlib" fi LIBS="" -# Defined in aclocal.m4. +# Defined in acinclude.m4. +grub_ASM_USCORE grub_PROG_TARGET_CC -if test "x$TARGET_APPLE_CC" != x1 ; then +if test "x$TARGET_APPLE_LINKER" != x1 ; then grub_PROG_OBJCOPY_ABSOLUTE fi grub_PROG_LD_BUILD_ID_NONE if test "x$target_cpu" = xi386; then - if test "$platform" != emu && test "x$TARGET_APPLE_CC" != x1 ; then + if test "$platform" != emu && test "x$TARGET_APPLE_LINKER" != x1 ; then if test ! -z "$TARGET_IMG_LDSCRIPT"; then # Check symbols provided by linker script. - CFLAGS="$TARGET_CFLAGS -nostdlib ${TARGET_IMG_LDFLAGS_AC} ${TARGET_IMG_BASE_LDOPT},8000 -Wl,--defsym,___main=0x8100" + CFLAGS="$TARGET_CFLAGS -nostdlib ${TARGET_IMG_LDFLAGS_AC} ${TARGET_IMG_BASE_LDOPT},0x8000" fi grub_CHECK_BSS_START_SYMBOL grub_CHECK_END_SYMBOL fi CFLAGS="$TARGET_CFLAGS" - grub_I386_ASM_PREFIX_REQUIREMENT - grub_I386_ASM_ADDR32 fi +grub_PROG_NM_WORKS +grub_PROG_NM_MINUS_P +grub_PROG_NM_DEFINED_ONLY +AC_SUBST(TARGET_NMFLAGS_MINUS_P) +AC_SUBST(TARGET_NMFLAGS_DEFINED_ONLY) + if test "$platform" != emu; then AC_CACHE_CHECK([whether -nostdinc -isystem works], [grub_cv_cc_isystem], [ SAVED_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$TARGET_CPPFLAGS -nostdinc -isystem `$TARGET_CC -print-file-name=include`" + CPPFLAGS="$TARGET_CPPFLAGS -nostdlib -nostdinc -isystem `$TARGET_CC -print-file-name=include`" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +#include int va_arg_func (int fixed, va_list args);]], [[]])], [grub_cv_cc_isystem=yes], [grub_cv_cc_isystem=no]) CPPFLAGS="$SAVED_CPPFLAGS" ]) -if test x"$grub_cv_cc_isystem" = xyes ; then - TARGET_CPPFLAGS="$TARGET_CPPFLAGS -nostdinc -isystem `$TARGET_CC -print-file-name=include`" -fi + if test x"$grub_cv_cc_isystem" = xyes ; then + TARGET_CPPFLAGS="$TARGET_CPPFLAGS -nostdinc -isystem `$TARGET_CC -print-file-name=include`" + fi fi -AC_CACHE_CHECK([whether -Wno-trampolines work], [grub_cv_cc_wnotrampolines], [ - SAVED_CFLAGS="$CFLAGS" - # Test for -Wtrampolines rather than -Wno-trampolines to reduce confusion - # in the event of later failures (since -Wno-* is always accepted, but - # produces a diagnostic if something else is wrong). - CFLAGS="$TARGET_CFLAGS -Wtrampolines" +AC_CACHE_CHECK([whether -Wtrampolines work], [grub_cv_cc_wtrampolines], [ + CFLAGS="$TARGET_CFLAGS -Wtrampolines -Werror" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include int va_arg_func (int fixed, va_list args);]], [[]])], - [grub_cv_cc_wnotrampolines=yes], - [grub_cv_cc_wnotrampolines=no]) - CFLAGS="$SAVED_CFLAGS" + [grub_cv_cc_wtrampolines=yes], + [grub_cv_cc_wtrampolines=no]) ]) -if test x"$grub_cv_cc_wnotrampolines" = xyes ; then - TARGET_CFLAGS="$TARGET_CFLAGS -Wno-trampolines" +if test x"$grub_cv_cc_wtrampolines" = xyes ; then + TARGET_CFLAGS="$TARGET_CFLAGS -Wtrampolines" fi # Restore the flags. @@ -759,9 +1626,14 @@ LIBS="$tmp_LIBS" # Memory manager debugging. AC_ARG_ENABLE([mm-debug], AS_HELP_STRING([--enable-mm-debug], - [include memory manager debugging]), - [AC_DEFINE([MM_DEBUG], [1], - [Define to 1 if you enable memory manager debugging.])]) + [include memory manager debugging])) +if test x$enable_mm_debug = xyes; then + MM_DEBUG=1 +else + MM_DEBUG=0 +fi +AC_SUBST([MM_DEBUG]) +AM_CONDITIONAL([COND_MM_DEBUG], [test x$MM_DEBUG = x1]) AC_ARG_ENABLE([cache-stats], AS_HELP_STRING([--enable-cache-stats], @@ -774,9 +1646,20 @@ else fi AC_SUBST([DISK_CACHE_STATS]) -AC_ARG_ENABLE([grub-emu-usb], - [AS_HELP_STRING([--enable-grub-emu-usb], - [build and install the `grub-emu' debugging utility with USB support (default=guessed)])]) +AC_ARG_ENABLE([boot-time], + AS_HELP_STRING([--enable-boot-time], + [enable boot time statistics collection])) + +if test x$enable_boot_time = xyes; then + BOOT_TIME_STATS=1 +else + BOOT_TIME_STATS=0 +fi +AC_SUBST([BOOT_TIME_STATS]) + +AC_ARG_ENABLE([grub-emu-sdl2], + [AS_HELP_STRING([--enable-grub-emu-sdl2], + [build and install the `grub-emu' debugging utility with SDL2 support (default=guessed)])]) AC_ARG_ENABLE([grub-emu-sdl], [AS_HELP_STRING([--enable-grub-emu-sdl], @@ -787,106 +1670,86 @@ AC_ARG_ENABLE([grub-emu-pci], [build and install the `grub-emu' debugging utility with PCI support (potentially dangerous) (default=no)])]) if test "$platform" = emu; then - missing_ncurses= -[# Check for curses libraries.] - AC_CHECK_LIB([ncurses], [wgetch], [LIBCURSES="-lncurses"], - [AC_CHECK_LIB([curses], [wgetch], [LIBCURSES="-lcurses"], - [missing_ncurses=[true]])]) - AC_SUBST([LIBCURSES]) -[if [ x"$missing_ncurses" = x ]; then ] - [# Check for headers.] - AC_CHECK_HEADERS([ncurses/curses.h], [], - [AC_CHECK_HEADERS([ncurses.h], [], - [AC_CHECK_HEADERS([curses.h], [], - [missing_ncurses=[true]])])]) -[fi] -if test x"$missing_ncurses" = xtrue ; then - AC_MSG_ERROR([grub-emu can't be compiled without ncurses]) -fi + if test x"$enable_grub_emu_sdl2" = xno ; then + grub_emu_sdl2_excuse="explicitly disabled" + fi + [if [ x"$grub_emu_sdl2_excuse" = x ]; then + # Check for libSDL libraries.] + PKG_CHECK_MODULES([SDL2], [sdl2], [ + AC_DEFINE([HAVE_SDL2], [1], [Define to 1 if you have SDL2 library.]) + AC_SUBST(HAVE_SDL2)], + [grub_emu_sdl2_excuse="libSDL2 libraries are required to build \`grub-emu' with SDL2 support"]) + [fi] + if test x"$enable_grub_emu_sdl2" = xyes && test x"$grub_emu_sdl2_excuse" != x ; then + AC_MSG_ERROR([SDL2 support for grub-emu was explicitly requested but can't be compiled ($grub_emu_sdl2_excuse)]) + fi + if test x"$grub_emu_sdl2_excuse" = x ; then + enable_grub_emu_sdl2=yes + else + enable_grub_emu_sdl2=no + fi + if test x"$enable_grub_emu_sdl2" = xyes ; then + grub_emu_sdl_excuse="disabled by sdl2" + fi -if test x"$enable_grub_emu_usb" != xyes ; then - grub_emu_usb_excuse="not enabled" -fi -if test x"$enable_grub_emu_pci" = xyes ; then - grub_emu_usb_excuse="conflicts with PCI support" -fi - -[if [ x"$grub_emu_usb_excuse" = x ]; then - # Check for libusb libraries.] -AC_CHECK_LIB([usb], [usb_claim_interface], [LIBUSB="-lusb"], - [grub_emu_usb_excuse=["need libusb library"]]) - AC_SUBST([LIBUSB]) -[fi] -[if [ x"$grub_emu_usb_excuse" = x ]; then - # Check for headers.] - AC_CHECK_HEADERS([usb.h], [], - [grub_emu_usb_excuse=["need libusb headers"]]) -[fi] -if test x"$enable_grub_emu_usb" = xyes && test x"$grub_emu_usb_excuse" != x ; then - AC_MSG_ERROR([USB support for grub-emu was explicitly requested but can't be compiled]) -fi -if test x"$grub_emu_usb_excuse" = x ; then -enable_grub_emu_usb=yes -else -enable_grub_emu_usb=no -fi - -if test x"$enable_grub_emu_sdl" = xno ; then - grub_emu_sdl_excuse="explicitely disabled" -fi -[if [ x"$grub_emu_sdl_excuse" = x ]; then + if test x"$enable_grub_emu_sdl" = xno ; then + grub_emu_sdl_excuse="explicitly disabled" + fi + [if [ x"$grub_emu_sdl_excuse" = x ]; then # Check for libSDL libraries.] AC_CHECK_LIB([SDL], [SDL_Init], [LIBSDL="-lSDL"], [grub_emu_sdl_excuse=["libSDL libraries are required to build \`grub-emu' with SDL support"]]) AC_SUBST([LIBSDL]) -[fi] + [fi] -[if [ x"$grub_emu_sdl_excuse" = x ]; then + [if [ x"$grub_emu_sdl_excuse" = x ]; then # Check for headers.] AC_CHECK_HEADERS([SDL/SDL.h], [], [grub_emu_sdl_excuse=["libSDL header file is required to build \`grub-emu' with SDL support"]]) -[fi] + [fi] -if test x"enable_grub_emu_sdl" = xyes && test x"$grub_emu_sdl_excuse" != x ; then - AC_MSG_ERROR([SDL support for grub-emu was explicitely requested but can't be compiled]) -fi -if test x"$grub_emu_sdl_excuse" = x ; then -enable_grub_emu_sdl=yes -else -enable_grub_emu_sdl=no -fi + if test x"$enable_grub_emu_sdl" = xyes && test x"$grub_emu_sdl_excuse" != x ; then + AC_MSG_ERROR([SDL support for grub-emu was explicitly requested but can't be compiled ($grub_emu_sdl_excuse)]) + fi + if test x"$grub_emu_sdl_excuse" = x ; then + enable_grub_emu_sdl=yes + else + enable_grub_emu_sdl=no + fi -if test x"$enable_grub_emu_pci" != xyes ; then - grub_emu_pci_excuse="not enabled" -fi + if test x"$enable_grub_emu_pci" != xyes ; then + grub_emu_pci_excuse="not enabled" + fi -if test x"$enable_grub_emu_usb" = xyes ; then - grub_emu_pci_excuse="conflicts with USB support" -fi - -[if [ x"$grub_emu_pci_excuse" = x ]; then - # Check for libpci libraries.] - AC_CHECK_LIB([pciaccess], [pci_system_init], [LIBPCIACCESS="-lpciaccess"], + [if [ x"$grub_emu_pci_excuse" = x ]; then + # Check for libpci libraries.] + AC_CHECK_LIB([pciaccess], [pci_system_init], [LIBPCIACCESS="-lpciaccess"], [grub_emu_pci_excuse=["need libpciaccess library"]]) AC_SUBST([LIBPCIACCESS]) -[fi] -[if [ x"$grub_emu_pci_excuse" = x ]; then + [fi] + [if [ x"$grub_emu_pci_excuse" = x ]; then # Check for headers.] - AC_CHECK_HEADERS([pci/pci.h], [], + AC_CHECK_HEADERS([pciaccess.h], [], [grub_emu_pci_excuse=["need libpciaccess headers"]]) -[fi] + [fi] + + if test x"$grub_emu_pci_excuse" = x ; then + enable_grub_emu_pci=yes + else + enable_grub_emu_pci=no + fi + + AC_SUBST([enable_grub_emu_sdl2]) + AC_SUBST([enable_grub_emu_sdl]) + AC_SUBST([enable_grub_emu_pci]) -if test x"$grub_emu_pci_excuse" = x ; then -enable_grub_emu_pci=yes else -enable_grub_emu_pci=no -fi - -AC_SUBST([enable_grub_emu_sdl]) -AC_SUBST([enable_grub_emu_usb]) -AC_SUBST([enable_grub_emu_pci]) + # Ignore --enable-emu-* if platform is not emu + enable_grub_emu_sdl2=no + enable_grub_emu_sdl=no + enable_grub_emu_pci=no fi AC_ARG_ENABLE([grub-mkfont], @@ -896,65 +1759,195 @@ if test x"$enable_grub_mkfont" = xno ; then grub_mkfont_excuse="explicitly disabled" fi +unset ac_cv_header_ft2build_h + if test x"$grub_mkfont_excuse" = x ; then # Check for freetype libraries. - AC_CHECK_PROGS([FREETYPE], [freetype-config]) - if test "x$FREETYPE" = x ; then - grub_mkfont_excuse=["need freetype2 library"] + PKG_CHECK_MODULES([FREETYPE], [freetype2], [ + SAVED_CPPFLAGS="$CPPFLAGS" + SAVED_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $FREETYPE_CFLAGS" + LIBS="$LIBS $FREETYPE_LIBS" + AC_CHECK_HEADERS([ft2build.h], [], + [grub_mkfont_excuse=["need freetype2 headers"]]) + AC_LINK_IFELSE([AC_LANG_CALL([], [FT_Load_Glyph])], [], + [grub_mkfont_excuse=["freetype2 library unusable"]]) + CPPFLAGS="$SAVED_CPPFLAGS" + LIBS="$SAVED_LIBS" + ], [grub_mkfont_excuse=["need freetype2 library"]]) + if test x"$grub_mkfont_excuse" = x && test x"$host_kernel" = xnetbsd ; then + FREETYPE_LIBS="$FREETYPE_LIBS -Wl,-R,/usr/pkg/lib" ; fi fi -if test x"$grub_mkfont_excuse" = x ; then - # Check for freetype libraries. - freetype_cflags=`freetype-config --cflags` - freetype_libs=`freetype-config --libs` - SAVED_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $freetype_cflags" - AC_CHECK_HEADERS([ft2build.h], [], - [grub_mkfont_excuse=["need freetype2 headers"]]) - CPPFLAGS="$SAVED_CPPFLAGS" -fi - if test x"$enable_grub_mkfont" = xyes && test x"$grub_mkfont_excuse" != x ; then - AC_MSG_ERROR([grub-mkfont was explicitly requested but can't be compiled]) + AC_MSG_ERROR([grub-mkfont was explicitly requested but can't be compiled ($grub_mkfont_excuse)]) fi if test x"$grub_mkfont_excuse" = x ; then -enable_grub_mkfont=yes + enable_grub_mkfont=yes else -enable_grub_mkfont=no -fi -if test x"$enable_grub_mkfont" = xno && test "x$platform" = xloongson; then - AC_MSG_ERROR([loongson port needs grub-mkfont]) + enable_grub_mkfont=no fi AC_SUBST([enable_grub_mkfont]) -AC_SUBST([freetype_cflags]) -AC_SUBST([freetype_libs]) -DJVU_FONT_SOURCE= +SAVED_CC="$CC" +SAVED_CPP="$CPP" +SAVED_CFLAGS="$CFLAGS" +SAVED_CPPFLAGS="$CPPFLAGS" +SAVED_LDFLAGS="$LDFLAGS" +CC="$BUILD_CC" +CPP="$BUILD_CPP" +CFLAGS="$BUILD_CFLAGS" +CPPFLAGS="$BUILD_CPPFLAGS" +LDFLAGS="$BUILD_LDFLAGS" + +unset ac_cv_c_bigendian +unset ac_cv_header_ft2build_h + +AC_COMPUTE_INT([BUILD_SIZEOF_VOID_P], [sizeof (void *)]) +AC_COMPUTE_INT([BUILD_SIZEOF_LONG], [sizeof (long)]) +AC_C_BIGENDIAN([BUILD_WORDS_BIGENDIAN=1], [BUILD_WORDS_BIGENDIAN=0], [BUILD_WORDS_BIGENDIAN=err], [BUILD_WORDS_BIGENDIAN=err]) + +if test x$BUILD_WORDS_BIGENDIAN = xerr ; then + AC_MSG_ERROR([couldnt determine build endianness]) +fi + +AC_SUBST([BUILD_SIZEOF_LONG]) +AC_SUBST([BUILD_SIZEOF_VOID_P]) +AC_SUBST([BUILD_WORDS_BIGENDIAN]) + +if test x"$grub_build_mkfont_excuse" = x ; then + # Check for freetype libraries. + SAVED_PKG_CONFIG="$PKG_CONFIG" + test -z "$BUILD_PKG_CONFIG" || PKG_CONFIG="$BUILD_PKG_CONFIG" + PKG_CHECK_MODULES([BUILD_FREETYPE], [freetype2], [ + SAVED_CPPFLAGS_2="$CPPFLAGS" + SAVED_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $BUILD_FREETYPE_CFLAGS" + LIBS="$LIBS $BUILD_FREETYPE_LIBS" + AC_CHECK_HEADERS([ft2build.h], [], + [grub_build_mkfont_excuse=["need freetype2 headers"]]) + AC_LINK_IFELSE([AC_LANG_CALL([], [FT_Load_Glyph])], [], + [grub_build_mkfont_excuse=["freetype2 library unusable"]]) + LIBS="$SAVED_LIBS" + CPPFLAGS="$SAVED_CPPFLAGS_2" + ], [grub_build_mkfont_excuse=["need freetype2 library"]]) + if test x"$grub_build_mkfont_excuse" = x ; then + case x"$build_os" in + xnetbsd*) BUILD_FREETYPE_LIBS="$BUILD_FREETYPE_LIBS -Wl,-R,/usr/pkg/lib" ;; + esac + fi + PKG_CONFIG="$SAVED_PKG_CONFIG" +fi + +if test x"$enable_build_grub_mkfont" = xyes && test x"$grub_build_mkfont_excuse" != x ; then + AC_MSG_ERROR([build-grub-mkfont was explicitly requested but can't be compiled ($grub_build_mkfont_excuse)]) +fi +if test x"$grub_build_mkfont_excuse" = x ; then + enable_build_grub_mkfont=yes +else + enable_build_grub_mkfont=no +fi +if test x"$enable_build_grub_mkfont" = xno && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$platform" = xcoreboot ); then + if test x"$grub_build_mkfont_excuse" = x ; then + AC_MSG_ERROR([qemu, coreboot and loongson ports need build-time grub-mkfont]) + else + AC_MSG_ERROR([qemu, coreboot and loongson ports need build-time grub-mkfont ($grub_build_mkfont_excuse)]) + fi +fi + +CC="$SAVED_CC" +CPP="$SAVED_CPP" +CFLAGS="$SAVED_CFLAGS" +CPPFLAGS="$SAVED_CPPFLAGS" +LDFLAGS="$SAVED_LDFLAGS" + starfield_excuse= -if test x$enable_grub_mkfont = xno; then - starfield_excuse="No grub-mkfont" +AC_ARG_ENABLE([grub-themes], + [AS_HELP_STRING([--enable-grub-themes], + [build and install GRUB themes (default=guessed)])]) +if test x"$enable_grub_themes" = xno ; then + starfield_excuse="explicitly disabled" fi -if test x"$starfield_excuse" = x; then - for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do - for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu; do - if test -f "$dir/DejaVuSans.$ext"; then - DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext" - break 2 - fi - done - done +if test x"$starfield_excuse" = x && test x"$enable_build_grub_mkfont" = xno ; then + starfield_excuse="No build-time grub-mkfont" +fi - if test "x$DJVU_FONT_SOURCE" = x; then - starfield_excuse="No DejaVu found" - fi +AC_ARG_WITH([dejavufont], + AS_HELP_STRING([--with-dejavufont=FILE], + [set the DejeVu source [[guessed]]])) + +if test "x$with_dejavufont" = x; then + # search in well-known directories + if test x"$starfield_excuse" = x; then + for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do + for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/truetype/ttf-dejavu /usr/share/fonts/dejavu /usr/share/fonts/truetype /usr/pkg/share/fonts/X11/TTF /usr/local/share/fonts/dejavu /usr/X11R6/lib/X11/fonts/TTF /usr/share/fonts/dejavu-sans-fonts /usr/share/fonts/truetype/dejavu; do + if test -f "$dir/DejaVuSans.$ext"; then + DJVU_FONT_SOURCE="$dir/DejaVuSans.$ext" + break 2 + fi + done + done + + if test "x$DJVU_FONT_SOURCE" = x; then + starfield_excuse="No DejaVu found" + fi + fi +else + DJVU_FONT_SOURCE="$with_dejavufont" +fi + +if test x"$enable_grub_themes" = xyes && test x"$starfield_excuse" != x; then + AC_MSG_ERROR([themes were explicitly requested but requirements are not satisfied ($starfield_excuse)]) fi AC_SUBST([DJVU_FONT_SOURCE]) +AC_ARG_WITH([unifont], + AS_HELP_STRING([--with-unifont=FILE], + [set the unifont source [[guessed]]])) + +if test "x$with_unifont" = x; then + # search in well-known directories + for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz otf otf.gz; do + for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/unifont /usr/share/fonts/uni /usr/share/fonts/truetype/unifont /usr/share/fonts/misc /usr/pkg/share/fonts/X11/misc /usr/local/share/fonts/gnu-unifont /usr/local/share/fonts/unifont; do + if test -f "$dir/unifont.$ext"; then + md5="$(md5sum "$dir/unifont.$ext"|awk '{ print $1; }')" + # PCF and BDF from version 6.3 isn't hanled properly by libfreetype. + if test "$md5" = 0a54834d2788c83886a3e1785a6a1e61 || test "$md5" = 28f2565c7a41d8d407e2551159385edb || test "$md5" = dae5e588461b3b92b87b6ffee734f936 || test "$md5" = 4a3d687aa5bb329ed05f4263a1016791 ; then + continue + fi + FONT_SOURCE="$dir/unifont.$ext" + break 2 + fi + done + done +else + FONT_SOURCE="$with_unifont" +fi + +if test x"$enable_build_grub_mkfont" = xno ; then + FONT_SOURCE= +fi + +if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson || test "x$platform" = xqemu_mips || test "x$platform" = xcoreboot ); then + if test x"$grub_build_mkfont_excuse" = x ; then + AC_MSG_ERROR([qemu, coreboot and loongson ports need unifont]) + else + AC_MSG_ERROR([qemu, coreboot and loongson ports need unifont ($grub_build_mkfont_excuse)]) + fi +fi + +AC_SUBST([FONT_SOURCE]) + +if test x"$FONT_SOURCE" = x && test x"$DJVU_FONT_SOURCE" = x && test x"$grub_build_mkfont_excuse" = x; then + grub_build_mkfont_excuse="no fonts" +fi + + AC_ARG_ENABLE([grub-mount], [AS_HELP_STRING([--enable-grub-mount], [build and install the `grub-mount' utility (default=guessed)])]) @@ -963,21 +1956,15 @@ if test x"$enable_grub_mount" = xno ; then fi if test x"$grub_mount_excuse" = x ; then - AC_CHECK_LIB([fuse], [fuse_main_real], [], - [grub_mount_excuse="need FUSE library"]) -fi - -if test x"$grub_mount_excuse" = x ; then - # Check for fuse headers. - SAVED_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=26" - AC_CHECK_HEADERS([fuse/fuse.h], [], - [grub_mount_excuse=["need FUSE headers"]]) - CPPFLAGS="$SAVED_CPPFLAGS" + PKG_CHECK_MODULES([FUSE], [fuse3], [FUSE_CFLAGS="$FUSE_CFLAGS -DFUSE_USE_VERSION=32"], [ + PKG_CHECK_MODULES([FUSE], [fuse], [FUSE_CFLAGS="$FUSE_CFLAGS -DFUSE_USE_VERSION=26"], [ + grub_mount_excuse="need fuse or fuse3 libraries" + ]) + ]) fi if test x"$enable_grub_mount" = xyes && test x"$grub_mount_excuse" != x ; then - AC_MSG_ERROR([grub-mount was explicitly requested but can't be compiled]) + AC_MSG_ERROR([grub-mount was explicitly requested but can't be compiled ($grub_mount_excuse)]) fi if test x"$grub_mount_excuse" = x ; then enable_grub_mount=yes @@ -1013,7 +2000,7 @@ if test x"$device_mapper_excuse" = x ; then fi if test x"$device_mapper_excuse" = x ; then - LIBDEVMAPPER="-ldevmapper"; + LIBDEVMAPPER="-ldevmapper" AC_DEFINE([HAVE_DEVICE_MAPPER], [1], [Define to 1 if you have the devmapper library.]) fi @@ -1029,10 +2016,32 @@ fi AC_SUBST([LIBGEOM]) +AC_ARG_ENABLE([liblzma], + [AS_HELP_STRING([--enable-liblzma], + [enable liblzma integration (default=guessed)])]) +if test x"$enable_liblzma" = xno ; then + liblzma_excuse="explicitly disabled" +fi + +if test x"$liblzma_excuse" = x ; then AC_CHECK_LIB([lzma], [lzma_code], - [LIBLZMA="-llzma" - AC_DEFINE([HAVE_LIBLZMA], [1], - [Define to 1 if you have the LZMA library.])],) + [],[liblzma_excuse="need lzma library"]) +fi +if test x"$liblzma_excuse" = x ; then +AC_CHECK_HEADER([lzma.h], [], [liblzma_excuse="need lzma header"]) +fi + +if test x"$enable_liblzma" = xyes && test x"$liblzma_excuse" != x ; then + AC_MSG_ERROR([liblzma support was explicitly requested but requirements are not satisfied ($liblzma_excuse)]) +fi + + +if test x"$liblzma_excuse" = x ; then + LIBLZMA="-llzma" + AC_DEFINE([USE_LIBLZMA], [1], + [Define to 1 if you have the LZMA library.]) +fi + AC_SUBST([LIBLZMA]) AC_ARG_ENABLE([libzfs], @@ -1054,67 +2063,161 @@ if test x"$libzfs_excuse" = x ; then fi if test x"$libzfs_excuse" = x ; then - AC_CHECK_LIB([nvpair], [nvlist_print], - [], - [libzfs_excuse="need nvpair library"]) + AC_CHECK_LIB([nvpair], [nvlist_lookup_string], + [have_normal_nvpair=yes], + [have_normal_nvpair=no]) + if test x"$have_normal_nvpair" = xno ; then + AC_CHECK_LIB([nvpair], [opensolaris_nvlist_lookup_string], + [have_prefixed_nvpair=yes], + [have_prefixed_nvpair=no]) + if test x"$have_prefixed_nvpair" = xyes ; then + AC_DEFINE([GRUB_UTIL_NVPAIR_IS_PREFIXED], [1], + [Define to 1 if libnvpair symbols are prefixed with opensolaris_.]) + else + libzfs_excuse="need nvpair library" + fi + fi fi if test x"$enable_libzfs" = xyes && test x"$libzfs_excuse" != x ; then - AC_MSG_ERROR([libzfs support was explicitly requested but requirements are not satisfied]) + AC_MSG_ERROR([libzfs support was explicitly requested but requirements are not satisfied ($libzfs_excuse)]) fi if test x"$libzfs_excuse" = x ; then # We need both libzfs and libnvpair for a successful build. LIBZFS="-lzfs" - AC_DEFINE([HAVE_LIBZFS], [1], - [Define to 1 if you have the ZFS library.]) LIBNVPAIR="-lnvpair" - AC_DEFINE([HAVE_LIBNVPAIR], [1], - [Define to 1 if you have the NVPAIR library.]) + AC_DEFINE([USE_LIBZFS], [1], + [Define to 1 if ZFS library should be used.]) fi AC_SUBST([LIBZFS]) AC_SUBST([LIBNVPAIR]) +AC_ARG_ENABLE([grub-protect], + [AS_HELP_STRING([--enable-grub-protect], + [build and install the `grub-protect' utility (default=guessed)])]) +if test x"$enable_grub_protect" = xno ; then + grub_protect_excuse="explicitly disabled" +fi + +LIBTASN1= +if test x"$grub_protect_excuse" = x ; then + AC_CHECK_LIB([tasn1], [asn1_write_value], [LIBTASN1="-ltasn1"], [grub_protect_excuse="need libtasn1 library"]) +fi +AC_SUBST([LIBTASN1]) + +if test x"$enable_grub_protect" = xyes && test x"$grub_protect_excuse" != x ; then + AC_MSG_ERROR([grub-protect was explicitly requested but can't be compiled ($grub_protect_excuse)]) +fi +if test x"$grub_protect_excuse" = x ; then +enable_grub_protect=yes +else +enable_grub_protect=no +fi +AC_SUBST([enable_grub_protect]) + LIBS="" AC_SUBST([FONT_SOURCE]) AS_IF([test x$target_cpu = xi386 -a x$platform = xqemu], [AC_SUBST([GRUB_BOOT_MACHINE_LINK_ADDR], 0xffe00)]) -AS_IF([test x$TARGET_APPLE_CC = x1], - [AC_SUBST([USE_APPLE_CC_FIXES], yes)]) AC_SUBST(HAVE_ASM_USCORE) -AC_SUBST(ADDR32) -AC_SUBST(DATA32) AC_SUBST(BSS_START_SYMBOL) AC_SUBST(END_SYMBOL) AC_SUBST(PACKAGE) AC_SUBST(VERSION) -AC_SUBST(NEED_ENABLE_EXECUTE_STACK) -AC_SUBST(NEED_REGISTER_FRAME_INFO) + +AC_ARG_ENABLE([werror], + [AS_HELP_STRING([--disable-werror], + [do not use -Werror when building GRUB])]) +if test x"$enable_werror" != xno ; then + TARGET_CFLAGS="$TARGET_CFLAGS -Werror" + HOST_CFLAGS="$HOST_CFLAGS -Werror" + if test "x$grub_cv_cc_target_clang" = xyes; then + TARGET_CFLAGS="$TARGET_CFLAGS -Wno-error=vla" + HOST_CFLAGS="$HOST_CFLAGS -Wno-error=vla" + fi +fi + +TARGET_CPP="$TARGET_CC -E" +TARGET_CCAS=$TARGET_CC + +# Includes which include make-time substitutions. They must come last +# as to avoid executing top_builddir in shell. +HOST_CPPFLAGS="$HOST_CPPFLAGS -I\$(top_builddir)/include" +TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_srcdir)/include" +TARGET_CPPFLAGS="$TARGET_CPPFLAGS -I\$(top_builddir)/include" + +GRUB_TARGET_CPU="${target_cpu}" +GRUB_PLATFORM="${platform}" + +AC_SUBST(GRUB_TARGET_CPU) +AC_SUBST(GRUB_PLATFORM) + +AC_SUBST(TARGET_OBJCONV) +AC_SUBST(TARGET_CPP) +AC_SUBST(TARGET_CCAS) +AC_SUBST(TARGET_OBJ2ELF) +AC_SUBST(TARGET_MODULE_FORMAT) +AC_SUBST(TARGET_CC_VERSION) + +AC_SUBST(TARGET_CFLAGS) +AC_SUBST(TARGET_LDFLAGS) +AC_SUBST(TARGET_CPPFLAGS) +AC_SUBST(TARGET_CCASFLAGS) + +AC_SUBST(TARGET_IMG_LDFLAGS) +AC_SUBST(TARGET_IMG_CFLAGS) +AC_SUBST(TARGET_IMG_BASE_LDOPT) +AC_SUBST(TARGET_APPLE_LINKER) + +AC_SUBST(HOST_CFLAGS) +AC_SUBST(HOST_LDFLAGS) +AC_SUBST(HOST_CPPFLAGS) +AC_SUBST(HOST_CCASFLAGS) + +AC_SUBST(BUILD_LIBM) # # Automake conditionals # +AM_CONDITIONAL([COND_real_platform], [test x$platform != xnone]) AM_CONDITIONAL([COND_emu], [test x$platform = xemu]) +AM_CONDITIONAL([COND_arm], [test x$target_cpu = xarm ]) +AM_CONDITIONAL([COND_arm_uboot], [test x$target_cpu = xarm -a x$platform = xuboot]) +AM_CONDITIONAL([COND_arm_coreboot], [test x$target_cpu = xarm -a x$platform = xcoreboot]) +AM_CONDITIONAL([COND_arm_efi], [test x$target_cpu = xarm -a x$platform = xefi]) +AM_CONDITIONAL([COND_arm64], [test x$target_cpu = xarm64 ]) +AM_CONDITIONAL([COND_arm64_efi], [test x$target_cpu = xarm64 -a x$platform = xefi]) +AM_CONDITIONAL([COND_ia64_efi], [test x$target_cpu = xia64 -a x$platform = xefi]) AM_CONDITIONAL([COND_i386_pc], [test x$target_cpu = xi386 -a x$platform = xpc]) AM_CONDITIONAL([COND_i386_efi], [test x$target_cpu = xi386 -a x$platform = xefi]) -AM_CONDITIONAL([COND_ia64_efi], [test x$target_cpu = xia64 -a x$platform = xefi]) AM_CONDITIONAL([COND_i386_qemu], [test x$target_cpu = xi386 -a x$platform = xqemu]) AM_CONDITIONAL([COND_i386_ieee1275], [test x$target_cpu = xi386 -a x$platform = xieee1275]) AM_CONDITIONAL([COND_i386_coreboot], [test x$target_cpu = xi386 -a x$platform = xcoreboot]) AM_CONDITIONAL([COND_i386_multiboot], [test x$target_cpu = xi386 -a x$platform = xmultiboot]) -AM_CONDITIONAL([COND_x86_64_efi], [test x$target_cpu = xx86_64 -a x$platform = xefi]) +AM_CONDITIONAL([COND_i386_xen], [test x$target_cpu = xi386 -a x$platform = xxen]) +AM_CONDITIONAL([COND_i386_xen_pvh], [test x$target_cpu = xi386 -a x$platform = xxen_pvh]) +AM_CONDITIONAL([COND_loongarch64], [test x$target_cpu = xloongarch64]) +AM_CONDITIONAL([COND_loongarch64_efi], [test x$target_cpu = xloongarch64 -a x$platform = xefi]) +AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips -o x$target_cpu = xmipsel]) +AM_CONDITIONAL([COND_mips_arc], [test "(" x$target_cpu = xmips -o x$target_cpu = xmipsel ")" -a x$platform = xarc]) AM_CONDITIONAL([COND_mips_loongson], [test x$target_cpu = xmipsel -a x$platform = xloongson]) AM_CONDITIONAL([COND_mips_qemu_mips], [test "(" x$target_cpu = xmips -o x$target_cpu = xmipsel ")" -a x$platform = xqemu_mips]) -AM_CONDITIONAL([COND_mips_arc], [test x$target_cpu = xmips -a x$platform = xarc]) -AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) -AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) -AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips -o x$target_cpu = xmipsel]) AM_CONDITIONAL([COND_mipsel], [test x$target_cpu = xmipsel]) AM_CONDITIONAL([COND_mipseb], [test x$target_cpu = xmips]) +AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) +AM_CONDITIONAL([COND_riscv32], [test x$target_cpu = xriscv32 ]) +AM_CONDITIONAL([COND_riscv64], [test x$target_cpu = xriscv64 ]) +AM_CONDITIONAL([COND_riscv32_efi], [test x$target_cpu = xriscv32 -a x$platform = xefi]) +AM_CONDITIONAL([COND_riscv64_efi], [test x$target_cpu = xriscv64 -a x$platform = xefi]) +AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) +AM_CONDITIONAL([COND_sparc64_emu], [test x$target_cpu = xsparc64 -a x$platform = xemu]) +AM_CONDITIONAL([COND_x86_64_efi], [test x$target_cpu = xx86_64 -a x$platform = xefi]) +AM_CONDITIONAL([COND_x86_64_xen], [test x$target_cpu = xx86_64 -a x$platform = xxen]) AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd]) AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) @@ -1125,45 +2228,74 @@ AM_CONDITIONAL([COND_HOST_XNU], [test x$host_kernel = xxnu]) AM_CONDITIONAL([COND_HOST_ILLUMOS], [test x$host_kernel = xillumos]) AM_CONDITIONAL([COND_MAN_PAGES], [test x$cross_compiling = xno -a x$HELP2MAN != x]) -AM_CONDITIONAL([COND_GRUB_EMU_USB], [test x$enable_grub_emu_usb = xyes]) +AM_CONDITIONAL([COND_GRUB_EMU_SDL2], [test x$enable_grub_emu_sdl2 = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes]) AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes]) AM_CONDITIONAL([COND_GRUB_MOUNT], [test x$enable_grub_mount = xyes]) +AM_CONDITIONAL([COND_GRUB_PROTECT], [test x$enable_grub_protect = xyes]) AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) -AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) -AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) +if test x$FONT_SOURCE != x ; then + HAVE_FONT_SOURCE=1 +else + HAVE_FONT_SOURCE=0 +fi +AC_SUBST(HAVE_FONT_SOURCE) +AM_CONDITIONAL([COND_APPLE_LINKER], [test x$TARGET_APPLE_LINKER = x1]) AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes]) AM_CONDITIONAL([COND_ENABLE_CACHE_STATS], [test x$DISK_CACHE_STATS = x1]) +AM_CONDITIONAL([COND_ENABLE_BOOT_TIME_STATS], [test x$BOOT_TIME_STATS = x1]) + +AM_CONDITIONAL([COND_HAVE_CXX], [test x$HAVE_CXX = xyes]) AM_CONDITIONAL([COND_HAVE_ASM_USCORE], [test x$HAVE_ASM_USCORE = x1]) -AM_CONDITIONAL([COND_CYGWIN], [test x$host_os = xcygwin]) AM_CONDITIONAL([COND_STARFIELD], [test "x$starfield_excuse" = x]) +AM_CONDITIONAL([COND_HAVE_EXEC], [test "x$have_exec" = xy]) +AM_CONDITIONAL([COND_HAVE_PCI], [test "x$have_pci" = xy]) + +test "x$prefix" = xNONE && prefix="$ac_default_prefix" +test "x$exec_prefix" = xNONE && exec_prefix="${prefix}" +datarootdir="$(eval echo "$datarootdir")" +grub_libdir="$(eval echo "$libdir")" +grub_localedir="$(eval echo "$localedir")" +grub_datadir="$(eval echo "$datadir")" +grub_sysconfdir="$(eval echo "$sysconfdir")" +AC_DEFINE_UNQUOTED(LOCALEDIR, "$grub_localedir", [Locale dir]) +AC_DEFINE_UNQUOTED(GRUB_LIBDIR, "$grub_libdir", [Library dir]) +AC_DEFINE_UNQUOTED(GRUB_DATADIR, "$grub_datadir", [Data dir]) +AC_DEFINE_UNQUOTED(GRUB_SYSCONFDIR, "$grub_sysconfdir", [Configuration dir]) + # Output files. -cpudir="${target_cpu}" -if test x${cpudir} = xmipsel; then - cpudir=mips; -fi -grub_CHECK_LINK_DIR -if test x"$link_dir" = xyes ; then - AC_CONFIG_LINKS([include/grub/cpu:include/grub/$cpudir]) - if test "$platform" != emu ; then - AC_CONFIG_LINKS([include/grub/machine:include/grub/$cpudir/$platform]) +if test "$platform" != none; then + cpudir="${target_cpu}" + if test x${cpudir} = xmipsel; then + cpudir=mips; + fi + grub_CHECK_LINK_DIR + if test x"$link_dir" = xyes ; then + AC_CONFIG_LINKS([include/grub/cpu:include/grub/$cpudir]) + if test "$platform" != emu ; then + AC_CONFIG_LINKS([include/grub/machine:include/grub/$cpudir/$platform]) + fi + else + mkdir -p include/grub 2>/dev/null + rm -rf include/grub/cpu + cp -rp $srcdir/include/grub/$cpudir include/grub/cpu 2>/dev/null + if test "$platform" != emu ; then + rm -rf include/grub/machine + cp -rp $srcdir/include/grub/$cpudir/$platform include/grub/machine 2>/dev/null + fi fi else - mkdir -p include/grub 2>/dev/null - rm -rf include/grub/cpu - cp -rp $srcdir/include/grub/$cpudir include/grub/cpu 2>/dev/null - if test "$platform" != emu ; then - rm -rf include/grub/machine - cp -rp $srcdir/include/grub/$cpudir/$platform include/grub/machine 2>/dev/null - fi + # Just enough to stop the compiler failing with -I$(srcdir)/include. + mkdir -p include 2>/dev/null + rm -rf include/grub/cpu include/grub/machine fi AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([grub-core/Makefile]) -AC_CONFIG_FILES([grub-core/gnulib/Makefile]) +AC_CONFIG_FILES([grub-core/lib/gnulib/Makefile]) AC_CONFIG_FILES([po/Makefile.in]) AC_CONFIG_FILES([docs/Makefile]) AC_CONFIG_FILES([util/bash-completion.d/Makefile]) @@ -1176,10 +2308,10 @@ echo "*******************************************************" echo GRUB2 will be compiled with following components: echo Platform: "$target_cpu"-"$platform" if [ x"$platform" = xemu ]; then -if [ x"$grub_emu_usb_excuse" = x ]; then -echo USB support for grub-emu: Yes +if [ x"$grub_emu_sdl2_excuse" = x ]; then +echo SDL2 support for grub-emu: Yes else -echo USB support for grub-emu: No "($grub_emu_usb_excuse)" +echo SDL2 support for grub-emu: No "($grub_emu_sdl2_excuse)" fi if [ x"$grub_emu_sdl_excuse" = x ]; then echo SDL support for grub-emu: Yes @@ -1207,6 +2339,13 @@ echo With disk cache statistics: Yes else echo With disk cache statistics: No fi + +if [ x"$enable_boot_time" = xyes ]; then +echo With boot time statistics: Yes +else +echo With boot time statistics: No +fi + if [ x"$efiemu_excuse" = x ]; then echo efiemu runtime: Yes else @@ -1222,8 +2361,14 @@ echo grub-mount: Yes else echo grub-mount: No "($grub_mount_excuse)" fi +if [ x"$grub_protect_excuse" = x ]; then +echo grub-protect: Yes +else +echo grub-protect: No "($grub_protect_excuse)" +fi if [ x"$starfield_excuse" = x ]; then echo starfield theme: Yes +echo With DejaVuSans font from $DJVU_FONT_SOURCE else echo starfield theme: No "($starfield_excuse)" fi @@ -1232,5 +2377,26 @@ echo With libzfs support: Yes else echo With libzfs support: No "($libzfs_excuse)" fi +if [ x"$grub_build_mkfont_excuse" = x ]; then + echo Build-time grub-mkfont: Yes + if test "x$FONT_SOURCE" = x ; then + echo "Without unifont" + else + echo "With unifont from $FONT_SOURCE" + fi +else + echo Build-time grub-mkfont: No "($grub_build_mkfont_excuse)" + echo "Without unifont (no build-time grub-mkfont)" +fi +if test x"$liblzma_excuse" != x ; then +echo "Without liblzma (no support for XZ-compressed mips images) ($liblzma_excuse)" +else +echo "With liblzma from $LIBLZMA (support for XZ-compressed mips images)" +fi +if test "x$enable_stack_protector" != xno; then +echo "With stack smashing protector: Yes" +else +echo "With stack smashing protector: No" +fi echo "*******************************************************" ] diff --git a/coreboot.cfg b/coreboot.cfg new file mode 100644 index 000000000..188090d3a --- /dev/null +++ b/coreboot.cfg @@ -0,0 +1,3 @@ +if test -f (cbfsdisk)/etc/grub.cfg; then + source (cbfsdisk)/etc/grub.cfg +fi diff --git a/docs/autoiso.cfg b/docs/autoiso.cfg new file mode 100644 index 000000000..9ce51c692 --- /dev/null +++ b/docs/autoiso.cfg @@ -0,0 +1,244 @@ +# Sample GRUB script to autodetect operating systems +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB 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 GRUB. If not, see . + +function pathname { regexp -s 2:"$2" '^(\(.*\))?(/.*)$' "$1"; } +function devname { regexp -s "$2" '^(\(.*\)).*$' "$1"; } + +function loopback_iso_entry { + realdev="$1" + isopath="$2" + loopdev="$3" + + if test -f /boot/grub/loopback.cfg; then + cfgpath=/boot/grub/loopback.cfg + elif test -f /grub/loopback.cfg; then + cfgpath=/grub/loopback.cfg + else + return 1; + fi + + echo loopback.cfg $isopath: yes + menuentry "Boot GRUB Loopback Config from ${realdev}${isopath}" "$realdev" "$isopath" "$cfgpath" { + set device="$2" + set iso_path="$3" + set cfg_path="$4" + + export iso_path + loopback loopdev_cfg "${device}${iso_path}" + set root=(loopdev_cfg) + configfile $cfg_path + loopback -d loopdev_cfg + } + return 0 +} + +function grml_iso_entry { + realdev="$1" + isopath="$2" + loopdev="$3" + + result=1 + for dir in /boot/grml /boot/grmlsmall /boot/grmlmedium; do + if ! test -f ${dir}/linux26 -a -f ${dir}/initrd.gz; then continue; fi + + echo grml $isopath: yes + result=0 + menuentry "GRML Linux from ${realdev}${isopath}" \ + "$realdev" "$isopath" "$dir" { + set device="$2" + set isopath="$3" + set grmldir="$4" + + loopback loopdev_grml "${device}${isopath}" + set root=(loopdev_grml) + linux $grmldir/linux26 findiso="$isopath" apm=power-off quiet \ + boot=live nomce + initrd $grmldir/initrd.gz + loopback -d loopdev_grml + } + done + return $result +} + +function pmagic_iso_entry { + realdev="$1" + isopath="$2" + loopdev="$3" + + if ! test -f /pmagic/bzImage -a -f /pmagic/initramfs; then return 1; fi + + echo pmagic $isopath: yes + menuentry "Parted Magic from ${realdev}${isopath}" "$realdev" "$isopath" { + set device="$2" + set isopath="$3" + + loopback loopdev_pmagic "${device}${isopath}" + set root=(loopdev_pmagic) + linux /pmagic/bzImage iso_filename="$isopath" edd=off noapic \ + load_ramdisk=1 prompt_ramdisk=0 rw sleep=10 loglevel=0 \ + keymap=$langcode + initrd /pmagic/initramfs + loopback -d loopdev_pmagic + } + return 0 +} + +function sidux_iso_entry { + realdev="$1" + isopath="$2" + loopdev="$3" + + result=1 + for kernel in /boot/vmlinuz-*-sidux-*; do + if ! test -f "$kernel"; then continue; fi + regexp -s 1:v1 -s 2:v2 '/boot/vmlinuz-(.*)-sidux-(.*)' "$kernel" + + initrd="/boot/initrd.img-$v1-sidux-$v2" + if ! test -f "$initrd"; then continue; fi + + result=0 + echo sidux $isopath: yes + menuentry "Sidux vmlinux-$v1-sidux-$v2 from ${realdev}${isopath}" "$realdev" "$isopath" "$kernel" "$initrd" { + set device="$2" + set isopath="$3" + set kernel="$4" + set initrd="$5" + + loopback loopdev_sidux "${device}${isopath}" + set root=(loopdev_sidux) + linux $kernel fromiso=$isopath boot=fll quiet + initrd $initrd + loopback -d loopdev_sidux + } + done + return $result +} + +function slax_iso_entry { + realdev="$1" + isopath="$2" + loopdev="$3" + + if ! test -f /boot/vmlinuz -a -f /boot/initrd.gz; then return 1; fi + + echo slax $isopath: yes + menuentry "Slax Linux from ${realdev}${isopath}" "$realdev" "$isopath" { + set device="$2" + set isopath="$3" + + loopback loopdev_slax "${device}${isopath}" + set root=(loopdev_slax) + linux /boot/vmlinuz from=$isopath ramdisk_size=6666 root=/dev/ram0 rw + initrd /boot/initrd.gz + loopback -d loopdev_slax + } + return 0 +} + +function tinycore_iso_entry { + realpath="$1" + isopath="$2" + loopdev="$3" + + if ! test -f /boot/bzImage -a -f /boot/tinycore.gz; then return 1; fi + + echo tinycore $isopath: yes + menuentry "Tinycore Linux from ${realdev}${isopath}" "$realdev" "$isopath" { + set device="$2" + set isopath="$3" + + loopback loopdev_tiny "${device}${isopath}" + set root=(loopdev_tiny) + linux /boot/bzImage + initrd /boot/tinycore.gz + loopback -d loopdev_tiny + } + return 0 +} + +function casper_iso_entry { + realpath="$1" + isopath="$2" + loopdev="$3" + + if ! test -f /casper/vmlinuz; then return 1; fi + initrd= + for f in /casper/initrd.*z; do + if ! test -f "$f"; then continue; fi + pathname "$f" initrd + done + if test -z "$initrd"; then return 1; fi + + echo casper $isopath: yes + menuentry "Casper based Linux from ${realdev}${isopath}" "$realdev" "$isopath" "$initrd" { + set device="$2" + set isopath="$3" + set initrd="$4" + + loopback loopdev_casper "${device}${isopath}" + set root=(loopdev_casper) + linux /casper/vmlinuz boot=casper iso-scan/filename="$isopath" quiet splash noprompt keyb="$langcode" \ + debian-installer/language="$langcode" console-setup/layoutcode?="$langcode" -- + initrd $initrd + loopback -d loopdev_casper + } + return 0 +} + +function scan_isos { + isodirs="$1" + + for dev in (*); do + for dir in $isodirs; do + for file in ${dev}${dir}/*.iso ${dev}${dir}/*.ISO; do + if ! test -f "$file"; then continue; fi + + pathname $file isopath + if test -z "$dev" -o -z "$isopath"; then continue; fi + + if ! loopback loopdev_scan "$file"; then continue; fi + saved_root=$root + set root=(loopdev_scan) + + if loopback_iso_entry $dev $isopath (loopdev_scan); then true; + elif grml_iso_entry $dev $isopath (loopdev_scan); then true; + elif pmagic_iso_entry $dev $isopath (loopdev_scan); then true; + elif sidux_iso_entry $dev $isopath (loopdev_scan); then true; + elif slax_iso_entry $dev $isopath (loopdev_scan); then true; + elif tinycore_iso_entry $dev $isopath (loopdev_scan); then true; + elif casper_iso_entry $dev $isopath (loopdev_scan); then true; + else true; fi + + set root=$saved_root + loopback -d loopdev_scan + done + done + done + return 0 +} + +# XXX Remove later +insmod serial +serial +terminal_output --append serial +# terminal_input --append serial + +langcode="$lang" + +insmod regexp +scan_isos /iso /boot/iso + diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi index a4a38206e..f4367f895 100644 --- a/docs/grub-dev.texi +++ b/docs/grub-dev.texi @@ -74,16 +74,21 @@ This edition documents version @value{VERSION}. @menu * Getting the source code:: -* Finding your way around:: * Coding style:: +* Finding your way around:: * Contributing Changes:: +* Setting up and running test suite:: +* Updating External Code:: +* Debugging:: * Porting:: * Error Handling:: -* CIA:: +* Stack and heap size:: * BIOS port memory map:: * Video Subsystem:: * PFF2 Font File Format:: * Graphical Menu Software Design:: +* Verifiers framework:: +* Lockdown framework:: * Copying This Manual:: Copying This Manual * Index:: @end menu @@ -92,24 +97,36 @@ This edition documents version @value{VERSION}. @node Getting the source code @chapter Getting the source code -GRUB is maintained using the @uref{http://bazaar-vcs.org/, Bazaar revision -control system}. To fetch the primary development branch: +GRUB is maintained using the @uref{https://git-scm.com/book/en/v2, +GIT revision control system}. To fetch: @example -bzr get http://bzr.savannah.gnu.org/r/grub/trunk/grub +git clone git://git.sv.gnu.org/grub.git @end example -The GRUB developers maintain several other branches with work in progress. -Of these, the most interesting is the experimental branch, which is a -staging area for new code which we expect to eventually merge into trunk but -which is not yet ready: - +Web access is available under @example -bzr get http://bzr.savannah.gnu.org/r/grub/branches/experimental +http://git.savannah.gnu.org/cgit/grub.git/ @end example -Once you have used @kbd{bzr get} to fetch an initial copy of a branch, you -can use @kbd{bzr pull} to keep it up to date. If you have modified your +The branches available are: + +@table @samp +@item master + Main development branch. +@item grub-legacy + GRUB 0.97 codebase. Kept for reference and legal reasons +@item multiboot + Multiboot specfication +@item multiboot2 + Multiboot2 specfication +@item developer branches + Prefixed with developer name. Every developer of a team manages his own branches. + Developer branches do not need changelog entries. +@end table + +Once you have used @kbd{git clone} to fetch an initial copy of a branch, you +can use @kbd{git pull} to keep it up to date. If you have modified your local version, you may need to resolve conflicts when pulling. @node Coding style @@ -169,38 +186,44 @@ If a macro is global, its name must be prefixed with GRUB_ and must consist of o @section Comments All comments shall be C-style comments, of the form @samp{/* @dots{} */}. - -Comments shall be placed only on a line by themselves. They shall not be placed together with code, variable declarations, or other non-comment entities. A comment should be placed immediately preceding the entity it describes. +A comment can be placed immediately preceding the entity it describes or it +can be placed together with code, variable declarations, or other non-comment +entities. However, it is recommended to not mix various forms especially in +types/structs descriptions. Acceptable: @example -/* The page # that is the front buffer. */ +/* The page # that is the front buffer. */ int displayed_page; -/* The page # that is the back buffer. */ -int render_page; @end example -Unacceptable: @example -int displayed_page; /* The page # that is the front buffer. */ -int render_page; /* The page # that is the back buffer. */ +int render_page; /* The page # that is the back buffer. */ @end example @node Multi-Line Comments @section Multi-Line Comments -Comments spanning multiple lines shall be formatted with all lines after the first aligned with the first line. - -Asterisk characters should not be repeated a the start of each subsequent line. +Comments spanning multiple lines shall be formatted with all lines after the +first aligned with the first line. Asterisk characters should be repeated at +the start of each subsequent line. Acceptable: @example -/* This is a comment - which spans multiple lines. - It is long. */ +/* + * This is a comment + * which spans multiple lines. + * It is long. + */ @end example Unacceptable: +@example +/* This is a comment + which spans multiple lines. + It is long. */ +@end example + @example /* * This is a comment @@ -208,7 +231,16 @@ Unacceptable: * It is long. */ @end example -The opening @samp{/*} and closing @samp{*/} should be placed together on a line with text. +@example +/* This is a comment + * which spans multiple lines. + * It is long. + */ +@end example + +In particular first unacceptable form makes comment difficult to distinguish +from the code itself. Especially if it contains the code snippets and/or is +long. So, its usage is disallowed. @node Finding your way around @chapter Finding your way around @@ -216,12 +248,12 @@ The opening @samp{/*} and closing @samp{*/} should be placed together on a line Here is a brief map of the GRUB code base. GRUB uses Autoconf and Automake, with most of the Automake input generated -by AutoGen. The top-level build rules are in @file{configure.ac}, +by a Python script. The top-level build rules are in @file{configure.ac}, @file{grub-core/Makefile.core.def}, and @file{Makefile.util.def}. Each block in a @file{*.def} file represents a build target, and specifies the source files used to build it on various platforms. The @file{*.def} files -are processed into AutoGen input by @file{gentpl.py} (which you only need to -look at if you are extending the build system). If you are adding a new +are processed into Automake input by @file{gentpl.py} (which you only need +to look at if you are extending the build system). If you are adding a new module which follows an existing pattern, such as a new command or a new filesystem implementation, it is usually easiest to grep @file{grub-core/Makefile.core.def} and @file{Makefile.util.def} for an @@ -286,14 +318,19 @@ live under @file{grub-core/term/}. @item The @samp{efiemu_*} commands live under @file{grub-core/efiemu/}. + +@item +OS-dependent code should be under @file{grub-core/osdep/} + +@item +Utility programs meant to be run from a full operating system +(except OS-dependent code mentioned previously) are in @file{util/}. + @end itemize There are a few other special-purpose exceptions; grep for them if they matter to you. -Utility programs meant to be run from a full operating system are in -@file{util/}. - @node Contributing Changes @chapter Contributing changes @c By YoshinoriOkuji, VesaJääskeläinen, ColinWatson @@ -310,8 +347,8 @@ manual and try GRUB 2 out to see what you think is missing from there. Here are additional pointers: @itemize -@item @url{https://savannah.gnu.org/task/?group=grub GRUB's Task Tracker} -@item @url{https://savannah.gnu.org/bugs/?group=grub GRUB's Bug Tracker} +@item @uref{https://savannah.gnu.org/task/?group=grub, GRUB's Task Tracker} +@item @uref{https://savannah.gnu.org/bugs/?group=grub, GRUB's Bug Tracker} @end itemize If you intended to make changes to GRUB Legacy (<=0.97) those are not accepted @@ -329,10 +366,10 @@ anymore. @itemize @item Always use latest GRUB 2 source code. So get that first. -For developers it is recommended always to use the newest development version of GRUB 2. If development takes a long period of time, please remember to keep in sync with newest developments regularly so it is much easier to integrate your change in the future. GRUB 2 is being developed in a Bazaar (bzr) repository. +For developers it is recommended always to use the newest development version of GRUB 2. If development takes a long period of time, please remember to keep in sync with newest developments regularly so it is much easier to integrate your change in the future. GRUB 2 is being developed in a GIT repository. -Please check Savannah's GRUB project page for details how to get newest bzr: -@uref{http://savannah.gnu.org/bzr/?group=grub, GRUB 2 bzr Repository} +Please check Savannah's GRUB project page for details how to get newest git: +@uref{https://savannah.gnu.org/git/?group=grub, GRUB 2 git Repository} @item Compile it and try it out. @@ -425,7 +462,7 @@ and the FSF clerks have dealt with your copyright assignment. @section When you are approved for write access to project's files As you might know, GRUB is hosted on -@url{https://savannah.gnu.org/projects/grub Savannah}, thus the membership +@uref{https://savannah.gnu.org/projects/grub, Savannah}, thus the membership is managed by Savannah. This means that, if you want to be a member of this project: @@ -448,6 +485,380 @@ If your intention is to just get started, please do not submit a inclusion request. Instead, please subscribe to the mailing list, and communicate first (e.g. sending a patch, asking a question, commenting on another message...). +@node Setting up and running test suite +@chapter Setting up and running test suite + +GRUB is basically a tiny operating system with read support for many file +systems and which has been ported to a variety of architectures. As such, its +test suite has quite a few dependencies required to fully run the suite. +These dependencies are currently documented in the +@uref{https://git.savannah.gnu.org/cgit/grub.git/tree/INSTALL, INSTALL} +file in the source repository. Once installed, the test suite can be started +by running the @command{make check} command from the GRUB build directory. + +@node Updating External Code +@chapter Updating external code + +GRUB includes some code from other projects, and it is sometimes necessary +to update it. + +@menu +* Gnulib:: +* jsmn:: +* minilzo:: +* libtasn1:: +@end menu + +@node Gnulib +@section Gnulib + +Gnulib is a source code library that provides basic functionality to +programs and libraries. Many software packages make use of Gnulib +to avoid reinventing the portability wheel. + +GRUB imports Gnulib using its @command{bootstrap} utility, identifying a +particular Git commit in @file{bootstrap.conf}. To upgrade to a new Gnulib +commit, set @code{GNULIB_REVISION} in @file{bootstrap.conf} to the new commit +ID, then run @kbd{./bootstrap} and whatever else you need to make sure it +works. Check for changes to Gnulib's @file{NEWS} file between the old and new +commits; in some cases it will be necessary to adjust GRUB to match. You may +also need to update the patches in @file{grub-core/lib/gnulib-patches/}. + +To add a new Gnulib module or remove one that is no longer needed, change +@code{gnulib_modules} in @file{bootstrap.conf}. Again, run @kbd{./bootstrap} +and whatever else you need to make sure it works. + +Bootstrapping from an older distribution containing gettext version < 0.18.3, +will require a patch similar to this to be applied first before running the +@command{./bootstrap} utility: + +@example +diff --git a/bootstrap.conf b/bootstrap.conf +index 988dda0..a3193a9 100644 +--- a/bootstrap.conf ++++ b/bootstrap.conf +@@ -67,7 +67,7 @@ SKIP_PO=t +buildreq="\ +autoconf 2.63 +automake 1.11 +-gettext 0.18.3 ++gettext 0.17 +git 1.5.5 +tar - +" +diff --git a/configure.ac b/configure.ac +index 08b518f..99f5b36 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -362,7 +362,7 @@ AC_CHECK_PROG(HAVE_CXX, $CXX, yes, no) + +AC_GNU_SOURCE +AM_GNU_GETTEXT([external]) +-AM_GNU_GETTEXT_VERSION([0.18.3]) ++AM_GNU_GETTEXT_VERSION([0.17]) +AC_SYS_LARGEFILE + +# Identify characteristics of the host architecture. + +@end example + +It will also be necessary to adjust the patches in +@file{po/gettext-patches/} to apply to an older version of gettext. + +@node jsmn +@section jsmn + +jsmn is a minimalistic JSON parser which is implemented in a single header file +@file{jsmn.h}. To import a different version of the jsmn parser, you may simply +download the @file{jsmn.h} header from the desired tag or commit to the target +directory: + +@example +curl -L https://raw.githubusercontent.com/zserge/jsmn/v1.1.0/jsmn.h \ + -o grub-core/lib/json/jsmn.h +@end example + +@node minilzo +@section minilzo + +miniLZO is a very lightweight subset of the LZO library intended for easy +inclusion in other projects. It is generated automatically from the LZO +source code and contains the most important LZO functions. + +To upgrade to a new version of the miniLZO library, download the release +tarball and copy the files into the target directory: + +@example +curl -L -O https://www.oberhumer.com/opensource/lzo/download/minilzo-2.10.tar.gz +tar -zxf minilzo-2.10.tar.gz +rm minilzo-2.10/testmini.c +rm -r grub-core/lib/minilzo/* +cp minilzo-2.10/*.[hc] grub-core/lib/minilzo +rm -r minilzo-2.10* +@end example + +@node libtasn1 +@section libtasn1 + +libtasn1 is a library providing Abstract Syntax Notation One (ASN.1, as +specified by the X.680 ITU-T recommendation) parsing and structures management, +and Distinguished Encoding Rules (DER, as per X.690) encoding and decoding +functions. + +To upgrade to a new version of the libtasn1 library, download the release +tarball and copy the files into the target directory: + +@example +curl -L -O https://ftp.gnu.org/gnu/libtasn1/libtasn1-4.19.0.tar.gz +tar xvzf libtasn1-4.19.0.tar.gz +rm -rf grub-core/lib/libtasn1 +mkdir -p grub-core/lib/libtasn1/lib +mkdir -p grub-core/lib/libtasn1/tests +cp libtasn1-4.19.0/@{README.md,COPYING@} grub-core/lib/libtasn1 +cp libtasn1-4.19.0/lib/@{coding.c,decoding.c,element.c,element.h,errors.c,gstr.c,gstr.h,int.h,parser_aux.c,parser_aux.h,structure.c,structure.h@} grub-core/lib/libtasn1/lib +cp libtasn1-4.19.0/lib/includes/libtasn1.h grub-core/lib/libtasn1 +cp libtasn1-4.19.0/tests/@{CVE-2018-1000654-1_asn1_tab.h,CVE-2018-1000654-2_asn1_tab.h,CVE-2018-1000654.c,object-id-decoding.c,object-id-encoding.c,octet-string.c,reproducers.c,Test_overflow.c,Test_simple.c,Test_strings.c@} grub-core/lib/libtasn1/tests +rm -rf libtasn1-4.19.0* +@end example + +After upgrading the library, it may be necessary to apply the patches in +@file{grub-core/lib/libtasn1-patches/} to adjust the code to be compatible with +GRUB. These patches were needed to use the current version of libtasn1. The +existing patches may not apply cleanly, apply at all, or even be needed for a +newer version of the library, and other patches may be needed due to changes in +the newer version. If existing patches need to be refreshed to apply cleanly, +please include updated patches as part of the a patch set sent to the list. +If new patches are needed or existing patches are not needed, also please send +additions or removals as part of any patch set upgrading libtasn1. + +@node Debugging +@chapter Debugging + +GRUB2 can be difficult to debug because it runs on the bare-metal and thus +does not have the debugging facilities normally provided by an operating +system. This chapter aims to provide useful information on some ways to +debug GRUB2 for some architectures. It by no means intends to be exhaustive. +The focus will be one x86_64 and i386 architectures. Luckily for some issues +virtual machines have made the ability to debug GRUB2 much easier, and this +chapter will focus debugging via the QEMU virtual machine. We will not be +going over debugging of the userland tools (eg. grub-install), there are +many tutorials on debugging programs in userland. + +You will need GDB and the QEMU binaries for your system, on Debian these +can be installed with the @samp{gdb} and @samp{qemu-system-x86} packages. +Also it is assumed that you have already successfully compiled GRUB2 from +source for the target specified in the section below and have some +familiarity with GDB. When GRUB2 is built it will create many different +binaries. The ones of concern will be in the @file{grub-core} +directory of the GRUB2 build dir. To aide in debugging we will want the +debugging symbols generated during the build because these symbols are not +kept in the binaries which get installed to the boot location. The build +process outputs two sets of binaries, one without symbols which gets executed +at boot, and another set of ELF images with debugging symbols. The built +images with debugging symbols will have a @file{.image} suffix, and the ones +without a @file{.img} suffix. Similarly, loadable modules with debugging +symbols will have a @file{.module} suffix, and ones without a @file{.mod} +suffix. In the case of the kernel the binary with symbols is named +@file{kernel.exec}. + +In the following sections, information will be provided on debugging on +various targets using @command{gdb} and the @samp{gdb_grub} GDB script. + +@menu +* i386-pc:: +* x86_64-efi:: +@end menu + +@node i386-pc +@section i386-pc + +The i386-pc target is a good place to start when first debugging GRUB2 +because in some respects it's easier than EFI platforms. The reason being +that the initial load address is always known in advance. To start +debugging GRUB2 first QEMU must be started in GDB stub mode. The following +command is a simple illustration: + +@example +qemu-system-i386 -drive file=disk.img,format=raw \ + -device virtio-scsi-pci,id=scsi0 -S -s +@end example + +This will start a QEMU instance booting from @file{disk.img}. It will pause +at start waiting for a GDB instance to attach to it. You should change +@file{disk.img} to something more appropriate. A block device can be used, +but you may need to run QEMU as a privileged user. + +To connect to this QEMU instance with GDB, the @code{target remote} GDB +command must be used. We also need to load a binary image, preferably with +symbols. This can be done using the GDB command @code{file kernel.exec}, if +GDB is started from the @file{grub-core} directory in the GRUB2 build +directory. GRUB2 developers have made this more simple by including a GDB +script which does much of the setup. This file is at @file{grub-core/gdb_grub} +in the build directory and is also installed via @command{make install}. +When using a pre-built GRUB, the distribution may have a package which installs +this GDB script along with debug symbol binaries, such as Debian's +@samp{grub-pc-dbg} package. The GDB script is intended to be used +like so, assuming that @samp{/path/to/script} is the path to the directory +containing the gdb_grub script and debug symbol files: + +@example +cd $(dirname /path/to/script/gdb_grub) +gdb -x gdb_grub +@end example + +Once GDB has been started with the @file{gdb_grub} script it will +automatically connect to the QEMU instance. You can then do things you +normally would in GDB like set a break point on @var{grub_main}. + +Setting breakpoints in modules is trickier since they haven't been loaded +yet and are loaded at addresses determined at runtime. The module could be +loaded to different addresses in different QEMU instances. The debug symbols +in the modules @file{.module} binary, thus are always wrong, and GDB needs +to be told where to load the symbols to. But this must happen at runtime +after GRUB2 has determined where the module will get loaded. Luckily the +@file{gdb_grub} script takes care of this with the @command{runtime_load_module} +command, which configures GDB to watch for GRUB2 module loading and when +it does add the module symbols with the appropriate offset. + +@node x86_64-efi +@section x86_64-efi + +Using GDB to debug GRUB2 for the x86_64-efi target has some similarities with +the i386-pc target. Please read and familiarize yourself with the @ref{i386-pc} +section when reading this one. Extra care must be used to run QEMU such that it +boots a UEFI firmware. This usually involves either using the @samp{-bios} +option with a UEFI firmware blob (eg. @file{OVMF.fd}) or loading the firmware +via pflash. This document will not go further into how to do this as there are +ample resource on the web. + +Like all EFI implementations, on x86_64-efi the (U)EFI firmware that loads +the GRUB2 EFI application determines at runtime where the application will +be loaded. This means that we do not know where to tell GDB to load the +symbols for the GRUB2 core until the (U)EFI firmware determines it. There are +two good ways of figuring this out when running in QEMU: use a @ref{OVMF debug log, +debug build of OVMF} and check the debug log, or have GRUB2 say where it is +loaded. Neither of these are ideal because they both generally give the +information after GRUB2 is already running, which makes debugging early boot +infeasible. Technically, the first method does give the load address before +GRUB2 is run, but without debugging the EFI firmware with symbols, the author +currently does not know how to cause the OVMF firmware to pause at that point +to use the load address before GRUB2 is run. + +Even after getting the application load address, the loading of core symbols +is complicated by the fact that the debugging symbols for the kernel are in +an ELF binary named @file{kernel.exec} while what is in memory are sections +for the PE32+ EFI binary. When @command{grub-mkimage} creates the PE32+ +binary it condenses several segments from the ELF kernel binary into one +.data section in the PE32+ binary. This must be taken into account to +properly load the other non-text sections. Otherwise, GDB will work as +expected when breaking on functions, but, for instance, global variables +will point to the wrong address in memory and thus give incorrect values +(which can be difficult to debug). + +Calculating the correct offsets for sections is taken care of automatically +when loading the kernel symbols via the user-defined GDB command +@command{dynamic_load_kernel_exec_symbols}, which takes one argument, the +address where the text section is loaded as determined by one of the methods +above. Alternatively, the command @command{dynamic_load_symbols} with the text +section address as an agrument can be called to load the kernel symbols and set +up loading the module symbols as they are loaded at runtime. + +In the author's experience, when debugging with QEMU and OVMF, to have +debugging symbols loaded at the start of GRUB2 execution the GRUB2 EFI +application must be run via QEMU at least once prior in order to get the +load address. Two methods for obtaining the load address are described in +two subsections below. Generally speaking, the load address does not change +between QEMU runs. There are exceptions to this, namely that different +GRUB2 EFI applications can be run at different addresses. Also, it has been +observed that after running the EFI application for the first time, the +second run will sometimes have a different load address, but subsequent +runs of the same EFI application will have the same load address as the +second run. And it's a near certainty that if the GRUB EFI binary has changed, +eg. been recompiled, the load address will also be different. + +This ability to predict what the load address will be allows one to assume +the load address on subsequent runs and thus load the symbols before GRUB2 +starts. The following command illustrates this, assuming that QEMU is +running and waiting for a debugger connection and the current working +directory is where @file{gdb_grub} resides: + +@example +gdb -x gdb_grub -ex 'dynamic_load_symbols @var{address of .text section}' +@end example + +If you load the symbols in this manner and, after continuing execution, do +not see output showing the module symbols loading, then it is very likely +that the load address was incorrect. + +Another thing to be aware of is how the loading of the GRUB image by the +firmware affects previously set software breakpoints. On x86 platforms, +software breakpoints are implemented by GDB by writing a special processor +instruction at the location of the desired breakpoint. This special instruction +when executed will stop the program execution and hand control to the +debugger, GDB. GDB will first save the instruction bytes that are +overwritten at the breakpoint and will put them back when the breakpoint +is hit. If GRUB is being run for the first time in QEMU, the firmware will +be loading the GRUB image into memory where every byte is already set to 0. +This means that if a breakpoint is set before GRUB is loaded, GDB will save +the 0-byte(s) where the the special instruction will go. Then when the firmware +loads the GRUB image and because it is unaware of the debugger, it will +write the GRUB image to memory, overwriting anything that was there previously --- +notably in this case the instruction that implements the software breakpoint. +This will be confusing for the person using GDB because GDB will show the +breakpoint as set, but the brekapoint will never be hit. Furthermore, GDB +then becomes confused, such that even deleting an recreating the breakpoint +will not create usable breakpoints. The @file{gdb_grub} script takes care of +this by saving the breakpoints just before they are overwritten, and then +restores them at the start of GRUB execution. So breakpoints for GRUB can be +set before GRUB is loaded, but be mindful of this effect if you are confused +as to why breakpoints are not getting hit. + +Also note, that hardware breakpoints do not suffer this problem. They are +implemented by having the breakpoint address in special debug registers on +the CPU. So they can always be set freely without regard to whether GRUB has +been loaded or not. The reason that hardware breakpoints aren't always used +is because there are a limited number of them, usually around 4 on various +CPUs, and specifically exactly 4 for x86 CPUs. The @file{gdb_grub} script goes +out of its way to avoid using hardware breakpoints internally and uses them as +briefly as possible when needed, thus allowing the user to have a maximal +number at their disposal. + +@menu +* OVMF debug log:: +* Using the gdbinfo command:: +@end menu + +@node OVMF debug log +@subsection OVMF debug log + +In order to get the GRUB2 load address from OVMF, first, a debug build +of OVMF must be obtained (@uref{https://github.com/retrage/edk2-nightly/raw/master/bin/DEBUGX64_OVMF.fd, +here is one} which is not officially recommended). OVMF will output debug +messages to a special serial device, which we must add to QEMU. The following +QEMU command will run the debug OVMF and write the debug messages to a +file named @file{debug.log}. It is assumed that @file{disk.img} is a disk +image or block device that is set up to boot GRUB2 EFI. + +@example +qemu-system-x86_64 -bios /path/to/debug/OVMF.fd \ + -drive file=disk.img,format=raw \ + -device virtio-scsi-pci,id=scsi0 \ + -debugcon file:debug.log -global isa-debugcon.iobase=0x402 +@end example + +If GRUB2 was started by the (U)EFI firmware, then in the @file{debug.log} +file one of the last lines should be a log message like: +@samp{Loading driver at 0x00006AEE000 EntryPoint=0x00006AEE756}. This +means that the GRUB2 EFI application was loaded at @samp{0x00006AEE000} and +its .text section is at @samp{0x00006AEE756}. + +@node Using the gdbinfo command +@subsection Using the gdbinfo command + +On EFI platforms the command @command{gdbinfo} will output a string that +is to be run in a GDB session running with the @file{gdb_grub} GDB script. + + @node Porting @chapter Porting @@ -625,7 +1036,7 @@ void grub_arch_sync_caches (void *address, grub_size_t len) (cache.S). They won't be used for now. You will need to create directory include/$cpu/$platform and a file -include/$cpu/types.h. The later folowing this template: +include/$cpu/types.h. The latter following this template: @example #ifndef GRUB_TYPES_CPU_HEADER @@ -654,7 +1065,7 @@ is already present and you'll need to make it follow the existant code paths for your platform adding adjustments if necessary. When done compile: @example -./autogen.sh +./bootstrap ./configure --target=$cpu --with-platform=$platform TARGET_CC=.. OBJCOPY=... STRIP=... make > /dev/null @end example @@ -671,13 +1082,13 @@ If it works next stage is to have heap, console and timer. To have the heap working you need to determine which regions are suitable for heap usage, allocate them from firmware and map (if applicable). Then call -grub_mm_init_region (vois *start, grub_size_t s) for every of this region. +grub_mm_init_region (void *start, grub_size_t s) for every of this region. As a shortcut for early port you can allocate right after _end or have a big static array for heap. If you do you'll probably need to come back to this later. As for output console you should distinguish between an array of text, terminfo or graphics-based console. Many of real-world examples don't fit perfectly into any of these categories but one of the models is easier -to be used as base. In second and third case you should add your platform to +to be used as base. In second and third case you should add your platform to terminfokernel respectively videoinkernel group. A good example of array of text is i386-pc (kern/i386/pc/init.c and term/i386/pc/console.c). Of terminfo is ieee1275 (kern/ieee1275/init.c and term/ieee1275/console.c). @@ -685,7 +1096,7 @@ Of video is loongson (kern/mips/loongson/init.c). Note that terminfo has to be inited in 2 stages: one before (to get at least rudimentary console as early as possible) and another after the heap (to get full-featured console). For the input there are string of keys, terminfo and direct hardware. For string -of keys look at i386-pc (same files), for termino ieee1275 (same files) and for +of keys look at i386-pc (same files), for terminfo ieee1275 (same files) and for hardware loongson (kern/mips/loongson/init.c and term/at_keyboard.c). For the timer you'll need to call grub_install_get_time_ms (...) with as sole @@ -890,33 +1301,71 @@ if (grub_errno != GRUB_ERR_NONE) grub_error_pop (); @end example -@node CIA -@chapter CIA -@c By Robert Millan and Carles Pina -If you have commit access, please setup CIA in your Bazaar -config so those in IRC receive notification of your commits. +@node Stack and heap size +@chapter Stack and heap size -In @file{~/.bazaar/bazaar.conf}, add "cia_send_revno = true". -Optionally, you can also add "cia_user = myusername" if you'd -like CIA service to use a specific account (for statistical purpose). +On emu stack and heap are just normal host OS stack and heap. Stack is typically +8 MiB although it's OS-dependent. -In the @file{.bzr/branch/branch.conf} of your checkout branch, -"set nickname = /path_to_this_branch" and "cia_project = GNU GRUB". +On i386-pc, i386-coreboot, i386-qemu and i386-multiboot the stack is 60KiB. +All available space between 1MiB and 4GiB marks is part of heap. -Additionally, please set cia_send_revno in the [DEFAULT] section -of your @file{~/.bazaar/bazaar.conf}. E.g.: +On *-xen stack is 4MiB. If compiled for x86-64 with GCC 4.4 or later addressable +space is unlimited. When compiled for x86-64 with older GCC version addressable +space is limited to 2GiB. When compiling for i386 addressable space is limited +to 4GiB. All addressable pages except the ones for stack, GRUB binary, special +pages and page table are in the heap. -@example -[DEFAULT] -cia_send_revno = true -@end example +On *-efi GRUB uses same stack as EFI. If compiled for x86-64 with GCC 4.4 or +later addressable space is unlimited. When compiled for x86-64 with older GCC +version addressable space is limited to 2GiB. For all other platforms addressable +space is limited to 4GiB. GRUB allocates pages from EFI for its heap, at most +1.6 GiB. -Remember to install cia-clients (Debian/Ubuntu package) to be able to use CIA. +On i386-ieee1275 and powerpc-ieee1275 GRUB uses same stack as IEEE1275. + +On i386-ieee1275 and powerpc-ieee1275, GRUB will allocate 32MiB for its heap on +startup. It may allocate more at runtime, as long as at least 128MiB remain free +in OpenFirmware. + +On sparc64-ieee1275 stack is 256KiB and heap is 2MiB. + +On mips(el)-qemu_mips and mipsel-loongson stack is 2MiB (everything below +GRUB image) and everything above GRUB image (from 2MiB + kernel size) +until 256MiB is part of heap. + +On mips-arc stack is 2MiB (everything below GRUB image) and everything above +GRUB image(from 2MiB + kernel size) until 128MiB is part of heap. + +On mipsel-arc stack is 2MiB (everything below GRUB image which is not part +of ARC) and everything above GRUB image (from 7MiB + kernel size) +until 256MiB is part of heap. + +On arm-uboot stack is 256KiB and heap is 2MiB. + +In short: + +@multitable @columnfractions .15 .25 .5 +@headitem Platform @tab Stack @tab Heap +@item emu @tab 8 MiB @tab ? +@item i386-pc @tab 60 KiB @tab < 4 GiB +@item i386-coreboot @tab 60 KiB @tab < 4 GiB +@item i386-multiboot @tab 60 KiB @tab < 4 GiB +@item i386-qemu @tab 60 KiB @tab < 4 GiB +@item *-efi @tab ? @tab < 1.6 GiB +@item i386-ieee1275 @tab ? @tab < 32 MiB +@item powerpc-ieee1275 @tab ? @tab available memory - 128MiB +@item sparc64-ieee1275 @tab 256KiB @tab 2 MiB +@item arm-uboot @tab 256KiB @tab 2 MiB +@item mips(el)-qemu_mips @tab 2MiB @tab 253 MiB +@item mipsel-loongson @tab 2MiB @tab 253 MiB +@item mips-arc @tab 2MiB @tab 125 MiB +@item mipsel-arc @tab 2MiB @tab 248 MiB +@item x86_64-xen (GCC >= 4.4) @tab 4MiB @tab unlimited +@item x86_64-xen (GCC < 4.4) @tab 4MiB @tab < 2GiB +@item i386-xen @tab 4MiB @tab < 4GiB +@end multitable -Keep in mind Bazaar sends notifications for all commits to branches that have -this setting, regardless of whether they're bound branches (checkouts) or not. -So if you make local commits in a non-bound branch and it bothers you that -others can read them, do not use this setting. @node BIOS port memory map @chapter BIOS port memory map @@ -929,9 +1378,8 @@ others can read them, do not use this setting. @item ? @tab 0x2000 - 1 @tab Real mode stack @item 0x7C00 @tab 0x7D00 - 1 @tab Boot sector @item 0x8000 @tab ? @tab GRUB kernel -@item 0x68000 @tab 0x78000 - 1 @tab Disk buffer +@item 0x68000 @tab 0x71000 - 1 @tab Disk buffer @item ? @tab 0x80000 - 1 @tab Protected mode stack -@item 0x80000 @tab ? @tab Heap @item ? @tab 0xA0000 - 1 @tab Extended BIOS Data Area @item 0xA0000 @tab 0xC0000 - 1 @tab Video RAM @item 0xC0000 @tab 0x100000 - 1 @tab BIOS @@ -948,8 +1396,8 @@ driver manager works are not included here. @menu * Video API:: -* Bitmap API:: * Example usage of Video API:: +* Bitmap API:: @end menu @node Video API @@ -1108,6 +1556,47 @@ struct grub_video_palette_data Used to query indexed color palettes. If mode is RGB mode, colors will be copied from emulated palette data. In Indexed Color modes, palettes will be read from hardware. Color values will be converted to suit structure format. @code{start} will tell what hardware color index (or emulated color index) will be used as a source for first indice of @code{palette_data}, after that both hardware color index and @code{palette_data} index will be incremented until @code{count} number of colors have been read. @end itemize +@subsection grub_video_set_area_status +@itemize + +@item Prototype: +@example +grub_err_t +grub_video_set_area_status (grub_video_area_status_t area_status); +@end example +@example +enum grub_video_area_status_t + @{ + GRUB_VIDEO_AREA_DISABLED, + GRUB_VIDEO_AREA_ENABLED + @}; +@end example + +@item Description: + +Used to set area drawing mode for redrawing the specified region. Draw commands +are performed in the intersection of the viewport and the region called area. +Coordinates remain related to the viewport. If draw commands try to draw over +the area, they are clipped. +Set status to DISABLED if you need to draw everything. +Set status to ENABLED and region to the desired rectangle to redraw everything +inside the region leaving everything else intact. +Should be used for redrawing of active elements. +@end itemize + +@subsection grub_video_get_area_status +@itemize + +@item Prototype: +@example +grub_err_r +grub_video_get_area_status (grub_video_area_status_t *area_status); +@end example + +@item Description: +Used to query the area status. +@end itemize + @subsection grub_video_set_viewport @itemize @item Prototype: @@ -1134,6 +1623,37 @@ grub_video_get_viewport (unsigned int *x, unsigned int *y, unsigned int *width, Used to query current viewport dimensions. Software developer can use this to choose best way to render contents of the viewport. @end itemize +@subsection grub_video_set_region +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_set_region (unsigned int x, unsigned int y, unsigned int width, unsigned int height); +@end example +@item Description: + +Used to specify the region of the screen which should be redrawn. Use absolute +values. When the region is set and area status is ENABLE all draw commands will +be performed inside the interseption of region and viewport named area. +If draw commands try to draw over viewport, they are clipped. If developer +requests larger than possible region, width and height will be clamped to fit +screen. Should be used for redrawing of active elements. +@end itemize + +@subsection grub_video_get_region +@itemize +@item Prototype: + +@example +grub_err_t +grub_video_get_region (unsigned int *x, unsigned int *y, unsigned int *width, unsigned int *height); +@end example +@item Description: + +Used to query current region dimensions. +@end itemize + @subsection grub_video_map_color @itemize @item Prototype: @@ -1394,8 +1914,8 @@ grub_video_blit_glyph (&glyph, color, 0, 0); @node Bitmap API @section Bitmap API -@itemize @subsection grub_video_bitmap_create +@itemize @item Prototype: @example grub_err_t grub_video_bitmap_create (struct grub_video_bitmap **bitmap, unsigned int width, unsigned int height, enum grub_video_blit_format blit_format) @@ -1528,7 +2048,7 @@ use in GRUB at this time: @item BDF Inefficient storage; uses ASCII to describe properties and hexadecimal numbers in ASCII for the bitmap rows. -@item PCF +@item PCF Many format variations such as byte order and bitmap padding (rows padded to byte, word, etc.) would result in more complex code to handle the font format. @@ -1649,8 +2169,8 @@ bit in the byte. For the sake of compact storage, rows are not padded to byte boundaries (i.e., a single byte may contain bits belonging to multiple rows). The last byte of the bitmap @strong{is} padded with zero bits in the bits positions to the right of the last used bit if the -bitmap data does not fill the last byte. - +bitmap data does not fill the last byte. + The length of the @strong{bitmap data} field is (@var{width} * @var{height} + 7) / 8 using integer arithmetic, which is equivalent to ceil(@var{width} * @var{height} / 8) using real number arithmetic. @@ -1689,7 +2209,9 @@ right edges of two adjacent glyphs. The @strong{device width} field determines the effective leading value that is used to render the font. @end itemize -@image{font_char_metrics,,,,png} +@ifnottex +@image{font_char_metrics,,,,.png} +@end ifnottex An illustration of how the various font metrics apply to characters. @@ -1793,7 +2315,7 @@ functions (defined in @file{gfxmenu/gui_util.c}) that are particularly useful: @item @code{grub_gui_find_by_id (root, id, callback, userdata)}: -This function ecursively traverses the component tree rooted at @var{root}, and +This function recursively traverses the component tree rooted at @var{root}, and for every component that has an ID equal to @var{id}, calls the function pointed to by @var{callback} with the matching component and the void pointer @var{userdata} as arguments. The callback function can do whatever is desired to use the @@ -1824,6 +2346,89 @@ the graphics mode that was in use before @code{grub_video_setup()} was called might fix some of the problems. +@node Verifiers framework +@chapter Verifiers framework + +To register your own verifier call @samp{grub_verifier_register} with a structure +pointing to your functions. + +The interface is inspired by the hash interface with @samp{init}/@samp{write}/@samp{fini}. + +There are essentially 2 ways of using it, hashing and whole-file verification. + +With the hashing approach: +During @samp{init} you decide whether you want to check the given file and init context. +In @samp{write} you update your hashing state. +In @samp{fini} you check that the hash matches the expected value/passes some check/... + +With whole-file verification: +During @samp{init} you decide whether you want to check the given file and init context. +In @samp{write} you verify the file and return an error if it fails. +You don't have @samp{fini}. + +Additional @samp{verify_string} receives various strings like kernel parameters +to verify. Returning no error means successful verification and an error stops +the current action. + +Detailed description of the API: + +Every time a file is opened your @samp{init} function is called with file descriptor +and file type. Your function can have the following outcomes: + +@itemize + +@item returning no error and setting @samp{*flags} to @samp{GRUB_VERIFY_FLAGS_DEFER_AUTH}. +In this case verification is deferred to other active verifiers. Verification +fails if nobody cares or selected verifier fails. + +@item returning no error and setting @samp{*flags} to @samp{GRUB_VERIFY_FLAGS_SKIP_VERIFICATION}. +In this case your verifier will not be called anymore and it is assumed to have +skipped verification. + +@item returning no error and not setting @samp{*flags} to @samp{GRUB_VERIFY_FLAGS_SKIP_VERIFICATION} +In this case verification is done as described in the following section. + +@item returning an error. Then opening of the file will fail due to failed verification. + +@end itemize + +In the third case your @samp{write} will be called with chunks of the file. If +you need the whole file in a single chunk then during @samp{init} set the bit +@samp{GRUB_VERIFY_FLAGS_SINGLE_CHUNK} in @samp{*flags}. During @samp{init} you +may set @samp{*context} if you need additional context. At every iteration you +may return an error and the file will be considered as having failed the +verification. If you return no error then verification continues. + +Optionally at the end of the file @samp{fini}, if it exists, is called with just +the context. If you return no error during any of @samp{init}, @samp{write} and +@samp{fini} then the file is considered as having succeded verification. + +@node Lockdown framework +@chapter Lockdown framework + +The GRUB can be locked down, which is a restricted mode where some operations +are not allowed. For instance, some commands cannot be used when the GRUB is +locked down. + +The function +@code{grub_lockdown()} is used to lockdown GRUB and the function +@code{grub_is_lockdown()} function can be used to check whether lockdown is +enabled or not. When enabled, the function returns @samp{GRUB_LOCKDOWN_ENABLED} +and @samp{GRUB_LOCKDOWN_DISABLED} when is not enabled. + +The following functions can be used to register the commands that can only be +used when lockdown is disabled: + +@itemize + +@item @code{grub_cmd_lockdown()} registers command which should not run when the +GRUB is in lockdown mode. + +@item @code{grub_cmd_lockdown()} registers extended command which should not run +when the GRUB is in lockdown mode. + +@end itemize + @node Copying This Manual @appendix Copying This Manual diff --git a/docs/grub.texi b/docs/grub.texi index b5954da82..34b3484dc 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -20,7 +20,7 @@ This manual is for GNU GRUB (version @value{VERSION}, @value{UPDATED}). -Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009,2010,2011,2012 Free Software Foundation, Inc. +Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document @@ -36,8 +36,11 @@ Invariant Sections. * grub-install: (grub)Invoking grub-install. Install GRUB on your drive * grub-mkconfig: (grub)Invoking grub-mkconfig. Generate GRUB configuration * grub-mkpasswd-pbkdf2: (grub)Invoking grub-mkpasswd-pbkdf2. +* grub-mkrelpath: (grub)Invoking grub-mkrelpath. * grub-mkrescue: (grub)Invoking grub-mkrescue. Make a GRUB rescue image +* grub-mount: (grub)Invoking grub-mount. Mount a file system using GRUB * grub-probe: (grub)Invoking grub-probe. Probe device information +* grub-script-check: (grub)Invoking grub-script-check. @end direntry @setchapternewpage odd @@ -78,6 +81,9 @@ This edition documents version @value{VERSION}. @menu * Introduction:: Capturing the spirit of GRUB * Naming convention:: Names of your drives in GRUB +* OS-specific notes about grub tools:: + Some notes about OS-specific behaviour of GRUB + tools * Installation:: Installing GRUB on your drive * Booting:: How to boot different operating systems * Configuration:: Writing your own configuration file @@ -86,22 +92,19 @@ This edition documents version @value{VERSION}. * Serial terminal:: Using GRUB via a serial line * Vendor power-on keys:: Changing GRUB behaviour on vendor power-on keys * Images:: GRUB image files +* Core image size limitation:: GRUB image files size limitations * Filesystem:: Filesystem syntax and semantics * Interface:: The menu and the command-line * Environment:: GRUB environment variables -* Commands:: The list of available builtin commands +* Modules:: Available modules +* Commands:: Available builtin commands * Internationalisation:: Topics relating to language support -* Security:: Authentication and authorisation -* Platform limitations:: The list of platform-specific limitations +* Security:: Authentication, authorisation, and signatures +* Platform limitations:: Platform-specific limitations * Platform-specific operations:: Platform-specific operations -* Supported kernels:: The list of supported kernels +* Supported kernels:: Supported kernels * Troubleshooting:: Error messages produced by GRUB -* Invoking grub-install:: How to use the GRUB installer -* Invoking grub-mkconfig:: Generate a GRUB configuration file -* Invoking grub-mkpasswd-pbkdf2:: - Generate GRUB password hashes -* Invoking grub-mkrescue:: Make a GRUB rescue image -* Invoking grub-probe:: Probe device information for GRUB +* User-space utilities:: Usage of user-space utilities * Obtaining and Building GRUB:: How to obtain and build GRUB * Reporting bugs:: Where you should send a bug report * Future:: Some future plans on GRUB @@ -311,8 +314,10 @@ tables are also loaded. @item Support non-Multiboot kernels Support many of the various free 32-bit kernels that lack Multiboot -compliance (primarily FreeBSD, NetBSD, OpenBSD, and -Linux). Chain-loading of other boot loaders is also supported. +compliance (primarily FreeBSD, NetBSD@footnote{The NetBSD/i386 kernel +is Multiboot-compliant, but lacks support for Multiboot modules.}, +OpenBSD, and Linux). Chain-loading of other boot loaders is also +supported. @item Load multiples modules Fully support the Multiboot feature of loading multiple modules. @@ -348,14 +353,18 @@ blocklist notation. The currently supported filesystem types are @dfn{Amiga Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS}, @dfn{BtrFS} (including raid0, raid1, raid10, gzip and lzo), @dfn{cpio} (little- and big-endian bin, odc and newc variants), -@dfn{Linux ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{exFAT}, @dfn{HFS}, -@dfn{HFS+}, @dfn{ISO9660} (including Joliet, Rock-ridge and multi-chunk files), +@dfn{EROFS} (only uncompressed support for now), +@dfn{Linux ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, +@dfn{exFAT}, @dfn{F2FS}, @dfn{HFS}, @dfn{HFS+}, +@dfn{ISO9660} (including Joliet, Rock-ridge and multi-chunk files), @dfn{JFS}, @dfn{Minix fs} (versions 1, 2 and 3), @dfn{nilfs2}, @dfn{NTFS} (including compression), @dfn{ReiserFS}, @dfn{ROMFS}, @dfn{Amiga Smart FileSystem (SFS)}, @dfn{Squash4}, @dfn{tar}, @dfn{UDF}, @dfn{BSD UFS/UFS2}, @dfn{XFS}, and @dfn{ZFS} (including lzjb, gzip, zle, mirror, stripe, raidz1/2/3 and encryption in AES-CCM and AES-GCM). @xref{Filesystem}, for more information. +Note: Only a subset of filesystems are supported in lockdown mode (such +as when secure boot is enabled, @pxref{Lockdown} for more information). @item Support automatic decompression Can decompress files which were compressed by @command{gzip} or @@ -529,6 +538,75 @@ completion works with file names, too. That was easy, admit it. Now read the next chapter, to find out how to actually install GRUB on your drive. +@node OS-specific notes about grub tools +@chapter OS-specific notes about grub tools + +On OS which have device nodes similar to Unix-like OS GRUB tools use the +OS name. E.g. for GNU/Linux: + +@example +# @kbd{grub-install /dev/sda} +@end example + +On AROS we use another syntax. For volumes: + +@example +//: +@end example + +E.g. + +@example +//:DH0 +@end example + +For disks we use syntax: +@example +//:/unit/flags +@end example + +E.g. + +@example +# @kbd{grub-install //:ata.device/0/0} +@end example + +On Windows we use UNC path. For volumes it's typically + +@example +\\?\Volume@{@} +\\?\: +@end example + +E.g. + +@example +\\?\Volume@{17f34d50-cf64-4b02-800e-51d79c3aa2ff@} +\\?\C: +@end example + + +For disks it's + +@example +\\?\PhysicalDrive +@end example + +E.g. + +@example +# @kbd{grub-install \\?\PhysicalDrive0} +@end example + +Beware that you may need to further escape the backslashes depending on your +shell. + +When compiled with cygwin support then cygwin drive names are automatically +when needed. E.g. + +@example +# @kbd{grub-install /dev/sda} +@end example @node Installation @chapter Installation @@ -575,7 +653,7 @@ For example, under Linux the following will install GRUB into the MBR of the first IDE disk: @example -# @kbd{grub-install /dev/hda} +# @kbd{grub-install /dev/sda} @end example Likewise, under GNU/Hurd, this has the same effect: @@ -613,12 +691,25 @@ floppy instead of exposing the USB drive as a hard disk (they call it This install doesn't conflict with standard install as long as they are in separate directories. -Note that @command{grub-install} is actually just a shell script and the -real task is done by @command{grub-mkimage} and @command{grub-setup}. -Therefore, you may run those commands directly to install GRUB, without -using @command{grub-install}. Don't do that, however, unless you are very -familiar with the internals of GRUB. Installing a boot loader on a running -OS may be extremely dangerous. +On EFI systems for fixed disk install you have to mount EFI System Partition. +If you mount it at @file{/boot/efi} then you don't need any special arguments: + +@example +# @kbd{grub-install} +@end example + +Otherwise you need to specify where your EFI System partition is mounted: + +@example +# @kbd{grub-install --efi-directory=/mnt/efi} +@end example + +For removable installs you have to use @option{--removable} and specify both +@option{--boot-directory} and @option{--efi-directory}: + +@example +# @kbd{grub-install --efi-directory=/mnt/usb --boot-directory=/mnt/usb/boot --removable} +@end example @node Making a GRUB bootable CD-ROM @section Making a GRUB bootable CD-ROM @@ -680,8 +771,8 @@ storage devices. @section The map between BIOS drives and OS devices If the device map file exists, the GRUB utilities (@command{grub-probe}, -@command{grub-setup}, etc.) read it to map BIOS drives to OS devices. This -file consists of lines like this: +etc.) read it to map BIOS drives to OS devices. This file consists of lines +like this: @example (@var{device}) @var{file} @@ -727,25 +818,55 @@ four primary partitions and additional logical partitions. With this partition table format, there are two ways to install GRUB: it can be embedded in the area between the MBR and the first partition (called by various names, such as the "boot track", "MBR gap", or "embedding area", and -which is usually at least 31 KiB), or the core image can be installed in a +which is usually at least 1000 KiB), or the core image can be installed in a file system and a list of the blocks that make it up can be stored in the first sector of that partition. -Each of these has different problems. There is no way to reserve space in +Modern tools usually leave MBR gap of at least 1023 KiB. This amount is +sufficient to cover most configurations. Hence this value is recommended +by the GRUB team. + +Historically many tools left only 31 KiB of space. This is not enough to +parse reliably difficult structures like Btrfs, ZFS, RAID or LVM, or to +use difficult disk access methods like ahci. Hence GRUB will warn if attempted +to install into small MBR gap except in a small number of configurations +that were grandfathered. The grandfathered config must: + +@itemize @bullet +@item +use biosdisk as disk access module for @file{/boot} + +@item +not use any additional partition maps to access @file{/boot} + +@item +@file{/boot} must be on one of following filesystems: + AFFS, AFS, BFS, cpio, newc, odc, ext2/3/4, FAT, exFAT, + F2FS, HFS, uncompressed HFS+, ISO9660, JFS, Minix, Minix2, Minix3, NILFS2, + NTFS, ReiserFS, ROMFS, SFS, tar, UDF, UFS1, UFS2, XFS +@end itemize +Note: Only a subset of filesystems are supported in lockdown mode (such +as when secure boot is enabled, @pxref{Lockdown} for more information). + +MBR gap has few technical problems. There is no way to reserve space in the embedding area with complete safety, and some proprietary software is known to use it to make it difficult for users to work around licensing -restrictions; and systems are sometimes partitioned without leaving enough -space before the first partition. On the other hand, installing to a -filesystem means that GRUB is vulnerable to its blocks being moved around by -filesystem features such as tail packing, or even by aggressive fsck -implementations, so this approach is quite fragile; and this approach can -only be used if the @file{/boot} filesystem is on the same disk that the -BIOS boots from, so that GRUB does not have to rely on guessing BIOS drive -numbers. +restrictions. GRUB works around it by detecting sectors by other software and +avoiding them and protecting its own sectors using Reed-Solomon encoding. + +GRUB team recommends having MBR gap of at least 1000 KiB. + +Should it not be possible, GRUB has support for a fallback solution which is +heavily recommended against. Installing to a filesystem means that GRUB is +vulnerable to its blocks being moved around by filesystem features such as +tail packing, or even by aggressive fsck implementations, so this approach +is quite fragile; and this approach can only be used if the @file{/boot} +filesystem is on the same disk that the BIOS boots from, so that GRUB does +not have to rely on guessing BIOS drive numbers. The GRUB development team generally recommends embedding GRUB before the first partition, unless you have special requirements. You must ensure that -the first partition starts at least 31 KiB (63 sectors) from the start of +the first partition starts at least 1000 KiB (2000 sectors) from the start of the disk; on modern disks, it is often a performance advantage to align partitions on larger boundaries anyway, so the first partition might start 1 MiB from the start of the disk. @@ -792,6 +913,7 @@ magic. @menu * General boot methods:: How to boot OSes with GRUB generally * Loopback booting:: Notes on booting from loopbacks +* LVM cache booting:: Notes on booting from LVM cache logical volume * OS-specific notes:: Notes on some operating systems @end menu @@ -799,17 +921,17 @@ magic. @node General boot methods @section How to boot operating systems -GRUB has two distinct boot methods. One of the two is to load an -operating system directly, and the other is to chain-load another boot -loader which then will load an operating system actually. Generally -speaking, the former is more desirable, because you don't need to -install or maintain other boot loaders and GRUB is flexible enough to -load an operating system from an arbitrary disk/partition. However, -the latter is sometimes required, since GRUB doesn't support all the -existing operating systems natively. +GRUB has three distinct boot methods: loading an operating system +directly, using kexec from userspace, and chainloading another +bootloader. Generally speaking, the first two are more desirable +because you don't need to install or maintain other boot loaders and +GRUB is flexible enough to load an operating system from an arbitrary +disk/partition. However, chainloading is sometimes required, as GRUB +doesn't support all existing operating systems natively. @menu * Loading an operating system directly:: +* Kexec:: * Chain-loading:: @end menu @@ -835,13 +957,27 @@ use more complicated instructions. @xref{DOS/Windows}, for more information. +@node Kexec +@subsection Kexec with grub2-emu + +GRUB can be run in userspace by invoking the grub2-emu tool. It will +read all configuration scripts as if booting directly (see @ref{Loading +an operating system directly}). With the @code{--kexec} flag, and +kexec(8) support from the operating system, the @command{linux} command +will directly boot the target image. For systems that lack working +systemctl(1) support for kexec, passing the @code{--kexec} flag twice +will fallback to invoking kexec(8) directly; note however that this +fallback may be unsafe outside read-only environments, as it does not +invoke shutdown machinery. + + @node Chain-loading @subsection Chain-loading an OS Operating systems that do not support Multiboot and do not have specific support in GRUB (specific support is available for Linux, FreeBSD, NetBSD and OpenBSD) must be chain-loaded, which involves loading another boot -loader and jumping to it in real mode. +loader and jumping to it in real mode or via the firmware. The @command{chainloader} command (@pxref{chainloader}) is used to set this up. It is normally also necessary to load some GRUB modules and set the @@ -873,21 +1009,42 @@ is discovered. This is achieved by GRUB loading a specially made small image and passing it as ramdisk to the kernel. This is achieved by commands @command{kfreebsd_module}, @command{knetbsd_module_elf}, @command{kopenbsd_ramdisk}, @command{initrd} (@pxref{initrd}), -@command{initrd16} (@pxref{initrd}), @command{multiboot_module}, +@command{initrd16} (@pxref{initrd16}), @command{multiboot_module}, @command{multiboot2_module} or @command{xnu_ramdisk} depending on the loader. Note that for knetbsd the image must be put inside miniroot.kmod and the whole miniroot.kmod has to be loaded. In -kopenbsd payload this is disabled by default. Aditionally behaviour of +kopenbsd payload this is disabled by default. Additionally, behaviour of initial ramdisk depends on command line options. Several distributors provide the image for this purpose or it's integrated in their standard ramdisk and activated by special option. Consult your kernel and distribution manual for -more details. Other loaders like appleloader, chainloader (BIOS, EFI, coreboot), -freedos, ntldr and plan9 provide no possibility of loading initial ramdisk and +more details. Other loaders like @command{appleloader}, @command{chainloader} +(BIOS, EFI, coreboot), @command{freedos}, @command{ntldr}, @command{plan9} +and @command{truecrypt} provide no possibility of loading initial ramdisk and as far as author is aware the payloads in question don't support either initial ramdisk or discovering loopback boot in other way and as such not bootable this way. Please consider alternative boot methods like copying all files from the image to actual partition. Consult your OS documentation for -more details +more details. + +@node LVM cache booting +@section Booting from LVM cache logical volume + +The LVM cache logical volume is the logical volume consisting of the original +and the cache pool logical volume. The original is usually on a larger and +slower storage device while the cache pool is on a smaller and faster one. The +performance of the original volume can be improved by storing the frequently +used data on the cache pool to utilize the greater performance of faster +device. + +GRUB boots from LVM cache logical volume merely by reading it's original +logical volume so that dirty data in cache pool volume is disregarded. This is +not a problem for "writethrough" cache mode as it ensures that any data written +will be stored both on the cache and the origin LV. For the other cache mode +"writeback", which delays writing from the cache pool back to the origin LV to +boost performance, GRUB may fail to boot in the wake of accidental power outage +due to it's inability to assemble the cache device for reading the required +dirty data left behind. The situation will be improved after adding full +support to the LVM cache logical volume in the future. @node OS-specific notes @section Some caveats on OS-specific issues @@ -897,6 +1054,7 @@ Here, we describe some caveats on several operating systems. @menu * GNU/Hurd:: * GNU/Linux:: +* NetBSD:: * DOS/Windows:: @end menu @@ -990,11 +1148,62 @@ grub> @kbd{initrd16 /initrd} Finally, run the command @command{boot} (@pxref{boot}). @end enumerate -@strong{Caution:} If you use an initrd and specify the @samp{mem=} -option to the kernel to let it use less than actual memory size, you -will also have to specify the same memory size to GRUB. To let GRUB know -the size, run the command @command{uppermem} @emph{before} loading the -kernel. @xref{uppermem}, for more information. + +@node NetBSD +@subsection NetBSD + +Booting a NetBSD kernel from GRUB is also relatively easy: first set +GRUB's root device, then load the kernel and the modules, and finally +run @command{boot}. + +@enumerate +@item +Set GRUB's root device to the partition holding the NetBSD root file +system. For a disk with a NetBSD disk label, this is usually the first +partition (a:). In that case, and assuming that the partition is on the +first hard disk, set GRUB's root device as follows: + +@example +grub> @kbd{insmod part_bsd} +grub> @kbd{set root=(hd0,netbsd1)} +@end example + +For a disk with a GUID Partition Table (GPT), and assuming that the +NetBSD root partition is the third GPT partition, do this: + +@example +grub> @kbd{insmod part_gpt} +grub> @kbd{set root=(hd0,gpt3)} +@end example + +@item +Load the kernel using the command @command{knetbsd}: + +@example +grub> @kbd{knetbsd /netbsd} +@end example + +Various options may be given to @command{knetbsd}. These options are, +for the most part, the same as in the NetBSD boot loader. For instance, +to boot the system in single-user mode and with verbose messages, do +this: + +@example +grub> @kbd{knetbsd /netbsd -s -v} +@end example + +@item +If needed, load kernel modules with the command +@command{knetbsd_module_elf}. A typical example is the module for the +root file system: + +@example +grub> @kbd{knetbsd_module_elf /stand/amd64/6.0/modules/ffs/ffs.kmod} +@end example + +@item +Finally, run the command @command{boot} (@pxref{boot}). +@end enumerate @node DOS/Windows @@ -1054,10 +1263,11 @@ GRUB is configured using @file{grub.cfg}, usually located under need to write the whole thing by hand. @menu -* Simple configuration:: Recommended for most users -* Shell-like scripting:: For power users and developers -* Multi-boot manual config:: For non-standard multi-OS scenarios -* Embedded configuration:: Embedding a configuration file into GRUB +* Simple configuration:: Recommended for most users +* Root Identification Heuristics:: Summary on how the root file system is identified. +* Shell-like scripting:: For power users and developers +* Multi-boot manual config:: For non-standard multi-OS scenarios +* Embedded configuration:: Embedding a configuration file into GRUB @end menu @@ -1095,14 +1305,14 @@ Valid keys in @file{/etc/default/grub} are as follows: @item GRUB_DEFAULT The default menu entry. This may be a number, in which case it identifies the Nth entry in the generated menu counted from zero, or the title of a -menu entry, or the special string @samp{saved}. Using the title may be +menu entry, or the special string @samp{saved}. Using the id may be useful if you want to set a menu entry as the default even though there may be a variable number of entries before it. For example, if you have: @verbatim -menuentry 'Example GNU/Linux distribution' --class gnu-linux { +menuentry 'Example GNU/Linux distribution' --class gnu-linux --id example-gnu-linux { ... } @end verbatim @@ -1110,12 +1320,17 @@ menuentry 'Example GNU/Linux distribution' --class gnu-linux { then you can make this the default using: @example -GRUB_DEFAULT='Example GNU/Linux distribution' +GRUB_DEFAULT=example-gnu-linux @end example +Previously it was documented the way to use entry title. While this still +works it's not recommended since titles often contain unstable device names +and may be translated + If you set this to @samp{saved}, then the default menu entry will be that -saved by @samp{GRUB_SAVEDEFAULT}, @command{grub-set-default}, or -@command{grub-reboot}. +saved by @samp{GRUB_SAVEDEFAULT} or @command{grub-set-default}. This relies on +the environment block, which may not be available in all situations +(@pxref{Environment block}). The default is @samp{0}. @@ -1124,7 +1339,7 @@ If this option is set to @samp{true}, then, when an entry is selected, save it as a new default entry for use by future runs of GRUB. This is only useful if @samp{GRUB_DEFAULT=saved}; it is a separate option because @samp{GRUB_DEFAULT=saved} is useful without this option, in conjunction with -@command{grub-set-default} or @command{grub-reboot}. Unset by default. +@command{grub-set-default}. Unset by default. This option relies on the environment block, which may not be available in all situations (@pxref{Environment block}). @@ -1134,22 +1349,26 @@ a key is pressed. The default is @samp{5}. Set to @samp{0} to boot immediately without displaying the menu, or to @samp{-1} to wait indefinitely. -@item GRUB_HIDDEN_TIMEOUT -Wait this many seconds for a key to be pressed before displaying the menu. -If no key is pressed during that time, display the menu for the number of -seconds specified in GRUB_TIMEOUT before booting the default entry. We expect -that most people who use GRUB_HIDDEN_TIMEOUT will want to have GRUB_TIMEOUT set -to @samp{0} so that the menu is not displayed at all unless a key is pressed. -Unset by default. +If @samp{GRUB_TIMEOUT_STYLE} is set to @samp{countdown} or @samp{hidden}, +the timeout is instead counted before the menu is displayed. -@item GRUB_HIDDEN_TIMEOUT_QUIET -In conjunction with @samp{GRUB_HIDDEN_TIMEOUT}, set this to @samp{true} to -suppress the verbose countdown while waiting for a key to be pressed before -displaying the menu. Unset by default. +@item GRUB_TIMEOUT_STYLE +If this option is unset or set to @samp{menu}, then GRUB will display the +menu and then wait for the timeout set by @samp{GRUB_TIMEOUT} to expire +before booting the default entry. Pressing a key interrupts the timeout. + +If this option is set to @samp{countdown} or @samp{hidden}, then, before +displaying the menu, GRUB will wait for the timeout set by @samp{GRUB_TIMEOUT} +to expire. If @key{ESC} or @key{F4} are pressed, or @key{SHIFT} is held down +during that time, it will display the menu and wait for input. If a hotkey +associated with a menu entry is pressed, it will boot the associated menu entry +immediately. If the timeout expires before either of these happens, it will +boot the default entry. In the @samp{countdown} case, it will show a one-line +indication of the remaining time. @item GRUB_DEFAULT_BUTTON @itemx GRUB_TIMEOUT_BUTTON -@itemx GRUB_HIDDEN_TIMEOUT_BUTTON +@itemx GRUB_TIMEOUT_STYLE_BUTTON @itemx GRUB_BUTTON_CMOS_ADDRESS Variants of the corresponding variables without the @samp{_BUTTON} suffix, used to support vendor-specific power buttons. @xref{Vendor power-on keys}. @@ -1163,9 +1382,9 @@ Select the terminal input device. You may select multiple devices here, separated by spaces. Valid terminal input names depend on the platform, but may include -@samp{console} (PC BIOS and EFI consoles), @samp{serial} (serial terminal), -@samp{ofconsole} (Open Firmware console), @samp{at_keyboard} (PC AT -keyboard, mainly useful with Coreboot), or @samp{usb_keyboard} (USB keyboard +@samp{console} (native platform console), @samp{serial} (serial terminal), +@samp{serial_} (serial terminal with explicit port selection), +@samp{at_keyboard} (PC AT keyboard), or @samp{usb_keyboard} (USB keyboard using the HID Boot Protocol, for cases where the firmware does not handle this). @@ -1176,9 +1395,21 @@ Select the terminal output device. You may select multiple devices here, separated by spaces. Valid terminal output names depend on the platform, but may include -@samp{console} (PC BIOS and EFI consoles), @samp{serial} (serial terminal), -@samp{gfxterm} (graphics-mode output), @samp{ofconsole} (Open Firmware -console), or @samp{vga_text} (VGA text output, mainly useful with Coreboot). +@samp{console} (native platform console), @samp{serial} (serial terminal), +@samp{serial_} (serial terminal with explicit port selection), +@samp{gfxterm} (graphics-mode output), @samp{vga_text} (VGA text output), +@samp{mda_text} (MDA text output), @samp{morse} (Morse-coding using system +beeper) or @samp{spkmodem} (simple data protocol using system speaker). + +@samp{spkmodem} is useful when no serial port is available. Connect the output +of sending system (where GRUB is running) to line-in of receiving system +(usually developer machine). +On receiving system compile @samp{spkmodem-recv} from +@samp{util/spkmodem-recv.c} and run: + +@example +parecord --channels=1 --rate=48000 --format=s16le | ./spkmodem-recv +@end example The default is to use the platform's native terminal output. @@ -1200,6 +1431,13 @@ entry for recovery mode. This option lists command-line arguments to add only to the default menu entry, after those listed in @samp{GRUB_CMDLINE_LINUX}. +@item GRUB_CMDLINE_LINUX_RECOVERY +Unless @samp{GRUB_DISABLE_RECOVERY} is set to @samp{true}, two menu +entries will be generated for each Linux kernel: one default entry and one +entry for recovery mode. This option lists command-line arguments to add +only to the recovery menu entry, before those listed in @samp{GRUB_CMDLINE_LINUX}. +The default is @samp{single}. + @item GRUB_CMDLINE_NETBSD @itemx GRUB_CMDLINE_NETBSD_DEFAULT As @samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT}, but for @@ -1210,15 +1448,43 @@ As @samp{GRUB_CMDLINE_LINUX}, but for GNU Mach. @item GRUB_CMDLINE_XEN @itemx GRUB_CMDLINE_XEN_DEFAULT -The values of these options are appended to the values of -@samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT} for Linux -and Xen menu entries. +The values of these options are passed to Xen hypervisor Xen menu entries, +for all respectively normal entries. @item GRUB_CMDLINE_LINUX_XEN_REPLACE @item GRUB_CMDLINE_LINUX_XEN_REPLACE_DEFAULT The values of these options replace the values of @samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT} for Linux and Xen menu entries. +@item GRUB_TOP_LEVEL +@item GRUB_TOP_LEVEL_XEN +This option should be an absolute path to a kernel image. If provided, the +image specified will be made the top-level entry if it is found in the scan. + +@item GRUB_TOP_LEVEL_OS_PROBER +This option should be a line of output from @command{os-prober}. As +@samp{GRUB_TOP_LEVEL}, if provided, the image specified will be made the +top-level entry if it is found in the scan. + +@item GRUB_EARLY_INITRD_LINUX_CUSTOM +@itemx GRUB_EARLY_INITRD_LINUX_STOCK +List of space-separated early initrd images to be loaded from @samp{/boot}. +This is for loading things like CPU microcode, firmware, ACPI tables, crypto +keys, and so on. These early images will be loaded in the order declared, +and all will be loaded before the actual functional initrd image. + +@samp{GRUB_EARLY_INITRD_LINUX_STOCK} is for your distribution to declare +images that are provided by the distribution. It should not be modified +without understanding the consequences. They will be loaded first. + +@samp{GRUB_EARLY_INITRD_LINUX_CUSTOM} is for your custom created images. + +The default stock images are as follows, though they may be overridden by +your distribution: +@example +intel-uc.img intel-ucode.img amd-uc.img amd-ucode.img early_ucode.cpio microcode.cpio +@end example + @item GRUB_DISABLE_LINUX_UUID Normally, @command{grub-mkconfig} will generate menu entries that use universally-unique identifiers (UUIDs) to identify the root filesystem to @@ -1226,10 +1492,30 @@ the Linux kernel, using a @samp{root=UUID=...} kernel parameter. This is usually more reliable, but in some cases it may not be appropriate. To disable the use of UUIDs, set this option to @samp{true}. +@item GRUB_DISABLE_LINUX_PARTUUID +If @command{grub-mkconfig} cannot identify the root filesystem via its +universally-unique indentifier (UUID), @command{grub-mkconfig} can use the UUID +of the partition containing the filesystem to identify the root filesystem to +the Linux kernel via a @samp{root=PARTUUID=...} kernel parameter. This is not +as reliable as using the filesystem UUID, but is more reliable than using the +Linux device names. When @samp{GRUB_DISABLE_LINUX_PARTUUID} is set to +@samp{false}, the Linux kernel version must be 2.6.37 (3.10 for systems using +the MSDOS partition scheme) or newer. This option defaults to @samp{true}. To +enable the use of partition UUIDs, set this option to @samp{false}. + @item GRUB_DISABLE_RECOVERY If this option is set to @samp{true}, disable the generation of recovery mode menu entries. +@item GRUB_DISABLE_UUID +Normally, @command{grub-mkconfig} will generate menu entries that use +universally-unique identifiers (UUIDs) to identify various filesystems to +search for files. This is usually more reliable, but in some cases it may +not be appropriate. To disable this use of UUIDs, set this option to +@samp{true}. Setting this option to @samp{true}, will also set the options +@samp{GRUB_DISABLE_LINUX_UUID} and @samp{GRUB_DISABLE_LINUX_PARTUUID} to +@samp{true}, unless they have been explicitly set to @samp{false}. + @item GRUB_VIDEO_BACKEND If graphical video support is required, either because the @samp{gfxterm} graphical terminal is in use or because @samp{GRUB_GFXPAYLOAD_LINUX} is set, @@ -1251,7 +1537,8 @@ resolution. @xref{gfxmode}. Set a background image for use with the @samp{gfxterm} graphical terminal. The value of this option must be a file readable by GRUB at boot time, and it must end with @file{.png}, @file{.tga}, @file{.jpg}, or @file{.jpeg}. -The image will be scaled if necessary to fit the screen. +The image will be scaled if necessary to fit the screen. Image height and +width will be restricted by an artificial limit of 16384. @item GRUB_THEME Set a theme for use with the @samp{gfxterm} graphical terminal. @@ -1270,10 +1557,38 @@ boot sequence. If you have problems, set this option to @samp{text} and GRUB will tell Linux to boot in normal text mode. @item GRUB_DISABLE_OS_PROBER -Normally, @command{grub-mkconfig} will try to use the external -@command{os-prober} program, if installed, to discover other operating -systems installed on the same system and generate appropriate menu entries -for them. Set this option to @samp{true} to disable this. +The @command{grub-mkconfig} has a feature to use the external +@command{os-prober} program to discover other operating systems installed on +the same machine and generate appropriate menu entries for them. It is disabled +by default since automatic and silent execution of @command{os-prober}, and +creating boot entries based on that data, is a potential attack vector. Set +this option to @samp{false} to enable this feature in the +@command{grub-mkconfig} command. + +@item GRUB_OS_PROBER_SKIP_LIST +List of space-separated case insensitive UUIDs of filesystems to be ignored +from os-prober output. For EFI chainloaders it's @@. For +backward compatibility with previous behaviour, @@/dev/* is also accepted +for non-EFI chainloaders even if the device does not match, and comma and +semicolon are also accepted as separator. + +@item GRUB_DISABLE_SUBMENU +Normally, @command{grub-mkconfig} will generate top level menu entry for +the kernel with highest version number and put all other found kernels +or alternative menu entries for recovery mode in submenu. For entries returned +by @command{os-prober} first entry will be put on top level and all others +in submenu. If this option is set to @samp{true}, flat menu with all entries +on top level will be generated instead. Changing this option will require +changing existing values of @samp{GRUB_DEFAULT}, @samp{fallback} (@pxref{fallback}) +and @samp{default} (@pxref{default}) environment variables as well as saved +default entry using @command{grub-set-default} and value used with +@command{grub-reboot}. + +@item GRUB_ENABLE_CRYPTODISK +If set to @samp{y}, @command{grub-mkconfig} and @command{grub-install} will +check for encrypted disks and generate additional commands needed to access +them during boot. Note that in this case unattended boot is not possible +because GRUB will wait for passphrase to unlock encrypted container. @item GRUB_INIT_TUNE Play a tune on the speaker when GRUB starts. This is particularly useful @@ -1291,12 +1606,98 @@ Each module will be loaded as early as possible, at the start of @end table +The following options are still accepted for compatibility with existing +configurations, but have better replacements: + +@table @samp +@item GRUB_HIDDEN_TIMEOUT +Wait this many seconds before displaying the menu. If @key{ESC} or @key{F4} are +pressed, or @key{SHIFT} is held down during that time, display the menu and wait +for input according to @samp{GRUB_TIMEOUT}. If a hotkey associated with a menu +entry is pressed, boot the associated menu entry immediately. If the timeout +expires before either of these happens, display the menu for the number of +seconds specified in @samp{GRUB_TIMEOUT} before booting the default entry. + +If you set @samp{GRUB_HIDDEN_TIMEOUT}, you should also set +@samp{GRUB_TIMEOUT=0} so that the menu is not displayed at all unless +@key{ESC} or @key{F4} are pressed, or @key{SHIFT} is held down. + +This option is unset by default, and is deprecated in favour of the less +confusing @samp{GRUB_TIMEOUT_STYLE=countdown} or +@samp{GRUB_TIMEOUT_STYLE=hidden}. + +@item GRUB_HIDDEN_TIMEOUT_QUIET +In conjunction with @samp{GRUB_HIDDEN_TIMEOUT}, set this to @samp{true} to +suppress the verbose countdown while waiting for a key to be pressed before +displaying the menu. + +This option is unset by default, and is deprecated in favour of the less +confusing @samp{GRUB_TIMEOUT_STYLE=countdown}. + +@item GRUB_HIDDEN_TIMEOUT_BUTTON +Variant of @samp{GRUB_HIDDEN_TIMEOUT}, used to support vendor-specific power +buttons. @xref{Vendor power-on keys}. + +This option is unset by default, and is deprecated in favour of the less +confusing @samp{GRUB_TIMEOUT_STYLE=countdown} or +@samp{GRUB_TIMEOUT_STYLE=hidden}. + +@end table + For more detailed customisation of @command{grub-mkconfig}'s output, you may edit the scripts in @file{/etc/grub.d} directly. @file{/etc/grub.d/40_custom} is particularly useful for adding entire custom menu entries; simply type the menu entries you want to add at the end of that file, making sure to leave at least the first two lines intact. +@node Root Identification Heuristics +@section Root Identification Heuristics +If the target operating system uses the Linux kernel, @command{grub-mkconfig} +attempts to identify the root file system via a heuristic algoirthm. This +algorithm selects the identification method of the root file system by +considering three factors. The first is if an initrd for the target operating +system is also present. The second is @samp{GRUB_DISABLE_LINUX_UUID} and if set +to @samp{true}, prevents @command{grub-mkconfig} from identifying the root file +system by its UUID. The third is @samp{GRUB_DISABLE_LINUX_PARTUUID} and if set +to @samp{true}, prevents @command{grub-mkconfig} from identifying the root file +system via the UUID of its enclosing partition. If the variables are assigned +any other value, that value is considered equivalent to @samp{false}. The +variables are also considered to be set to @samp{false} if they are not set. + +When booting, the Linux kernel will delegate the task of mounting the root +filesystem to the initrd. Most initrd images determine the root file system by +checking the Linux kernel's command-line for the @samp{root} key and use its +value as the identification method of the root file system. To improve the +reliability of booting, most initrd images also allow the root file system to be +identified by its UUID. Because of this behavior, the @command{grub-mkconfig} +command will set @samp{root} to @samp{root=UUID=...} to provide the initrd with +the filesystem UUID of the root file system. + +If no initrd is detected or @samp{GRUB_DISABLE_LINUX_UUID} is set to @samp{true} +then @command{grub-command} will identify the root filesystem by setting the +kernel command-line variable @samp{root} to @samp{root=PARTUUID=...} unless +@samp{GRUB_DISABLE_LINUX_PARTUUID} is also set to @samp{true}. If +@samp{GRUB_DISABLE_LINUX_PARTUUID} is also set to @samp{true}, +@command{grub-command} will identify by its Linux device name. + +The following table summarizes the behavior of the @command{grub-mkconfig} +command. + +@multitable {detected} {GRUB_DISABLE_LINUX_PARTUUID} {GRUB_DISABLE_LINUX_UUID} {Linux Root} +@headitem Initrd detected @tab GRUB_DISABLE_LINUX_PARTUUID Set To @tab GRUB_DISABLE_LINUX_UUID Set To @tab Linux Root ID Method +@item false @tab false @tab false @tab part UUID +@item false @tab false @tab true @tab part UUID +@item false @tab true @tab false @tab dev name +@item false @tab true @tab true @tab dev name +@item true @tab false @tab false @tab fs UUID +@item true @tab false @tab true @tab part UUID +@item true @tab true @tab false @tab fs UUID +@item true @tab true @tab true @tab dev name +@end multitable + +Remember, @samp{GRUB_DISABLE_LINUX_PARTUUID} and @samp{GRUB_DISABLE_LINUX_UUID} +are also considered to be set to @samp{true} and @samp{false}, respectively, +when they are unset. @node Shell-like scripting @section Writing full configuration files directly @@ -1415,18 +1816,20 @@ of the last command that executes. If the expansion of the items following status is 0. @item if @var{list}; then @var{list}; [elif @var{list}; then @var{list};] @dots{} [else @var{list};] fi -The @code{if} @var{list} is executed. If its exit status is zero, the -@code{then} @var{list} is executed. Otherwise, each @code{elif} @var{list} -is executed in turn, and if its exit status is zero, the corresponding -@code{then} @var{list} is executed and the command completes. Otherwise, -the @code{else} @var{list} is executed, if present. The exit status is the -exit status of the last command executed, or zero if no condition tested -true. +The @code{if} @var{list} is executed, where @var{list} is a series of +@dfn{simple command}s separated by a ";". If its exit status of the last +command is zero, the @code{then} @var{list} is executed. Otherwise, each +@code{elif} @var{list} is executed in turn, and if its last command's exit +status is zero, the corresponding @code{then} @var{list} is executed and the +command completes. Otherwise, the @code{else} @var{list} is executed, if +present. The exit status is the exit status of the last command executed, or +zero if no condition tested true. @item while @var{cond}; do @var{list}; done @itemx until @var{cond}; do @var{list}; done The @code{while} command continuously executes the @code{do} @var{list} as -long as the last command in @var{cond} returns an exit status of zero. The +long as the last command in @var{cond} returns an exit status of zero, where +@var{cond} is a list of @dfn{simple command}s separated by a ";". The @code{until} command is identical to the @code{while} command, except that the test is negated; the @code{do} @var{list} is executed as long as the last command in @var{cond} returns a non-zero exit status. The exit status @@ -1442,7 +1845,7 @@ definitions do not affect the exit status in @code{$?}. When executed, the exit status of a function is the exit status of the last command executed in the body. -@item menuentry @var{title} [@option{--class=class} @dots{}] [@option{--users=users}] [@option{--unrestricted}] [@option{--hotkey=key}] @{ @var{command}; @dots{} @} +@item menuentry @var{title} [@option{--class=class} @dots{}] [@option{--users=users}] [@option{--unrestricted}] [@option{--hotkey=key}] [@option{--id=id}] @{ @var{command}; @dots{} @} @xref{menuentry}. @end table @@ -1474,6 +1877,10 @@ Causes a function to exit with the return value specified by @code{n}. If in the function body. If used outside a function the return status is false. +@item setparams [@code{arg}] @dots{} +Replace positional parameters starting with @code{$1} with arguments to +@command{setparams}. + @item shift [@code{n}] The positional parameters from @code{n}+1 @dots{} are renamed to @code{$1}@dots{}. Parameters represented by the numbers @code{$#} down to @@ -1490,10 +1897,9 @@ than zero; otherwise 0. @section Multi-boot manual config Currently autogenerating config files for multi-boot environments depends on -os-prober and has several shortcomings. While fixing it is scheduled for the -next release, meanwhile you can make use of the power of GRUB syntax and do it -yourself. A possible configuration is detailed here, feel free to adjust to your -needs. +os-prober and has several shortcomings. Due to that it is disabled by default. +It is advised to use the power of GRUB syntax and do it yourself. A possible +configuration is detailed here, feel free to adjust to your needs. First create a separate GRUB partition, big enough to hold GRUB. Some of the following entries show how to load OS installer images from this same partition, @@ -1578,7 +1984,7 @@ menuentry "Debian sid installer" @{ Notes: @itemize -@item Argument to search after --label is FS LABEL. You can also use UUIDs with --fs-uuid UUID instead of --label LABEL. You could also use direct @code{root=hd0,msdosX} but this is not recommened due to device name instability. +@item Argument to search after --label is FS LABEL. You can also use UUIDs with --fs-uuid UUID instead of --label LABEL. You could also use direct @code{root=hd0,msdosX} but this is not recommended due to device name instability. @end itemize @node Embedded configuration @@ -1671,8 +2077,8 @@ Colors can be specified in several ways: The fonts GRUB uses ``PFF2 font format'' bitmap fonts. Fonts are specified with full font names. Currently there is no provision for a preference list of fonts, or deriving one font from another. -Fonts are loaded with the ``loadfont'' command in GRUB. To see the list of -loaded fonts, execute the ``lsfonts'' command. If there are too many fonts to +Fonts are loaded with the ``loadfont'' command in GRUB (@ref{loadfont}). To see the list of +loaded fonts, execute the ``lsfonts'' command (@ref{lsfonts}). If there are too many fonts to fit on screen, do ``set pager=1'' before executing ``lsfonts''. @@ -1812,15 +2218,60 @@ In this example, name3 is assigned a color value. @subsection Global Property List @multitable @columnfractions 0.3 0.6 -@item title-text @tab Specifies the text to display at the top center of the screen as a title. -@item title-font @tab Defines the font used for the title message at the top of the screen. -@item title-color @tab Defines the color of the title message. -@item message-font @tab Defines the font used for messages, such as when GRUB is unable to automatically boot an entry. -@item message-color @tab Defines the color of the message text. -@item message-bg-color @tab Defines the background color of the message text area. -@item desktop-image @tab Specifies the image to use as the background. It will be scaled to fit the screen size. -@item desktop-color @tab Specifies the color for the background if *desktop-image* is not specified. -@item terminal-box @tab Specifies the file name pattern for the styled box slices used for the command line terminal window. For example, ``terminal-box: terminal_*.png'' will use the images ``terminal_c.png`` as the center area, ``terminal_n.png`` as the north (top) edge, ``terminal_nw.png`` as the northwest (upper left) corner, and so on. If the image for any slice is not found, it will simply be left empty. +@item title-text + @tab Specifies the text to display at the top center of the screen as a title. +@item title-font + @tab Defines the font used for the title message at the top of the screen. +@item title-color + @tab Defines the color of the title message. +@item message-font + @tab Currently unused. Left for backward compatibility. +@item message-color + @tab Currently unused. Left for backward compatibility. +@item message-bg-color + @tab Currently unused. Left for backward compatibility. +@item desktop-image + @tab Specifies the image to use as the background. It will be scaled + to fit the screen size or proportionally scaled depending on the scale + method. +@item desktop-image-scale-method + @tab Specifies the scaling method for the *desktop-image*. Options are + ``stretch``, ``crop``, ``padding``, ``fitwidth``, ``fitheight``. + ``stretch`` for fitting the screen size. Otherwise it is proportional + scaling of a part of *desktop-image* to the part of the screen. + ``crop`` part of the *desktop-image* will be proportionally scaled to + fit the screen sizes. ``padding`` the entire *desktop-image* will be + contained on the screen. ``fitwidth`` for fitting the *desktop-image*'s + width with screen width. ``fitheight`` for fitting the *desktop-image*'s + height with the screen height. Default is ``stretch``. +@item desktop-image-h-align + @tab Specifies the horizontal alignment of the *desktop-image* if + *desktop-image-scale-method* isn't equeal to ``stretch``. Options are + ``left``, ``center``, ``right``. Default is ``center``. +@item desktop-image-v-align + @tab Specifies the vertical alignment of the *desktop-image* if + *desktop-image-scale-method* isn't equeal to ``stretch``. Options are + ``top``, ``center``, ``bottom``. Default is ``center``. +@item desktop-color + @tab Specifies the color for the background if *desktop-image* is not + specified. +@item terminal-box + @tab Specifies the file name pattern for the styled box slices used for the + command line terminal window. For example, ``terminal-box: terminal_*.png`` + will use the images ``terminal_c.png`` as the center area, ``terminal_n.png`` + as the north (top) edge, ``terminal_nw.png`` as the northwest (upper left) + corner, and so on. If the image for any slice is not found, it will simply + be left empty. +@item terminal-border + @tab Specifies the border width of the terminal window. +@item terminal-left + @tab Specifies the left coordinate of the terminal window. +@item terminal-top + @tab Specifies the top coordinate of the terminal window. +@item terminal-width + @tab Specifies the width of the terminal window. +@item terminal-height + @tab Specifies the height of the terminal window. @end multitable @@ -1854,21 +2305,34 @@ The following is a list of the components and the properties they support. Properties: @multitable @columnfractions 0.2 0.7 - @item text @tab The text to display. - @item font @tab The font to use for text display. - @item color @tab The color of the text. - @item align @tab The horizontal alignment of the text within the component. Options are ``left``, ``center``, and ``right``. + @item id + @tab Set to ``__timeout__`` to display the time elapsed to an automatical + boot of the default entry. + @item text + @tab The text to display. If ``id`` is set to ``__timeout__`` and no + ``text`` property is set then the amount of seconds will be shown. + If set to ``@@KEYMAP_SHORT@@``, ``@@KEYMAP_MIDDLE@@`` or + ``@@KEYMAP_LONG@@`` then predefined hotkey information will be shown. + @item font + @tab The font to use for text display. + @item color + @tab The color of the text. + @item align + @tab The horizontal alignment of the text within the component. + Options are ``left``, ``center`` and ``right``. + @item visible + @tab Set to ``false`` to hide the label. @end multitable @item image - A component that displays an image. The image is scaled to fit the - component, although the preferred size defaults to the image's original - size unless the ``preferred_size`` property is explicitly set. + A component that displays an image. The image is scaled to fit + the component. Properties: @multitable @columnfractions 0.2 0.7 - @item file @tab The full path to the image file to load. + @item file + @tab The full path to the image file to load. @end multitable @item progress_bar @@ -1878,17 +2342,45 @@ The following is a list of the components and the properties they support. Properties: @multitable @columnfractions 0.2 0.7 - @item fg_color @tab The foreground color for plain solid color rendering. - @item bg_color @tab The background color for plain solid color rendering. - @item border_color @tab The border color for plain solid color rendering. - @item text_color @tab The text color. - @item show_text @tab Boolean value indicating whether or not text should be displayed on the progress bar. If set to *false*, then no text will be displayed on the bar. If set to any other value, text will be displayed on the bar. - @item bar_style @tab The styled box specification for the frame of the progress bar. Example: ``progress_frame_*.png`` - @item highlight_style @tab The styled box specification for the highlighted region of the progress bar. This box will be used to paint just the highlighted region of the bar, and will be increased in size as the bar nears completion. Example: ``progress_hl_*.png``. - @item text @tab The text to display on the progress bar. If the progress bar's ID is set to ``__timeout__``, then GRUB will updated this property with an informative message as the timeout approaches. - @item value @tab The progress bar current value. Normally not set manually. - @item start @tab The progress bar start value. Normally not set manually. - @item end @tab The progress bar end value. Normally not set manually. + @item id + @tab Set to ``__timeout__`` to display the time elapsed to an automatical + boot of the default entry. + @item fg_color + @tab The foreground color for plain solid color rendering. + @item bg_color + @tab The background color for plain solid color rendering. + @item border_color + @tab The border color for plain solid color rendering. + @item text_color + @tab The text color. + @item bar_style + @tab The styled box specification for the frame of the progress bar. + Example: ``progress_frame_*.png`` + If the value is equal to ``highlight_style`` then no styled boxes + will be shown. + @item highlight_style + @tab The styled box specification for the highlighted region of the + progress bar. This box will be used to paint just the highlighted region + of the bar, and will be increased in size as the bar nears completion. + Example: ``progress_hl_*.png``. + If the value is equal to ``bar_style`` then no styled boxes + will be shown. + @item highlight_overlay + @tab If this option is set to ``true`` then the highlight box + side slices (every slice except the center slice) will overlay the + frame box side slices. And the center slice of the highlight box + can move all the way (from top to bottom), being drawn on the center + slice of the frame box. That way we can make a progress bar with + round-shaped edges so there won't be a free space from the highlight to + the frame in top and bottom scrollbar positions. Default is ``false``. + @item font + @tab The font to use for progress bar. + @item text + @tab The text to display on the progress bar. If the progress bar's ID + is set to ``__timeout__`` and the value of this property is set to + ``@@TIMEOUT_NOTIFICATION_SHORT@@``, ``@@TIMEOUT_NOTIFICATION_MIDDLE@@`` + or ``@@TIMEOUT_NOTIFICATION_LONG@@``, then GRUB will update this + property with an informative message as the timeout approaches. @end multitable @item circular_progress @@ -1902,6 +2394,9 @@ The following is a list of the components and the properties they support. Properties: @multitable @columnfractions 0.3 0.6 + @item id + @tab Set to ``__timeout__`` to display the time elapsed to an automatical + boot of the default entry. @item center_bitmap @tab The file name of the image to draw in the center of the component. @item tick_bitmap @@ -1911,14 +2406,13 @@ The following is a list of the components and the properties they support. @item ticks_disappear @tab Boolean value indicating whether tick marks should progressively appear, or progressively disappear as *value* approaches *end*. Specify - ``true`` or ``false``. - @item value - @tab The progress indicator current value. Normally not set manually. - @item start - @tab The progress indicator start value. Normally not set manually. - @item end - @tab The progress indicator end value. Normally not set manually. + ``true`` or ``false``. Default is ``false``. + @item start_angle + @tab The position of the first tick mark to appear or disappear. + Measured in "parrots", 1 "parrot" = 1 / 256 of the full circle. + Use values ``xxx deg`` or ``xxx \xc2\xb0`` to set the angle in degrees. @end multitable + @item boot_menu Displays the GRUB boot menu. It allows selecting items and executing them. @@ -1952,6 +2446,8 @@ The following is a list of the components and the properties they support. @tab The image file pattern for the menu frame styled box. Example: ``menu_*.png`` (this will use images such as ``menu_c.png``, ``menu_w.png``, `menu_nw.png``, etc.) + @item item_pixmap_style + @tab The image file pattern for the item styled box. @item selected_item_pixmap_style @tab The image file pattern for the selected item highlight styled box. @item scrollbar @@ -1964,10 +2460,39 @@ The following is a list of the components and the properties they support. @tab The image file pattern for the scroll bar thumb (the part of the scroll bar that moves as scrolling occurs). Example: ``scrollbar_thumb_*.png`` - @item max_items_shown - @tab The maximum number of items to show on the menu. If there are more than - *max_items_shown* items in the menu, the list will scroll to make all - items accessible. + @item scrollbar_thumb_overlay + @tab If this option is set to ``true`` then the scrollbar thumb + side slices (every slice except the center slice) will overlay the + scrollbar frame side slices. And the center slice of the scrollbar_thumb + can move all the way (from top to bottom), being drawn on the center + slice of the scrollbar frame. That way we can make a scrollbar with + round-shaped edges so there won't be a free space from the thumb to + the frame in top and bottom scrollbar positions. Default is ``false``. + @item scrollbar_slice + @tab The menu frame styled box's slice in which the scrollbar will be + drawn. Possible values are ``west``, ``center``, ``east`` (default). + ``west`` - the scrollbar will be drawn in the west slice (right-aligned). + ``east`` - the scrollbar will be drawn in the east slice (left-aligned). + ``center`` - the scrollbar will be drawn in the center slice. + Note: in case of ``center`` slice: + a) If the scrollbar should be drawn then boot menu entry's width is + decreased by the scrollbar's width and the scrollbar is drawn at the + right side of the center slice. + b) If the scrollbar won't be drawn then the boot menu entry's width + is the width of the center slice. + c) We don't necessary need the menu pixmap box to display the scrollbar. + @item scrollbar_left_pad + @tab The left scrollbar padding in pixels. + Unused if ``scrollbar_slice`` is ``west``. + @item scrollbar_right_pad + @tab The right scrollbar padding in pixels. + Unused if ``scrollbar_slice`` is ``east``. + @item scrollbar_top_pad + @tab The top scrollbar padding in pixels. + @item scrollbar_bottom_pad + @tab The bottom scrollbar padding in pixels. + @item visible + @tab Set to ``false`` to hide the boot menu. @end multitable @item canvas @@ -2011,7 +2536,10 @@ The following properties are supported by all components: recognizes: @multitable @columnfractions 0.2 0.7 - @item ``__timeout__`` @tab Any component with this ID will have its *text*, *start*, *end*, *value*, and *visible* properties set by GRUB when it is counting down to an automatic boot of the default menu entry. + @item ``__timeout__`` + @tab Component with this ID will be updated by GRUB and will indicate + time elapsed to an automatical boot of the default entry. + Affected components: ``label``, ``circular_progress``, ``progress_bar``. @end multitable @end table @@ -2020,67 +2548,147 @@ The following properties are supported by all components: @node Network @chapter Booting GRUB from the network -The following instructions only work on PC BIOS systems where the Preboot -eXecution Environment (PXE) is available. +The following instructions don't work for *-emu, i386-qemu, i386-coreboot, +i386-multiboot, mips_loongson, mips-arc and mips_qemu_mips -To generate a PXE boot image, run: +To generate a netbootable directory, run: @example @group -grub-mkimage --format=i386-pc-pxe --output=grub.pxe --prefix='(pxe)/boot/grub' pxe pxecmd +grub-mknetdir --net-directory=/srv/tftp --subdir=/boot/grub -d /usr/lib/grub/ @end group @end example -Copy @file{grub.pxe}, @file{/boot/grub/*.mod}, and @file{/boot/grub/*.lst} -to the PXE (TFTP) server, ensuring that @file{*.mod} and @file{*.lst} are -accessible via the @file{/boot/grub/} path from the TFTP server root. Set -the DHCP server configuration to offer @file{grub.pxe} as the boot file (the -@samp{filename} option in ISC dhcpd). +E.g. for i386-pc: -You can also use the @command{grub-mknetdir} utility to generate an image -and a GRUB directory tree, rather than copying files around manually. +@example +@group +grub-mknetdir --net-directory=/srv/tftp --subdir=/boot/grub -d /usr/lib/grub/i386-pc +@end group +@end example + +Then follow instructions printed out by grub-mknetdir on configuring your DHCP +server. + +The grub.cfg file is placed in the same directory as the path output by +grub-mknetdir hereafter referred to as FWPATH. GRUB will search for its +configuration files in order using the following rules where the appended +value corresponds to a value on the client machine. + +@example +@group +@samp{(FWPATH)}/grub.cfg-@samp{(UUID OF MACHINE)} +@samp{(FWPATH)}/grub.cfg-01-@samp{(MAC ADDRESS OF NIC)} +@samp{(FWPATH)}/grub.cfg-@samp{(IPv4 OR IPv6 ADDRESS)} +@samp{(FWPATH)}/grub.cfg +@end group +@end example + +The UUID is the Client Machine Identifier Option Definition as specified in +RFC 4578. The client will only attempt to look up a UUID config file if it +was provided by the DHCP server. + +The client will only attempt to look up an IPv6 address config once, however, +it will try the IPv4 multiple times. The concrete example below shows what +would happen under the IPv4 case. + +@example +@group +UUID: 7726a678-7fc0-4853-a4f6-c85ac36a120a +MAC: 52:54:00:ec:33:81 +IPV4: 10.0.0.130 (0A000082) +@end group +@end example + +@example +@group +@samp{(FWPATH)}/grub.cfg-7726a678-7fc0-4853-a4f6-c85ac36a120a +@samp{(FWPATH)}/grub.cfg-01-52-54-00-ec-33-81 +@samp{(FWPATH)}/grub.cfg-0A000082 +@samp{(FWPATH)}/grub.cfg-0A00008 +@samp{(FWPATH)}/grub.cfg-0A0000 +@samp{(FWPATH)}/grub.cfg-0A000 +@samp{(FWPATH)}/grub.cfg-0A00 +@samp{(FWPATH)}/grub.cfg-0A0 +@samp{(FWPATH)}/grub.cfg-0A +@samp{(FWPATH)}/grub.cfg-0 +@samp{(FWPATH)}/grub.cfg +@end group +@end example + +This feature is enabled by default but it can be disabled by setting the +@samp{feature_net_search_cfg} to @samp{n}. Since this happens before the +configuration file is read by GRUB, this option has to be disabled in an +embedded configuration file (@pxref{Embedded configuration}). After GRUB has started, files on the TFTP server will be accessible via the -@samp{(pxe)} device. +@samp{(tftp)} device. -The server and gateway IP address can be controlled by changing the -@samp{(pxe)} device name to @samp{(pxe:@var{server-ip})} or -@samp{(pxe:@var{server-ip}:@var{gateway-ip})}. Note that this should be -changed both in the prefix and in any references to the device name in the -configuration file. +The server IP address can be controlled by changing the +@samp{(tftp)} device name to @samp{(tftp,@var{server-ip})}. Note that +this should be changed both in the prefix and in any references to the +device name in the configuration file. GRUB provides several environment variables which may be used to inspect or -change the behaviour of the PXE device: +change the behaviour of the PXE device. In the following description +@var{} is placeholder for the name of network interface (platform +dependent): @table @samp -@item net_pxe_ip -The IP address of this machine. Read-only. +@item net_@var{}_ip +The network interface's IP address. Read-only. -@item net_pxe_mac +@item net_@var{}_mac The network interface's MAC address. Read-only. -@item net_pxe_hostname +@item net_@var{}_clientid +The client id provided by DHCP. Read-only. + +@item net_@var{}_clientuuid +The client uuid provided by DHCP. Read-only. + +@item net_@var{}_hostname The client host name provided by DHCP. Read-only. -@item net_pxe_domain +@item net_@var{}_domain The client domain name provided by DHCP. Read-only. -@item net_pxe_rootpath +@item net_@var{}_rootpath The path to the client's root disk provided by DHCP. Read-only. -@item net_pxe_extensionspath +@item net_@var{}_extensionspath The path to additional DHCP vendor extensions provided by DHCP. Read-only. -@item net_pxe_boot_file +@item net_@var{}_boot_file The boot file name provided by DHCP. Read-only. -@item net_pxe_dhcp_server_name +@item net_@var{}_dhcp_server_name The name of the DHCP server responsible for these boot parameters. Read-only. +@item net_@var{}_next_server +The IP address of the next (usually, TFTP) server provided by DHCP. +Read-only. + +@item net_default_interface +Initially set to name of network interface that was used to load grub. +Read-write, although setting it affects only interpretation of +@samp{net_default_ip} and @samp{net_default_mac} + +@item net_default_ip +The IP address of default interface. Read-only. This is alias for the +@samp{net_$@{net_default_interface@}_ip}. + +@item net_default_mac +The default interface's MAC address. Read-only. This is alias for the +@samp{net_$@{net_default_interface@}_mac}. + @item net_default_server -The default server. Read-write, although setting this is only useful -before opening a network device. +The default server used by network drives (@pxref{Device syntax}). Read-write, +although setting this is only useful before opening a network device. + +@item pxe_default_server +This performs the same function as @samp{net_default_server}. @end table @@ -2112,8 +2720,11 @@ grub> @kbd{terminal_input serial; terminal_output serial} The command @command{serial} initializes the serial unit 0 with the speed 9600bps. The serial unit 0 is usually called @samp{COM1}, so, if you want to use COM2, you must specify @samp{--unit=1} instead. This -command accepts many other options, so please refer to @ref{serial}, -for more details. +command accepts many other options, @pxref{serial} for more details. + +Without argument or with @samp{--port=auto}, GRUB will attempt to use +ACPI when available to auto-detect the default serial port and its +configuration. The commands @command{terminal_input} (@pxref{terminal_input}) and @command{terminal_output} (@pxref{terminal_output}) choose which type of @@ -2127,31 +2738,38 @@ command. However, note that GRUB assumes that your terminal emulator is compatible with VT100 by default. This is true for most terminal -emulators nowadays, but you should pass the option @option{--dumb} to -the command if your terminal emulator is not VT100-compatible or -implements few VT100 escape sequences. If you specify this option then -GRUB provides you with an alternative menu interface, because the normal -menu requires several fancy features of your terminal. +emulators nowadays. However if your terminal emulator is not VT100-compatible +or implements few VT100 escape sequences, you shoud tell GRUB that the +terminal is dumb using the @command{terminfo} (@pxref{terminfo}) command. +This will have GRUB provide you with an alternative menu interface, because +the normal menu requires several fancy features of your terminal. @node Vendor power-on keys @chapter Using GRUB with vendor power-on keys -Some laptop vendors provide an additional power-on button which boots another -OS. GRUB supports such buttons with the @samp{GRUB_TIMEOUT_BUTTON}, -@samp{GRUB_DEFAULT_BUTTON}, @samp{GRUB_HIDDEN_TIMEOUT_BUTTON} and +Some laptop vendors provide an additional power-on button which boots +another OS. GRUB supports such buttons with the @samp{GRUB_TIMEOUT_BUTTON}, +@samp{GRUB_TIMEOUT_STYLE_BUTTON}, @samp{GRUB_DEFAULT_BUTTON}, and @samp{GRUB_BUTTON_CMOS_ADDRESS} variables in default/grub (@pxref{Simple -configuration}). @samp{GRUB_TIMEOUT_BUTTON}, @samp{GRUB_DEFAULT_BUTTON} and -@samp{GRUB_HIDDEN_TIMEOUT_BUTTON} are used instead of the corresponding -variables without the @samp{_BUTTON} suffix when powered on using the special -button. @samp{GRUB_BUTTON_CMOS_ADDRESS} is vendor-specific and partially -model-specific. Values known to the GRUB team are: +configuration}). @samp{GRUB_TIMEOUT_BUTTON}, +@samp{GRUB_TIMEOUT_STYLE_BUTTON}, and @samp{GRUB_DEFAULT_BUTTON} are used +instead of the corresponding variables without the @samp{_BUTTON} suffix +when powered on using the special button. @samp{GRUB_BUTTON_CMOS_ADDRESS} +is vendor-specific and partially model-specific. Values known to the GRUB +team are: @table @key +@item Dell XPS M1330M +121:3 @item Dell XPS M1530 85:3 +@item Dell Latitude E4300 +85:3 @item Asus EeePC 1005PE 84:1 (unconfirmed) +@item LENOVO ThinkPad T410s (2912W1C) +101:3 @end table To take full advantage of this function, install GRUB into the MBR @@ -2216,8 +2834,8 @@ bytes. The sole function of @file{boot.img} is to read the first sector of the core image from a local disk and jump to it. Because of the size restriction, @file{boot.img} cannot understand any file system structure, so -@command{grub-setup} hardcodes the location of the first sector of the core -image into @file{boot.img} when installing GRUB. +@command{grub-install} hardcodes the location of the first sector of the +core image into @file{boot.img} when installing GRUB. @item diskboot.img This image is used as the first sector of the core image when booting from a @@ -2310,6 +2928,44 @@ In GRUB 2, images for PXE network booting are now constructed using contains the @samp{pxe} and @samp{pxecmd} modules. @xref{Network}. @end table +@node Core image size limitation +@chapter Core image size limitation + +Heavily limited platforms: +@itemize +@item i386-pc (normal and PXE): the core image size (compressed) is limited by 458240 bytes. + kernel.img (.text + .data + .bss, uncompressed) is limited by 392704 bytes. + module size (uncompressed) + kernel.img (.text + .data, uncompressed) is limited by the size of contiguous chunk at 1M address. +@item sparc64-ieee1275: kernel.img (.text + .data + .bss) + modules + 256K (stack) + 2M (heap) is limited by space available at 0x4400. On most platforms it's just 3 or 4M since ieee1275 maps only so much. +@item i386-ieee1275: kernel.img (.text + .data + .bss) + modules is limited by memory available at 0x10000, at most 596K +@end itemize + +Lightly limited platforms: + +@itemize +@item *-xen: limited only by adress space and RAM size. +@item i386-qemu: kernel.img (.text + .data + .bss) is limited by 392704 bytes. + (core.img would be limited by ROM size but it's unlimited on qemu +@item All EFI platforms: limited by contiguous RAM size and possibly firmware bugs +@item Coreboot and multiboot. kernel.img (.text + .data + .bss) is limited by 392704 bytes. + module size is limited by the size of contiguous chunk at 1M address. +@item mipsel-loongson (ELF), mips(el)-qemu_mips (ELF): if uncompressed: + kernel.img (.text + .data) + modules is limited by the space from 80200000 forward + if compressed: + kernel.img (.text + .data, uncompressed) + modules (uncompressed) + + (modules + kernel.img (.text + .data)) (compressed) + + decompressor is limited by the space from 80200000 forward +@item mipsel-loongson (Flash), mips(el)-qemu_mips (Flash): kernel.img (.text + .data) + modules is limited by the space from 80200000 forward + core.img (final) is limited by flash size (512K on yeeloong and fulooong) +@item mips-arc: if uncompressed: + kernel.img (.text + .data) is limited by the space from 8bd00000 forward + modules + dummy decompressor is limited by the space from 8bd00000 backward + if compressed: + kernel.img (.text + .data, uncompressed) is limited by the space from 8bd00000 forward + modules (uncompressed) + (modules + kernel.img (.text + .data)) (compressed, aligned to 1M) + + 1M (decompressor + scratch space) is limited by the space from 8bd00000 backward +@item powerpc-ieee1275: kernel.img (.text + .data + .bss) + modules is limited by space available at 0x200000 +@end itemize @node Filesystem @chapter Filesystem syntax and semantics @@ -2341,18 +2997,19 @@ The device syntax is like this: driver in use. BIOS and EFI disks use either @samp{fd} or @samp{hd} followed by a digit, like @samp{fd0}, or @samp{cd}. AHCI, PATA (ata), crypto, USB use the name of driver followed by a number. -Memdisk and host are limited to one disk and so it's refered just by driver +Memdisk and host are limited to one disk and so it's referred just by driver name. -RAID (md), ofdisk (ieee1275 and nand), LVM (lv), LDM and arcdisk (arc) use -intrinsic name of disk prefixed by driver name. Additionally just ``nand'' -refers to the disk aliased as ``nand''. -Conflicts are solved by suffixing a number if necessarry. +RAID (md), ofdisk (ieee1275 and nand), LVM (lvm), LDM, virtio (vdsk) +and arcdisk (arc) use intrinsic name of disk prefixed by driver name. +Additionally just ``nand'' refers to the disk aliased as ``nand''. +Conflicts are solved by suffixing a number if necessary. Commas need to be escaped. Loopback uses whatever name specified to @command{loopback} command. Hostdisk uses names specified in device.map as long as it's of the form [fhc]d[0-9]* or hostdisk/. For crypto and RAID (md) additionally you can use the syntax -uuid/. +uuid/. For LVM additionally you can use the syntax +lvmid//. @example (fd0) @@ -2364,7 +3021,8 @@ For crypto and RAID (md) additionally you can use the syntax (usb0) (cryptouuid/123456789abcdef0123456789abcdef0) (mduuid/123456789abcdef0123456789abcdef0) -(lv/system-root) +(lvm/system-root) +(lvmid/F1ikgD-2RES-306G-il9M-7iwa-4NKW-EbV1NV/eLGuCQ-L4Ka-XUgR-sjtJ-ffch-bajr-fCNfz5) (md/myraid) (md/0) (ieee1275/disk2) @@ -2395,11 +3053,25 @@ of the partition when installing GRUB). (hd0,1,3) @end example -If you enabled the network support, the special drives @samp{(tftp)}, -@samp{(http)} and so on ars also available. +If you enabled the network support, the special drives +@code{(@var{protocol}[,@var{server}])} are also available. Supported protocols +are @samp{http} and @samp{tftp}. If @var{server} is omitted, value of +environment variable @samp{net_default_server} is used. Before using the network drive, you must initialize the network. @xref{Network}, for more information. +When using @samp{http} or @samp{tftp}, ports other than @samp{80} can be +specified using a colon (@samp{:}) after the address. To avoid parsing +conflicts, when using IPv6 addresses with custom ports, the addresses +must be enclosed with square brackets (@samp{[]}), as is standard +practice. + +@example +(http,grub.example.com:31337) +(http,192.0.2.1:339) +(http,[2001:db8::1]:11235) +@end example + If you boot GRUB from a CD-ROM, @samp{(cd)} is available. @xref{Making a GRUB bootable CD-ROM}, for details. @@ -2419,22 +3091,31 @@ GRUB's @dfn{root device} implicitly. So if you set the root device to, say, @samp{(hd1,1)} by the command @samp{set root=(hd1,1)} (@pxref{set}), then @code{/boot/kernel} is the same as @code{(hd1,1)/boot/kernel}. +On ZFS filesystem the first path component must be +@var{volume}@samp{@@}[@var{snapshot}]. +So @samp{/rootvol@@snap-129/boot/grub/grub.cfg} refers to file +@samp{/boot/grub/grub.cfg} in snapshot of volume @samp{rootvol} with name +@samp{snap-129}. Trailing @samp{@@} after volume name is mandatory even if +snapshot name is omitted. + @node Block list syntax @section How to specify block lists A block list is used for specifying a file that doesn't appear in the filesystem, like a chainloader. The syntax is -@code{[@var{offset}]+@var{length}[,[@var{offset}]+@var{length}]@dots{}}. +@code{[@var{offset}]+[@var{length}][,[@var{offset}]+[@var{length}]]@dots{}}. Here is an example: @example -@code{0+100,200+1,300+300} +@code{0+100,200+1,300+300,800+} @end example This represents that GRUB should read blocks 0 through 99, block 200, -and blocks 300 through 599. If you omit an offset, then GRUB assumes -the offset is zero. +blocks 300 through 599, and blocks 800 until the end of the device. +If you omit an offset, then GRUB assumes the offset is zero. If the +length is omitted, then GRUB assumes the block list extends until the +end of the device. Like the file name syntax (@pxref{File name syntax}), if a blocklist does not contain a device name, then GRUB uses GRUB's @dfn{root @@ -2469,9 +3150,8 @@ The command-line interface provides a prompt and after it an editable text area much like a command-line in Unix or DOS. Each command is immediately executed after it is entered@footnote{However, this behavior will be changed in the future version, in a user-invisible -way.}. The commands (@pxref{Command-line and menu entry commands}) are a -subset of those available in the configuration file, used with exactly -the same syntax. +way.}. The commands (@pxref{Commands}) are a subset of those available +in the configuration file, used with exactly the same syntax. Cursor movement and editing of the text on the line can be done via a subset of the functions available in the Bash shell: @@ -2553,6 +3233,9 @@ If you protect the menu interface with a password (@pxref{Security}), all you can do is choose an entry by pressing @key{RET}, or press @key{p} to enter the password. +Pressing @key{Ctrl-l} will refresh the menu, which can be useful when +connecting via serial after the menu has been drawn. + @node Menu entry editor @section Editing a menu entry @@ -2598,37 +3281,53 @@ These variables have special meaning to GRUB. @menu * biosnum:: +* check_signatures:: * chosen:: +* cmdpath:: * color_highlight:: * color_normal:: +* config_directory:: +* config_file:: +* cryptodisk_passphrase_tries:: * debug:: * default:: * fallback:: * gfxmode:: * gfxpayload:: * gfxterm_font:: +* grub_cpu:: +* grub_platform:: * icondir:: * lang:: * locale_dir:: +* lockdown:: * menu_color_highlight:: * menu_color_normal:: -* net_pxe_boot_file:: -* net_pxe_dhcp_server_name:: -* net_pxe_domain:: -* net_pxe_extensionspath:: -* net_pxe_hostname:: -* net_pxe_ip:: -* net_pxe_mac:: -* net_pxe_rootpath:: +* net_@var{}_boot_file:: +* net_@var{}_clientid:: +* net_@var{}_clientuuid:: +* net_@var{}_dhcp_server_name:: +* net_@var{}_domain:: +* net_@var{}_extensionspath:: +* net_@var{}_hostname:: +* net_@var{}_ip:: +* net_@var{}_mac:: +* net_@var{}_next_server:: +* net_@var{}_rootpath:: +* net_default_interface:: +* net_default_ip:: +* net_default_mac:: +* net_default_server:: * pager:: * prefix:: -* pxe_blksize:: -* pxe_default_gateway:: * pxe_default_server:: * root:: +* shim_lock:: * superusers:: * theme:: * timeout:: +* timeout_style:: +* tpm_fail_fatal:: @end menu @@ -2645,6 +3344,12 @@ For an alternative approach which also changes BIOS drive mappings for the chain-loaded system, @pxref{drivemap}. +@node check_signatures +@subsection check_signatures + +This variable controls whether GRUB enforces digital signature +validation on loaded files. @xref{Using digital signatures}. + @node chosen @subsection chosen @@ -2656,6 +3361,16 @@ the titles of each of the submenus starting from the top level followed by the title of the menu entry itself, separated by @samp{>}. +@node cmdpath +@subsection cmdpath + +The location from which @file{core.img} was loaded as an absolute +directory name (@pxref{File name syntax}). This is set by GRUB at +startup based on information returned by platform firmware. Not every +platform provides this information and some may return only device +without path name. + + @node color_highlight @subsection color_highlight @@ -2663,7 +3378,7 @@ This variable contains the ``highlight'' foreground and background terminal colors, separated by a slash (@samp{/}). Setting this variable changes those colors. For the available color names, @pxref{color_normal}. -The default is @samp{black/white}. +The default is @samp{black/light-gray}. @node color_normal @@ -2692,43 +3407,117 @@ those colors. Each color must be a name from the following list: @item white @end itemize -The default is @samp{white/black}. +The default is @samp{light-gray/black}. + +The color support support varies from terminal to terminal. + +@samp{morse} has no color support at all. + +@samp{mda_text} color support is limited to highlighting by +black/white reversal. + +@samp{console} on ARC, EMU and IEEE1275, @samp{serial_*} and +@samp{spkmodem} are governed by terminfo and support +only 8 colors if in modes @samp{vt100-color} (default for console on emu), +@samp{arc} (default for console on ARC), @samp{ieee1275} (default +for console on IEEE1275). When in mode @samp{vt100} +then the color support is limited to highlighting by black/white +reversal. When in mode @samp{dumb} there is no color support. + +When console supports no colors this setting is ignored. +When console supports 8 colors, then the colors from the +second half of the previous list are mapped to the +matching colors of first half. + +@samp{console} on EFI and BIOS and @samp{vga_text} support all 16 colors. + +@samp{gfxterm} supports all 16 colors and would be theoretically extendable +to support whole rgb24 palette but currently there is no compelling reason +to go beyond the current 16 colors. + + +@node config_directory +@subsection config_directory + +This variable is automatically set by GRUB to the directory part of +current configuration file name (@pxref{config_file}). + + +@node config_file +@subsection config_file + +This variable is automatically set by GRUB to the name of configuration file that is being +processed by commands @command{configfile} (@pxref{configfile}) or @command{normal} +(@pxref{normal}). It is restored to the previous value when command completes. + + +@node cryptodisk_passphrase_tries +@subsection cryptodisk_passphrase_tries + +When prompting the user for a cryptodisk passphrase, allow this many attempts +before giving up. Defaults to @samp{3} if unset or set to an invalid value. +(The user can give up early by entering an empty passphrase.) @node debug @subsection debug This variable may be set to enable debugging output from various components -of GRUB. The value is a list of debug facility names separated by -whitespace or @samp{,}, or @samp{all} to enable all available debugging -output. +of GRUB. The value is an ordered list of debug facility names separated by +whitespace or @samp{,}. If the special facility named @samp{all} is present +then debugging output of all facility names is enabled at the start of +processing the value of this variable. A facility's debug output can then be +disabled by prefixing its name with a @samp{-}. The last occurence facility +name with or without a leading @samp{-} takes precendent over any previous +occurence. This allows the easy enabling or disabling of facilities by +appending a @samp{,} and then the facility name with or without the leading +@samp{-}, which will preserve the state of the rest of the facilities. +The facility names are the first argument to grub_dprintf. Consult the +source for more details. @node default @subsection default -If this variable is set, it identifies a menu entry that should be selected -by default, possibly after a timeout (@pxref{timeout}). The entry may be -identified by number or by title. +If this variable is set, it identifies a menu entry that should be +selected by default, possibly after a timeout (@pxref{timeout}). The +entry may be identified by number (starting from 0 at each level of +the hierarchy), by title, or by id. -If the entry is in a submenu, then it must be identified using the titles of -each of the submenus starting from the top level followed by the number or -title of the menu entry itself, separated by @samp{>}. For example, take -the following menu structure: +For example, if you have: + +@verbatim +menuentry 'Example GNU/Linux distribution' --class gnu-linux --id example-gnu-linux { + ... +} +@end verbatim + +then you can make this the default using: @example -Submenu 1 - Menu Entry 1 - Menu Entry 2 -Submenu 2 - Submenu 3 - Menu Entry 3 - Menu Entry 4 - Menu Entry 5 +default=example-gnu-linux @end example -``Menu Entry 3'' would then be identified as -@samp{Submenu 2>Submenu 3>Menu Entry 3}. +If the entry is in a submenu, then it must be identified using the +number, title, or id of each of the submenus starting from the top +level, followed by the number, title, or id of the menu entry itself, +with each element separated by @samp{>}. For example, take the +following menu structure: + +@example +GNU/Hurd --id gnu-hurd + Standard Boot --id=gnu-hurd-std + Rescue shell --id=gnu-hurd-rescue +Other platforms --id=other + Minix --id=minix + Version 3.4.0 --id=minix-3.4.0 + Version 3.3.0 --id=minix-3.3.0 + GRUB Invaders --id=grub-invaders +@end example + +The more recent release of Minix would then be identified as +@samp{Other platforms>Minix>Version 3.4.0}, or as @samp{1>0>0}, or as +@samp{other>minix>minix-3.4.0}. This variable is often set by @samp{GRUB_DEFAULT} (@pxref{Simple configuration}), @command{grub-set-default}, or @command{grub-reboot}. @@ -2749,7 +3538,8 @@ If this variable is set, it sets the resolution used on the @samp{gfxterm} graphical terminal. Note that you can only use modes which your graphics card supports via VESA BIOS Extensions (VBE), so for example native LCD panel resolutions may not be available. The default is @samp{auto}, which -selects a platform-specific default that should look reasonable. +selects a platform-specific default that should look reasonable. Supported +modes can be listed by @samp{videoinfo} command in GRUB. The resolution may be specified as a sequence of one or more modes, separated by commas (@samp{,}) or semicolons (@samp{;}); each will be tried @@ -2790,6 +3580,20 @@ If this variable is set, it names a font to use for text on the available font. +@node grub_cpu +@subsection grub_cpu + +In normal mode (@pxref{normal}), GRUB sets the @samp{grub_cpu} variable to +the CPU type for which GRUB was built (e.g. @samp{i386} or @samp{powerpc}). + + +@node grub_platform +@subsection grub_platform + +In normal mode (@pxref{normal}), GRUB sets the @samp{grub_platform} variable +to the platform for which GRUB was built (e.g. @samp{pc} or @samp{efi}). + + @node icondir @subsection icondir @@ -2822,6 +3626,13 @@ default for this variable if internationalization is needed and any translation files are available. +@node lockdown +@subsection lockdown + +If this variable is set to @samp{y}, it means that GRUB has entered +@pxref{Lockdown} mode. + + @node menu_color_highlight @subsection menu_color_highlight @@ -2845,50 +3656,92 @@ variable changes those colors. For the available color names, The default is the value of @samp{color_normal} (@pxref{color_normal}). -@node net_pxe_boot_file -@subsection net_pxe_boot_file +@node net_@var{}_boot_file +@subsection net_@var{}_boot_file @xref{Network}. -@node net_pxe_dhcp_server_name -@subsection net_pxe_dhcp_server_name +@node net_@var{}_clientid +@subsection net_@var{}_clientid @xref{Network}. -@node net_pxe_domain -@subsection net_pxe_domain +@node net_@var{}_clientuuid +@subsection net_@var{}_clientuuid @xref{Network}. -@node net_pxe_extensionspath -@subsection net_pxe_extensionspath +@node net_@var{}_dhcp_server_name +@subsection net_@var{}_dhcp_server_name @xref{Network}. -@node net_pxe_hostname -@subsection net_pxe_hostname +@node net_@var{}_domain +@subsection net_@var{}_domain @xref{Network}. -@node net_pxe_ip -@subsection net_pxe_ip +@node net_@var{}_extensionspath +@subsection net_@var{}_extensionspath @xref{Network}. -@node net_pxe_mac -@subsection net_pxe_mac +@node net_@var{}_hostname +@subsection net_@var{}_hostname @xref{Network}. -@node net_pxe_rootpath -@subsection net_pxe_rootpath +@node net_@var{}_ip +@subsection net_@var{}_ip + +@xref{Network}. + + +@node net_@var{}_mac +@subsection net_@var{}_mac + +@xref{Network}. + + +@node net_@var{}_next_server +@subsection net_@var{}_next_server + +@xref{Network}. + + +@node net_@var{}_rootpath +@subsection net_@var{}_rootpath + +@xref{Network}. + + +@node net_default_interface +@subsection net_default_interface + +@xref{Network}. + + +@node net_default_ip +@subsection net_default_ip + +@xref{Network}. + + +@node net_default_mac +@subsection net_default_mac + +@xref{Network}. + + +@node net_default_server +@subsection net_default_server @xref{Network}. @@ -2910,18 +3763,6 @@ dynamically loaded from this directory, so it must be set correctly in order for many parts of GRUB to work. -@node pxe_blksize -@subsection pxe_blksize - -@xref{Network}. - - -@node pxe_default_gateway -@subsection pxe_default_gateway - -@xref{Network}. - - @node pxe_default_server @subsection pxe_default_server @@ -2941,6 +3782,13 @@ disk, then @samp{prefix} might be set to @samp{(hd0,msdos1)/boot/grub} and @samp{root} to @samp{hd0,msdos1}. +@node shim_lock +@subsection shim_lock + +If this variable is set to @samp{y}, it means that the shim_lock verifier +is registered (see @pxref{UEFI secure boot and shim}). + + @node superusers @subsection superusers @@ -2966,9 +3814,36 @@ keyboard input before booting the default menu entry. A timeout of @samp{0} means to boot the default entry immediately without displaying the menu; a timeout of @samp{-1} (or unset) means to wait indefinitely. -This variable is often set by @samp{GRUB_TIMEOUT} or -@samp{GRUB_HIDDEN_TIMEOUT} (@pxref{Simple configuration}). +If @samp{timeout_style} (@pxref{timeout_style}) is set to @samp{countdown} +or @samp{hidden}, the timeout is instead counted before the menu is +displayed. +This variable is often set by @samp{GRUB_TIMEOUT} (@pxref{Simple +configuration}). + + +@node timeout_style +@subsection timeout_style + +This variable may be set to @samp{menu}, @samp{countdown}, or @samp{hidden} +to control the way in which the timeout (@pxref{timeout}) interacts with +displaying the menu. See the documentation of @samp{GRUB_TIMEOUT_STYLE} +(@pxref{Simple configuration}) for details. + + +@node tpm_fail_fatal +@subsection tpm_fail_fatal + +If this variable is set and true (i.e., not set to ``0'', ``false'', +``disable'', or ``no''), TPM measurements that fail will be treated as +fatal. Otherwise, they will merely be debug-logged and boot will +continue. + +Call to EFI firmware, like hash_log_extend_event(), can return an unknown +error, i.e. due to bug present in firmware. When this variable is set and +true (same values as with TPM measurements) this situation will be considered +to be fatal and error-logged as ``unknown TPM error''. If not set, booting +the OS will be enabled. @node Environment block @section The GRUB environment block @@ -2996,9 +3871,2111 @@ using BIOS or EFI functions (no ATA, USB or IEEE1275). @command{grub-mkconfig} uses this facility to implement @samp{GRUB_SAVEDEFAULT} (@pxref{Simple configuration}). +@node Modules +@chapter Modules + +In this chapter, we list all modules that are available in GRUB. + +Modules can be loaded via the @command{insmod} (@pxref{insmod}) command. + +@menu +* acpi_module:: +* adler32_module:: +* affs_module:: +* afs_module:: +* afsplitter_module:: +* ahci_module:: +* all_video_module:: +* aout_module:: +* appleldr_module:: +* archelp_module:: +* at_keyboard_module:: +* ata_module:: +* backtrace_module:: +* bfs_module:: +* biosdisk_module:: +* bitmap_module:: +* bitmap_scale_module:: +* bli_module:: +* blocklist_module:: +* boot_module:: +* boottime_module:: +* bsd_module:: +* bswap_test_module:: +* btrfs_module:: +* bufio_module:: +* cacheinfo_module:: +* cat_module:: +* cbfs_module:: +* cbls_module:: +* cbmemc_module:: +* cbtable_module:: +* cbtime_module:: +* chain_module:: +* cmdline_cat_test_module:: +* cmosdump_module:: +* cmostest_module:: +* cmp_module:: +* cmp_test_module:: +* configfile_module:: +* cpio_module:: +* cpio_be_module:: +* cpuid_module:: +* crc64_module:: +* crypto_module:: +* cryptodisk_module:: +* cs5536_module:: +* ctz_test_module:: +* date_module:: +* datehook_module:: +* datetime_module:: +* disk_module:: +* diskfilter_module:: +* div_module:: +* div_test_module:: +* dm_nv_module:: +* drivemap_module:: +* echo_module:: +* efi_gop_module:: +* efi_uga_module:: +* efiemu_module:: +* efifwsetup_module:: +* efinet_module:: +* efitextmode_module:: +* ehci_module:: +* elf_module:: +* emunet_module:: +* emupci_module:: +* erofs_module:: +* escc_module:: +* eval_module:: +* exfat_module:: +* exfctest_module:: +* ext2_module:: +* extcmd_module:: +* f2fs_module:: +* fat_module:: +* fdt_module:: +* file_module:: +* fixvideo_module:: +* font_module:: +* freedos_module:: +* fshelp_module:: +* functional_test_module:: +* gcry_arcfour_module:: +* gcry_blowfish_module:: +* gcry_camellia_module:: +* gcry_cast5_module:: +* gcry_crc_module:: +* gcry_des_module:: +* gcry_dsa_module:: +* gcry_idea_module:: +* gcry_md4_module:: +* gcry_md5_module:: +* gcry_rfc2268_module:: +* gcry_rijndael_module:: +* gcry_rmd160_module:: +* gcry_rsa_module:: +* gcry_seed_module:: +* gcry_serpent_module:: +* gcry_sha1_module:: +* gcry_sha256_module:: +* gcry_sha512_module:: +* gcry_tiger_module:: +* gcry_twofish_module:: +* gcry_whirlpool_module:: +* gdb_module:: +* geli_module:: +* gettext_module:: +* gfxmenu_module:: +* gfxterm_module:: +* gfxterm_background_module:: +* gfxterm_menu_module:: +* gptsync_module:: +* gzio_module:: +* halt_module:: +* hashsum_module:: +* hdparm_module:: +* hello_module:: +* help_module:: +* hexdump_module:: +* hfs_module:: +* hfsplus_module:: +* hfspluscomp_module:: +* http_module:: +* ieee1275_fb_module:: +* iorw_module:: +* iso9660_module:: +* jfs_module:: +* jpeg_module:: +* json_module:: +* keylayouts_module:: +* keystatus_module:: +* ldm_module:: +* legacy_password_test_module:: +* legacycfg_module:: +* linux_module:: +* linux16_module:: +* loadbios_module:: +* loadenv_module:: +* loopback_module:: +* ls_module:: +* lsacpi_module:: +* lsapm_module:: +* lsdev_module:: +* lsefi_module:: +* lsefimmap_module:: +* lsefisystab_module:: +* lsmmap_module:: +* lspci_module:: +* lssal_module:: +* lsspd_module:: +* lsxen_module:: +* luks_module:: +* luks2_module:: +* lvm_module:: +* lzopio_module:: +* macbless_module:: +* macho_module:: +* mda_text_module:: +* mdraid09_module:: +* mdraid09_be_module:: +* mdraid1x_module:: +* memdisk_module:: +* memrw_module:: +* memtools_module:: +* minicmd_module:: +* minix_module:: +* minix2_module:: +* minix2_be_module:: +* minix3_module:: +* minix3_be_module:: +* minix_be_module:: +* mmap_module:: +* morse_module:: +* mpi_module:: +* msdospart_module:: +* mul_test_module:: +* multiboot_module:: +* multiboot2_module:: +* nand_module:: +* nativedisk_module:: +* net_module:: +* newc_module:: +* nilfs2_module:: +* normal_module:: +* ntfs_module:: +* ntfscomp_module:: +* ntldr_module:: +* odc_module:: +* offsetio_module:: +* ofnet_module:: +* ohci_module:: +* part_acorn_module:: +* part_amiga_module:: +* part_apple_module:: +* part_bsd_module:: +* part_dfly_module:: +* part_dvh_module:: +* part_gpt_module:: +* part_msdos_module:: +* part_plan_module:: +* part_sun_module:: +* part_sunpc_module:: +* parttool_module:: +* password_module:: +* password_pbkdf2_module:: +* pata_module:: +* pbkdf2_module:: +* pbkdf2_test_module:: +* pci_module:: +* pcidump_module:: +* pgp_module:: +* plainmount_module:: +* plan9_module:: +* play_module:: +* png_module:: +* priority_queue_module:: +* probe_module:: +* procfs_module:: +* progress_module:: +* pxe_module:: +* pxechain_module:: +* raid5rec_module:: +* raid6rec_module:: +* random_module:: +* rdmsr_module:: +* read_module:: +* reboot_module:: +* regexp_module:: +* reiserfs_module:: +* relocator_module:: +* romfs_module:: +* scsi_module:: +* sdl_module:: +* search_module:: +* search_fs_file_module:: +* search_fs_uuid_module:: +* search_label_module:: +* sendkey_module:: +* serial_module:: +* setjmp_module:: +* setjmp_test_module:: +* setpci_module:: +* sfs_module:: +* shift_test_module:: +* signature_test_module:: +* sleep_module:: +* sleep_test_module:: +* smbios_module:: +* spkmodem_module:: +* squash4_module:: +* strtoull_test_module:: +* suspend_module:: +* syslinuxcfg_module:: +* tar_module:: +* terminal_module:: +* terminfo_module:: +* test_module:: +* test_blockarg_module:: +* testload_module:: +* testspeed_module:: +* tftp_module:: +* tga_module:: +* time_module:: +* tpm_module:: +* tr_module:: +* trig_module:: +* true_module:: +* truecrypt_module:: +* ubootnet_module:: +* udf_module:: +* ufs1_module:: +* ufs1_be_module:: +* ufs2_module:: +* uhci_module:: +* usb_module:: +* usb_keyboard_module:: +* usbms_module:: +* usbserial_common_module:: +* usbserial_ftdi_module:: +* usbserial_pl2303_module:: +* usbserial_usbdebug_module:: +* usbtest_module:: +* vbe_module:: +* verifiers_module:: +* vga_module:: +* vga_text_module:: +* video_module:: +* video_bochs_module:: +* video_cirrus_module:: +* video_colors_module:: +* video_fb_module:: +* videoinfo_module:: +* videotest_module:: +* videotest_checksum_module:: +* wrmsr_module:: +* xen_boot_module:: +* xfs_module:: +* xnu_module:: +* xnu_uuid_module:: +* xnu_uuid_test_module:: +* xzio_module:: +* zfs_module:: +* zfscrypt_module:: +* zfsinfo_module:: +* zstd_module:: + +@end menu + +@node acpi_module +@section acpi +This module provides the command @command{acpi} for loading / replacing Advanced +Configuration and Power Interface (ACPI) tables. Please @pxref{acpi} for more +information. + +@node adler32_module +@section adler32 +This module provides the library implementation for the adler32 checksum. +This is used as part of LZO decompression / compression. + +@node affs_module +@section affs +This module provides support for the Amiga Fast FileSystem (AFFS). +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node afs_module +@section afs +This module provides support for the AtheOS File System (AFS). +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node afsplitter_module +@section afsplitter +This module provides library support for the Anti forensic information splitter +(AFS) operation @code{AF_merge}. This is used by LUKS and LUKS2. + +@node ahci_module +@section ahci +This module provides support for the Advanced Host Controller Interface protocol +to access disks supporting this standard. AHCI is often an option for Serial +ATA (SATA) controllers (meant to replace the older IDE protocol). + +@node all_video_module +@section all_video +This is a "dummy module" with no actual function except to load all other video +modules as dependencies (a convenient way to load all video modules). + +@node aout_module +@section aout +This module provides support for loading files packaged in the "a.out" format. +The "a.out" format is considered to be an older format than some alternatives +such as "ELF", for example support for the "a.out" format was removed from the +Linux kernel in 5.18. + +@node appleldr_module +@section appleldr +This module provides support for loading files on a BIOS / EFI based Apple Mac +computer (Intel based Macs). + +@node archelp_module +@section archelp +This module provides Archive Helper functions for archive based file systems +such as TAR and CPIO archives. + +@node at_keyboard_module +@section at_keyboard +This module provides support for the AT keyboard input for the GRUB terminal. + +@node ata_module +@section ata +This modules provides support for direct ATA and ATAPI access to compatible +disks. + +@node backtrace_module +@section backtrace +This module provides the command @command{backtrace} for printing a backtrace +to the terminal for the current call stack. + +@node bfs_module +@section bfs +This module provides support for the BeOS "Be File System" (BFS). +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node biosdisk_module +@section biosdisk +This module provides support for booting from a bootable removable disk such +as a CD-ROM, BD-ROM, etc. + +@node bitmap_module +@section bitmap +This module provides support for reading and interacting with bitmap image +files. + +@node bitmap_scale_module +@section bitmap_scale +This module provides support for scaling bitmap image files. + +@node bli_module +@section bli +This module provides basic support for the Boot Loader Interface. The Boot +Loader Interface specifies a set of EFI variables that are used to communicate +boot-time information between the bootloader and the operating system. + +The following variables are placed under the vendor UUID +@code{4a67b082-0a4c-41cf-b6c7-440b29bb8c4f} when the module is loaded: + +The GPT partition UUID of the EFI System Partition used during boot is +published via the @code{LoaderDevicePartUUID} variable. The Boot Loader +Interface specification requires GPT formatted drives. The bli module +ignores drives/partitions in any other format. If GRUB is loaded from +a non-GPT partition, e.g. from an MSDOS formatted drive or network, +this variable will not be set. + +A string identifying GRUB as the active bootloader including the version +number is stored in @code{LoaderInfo}. + +This module is only available on UEFI platforms. + +@node blocklist_module +@section blocklist +This module provides support for the command @command{blocklist} to list +blocks for a given file. Please @pxref{blocklist} for more information. + +@node boot_module +@section boot +This module provides support for the command @command{boot} to boot an +operating system. Please @pxref{boot} for more information. + +@node boottime_module +@section boottime +This module provides support for the command @command{boottime} to display +time taken to perform various GRUB operations. This module is only available +when GRUB is built with the conditional compile option @code{BOOT_TIME_STATS}. + +@node bsd_module +@section bsd +This module provides support for loading BSD operating system images via +commands such as: @command{kfreebsd_loadenv}, @command{kfreebsd_module_elf}, +@command{kfreebsd_module}, @command{kfreebsd}, @command{knetbsd_module_elf}, +@command{knetbsd_module}, @command{knetbsd}, @command{kopenbsd}, and +@command{kopenbsd_ramdisk}. Please @pxref{Loader commands} for more info. + +@node bswap_test_module +@section bswap_test +This module is intended for performing a functional test of the byte swapping +functionality of GRUB. + +@node btrfs_module +@section btrfs +This module provides support for the B-Tree File System (BTRFS). + +@node bufio_module +@section bufio +This module is a library module for support buffered I/O of files to support +file reads performed in other modules. + +@node cacheinfo_module +@section cacheinfo +This module provides support for the command @command{cacheinfo} which provides +statistics on disk cache accesses. This module is only built if +@code{DISK_CACHE_STATS} is enabled. + +@node cat_module +@section cat +This module provides support for the command @command{cat} which outputs the +content of a file to the terminal. Please @pxref{cat} for more info. + +@node cbfs_module +@section cbfs +This module provides support for the Coreboot File System (CBFS) which is an +archive based file system. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node cbls_module +@section cbls +This module provides support for the command @command{lscoreboot} to list the +Coreboot tables. + +@node cbmemc_module +@section cbmemc +This module provides support for the command @command{cbmemc} to show the +content of the Coreboot Memory console. + +@node cbtable_module +@section cbtable +This module provides support for accessing the Coreboot tables. + +@node cbtime_module +@section cbtime +This module provides support for the command @command{coreboot_boottime} to show +the Coreboot boot time statistics. + +@node chain_module +@section chain +This module provides support for the command @command{chainloader} to boot +another bootloader. Please @pxref{chainloader} for more information. + +@node cmdline_cat_test_module +@section cmdline_cat_test +This module is intended for performing a functional test of the @command{cat} +command of GRUB. + +@node cmosdump_module +@section cmosdump +This module provides support for the command @command{cmosdump} to show a raw +dump of the CMOS contents. Please @pxref{cmosdump} for more information. + +@node cmostest_module +@section cmostest +This module provides support for the commands @command{cmostest}, +@command{cmosclean}, and @command{cmosset} to interact with a CMOS. +@xref{cmostest} / @pxref{cmosclean} for more information. + +@node cmp_module +@section cmp +This module provides support for the command @command{cmp} to compare the +content of two files. @xref{cmp} for more information. + +@node cmp_test_module +@section cmp_test +This module is intended for performing a functional test of relational +operations in GRUB. Note that this module is *not* associated with the +@command{cmp} command and does not test the @command{cmp} command. + +@node configfile_module +@section configfile +This module provides support for the commands: @command{configfile}, +@command{source}, @command{extract_entries_source}, +@command{extract_entries_configfile}, @command{.} (dot command). +@xref{configfile} / @pxref{source}. + +@node cpio_module +@section cpio +This module provides support for the CPIO archive file format. This module is +for the "bin" version of CPIO (default of GNU CPIO) supporting around 2GB. + +@node cpio_be_module +@section cpio_be +This module provides support for the CPIO archive file format in big-endian +format. This module is for the "bin" version of CPIO (default of GNU CPIO) +supporting around 2GB. + +@node cpuid_module +@section cpuid +This module provides support for the command @command{cpuid} to test for +various CPU features. @xref{cpuid} for more information. + +@node crc64_module +@section crc64 +This module provides support for the CRC64 operation. + +@node crypto_module +@section crypto +This module provides library support for various base cryptography operations +in GRUB. + +@node cryptodisk_module +@section cryptodisk +This module provides support for the command @command{cryptomount} to interact +with encrypted file systems. @xref{cryptomount} for more information. + +@node cs5536_module +@section cs5536 +This module provides support for the AMD Geode CS5536 companion device. + +@node ctz_test_module +@section ctz_test +This module is intended for performing a functional test of the ctz functions +in GRUB used to Count Trailing Zeros. + +@node date_module +@section date +This module provides support for the command @command{date} to get the date/time +or set the date/time. @xref{date} for more information. + +@node datehook_module +@section datehook +This module provides support for populating / providing the environment +variables @code{YEAR}, @code{MONTH}, @code{DAY}, @code{HOUR}, @code{MINUTE}, +@code{SECOND}, @code{WEEKDAY}. + +@node datetime_module +@section datetime +This module provides library support for getting and setting the date / time +from / to a hardware clock device. + +@node disk_module +@section disk +This module provides library support for writing to a storage disk. + +@node diskfilter_module +@section diskfilter +This module provides library support for reading a disk RAID array. +It also provides support for the command @command{cryptocheck}. +@xref{cryptocheck} for more information. + +@node div_module +@section div +This module provides library support for some operations such as divmod. + +@node div_test_module +@section div_test +This module is intended for performing a functional test of the divmod function +in GRUB. + +@node dm_nv_module +@section dm_nv +This module provides support for handling some Nvidia "fakeraid" disk devices. + +@node drivemap_module +@section drivemap +This module provides support for the @command{drivemap} to manage BIOS drive +mappings. @xref{drivemap} for more information. + +@node echo_module +@section echo +This module provides support for the @command{echo} to display a line of text. +@xref{echo} for more information. + +@node efi_gop_module +@section efi_gop +This module provides support for the UEFI video output protocol "Graphics +Output Protocol" (GOP). + +@node efi_uga_module +@section efi_uga +This module provides support for the EFI video protocol "Universal Graphic +Adapter" (UGA). + +@node efiemu_module +@section efiemu +This module provides support for the commands @command{efiemu_loadcore}, +@command{efiemu_prepare}, and @command{efiemu_unload}. This provides an EFI +emulation. + +@node efifwsetup_module +@section efifwsetup +This modules provides support for the command @command{fwsetup} to reboot into +the firmware setup menu. @xref{fwsetup} for more information. + +@node efinet_module +@section efinet +This module provides support for UEFI Network Booting for loading images and +data from the network. + +@node efitextmode_module +@section efitextmode +This module provides support for command @command{efitextmode} to get and set +output mode resolution. @xref{efitextmode} for more information. + +@node ehci_module +@section ehci +This module provides support for the USB Enhanced Host Controller Interface +(EHCI) specification (USB 2.0). + +@node elf_module +@section elf +This module provides support for loading Executable and Linkable Format (ELF) +files. + +@node emunet_module +@section emunet +This module provides support for networking in GRUB on the emu platform. + +@node emupci_module +@section emupci +This module provides support for accessing the PCI bus in GRUB on the emu +platform. + +@node erofs_module +@section erofs +This module provides support for the Enhanced Read Only File System (EROFS). + +@node escc_module +@section escc +This module provides support for the "mac-io" terminal device on PowerPC. + +@node eval_module +@section eval +This module provides support for command @command{eval} to evaluate the provided +input as a sequence of GRUB commands. @xref{eval} for more information. + +@node exfat_module +@section exfat +This module provides support for the Extensible File Allocation Table (exFAT) +file system in GRUB. + +@node exfctest_module +@section exfctest +This module is intended to provide an Example Functional Test of GRUB functions +to use as a template for developing other GRUB functional tests. + +@node ext2_module +@section ext2 +This module provides support for the Extended File System versions 2, 3, and 4 +(ext2, ext3, and ext4) file systems in GRUB. + +@node extcmd_module +@section extcmd +This module is a support module to provide wrapper functions for registering +other module commands depending on the state of the lockdown variable. + +@node f2fs_module +@section f2fs +This module provides support for the Flash-Friendly File System (F2FS) in GRUB. + +@node fat_module +@section fat +This module provides support for the File Allocation Table 12-bit, 16-bit, and +32-bit (FAT12, FAT16, and FAT32) file systems in GRUB. + +@node fdt_module +@section fdt +This module provides support for the commands @command{fdtdump} and +@command{devicetree} to dump the contents of a device tree blob (.dtb) to the +console and to load a device tree blob (.dtb) from a filesystem, for +later use by a Linux kernel, respectively. @xref{devicetree} and +@pxref{fdtdump} for more information. + +@node file_module +@section file +This module provides support for the command @command{file} to test if the +provided filename is of the specified type. @xref{file} for more information. + +@node fixvideo_module +@section fixvideo +This module provides support for the command @command{fix_video} to fix video +problems in specific PCIe video devices by "patching" specific device register +settings. Currently supports Intel 945GM (PCI ID @code{0x27a28086}) and Intel +965GM (PCI ID @code{0x2a028086}). + +@node font_module +@section font +This module provides support for the commands @command{loadfont} and +@command{lsfonts} to load a given font or list the loaded fonts. @xref{loadfont} +and @pxref{lsfonts} for more information. + +@node freedos_module +@section freedos +This module provides support for command @command{freedos} for loading a FreeDOS +kernel. + +@node fshelp_module +@section fshelp +This module provides support functions (helper functions) for file systems. + +@node functional_test_module +@section functional_test +This module provides support for running the GRUB functional tests using +commands @command{functional_test} and @command{all_functional_test}. + +@node gcry_arcfour_module +@section gcry_arcfour +This module provides support for the arcfour stream cipher also known as RC4. +If security is a concern, RC4 / arcfour cipher is consider broken (multiple +known vulnerabilities make this insecure). +This GRUB module is based on libgcrypt. + +@node gcry_blowfish_module +@section gcry_blowfish +This module provides support for the Blowfish cipher. +This GRUB module is based on libgcrypt. + +@node gcry_camellia_module +@section gcry_camellia +This module provides support for the Camellia cipher. +This GRUB module is based on libgcrypt. + +@node gcry_cast5_module +@section gcry_cast5 +This module provides support for the CAST5 (RFC2144, also known as CAST-128) +cipher. This GRUB module is based on libgcrypt. + +@node gcry_crc_module +@section gcry_crc +This module provides support for the CRC32, CRC32 RFC1510, and CRC24 RFC2440 +cyclic redundancy checks. +This GRUB module is based on libgcrypt. + +@node gcry_des_module +@section gcry_des +This module provides support for the Data Encryption Standard (DES) and +Triple-DES ciphers. +If security is a concern, DES has known vulnerabilities and is not recommended, +and Triple-DES is no longer recommended by NIST. +This GRUB module is based on libgcrypt. + +@node gcry_dsa_module +@section gcry_dsa +This module provides support for the Digital Signature Algorithm (DSA) cipher. +This GRUB module is based on libgcrypt. + +@node gcry_idea_module +@section gcry_idea +This module provides support for the International Data Encryption Algorithm +(IDEA) cipher. +This GRUB module is based on libgcrypt. + +@node gcry_md4_module +@section gcry_md4 +This module provides support for the Message Digest 4 (MD4) message digest. +If security is a concern, MD4 has known vulnerabilities and is not recommended. +This GRUB module is based on libgcrypt. + +@node gcry_md5_module +@section gcry_md5 +This module provides support for the Message Digest 5 (MD5) message digest. +If security is a concern, MD5 has known vulnerabilities and is not recommended. +This GRUB module is based on libgcrypt. + +@node gcry_rfc2268_module +@section gcry_rfc2268 +This module provides support for the RFC2268 (RC2 / Ron's Cipher 2) cipher. +If security is a concern, RC2 has known vulnerabilities and is not recommended. +This GRUB module is based on libgcrypt. + +@node gcry_rijndael_module +@section gcry_rijndael +This module provides support for the Advanced Encryption Standard (AES-128, +AES-192, and AES-256) ciphers. +This GRUB module is based on libgcrypt. + +@node gcry_rmd160_module +@section gcry_rmd160 +This module provides support for the RIPEMD-160 message digest. +This GRUB module is based on libgcrypt. + +@node gcry_rsa_module +@section gcry_rsa +This module provides support for the Rivest–Shamir–Adleman (RSA) cipher. +This GRUB module is based on libgcrypt. + +@node gcry_seed_module +@section gcry_seed +This module provides support for the SEED cipher. +This GRUB module is based on libgcrypt. + +@node gcry_serpent_module +@section gcry_serpent +This module provides support for the Serpent (128, 192, and 256) ciphers. +This GRUB module is based on libgcrypt. + +@node gcry_sha1_module +@section gcry_sha1 +This module provides support for the Secure Hash Algorithm 1 (SHA-1) message +digest. +If security is a concern, SHA-1 has known vulnerabilities and is not +recommended. +This GRUB module is based on libgcrypt. + +@node gcry_sha256_module +@section gcry_sha256 +This module provides support for the Secure Hash Algorithm 2 (224 and 256 bit) +(SHA-224 / SHA-256) message digests. +This GRUB module is based on libgcrypt. + +@node gcry_sha512_module +@section gcry_sha512 +This module provides support for the Secure Hash Algorithm 2 (384 and 512 bit) +(SHA-384 / SHA-512) message digests. +This GRUB module is based on libgcrypt. + +@node gcry_tiger_module +@section gcry_tiger +This module provides support for the Tiger, Tiger 1, and Tiger 2 message +digests. +This GRUB module is based on libgcrypt. + +@node gcry_twofish_module +@section gcry_twofish +This module provides support for the Twofish (128 and 256) ciphers. +This GRUB module is based on libgcrypt. + +@node gcry_whirlpool_module +@section gcry_whirlpool +This module provides support for the Whirlpool message digest. +This GRUB module is based on libgcrypt. + +@node gdb_module +@section gdb +This module provides support for remotely debugging GRUB using the GNU +Debugger (GDB) over serial. This is typically done when troubleshooting GRUB +during development and not required for normal GRUB operation. This module adds +support for commands required by the GDB remote debug function including +@command{gdbstub} to start GDB stub on given serial port, +@command{gdbstub_break} to break into GDB, @command{gdbstub_stop} to stop the +GDB stub. + +@node geli_module +@section geli +This module provides support for the GEOM ELI (GELI) disk encryption / +decryption protocol used by FreeBSD. This module supports the following ciphers +using the associated "gcry" modules: DES, Triple-DES, Blowfish, CAST5, AES, and +Camellia 128. + +@node gettext_module +@section gettext +This module provides support for the @command{gettext} command to support +translating information displayed / output by GRUB. @xref{gettext} for more +information. + +@node gfxmenu_module +@section gfxmenu +This module provides support for displaying a graphical menu / user interface +from GRUB. This includes features such as graphical font support, theme support, +image support, and icon support. + +@node gfxterm_module +@section gfxterm +This module provides support for displaying a terminal and menu interface from +GRUB using graphics mode. + +@node gfxterm_background_module +@section gfxterm_background +This module provides support for setting the gfxterm background color and +background image using commands @command{background_color} and +@command{background_image}. @xref{background_color} and @pxref{background_image} +for more information. + +@node gfxterm_menu_module +@section gfxterm_menu +This module is intended for performing a functional test of the gfxmenu function +in GRUB. + +@node gptsync_module +@section gptsync +This module provides support for the @command{gptsync} command.. @xref{gptsync} +for more information. + +@node gzio_module +@section gzio +This module provides support for decompression (inflate) of files compressed +with the GZ compression algorithm. This supports only the "DEFLATE" method for +GZIP. Unsupported flags (will result in failure to inflate) include: +@code{GRUB_GZ_CONTINUATION}, @code{GRUB_GZ_ENCRYPTED}, +@code{GRUB_GZ_RESERVED}, and @code{GRUB_GZ_EXTRA_FIELD}. + +@node halt_module +@section halt +This module provides support for the @command{halt} command to shutdown / halt +the system. @xref{halt} for more information. + +@node hashsum_module +@section hashsum +This module provide support for the commands @command{hashsum}, +@command{md5sum}, @command{sha1sum}, @command{sha256sum}, @command{sha512sum}, +and @command{crc} to calculate or check hashes of files using various methods. +@xref{hashsum}, @pxref{md5sum} @pxref{sha1sum}, @pxref{sha256sum}, +@pxref{sha512sum}, and @pxref{crc}. + +@node hdparm_module +@section hdparm +This module provides support for the @command{hdparm} command to get or set +various ATA disk parameters. This includes controlling Advanced Power Management +(APM), displaying power mode, freezing ATA security settings until reset, +displaying SMART status, controlling automatic acoustic management, setting +standby timeout, setting the drive to standby mode, setting the drive to sleep +mode, displaying the drive identification and settings, and enable/disable +SMART. + +@node hello_module +@section hello +This provides support for the @command{hello} command to simply output +"Hello World". This is intended for testing GRUB module loading / functionality. + +@node help_module +@section help +This module provides support for the @command{help} command to output help +text. @xref{help} for more information. + +@node hexdump_module +@section hexdump +This module provides support for the @command{hexdump} command to dump the +contents of a file in hexadecimal. @xref{hexdump} for more information. + +@node hfs_module +@section hfs +This module provides support for the Hierarchical File System (HFS) file system +in GRUB. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node hfsplus_module +@section hfsplus +This module provides support for the Hierarchical File System Plus (HFS+) file +system in GRUB. + +@node hfspluscomp_module +@section hfspluscomp +This module provides support for the Hierarchical File System Plus Compressed +(HFS+ Compressed) file system in GRUB. + +@node http_module +@section http +This module provides support for getting data over the HTTP network protocol in +GRUB (using the HTTP GET method). This may be used, for example, to obtain +an operating system over HTTP (network boot). + +@node ieee1275_fb_module +@section ieee1275_fb +This module provides support for the IEEE1275 video driver output for PowerPC +with a IEEE-1275 platform. + +@node iorw_module +@section iorw +This module provides support for commands @command{inb}, @command{inw}, +@command{inl}, @command{outb}, @command{outw}, and @command{outl} to read / +write data to physical I/O ports. The "in" commands accept one +parameter to specify the source port. The "out" commands require either two +or three parameters, with the order: port, value, . + +@node iso9660_module +@section iso9660 +This module provides support for the ISO9660 file system (often associated with +optical disks such as CD-ROMs and DVD-ROMs, with extensions: +System Use Sharing Protocol (SUSP), Rock Ridge (UNIX style permissions and +longer names) + +@node jfs_module +@section jfs +This module provides support for the Journaled File System (JFS) file system. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node jpeg_module +@section jpeg +This module provides support for reading JPEG image files in GRUB, such as +to support displaying a JPEG image as a background image of the gfxmenu. + +@node json_module +@section json +This module provides library support for parsing / processing JavaScript Object +Notation (JSON) formatted data. This is used, for example, to support LUKS2 +disk encryption / decryption as metadata is encoded in JSON. + +@node keylayouts_module +@section keylayouts +This module provides support for the @command{keymap} command. This command +accepts one parameter to specify either the @var{layout_name} or the +@var{filename}. +When specifying the @var{layout_name}, this command will attempt to open the +GRUB keymap file based on the following logic: + +Get the "prefix" from environment variable @var{prefix} + +Open keymap file @var{prefix}/layouts/@var{layout_name}.gkb + +When specifying the @var{filename}, the full path to the ".gkb" file should be +provided. The ".gkb" file can be generated by grub-kbdcomp. + +@node keystatus_module +@section keystatus +This module provides support for the @command{keystatus} command to check key +modifier status. @xref{keystatus} for more information. + +@node ldm_module +@section ldm +This module provides support for the Logical Disk Manager (LDM) disk format. +LDM is used to add support for logical volumes most often with Microsoft +Windows systems. A logical volume can be defined to span more than one physical +disk. + +@node legacy_password_test_module +@section legacy_password_test +This module is intended for performing a functional test of the legacy password +function in GRUB. + +@node legacycfg_module +@section legacycfg +This module provides support for commands @command{legacy_source}, +@command{legacy_configfile}, @command{extract_legacy_entries_source}, +@command{extract_legacy_entries_configfile}, @command{legacy_kernel}, +@command{legacy_initrd}, @command{legacy_initrd_nounzip}, +@command{legacy_password}, and @command{legacy_check_password}. For new uses / +configurations of GRUB other commands / modules offer the modern equivalents. + +@node linux_module +@section linux +This module provides support for the commands @command{linux} and +@command{initrd} to load Linux and an Initial RAM Disk respectively. +@xref{linux} and @pxref{initrd} for more information. + +@node linux16_module +@section linux16 +This module provides support for the commands @command{linux16} and +@command{initrd16} to load Linux in 16-bit mode and an Initial RAM Disk +in 16-bit mode respectively. +@xref{linux16} and @pxref{initrd16} for more information. + +@node loadbios_module +@section loadbios +This module provides support for the commands @command{fakebios} and +@command{loadbios}. These commands may only be useful on platforms with +issues requiring work-arounds. Command @command{fakebios} is used to create +BIOS-like structures for backward compatibility with existing OS. Command +@command{loadbios} is used to load a BIOS dump. + +@node loadenv_module +@section loadenv +This module provides support for commands @command{load_env}, +@command{list_env}, and @command{save_env}. These commands can be used to +load environment variables from a file, list environment variables in a file, +and save environment variables to a file. @xref{load_env}, @pxref{list_env}, and +@pxref{save_env}. + +@node loopback_module +@section loopback +This module provides support for the @command{loopback} command. +@xref{loopback} for more information. + +@node ls_module +@section ls +This module provides support for the @command{ls} command. +@xref{ls} for more information. + +@node lsacpi_module +@section lsacpi +This module provides support for the @command{lsacpi} command. This command +can be used to display Advanced Configuration and Power Interface (ACPI) tables. + +@node lsapm_module +@section lsapm +This module provides support for the @command{lsapm} command. This command +can be used to display Advanced power management (APM) information. + +@node lsdev_module +@section lsdev +This module provides support for the @command{lsdev} command. This command +can be used on MIPS Advanced RISC Computing (ARC) platforms to display devices. + +@node lsefi_module +@section lsefi +This module provides support for the @command{lsefi} command. This command +can be used on EFI platforms to display EFI handles. + +@node lsefimmap_module +@section lsefimmap +This module provides support for the @command{lsefimmap} command. This command +can be used on EFI platforms to display the EFI memory map. + +@node lsefisystab_module +@section lsefisystab +This module provides support for the @command{lsefisystab} command. This +command can be used on EFI platforms to display the EFI system tables. + +@node lsmmap_module +@section lsmmap +This module provides support for the @command{lsmmap} command. This +command can be used to display the memory map provided by firmware. + +@node lspci_module +@section lspci +This module provides support for the @command{lspci} command. This +command can be used to display the PCI / PCIe devices. + +@node lssal_module +@section lssal +This module provides support for the @command{lsefisystab} command. This +command can be used on Itanium (IA-64) EFI platforms to display the EFI +System Abstraction Layer system table. + +@node lsspd_module +@section lsspd +This module provides support for the @command{lsspd} command. This +command can be used on MIPS Loongson platforms to display the DDR RAM Serial +Presence Detect (SPD) EEPROM data. + +@node lsxen_module +@section lsxen +This module provides support for the commands @command{xen_ls} and +@command{xen_cat} on Xen platforms to list Xen storage. + +@node luks_module +@section luks +This module provides support for the Linux Unified Key Setup (LUKS) (version 1) +disk encryption / decryption protocol. + +@node luks2_module +@section luks2 +This module provides support for the Linux Unified Key Setup 2 (LUKS2) +disk encryption / decryption protocol. + +@node lvm_module +@section lvm +This module provides support for reading Logical Volume Management "logical" +disks. For example, a single "logical" disk may be mapped to span more than one +physical disk. This would be used when booting from a LVM formatted disk as may +be setup in Linux. + +@node lzopio_module +@section lzopio +This module provides support for decompressing LZO / LZOP compressed files / +archives. + +@node macbless_module +@section macbless +This module provides support for commands @command{mactelbless} and +@command{macppcbless} for "blessing" a bootloader on Intel / PPC based MACs +using the HFS or HFS+ file system. On HFS / HFS+ - "blessing" makes a file +run as the bootloader. + +@node macho_module +@section macho +This module provides support for Mach Object (Mach-O) object / executable files +in GRUB often used in MacOS. + +@node mda_text_module +@section mda_text +This module provides support for the Monochrome Display Adapter (MDA) terminal +output device. MDA is a predecessor to VGA. + +@node mdraid09_module +@section mdraid09 +This module provides support for handling Linux compatible "version 0.9" +software-based RAID disks in little-endian format. The "version 0.9" format +was largely replaced around the year 2009 with the "version 1.x" format +(@pxref{mdraid1x_module} for more information). + +@node mdraid09_be_module +@section mdraid09_be +This module provides support for handling Linux compatible "version 0.9" +software-based RAID disks in bid-endian format. The "version 0.9" format +was largely replaced around the year 2009 with the "version 1.x" format +(@pxref{mdraid1x_module} for more information). + +@node mdraid1x_module +@section mdraid1x +This module provides support for handling Linux compatible "version 1.x" +software-based RAID disks. This includes the current version used by Linux +at the time of writing. + +@node memdisk_module +@section memdisk +This module provides support for a memdisk device. A memdisk is a memory mapped +emulated disk. + +@node memrw_module +@section memrw +This module provides support for commands @command{read_byte}, +@command{read_word}, @command{read_dword}, @command{write_byte}, +@command{write_word}, and @command{write_dword} to read / +write data to physical memory (addresses). The "read" commands accept one +parameter to specify the source address. The "write" commands require either two +or three parameters, with the order: address, value, . +Note: The commands provided by this module are not allowed when lockdown is +enforced (@pxref{Lockdown}). + +@node memtools_module +@section memtools +This module provides support for GRUB development / debugging commands +@command{lsmem}, @command{lsfreemem}, and @command{stress_big_allocs}. + +@node minicmd_module +@section minicmd +This module provides support for a subset of commands for GRUB rescue mode +including: @command{cat}, @command{help}, @command{dump}, @command{rmmod}, +@command{lsmod}, and @command{exit}. The version of the commands in this module +are similar to their full-fledged counterparts implemented in other GRUB +modules. +Note: The @command{dump} command is not allowed when lockdown is enforced +(@pxref{Lockdown}). + +@node minix_module +@section minix +This module provides support for the Minix filesystem, version 1. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node minix2_module +@section minix2 +This module provides support for the Minix filesystem, version 2. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node minix2_be_module +@section minix2_be +This module provides support for the Minix filesystem, version 2 big-endian. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node minix3_module +@section minix3 +This module provides support for the Minix filesystem, version 3. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node minix3_be_module +@section minix3_be +This module provides support for the Minix filesystem, version 3 big-endian. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node minix_be_module +@section minix_be +This module provides support for the Minix filesystem, version 1 big-endian. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node mmap_module +@section mmap +This module provides support for mapping or unmapping devices or files into +memory as well as commands @command{badram} and @command{cutmem}. +@xref{badram} and @ref{cutmem}. + +@node morse_module +@section morse +This module provides support for outputting terminal output via Morse code +to an audio speaker output. + +@node mpi_module +@section mpi +This module provides support for multi-precision-integers (MPIs) in GRUB. MPIs +are used by the crypto functions as many depend on mathematics of large numbers. +This GRUB module is based on libgcrypt. + +@node msdospart_module +@section msdospart +This module provides support for modifying MSDOS formatted disk partitions +through the separate @command{parttool} command. + +@node mul_test_module +@section mul_test +This module is intended for performing a functional test of the multiplication +operations in GRUB. + +@node multiboot_module +@section multiboot +This module provides support for commands @command{multiboot} and +@command{module} to load a multiboot kernel and load a multiboot module, +respectively. @xref{multiboot} and @ref{module} for more information. This +is for loading data formatted per the GNU Multiboot specification. + +@node multiboot2_module +@section multiboot2 +This module provides support for commands @command{multiboot2} and +@command{module2} to load a multiboot kernel and load a multiboot module, +respectively. This is for loading data formatted per the GNU Multiboot +specification. + +@node nand_module +@section nand +This module provides support for accessing an IEEE-1275 compliant NAND disk +from GRUB. + +@node nativedisk_module +@section nativedisk +This module provides support for the @command{nativedisk} command. +@xref{nativedisk} for more information. + +@node net_module +@section net +This module provides support for networking protocols including ARP, BOOTP, +DNS, Ethernet, ICMPv6, ICMP, IP, TCP, and UDP. Support is included for both +IPv4 and IPv6. +This includes the following commands: +@itemize @bullet +@item +@command{net_bootp} - @pxref{net_bootp} + +@item +@command{net_dhcp} - @pxref{net_dhcp} + +@item +@command{net_get_dhcp_option} - @pxref{net_get_dhcp_option} + +@item +@command{net_nslookup} - @pxref{net_nslookup} + +@item +@command{net_add_dns} - @pxref{net_add_dns} + +@item +@command{net_del_dns} - @pxref{net_del_dns} + +@item +@command{net_ls_dns} - @pxref{net_ls_dns} + +@item +@command{net_add_addr} - @pxref{net_add_addr} + +@item +@command{net_ipv6_autoconf} - @pxref{net_ipv6_autoconf} + +@item +@command{net_del_addr} - @pxref{net_del_addr} + +@item +@command{net_add_route} - @pxref{net_add_route} + +@item +@command{net_del_route} - @pxref{net_del_route} + +@item +@command{net_set_vlan} - @pxref{net_set_vlan} + +@item +@command{net_ls_routes} - @pxref{net_ls_routes} + +@item +@command{net_ls_cards} - @pxref{net_ls_cards} + +@item +@command{net_ls_addr} - @pxref{net_ls_addr} + +@end itemize + +@node newc_module +@section newc +This module provides support for accessing a CPIO archive as a file system +from GRUB. This module is for the following newer variants of the CPIO archive +supported by GNU CPIO (but GNU CPIO defaults to the "bin" format which is +handled by the module @ref{cpio_module}). + +These are the variants supported by this module: + +@itemize @bullet +@item +"newc" - SVR4 portable format without CRC. GNU file utility will identify these +as something like "ASCII cpio archive (SVR4 with no CRC)" + +@item +‘crc’ - SVR4 portable format with CRC. GNU file utility will identify these as +something like "ASCII cpio archive (SVR4 with CRC)" + +@end itemize + +@node nilfs2_module +@section nilfs2 +This module provides support for the New Implementation of Log filesystem +(nilfs2). +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node normal_module +@section normal +This module provides support for the normal mode in GRUB. @xref{normal} for +more information. + +@node ntfs_module +@section ntfs +This module provides support for the New Technology File System (NTFS) in GRUB. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node ntfscomp_module +@section ntfscomp +This module provides support for compression with the New Technology File +System (NTFS) in GRUB. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node ntldr_module +@section ntldr +This module provides support for the @command{ntldr} command. This is may be +used to boot a Windows boot loader such as NTLDR or BootMGR. + +@node odc_module +@section odc +This module provides support for accessing a CPIO archive as a file system +from GRUB. This module is for "odc" variant of the CPIO archive +supported by GNU CPIO (but GNU CPIO defaults to the "bin" format which is +handled by the module @ref{cpio_module}). + +GNU file utility will identify these as something like "ASCII cpio archive +(pre-SVR4 or odc)" + +@node offsetio_module +@section offsetio +This module provides support for reading from a file / archive at specified +offsets in GRUB. + +@node ofnet_module +@section ofnet +This module provides support for the Open Firmware (IEEE-1275) network device +support in GRUB. + +@node ohci_module +@section ohci +This module provides support for the Open Host Controller Interface (OHCI) for +USB 1 / USB 1.1 support in GRUB. + +@node part_acorn_module +@section part_acorn +This module provides support for reading from disks partitioned with the +Acorn Disc Filing System (ADFS) used on RiscOS. + +@node part_amiga_module +@section part_amiga +This module provides support for reading from disks partitioned with the +Amiga partition table. + +@node part_apple_module +@section part_apple +This module provides support for reading from disks partitioned with the +Macintosh partition table. + +@node part_bsd_module +@section part_bsd +This module provides support for reading from disks partitioned with BSD +style partition tables. + +@node part_dfly_module +@section part_dfly +This module provides support for reading from disks partitioned with the +DragonFly BSD partition table. + +@node part_dvh_module +@section part_dvh +This module provides support for reading from disks partitioned with the +SGI Disk Volume Header partition table. + +@node part_gpt_module +@section part_gpt +This module provides support for reading from disks partitioned with the +GUID Partition Tables (GPT) partition table. + +@node part_msdos_module +@section part_msdos +This module provides support for reading from disks partitioned with the +MSDOS (Master Boot Record / MBR) style partition tables. + +@node part_plan_module +@section part_plan +This module provides support for reading from disk partitioned with the +Plan9 style partition table. + +@node part_sun_module +@section part_sun +This module provides support for reading from disk partitioned with the +Sun style partition table. + +@node part_sunpc_module +@section part_sunpc +This module provides support for reading from disk partitioned with the +Sun PC style partition table. + +@node parttool_module +@section parttool +This module provides support for the @command{parttool} command. @xref{parttool} +for more information. + +@node password_module +@section password +This module provides support for the @command{password} command. Please note +that this uses the password in plain text, if security is a concern consider +using @ref{password_pbkdf2_module} instead. @xref{password} for more +information. + +@node password_pbkdf2_module +@section password_pbkdf2 +This module provides support for the @command{password_pbkdf2} command. +@xref{password_pbkdf2} for more information. + +@node pata_module +@section pata +This module provides support for Parallel ATA (PATA) disk device interfaces. + +@node pbkdf2_module +@section pbkdf2 +This module provides support for the Password-Based Key Derivation Function 2 +(PBKDF2) / PKCS#5 PBKDF2 as per RFC 2898. + +@node pbkdf2_test_module +@section pbkdf2_test +This module is intended for performing a functional test of the PBKDF2 +operation in GRUB. + +@node pci_module +@section pci +This module provides support for generic Peripheral Component Interconnect (PCI) +bus in GRUB. + +@node pcidump_module +@section pcidump +This module provides support for the @command{pcidump} command in GRUB to dump +the PCI configuration registers in hexadecimal of a specified PCI device +(vendor / device ID) or by position on the bus. + +@node pgp_module +@section pgp +This module provides support for the commands: @command{verify_detached}, +@command{trust}, @command{list_trusted}, @command{distrust} associated with +digital signature checking via the "Open Pretty Good Privacy" (PGP) protocol / +RFC 4880 using a provided public key. This module also uses / sets +environment variable @code{check_signatures}. @xref{verify_detached}, +@ref{trust}, @ref{list_trusted}, @ref{distrust}, and @ref{check_signatures}. + +@node plainmount_module +@section plainmount +This module provides support for accessing / mounting partitions encrypted +by "cryptsetup" operating in "plain mode". @xref{plainmount} for more +information. + +@node plan9_module +@section plan9 +This module provides support for the @command{plan9} command to load a Plan9 +kernel. + +@node play_module +@section play +This module provides support for the @command{play} command to play a tune +through the PC speaker. @xref{play} for more information. + +@node png_module +@section png +This module provides support for reading Portable Network Graphics (PNG) image +files in GRUB. + +@node priority_queue_module +@section priority_queue +This module provides support for a priority queue function within GRUB such as +to support networking functions. + +@node probe_module +@section probe +This module provides support for the @command{probe} command to retrieve device +information. @xref{probe} for more information. + +@node procfs_module +@section procfs +This module provides support for a Proc File System to provide a file system +like interface to some GRUB internal data. + +@node progress_module +@section progress +This module provides support for showing file loading progress to the terminal. + +@node pxe_module +@section pxe +This module provides support for Preboot Execution Environment (PXE) network +boot services as a file system driver for other GRUB modules. + +@node pxechain_module +@section pxechain +This module provides support for the @command{pxechainloader} command to load +another bootloader by PXE. + +@node raid5rec_module +@section raid5rec +This module provides support for recovering from faulty RAID4/5 disk arrays + +@node raid6rec_module +@section raid6rec +This module provides support for recovering from faulty RAID6 disk arrays. + +@node random_module +@section random +This module provides support for library functions to get random data via +the hardware ACPI Power Management Timer and the TSC time source (Timestamp +Counter). + +@node rdmsr_module +@section rdmsr +This module provides support for the @command{rdmsr} command to read CPU +Model Specific Registers. @xref{rdmsr} for more information. + +@node read_module +@section read +This module provides support for the @command{read} command for getting user +input. @xref{read} for more information. + +@node reboot_module +@section reboot +This module provides support for the @command{reboot} command to reboot the +computer. @xref{reboot} for more information. + +@node regexp_module +@section regexp +This module provides support for the @command{regexp} command to check if a +regular expression matches a string. This module also provides support for the +GRUB script wildcard translator. @xref{regexp} for more information. + +@node reiserfs_module +@section reiserfs +This module provides support for the ReiserFS File System in GRUB. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node relocator_module +@section relocator +This module provides support for relocating the image / executable being loaded +to the expected memory location(s) and jumping to (invoking) the executable. + +@node romfs_module +@section romfs +This module provides support for the Read-Only Memory File System (ROMFS). +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node scsi_module +@section scsi +This module provides support for the Small Computer System Interface (SCSI) +protocol used for some types of disk communication include some modern ones +such as USB Mass Storage Devices supporting "USB Attached SCSI" (UAS). + +@node sdl_module +@section sdl +This module provides support for Simple DirectMedia Layer (SDL) video / image +output from the grub-emu tool used to preview the GRUB menu from a running +Operating System such as Linux (useful to test GRUB menu configuration changes +without rebooting). When available in the compilation target environment, SDL2 +will be used instead of SDL1. + +@node search_module +@section search +This module provides support for the @command{search} command to search devices +by file, filesystem label, or filesystem UUID. @xref{search} for more +information. + +@node search_fs_file_module +@section search_fs_file +This module provides support for the @command{search.file} command which +is an alias for the corresponding @command{search} command. @xref{search} for +more information. + +@node search_fs_uuid_module +@section search_fs_uuid +This module provides support for the @command{search.fs_uuid} command which +is an alias for the corresponding @command{search} command. @xref{search} for +more information. + +@node search_label_module +@section search_label +This module provides support for the @command{search.fs_label} command which +is an alias for the corresponding @command{search} command. @xref{search} for +more information. + +@node sendkey_module +@section sendkey +This module provides support for the @command{sendkey} command to send +emulated keystrokes. @xref{sendkey} for more information. + +@node serial_module +@section serial +This module provides support for the @command{serial} command and associated +driver support for communication over a serial interface from GRUB. +@xref{serial} for more information. + +@node setjmp_module +@section setjmp +This module provides support for the @code{setjmp} and @code{longjmp} functions +used within GRUB. + +@node setjmp_test_module +@section setjmp_test +This module is intended for performing a functional test of the @code{setjmp} +and @code{longjmp} functions in GRUB. + +@node setpci_module +@section setpci +This module provides support for the @command{setpci} command to get / set +values from / to specified PCI / PCIe devices. + +@node sfs_module +@section sfs +This module provides support for the Amiga Smart File System (SFS) in GRUB. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node shift_test_module +@section shift_test +This module is intended for performing a functional test of the bit-wise shift +operations in GRUB. + +@node signature_test_module +@section signature_test +This module is intended for performing a functional test of the digital +signature verification functions in GRUB. + +@node sleep_module +@section sleep +This module provides support for the @command{sleep} command to wait a specified +number of seconds in GRUB. @xref{sleep} for more information. + +@node sleep_test_module +@section sleep_test +This module is intended for performing a functional test of the sleep function +in GRUB. + +@node smbios_module +@section smbios +This module provides support for the @command{smbios} command to retrieve SMBIOS +information in GRUB. @xref{smbios} for more information. + +@node spkmodem_module +@section spkmodem +This module provides support for outputting GRUB console information over an +audio output. This output can be fed into another computer's sound input +and decoded using the @code{spkmodem_recv} utility. Note that this will slow +down GRUB's performance. + +@node squash4_module +@section squash4 +This module provides support for the SquashFS compressed read-only file system +in GRUB. + +@node strtoull_test_module +@section strtoull_test +This module is intended for performing a functional test of the strtoull +function in GRUB. + +@node suspend_module +@section suspend +This module provides support for the @command{suspend} command in GRUB to +return to IEEE1275 prompt on "Open Firmware" systems. + +@node syslinuxcfg_module +@section syslinuxcfg +This module provides support for commands @command{syslinux_source}, +@command{syslinux_configfile}, @command{extract_syslinux_entries_source}, +and @command{extract_syslinux_entries_configfile} in GRUB. These commands +can be used to parse and display GRUB menu entries based on a Syslinux based +configuration (used for SYSLINUX, ISOLINUX, and PXELINUX). It can also +be used to execute the Syslinux loader from GRUB. + +@node tar_module +@section tar +This module provides support for the GNU Tar and POSIX Tar file archives as a +file system in GRUB. + +@node terminal_module +@section terminal +This module provides support for the commands @command{terminal_input} and +@command{terminal_output} in GRUB. @xref{terminal_input} and +@ref{terminal_output} for more information. + +@node terminfo_module +@section terminfo +This module provides support for the @command{terminfo} command in GRUB to +set various terminal modes / options. @xref{terminfo} for more information. + +@node test_module +@section test +This module provides support for the commands @command{test} and @command{[}. +These commands can be used to evaluate (test) an expression. @xref{test} for +more information. + +@node test_blockarg_module +@section test_blockarg +This module is intended for performing a functional test of the "block" command +argument function in GRUB internal functions via a test command +@command{test_blockarg}. + +@node testload_module +@section testload +This module is intended for performing a functional test of some file reading / +seeking functions in GRUB internals via a test command @command{testload}. + +@node testspeed_module +@section testspeed +This module provides support for the @command{testspeed} command to test and +print file read speed of a specified file. + +@node tftp_module +@section tftp +This module provides support for the Trivial File Transfer Protocol (TFTP) for +receiving files via the network to GRUB. TFTP may be used along with PXE for +network booting for example. + +@node tga_module +@section tga +This module provides support for reading Truevision Graphics Adapter (TGA) +image files in GRUB. + +@node time_module +@section time +This module provides support for the @command{time} command to measure the +time taken by a given command and output it to the terminal. + +@node tpm_module +@section tpm +This module provides support for interacting with a Trusted Platform Module +(TPM) with GRUB to perform Measured Boot. @xref{Measured Boot} for more +information. + +@node tr_module +@section tr +This module provides support for the @command{tr} command in GRUB. This can be +used to translate characters in a string according to the provided arguments. +For example this can be used to convert upper-case to lower-case and visa-versa. + +@node trig_module +@section trig +This module provides support for internal trig functions @code{grub_cos} and +@code{grub_sin} using lookup based computation. Currently these trig functions +are used by the gfxmenu circular progress bar. + +@node true_module +@section true +This module provides support for the commands @command{true} and +@command{false}. @xref{true} and @ref{false} for more information. + +@node truecrypt_module +@section truecrypt +This module provides support for the @command{truecrypt} command. This can be +used to load a Truecrypt ISO image. + +@node ubootnet_module +@section ubootnet +This module provides support for configuring network interfaces in GRUB using +information provided by a U-Boot bootloader. + +@node udf_module +@section udf +This module provides support for the Universal Disk Format (UDF) used on some +newer optical disks. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node ufs1_module +@section ufs1 +This module provides support for the Unix File System version 1 in GRUB. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node ufs1_be_module +@section ufs1_be +This module provides support for the Unix File System version 1 (big-endian) in +GRUB. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node ufs2_module +@section ufs2 +This module provides support for the Unix File System version 2 in GRUB. +Note: This module is not allowed in lockdown mode, @pxref{Lockdown} for more +information. + +@node uhci_module +@section uhci +This module provides support for the Universal Host Controller Interface (UHCI) +for USB 1.x. + +@node usb_module +@section usb +This module provides support for USB interfaces, USB hubs, and USB transfers +in GRUB. + +@node usb_keyboard_module +@section usb_keyboard +This module provides support for a USB keyboard in GRUB. + +@node usbms_module +@section usbms +This module provides support for USB Mass Storage devices in GRUB. + +@node usbserial_common_module +@section usbserial_common +This module provides support for common operations needed to support USB Serial +port adapters in GRUB (to support a model / type specific USB to serial +adapter defined in another module). + +@node usbserial_ftdi_module +@section usbserial_ftdi +This module provides support for USB to serial adapters with vendor ID 0x0403 +and product ID 0x6001 (often associated with FTDI devices). + +@node usbserial_pl2303_module +@section usbserial_pl2303 +This module provides support for USB to serial adapters with vendor ID 0x067b +and product ID 0x2303 (PL2303 USB to Serial adapter). + +@node usbserial_usbdebug_module +@section usbserial_usbdebug +This module provides support for debugging GRUB via a "USB 2.0 Debug Cable". +The USB 2.0 specification includes a "USB2 Debug Device Functional +Specification" that this driver is intended to support for GRUB. This may +integrate with GDB server function in GRUB (@pxref{gdb_module}). + +@node usbtest_module +@section usbtest +This module provides support for the @command{usb} command in GRUB to test USB +functionality by iterating through all connected USB devices and printing +information for each to the terminal. + +@node vbe_module +@section vbe +This module provides support for the VESA BIOS Extension (VBE) Video Driver in +GRUB. + +@node verifiers_module +@section verifiers +This module is a built-in kernel module to provide a framework for GRUB file +verifiers and string verifiers. + +@node vga_module +@section vga +This module provides support for the Video Graphics Array (VGA) Video Driver in +GRUB. + +@node vga_text_module +@section vga_text +This module provides support for the Video Graphics Array (VGA) terminal +output device. + +@node video_module +@section video +This module provides support for video output support functions within GRUB. + +@node video_bochs_module +@section video_bochs +This module provides support for the Bochs PCI Video Driver (also known as +Bochs Graphics Adapter / BGA) in GRUB. + +@node video_cirrus_module +@section video_cirrus +This module provides support for the Cirrus CLGD 5446 PCI Video Driver (Cirrus +Video) in GRUB. + +@node video_colors_module +@section video_colors +This module provides support for interpreting named colors and parsing RBG +hexadecimal values. + +@node video_fb_module +@section video_fb +This module provides support for video frame buffer (FB) support in GRUB. + +@node videoinfo_module +@section videoinfo +This module provides support for the @command{videoinfo} command and (depending +on architecture) the @command{vbeinfo} command. @xref{videoinfo} for more +information. + +@node videotest_module +@section videotest +This module provides support for the @command{videotest} command and (depending +on architecture) the @command{vbetest} to test the video subsystem in the +specified width and height. + +@node videotest_checksum_module +@section videotest_checksum +This module is intended for performing a functional test of the video +functions in GRUB by displaying a test image and capturing a checksum. + +@node wrmsr_module +@section wrmsr +This module provides support for the @command{wrmsr} command to write to CPU +model-specific registers. @xref{wrmsr} for more information. + +@node xen_boot_module +@section xen_boot +This module provides support for the commands @command{xen_hypervisor} and +@command{xen_module} to load a XEN hypervisor and module respectively. + +@node xfs_module +@section xfs +This module provides support for the XFS file system in GRUB. + +@node xnu_module +@section xnu +This module provides support for the commands: @command{xnu_devprop_load}, +@command{xnu_kernel}, @command{xnu_kernel64}, @command{xnu_mkext}, +@command{xnu_kext}, @command{xnu_kextdir}, @command{xnu_ramdisk}, +@command{xnu_splash}, and @command{xnu_resume} (only for emulated machine). +These commands support loading and interacting with a XNU (MacOS / Apple) based +system / kernel. + +@node xnu_uuid_module +@section xnu_uuid +This module provides support for the @command{xnu_uuid} command to transform +a 64-bit UUID to a format suitable for XNU. + +@node xnu_uuid_test_module +@section xnu_uuid_test +This module is intended for performing a functional test of the XNU UUID +conversion function. + +@node xzio_module +@section xzio +This module provides support for decompression of XZ compressed data. + +@node zfs_module +@section zfs +This module provides support for the ZFS file system in GRUB. + +@node zfscrypt_module +@section zfscrypt +This module provides support for the @command{zfskey} to import a decryption +key as well as decryption support for encrypted ZFS file systems. + +@node zfsinfo_module +@section zfsinfo +This module provides support for the commands @command{zfsinfo} to output ZFS +info about a device and @command{zfs-bootfs} to output ZFS-BOOTFSOBJ or store +it into a variable. + +@node zstd_module +@section zstd +This module provides support for the Zstandard (zstd) decompression algorithm +in GRUB. @node Commands -@chapter The list of available commands +@chapter Available commands In this chapter, we list all commands that are available in GRUB. @@ -3015,13 +5992,16 @@ shell}. @menu * Menu-specific commands:: +* Loader commands:: * General commands:: -* Command-line and menu entry commands:: +* Command-line commands:: +* Networking commands:: +* Undocumented commands:: @end menu @node Menu-specific commands -@section The list of commands for the menu only +@section Commands for the menu only The semantics used in parsing the configuration file are the following: @@ -3054,13 +6034,13 @@ These commands can only be used in the menu: @deffn Command menuentry @var{title} @ [@option{--class=class} @dots{}] [@option{--users=users}] @ - [@option{--unrestricted}] [@option{--hotkey=key}] @ - @{ @var{command}; @dots{} @} + [@option{--unrestricted}] [@option{--hotkey=key}] [@option{--id=id}] @ + [@var{arg} @dots{}] @{ @var{command}; @dots{} @} This defines a GRUB menu entry named @var{title}. When this entry is selected from the menu, GRUB will set the @var{chosen} environment variable -to @var{title}, execute the list of commands given within braces, and if the -last command in the list returned successfully and a kernel was loaded it -will execute the @command{boot} command. +to value of @option{--id} if @option{--id} is given, execute the list of +commands given within braces, and if the last command in the list returned +successfully and a kernel was loaded it will execute the @command{boot} command. The @option{--class} option may be used any number of times to group menu entries into classes. Menu themes may display different classes using @@ -3075,6 +6055,13 @@ entries. @xref{Security}. The @option{--hotkey} option associates a hotkey with a menu entry. @var{key} may be a single letter, or one of the aliases @samp{backspace}, @samp{tab}, or @samp{delete}. + +The @option{--id} may be used to associate unique identifier with a menu entry. +@var{id} is string of ASCII aphanumeric characters, underscore and hyphen +and should not start with a digit. + +All other arguments including @var{title} are passed as positional parameters +when list of commands is executed with @var{title} always assigned to @code{$1}. @end deffn @@ -3083,7 +6070,7 @@ The @option{--hotkey} option associates a hotkey with a menu entry. @deffn Command submenu @var{title} @ [@option{--class=class} @dots{}] [@option{--users=users}] @ - [@option{--unrestricted}] [@option{--hotkey=key}] @ + [@option{--unrestricted}] [@option{--hotkey=key}] [@option{--id=id}] @ @{ @var{menu entries} @dots{} @} This defines a submenu. An entry called @var{title} will be added to the menu; when that entry is selected, a new menu will be displayed showing all @@ -3094,8 +6081,196 @@ All options are the same as in the @command{menuentry} command @end deffn +@node Loader commands +@section Various loader commands + +These commands are used to load necessary components to boot desired OS. +Many of the loader commands are not sufficiently documented. The following is +a list of commands that could use more documentation: + +@itemize @bullet +@item @command{appleloader} - Boot BIOS-based system. +@item @command{freedos} - Load FreeDOS kernel.sys. +@item @command{kfreebsd_loadenv} - Load FreeBSD env. +@item @command{kfreebsd_module_elf} - Load FreeBSD kernel module (ELF). +@item @command{kfreebsd_module} - Load FreeBSD kernel module. +@item @command{kfreebsd} - Load kernel of FreeBSD. +@item @command{knetbsd_module_elf} - Load NetBSD kernel module (ELF). +@item @command{knetbsd_module} - Load NetBSD kernel module. +@item @command{knetbsd} - Load kernel of NetBSD. +@item @command{kopenbsd} - Load kernel of OpenBSD. +@item @command{kopenbsd_ramdisk} - Load kOpenBSD ramdisk. +@item @command{legacy_initrd_nounzip} - Simulate grub-legacy `modulenounzip' command +@item @command{legacy_initrd} - Simulate grub-legacy `initrd' command +@item @command{legacy_kernel} - Simulate grub-legacy `kernel' command +@item @command{module2} - Load a multiboot 2 module. +@item @command{module} - Load a multiboot module. +@item @command{multiboot2} - Load a multiboot 2 kernel. +@item @command{multiboot} - Load a multiboot kernel. +@item @command{ntldr} - Load NTLDR or BootMGR. +@item @command{plan9} - Load Plan9 kernel. +@item @command{pxechainloader} - Load a PXE image. +@item @command{truecrypt} - Load Truecrypt ISO. +@item @command{xnu_kernel64} - Load 64-bit XNU image. +@item @command{xnu_kernel} - Load XNU image. +@item @command{xnu_kextdir} - Load XNU extension directory. +@item @command{xnu_kext} - Load XNU extension. +@item @command{xnu_mkext} - Load XNU extension package. +@item @command{xnu_ramdisk} - Load XNU ramdisk. It will be available in OS as md0. +@item @command{xnu_resume} - Load an image of hibernated XNU. +@item @command{xnu_splash} - Load a splash image for XNU. +@end itemize + + +@menu +* chainloader:: Chain-load another boot loader +* initrd:: Load a Linux initrd +* initrd16:: Load a Linux initrd (16-bit mode) +* linux:: Load a Linux kernel +* linux16:: Load a Linux kernel (16-bit mode) +@comment * xen_*:: Xen boot commands for AArch64 +* xen_hypervisor:: Load xen hypervisor binary (only on AArch64) +* xen_module:: Load xen modules for xen hypervisor (only on AArch64) +@end menu + + +@node chainloader +@subsection chainloader + +@deffn Command chainloader [@option{--force}] file [args...] +Load @var{file} as a chain-loader. Like any other file loaded by the +filesystem code, it can use the blocklist notation (@pxref{Block list +syntax}) to grab the first sector of the current partition with @samp{+1}. +On EFI platforms, any arguments after @var{file} will be sent to the loaded +image. + +If you specify the option @option{--force}, then load @var{file} forcibly, +whether it has a correct signature or not. This is required when you want to +load a defective boot loader, such as SCO UnixWare 7.1. +@end deffn + + +@node initrd +@subsection initrd + +@deffn Command initrd file [file @dots{}] +Load, in order, all initrds for a Linux kernel image, and set the +appropriate parameters in the Linux setup area in memory. This may only +be used after the @command{linux} command (@pxref{linux}) has been run. +See @ref{GNU/Linux} for more info on booting GNU/Linux. For more +information on initrds see the GNU/Linux kernel +@uref{https://docs.kernel.org/filesystems/ramfs-rootfs-initramfs.html, +documentation}. + +A new-style initrd (for kernels newer than 2.6) containing one file +with leading path components can also be generated at run time. This +can be done by prefixing an argument with @code{newc:} followed by the +path of the file in the new initrd, a @code{:}, and then the GRUB file +path to the file data to be be included. + +For example: +@example +initrd newc:/etc/ssh/config:(hd0,2)/home/user/.ssh/config \ + newc:/etc/ssh/ssh_host_rsa_key:/etc/ssh/ssh_host_rsa_key \ + /boot/initrd.gz \ + newc:/init:/home/user/init.fixed +@end example + +This command will generate two new-style initrds on the fly. The first +contains the path @samp{/etc/ssh/config} with the contents of +@samp{(hd0,2)/home/user/.ssh/config} and the path +@samp{/etc/ssh/ssh_host_rsa_key} with the contents of +@samp{/etc/ssh/ssh_host_rsa_key} on the @var{root} device. Parent directory +paths will automatically be generated as needed. This first generated initrd +will then have @samp{/boot/initrd.gz} concatenated after it. Next, another +new-style archive will be generated with the contents of @samp{/home/user/init.fixed} +in the path @samp{/init} and appended to the previous concatenation. Finally, +the result will be sent to the kernel when booted. + +Keep in mind that paths that come later will take precedence. So in the +example above, the generated path @samp{/init} will overwrite any @samp{/init} +in @samp{/boot/initrd.gz}. This can be useful when changing the main initrd +is undesirable or difficult. +@end deffn + + +@node initrd16 +@subsection initrd16 + +@deffn Command initrd16 file [file @dots{}] +Load, in order, all initrds for a Linux kernel image to be booted in +16-bit mode, and set the appropriate parameters in the Linux setup area in +memory. This may only be used after the @command{linux16} command +(@pxref{linux16}) has been run. See also @ref{GNU/Linux} and the @command{initrd} +command (@pxref{initrd}) for more details on arguments. + +This command is only available on the pc platform for x86 systems. +@end deffn + + +@node linux +@subsection linux + +@deffn Command linux file @dots{} +Load a Linux kernel image from @var{file}. The rest of the line is passed +verbatim as the @dfn{kernel command-line}. Any initrd must be reloaded +after using this command (@pxref{initrd}). + +On x86 systems, the kernel will be booted using the 32-bit boot protocol. +Note that this means that the @samp{vga=} boot option will not work; if you +want to set a special video mode, you will need to use GRUB commands such as +@samp{set gfxpayload=1024x768} or @samp{set gfxpayload=keep} (to keep the +same mode as used in GRUB) instead. GRUB can automatically detect some uses +of @samp{vga=} and translate them to appropriate settings of +@samp{gfxpayload}. The @command{linux16} command (@pxref{linux16}) avoids +this restriction. +@end deffn + + +@node linux16 +@subsection linux16 + +@deffn Command linux16 file @dots{} +Load a Linux kernel image from @var{file} in 16-bit mode. The rest of the +line is passed verbatim as the @dfn{kernel command-line}. Any initrd must +be reloaded after using this command (@pxref{initrd16}). + +The kernel will be booted using the traditional 16-bit boot protocol. As +well as bypassing problems with @samp{vga=} described in @ref{linux}, this +permits booting some other programs that implement the Linux boot protocol +for the sake of convenience. + +This command is only available on x86 systems. +@end deffn + + +@node xen_hypervisor +@subsection xen_hypervisor + +@deffn Command xen_hypervisor file [arguments] @dots{} +Load a Xen hypervisor binary from @var{file}. The rest of the line is passed +verbatim as the @dfn{kernel command-line}. Any other binaries must be +reloaded after using this command. +This command is only available on AArch64 systems. +@end deffn + + +@node xen_module +@subsection xen_module + +@deffn Command xen_module [--nounzip] file [arguments] +Load a module for xen hypervisor at the booting process of xen. +The rest of the line is passed verbatim as the module command line. +Modules should be loaded in the following order: + - dom0 kernel image + - dom0 ramdisk if present + - XSM policy if present +This command is only available on AArch64 systems. +@end deffn + + @node General commands -@section The list of general commands +@section General commands Commands usable anywhere in the menu and in the command-line. @@ -3113,18 +6288,53 @@ Commands usable anywhere in the menu and in the command-line. @deffn Command serial [@option{--unit=unit}] [@option{--port=port}] [@option{--speed=speed}] [@option{--word=word}] [@option{--parity=parity}] [@option{--stop=stop}] Initialize a serial device. @var{unit} is a number in the range 0-3 specifying which serial port to use; default is 0, which corresponds to -the port often called COM1. @var{port} is the I/O port where the UART -is to be found; if specified it takes precedence over @var{unit}. +the port often called COM1. + +@var{port} is the I/O port where the UART is to be found or, if prefixed +with @samp{mmio,}, the MMIO address of the UART. If specified it takes +precedence over @var{unit}. + +Additionally, an MMIO address can be suffixed with: +@itemize @bullet +@item +@samp{.b} for bytes access (default) +@item +@samp{.w} for 16-bit word access +@item +@samp{.l} for 32-bit long word access or +@item +@samp{.q} for 64-bit long long word access +@end itemize + +Also, @var{port} can be of the form @samp{pci,XX:XX.X} to indicate a serial +device exposed on the PCI bus. + @var{speed} is the transmission speed; default is 9600. @var{word} and @var{stop} are the number of data bits and stop bits. Data bits must be in the range 5-8 and stop bits must be 1 or 2. Default is 8 data bits and one stop bit. @var{parity} is one of @samp{no}, @samp{odd}, @samp{even} and defaults to @samp{no}. +If passed no @var{unit} nor @var{port}, or if @var{port} is set to +@samp{auto} then GRUB will attempt to use ACPI to automatically detect +the system default serial port and its configuration. If this information +is not available, it will default to @var{unit} 0. + The serial port is not used as a communication channel unless the @command{terminal_input} or @command{terminal_output} command is used (@pxref{terminal_input}, @pxref{terminal_output}). +Note, valid @var{port} values, excluding IO port addresses, can be found +by listing terminals with @command{terminal_output}, selecting all names +prefixed by @samp{serial_} and removing that prefix. + +Examples: +@example +serial --port=0x3f8 --speed=9600 +serial --port=mmio,fefb0000.l --speed=115200 +serial --port=pci,00:16.3 --speed=115200 +@end example + See also @ref{Serial terminal}. @end deffn @@ -3170,7 +6380,7 @@ names active. @node terminfo @subsection terminfo -@deffn Command terminfo [-a|-u|-v] [term] +@deffn Command terminfo [@option{-a}|@option{-u}|@option{-v}] [@option{-g WxH}] [term] [type] Define the capabilities of your terminal by giving the name of an entry in the terminfo database, which should correspond roughly to a @samp{TERM} environment variable in Unix. @@ -3187,67 +6397,118 @@ specifies logically-ordered UTF-8; and @option{-v} specifies emulator without bidirectional text support will display right-to-left text in the proper order; this is not really proper UTF-8, but a workaround). +The @option{-g} (@option{--geometry}) can be used to specify terminal geometry. + If no option or terminal type is specified, the current terminal type is printed. @end deffn -@node Command-line and menu entry commands -@section The list of command-line and menu entry commands +@node Command-line commands +@section Command-line commands These commands are usable in the command-line and in menu entries. If you forget a command, you can run the command @command{help} (@pxref{help}). @menu +* [:: Check file types and compare values * acpi:: Load ACPI tables +* authenticate:: Check whether user is in user list +* background_color:: Set background color for active terminal +* background_image:: Load background image for active terminal * badram:: Filter out bad regions of RAM * blocklist:: Print a block list * boot:: Start up your operating system * cat:: Show the contents of a file -* chainloader:: Chain-load another boot loader +* clear:: Clear the screen +* cmosclean:: Clear bit in CMOS +* cmosdump:: Dump CMOS contents +* cmostest:: Test bit in CMOS * cmp:: Compare two files * configfile:: Load a configuration file * cpuid:: Check for CPU features -* crc:: Calculate CRC32 checksums +* crc:: Compute or check CRC32 checksums +* cryptocheck:: Check if a device is encrypted +* cryptomount:: Mount a crypto device +* cutmem:: Remove memory regions * date:: Display or set current date and time +* devicetree:: Load a device tree blob +* distrust:: Remove a pubkey from trusted keys * drivemap:: Map a drive to another * echo:: Display a line of text +* efitextmode:: Set/Get text output mode resolution +* eval:: Evaluate agruments as GRUB commands * export:: Export an environment variable * false:: Do nothing, unsuccessfully +* fdtdump:: Retrieve device tree information +* file:: Test the provided file against a type +* fwsetup:: Reboot into the firmware setup menu +* gdbinfo:: Provide info for debugging with GDB * gettext:: Translate a string * gptsync:: Fill an MBR based on GPT entries * halt:: Shut down your computer +* hashsum:: Compute or check hash checksum * help:: Show help messages -* initrd:: Load a Linux initrd -* initrd16:: Load a Linux initrd (16-bit mode) +* hexdump:: Show raw contents of a file or memory * insmod:: Insert a module * keystatus:: Check key modifier status -* linux:: Load a Linux kernel -* linux16:: Load a Linux kernel (16-bit mode) * list_env:: List variables in environment block +* list_trusted:: List trusted public keys * load_env:: Load variables from environment block +* loadfont:: Load font files * loopback:: Make a device from a filesystem image * ls:: List devices or files +* lsfonts:: List loaded fonts +* lsmod:: Show loaded modules +* md5sum:: Compute or check MD5 hash +* module:: Load module for multiboot kernel +* multiboot:: Load multiboot compliant kernel +* nativedisk:: Switch to native disk drivers * normal:: Enter normal mode * normal_exit:: Exit from normal mode * parttool:: Modify partition table entries * password:: Set a clear-text password * password_pbkdf2:: Set a hashed password +* plainmount:: Open device encrypted in plain mode * play:: Play a tune -* pxe_unload:: Unload the PXE environment +* probe:: Retrieve device info +* rdmsr:: Read values from model-specific registers * read:: Read user input * reboot:: Reboot your computer +* regexp:: Test if regular expression matches string +* rmmod:: Remove a module * save_env:: Save variables to environment block * search:: Search devices by file, label, or UUID * sendkey:: Emulate keystrokes * set:: Set an environment variable +* sha1sum:: Compute or check SHA1 hash +* sha256sum:: Compute or check SHA256 hash +* sha512sum:: Compute or check SHA512 hash +* sleep:: Wait for a specified number of seconds +* smbios:: Retrieve SMBIOS information +* source:: Read a configuration file in same context +* test:: Check file types and compare values +* tpm2_key_protector_init:: Initialize the TPM2 key protector +* tpm2_key_protector_clear:: Clear the TPM2 key protector +* tpm2_dump_pcr:: Dump TPM2 PCRs * true:: Do nothing, successfully +* trust:: Add public key to list of trusted keys * unset:: Unset an environment variable -* uppermem:: Set the upper memory size +@comment * vbeinfo:: List available video modes +* verify_detached:: Verify detached digital signature +* videoinfo:: List available video modes +* wrmsr:: Write values to model-specific registers @end menu +@node [ +@subsection [ +@deffn Command @code{[} expression @code{]} +Alias for @code{test @var{expression}} (@pxref{test}). +@end deffn + + @node acpi @subsection acpi @@ -3267,14 +6528,54 @@ Normally, this command will replace the Root System Description Pointer (RSDP) in the Extended BIOS Data Area to point to the new tables. If the @option{--no-ebda} option is used, the new tables will be known only to GRUB, but may be used by GRUB's EFI emulation. + +Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}). + Otherwise an attacker can instruct the GRUB to load an SSDT table to + overwrite the kernel lockdown configuration and later load and execute + unsigned code. @end deffn + +@node authenticate +@subsection authenticate +@deffn Command authenticate [userlist] +Check whether user is in @var{userlist} or listed in the value of variable +@samp{superusers}. See @pxref{superusers} for valid user list format. +If @samp{superusers} is empty, this command returns true. @xref{Security}. +@end deffn + + +@node background_color +@subsection background_color + +@deffn Command background_color color +Set background color for active terminal. For valid color specifications see +@pxref{Theme file format, ,Colors}. Background color can be changed only when +using @samp{gfxterm} for terminal output. + +This command sets color of empty areas without text. Text background color +is controlled by environment variables @var{color_normal}, @var{color_highlight}, +@var{menu_color_normal}, @var{menu_color_highlight}. @xref{Special environment variables}. +@end deffn + + +@node background_image +@subsection background_image + +@deffn Command background_image [[@option{--mode} @samp{stretch}|@samp{normal}] file] +Load background image for active terminal from @var{file}. Image is stretched +to fill up entire screen unless option @option{--mode} @samp{normal} is given. +Without arguments remove currently loaded background image. Background image +can be changed only when using @samp{gfxterm} for terminal output. + +@end deffn + + @node badram @subsection badram @deffn Command badram addr,mask[,addr,mask...] Filter out bad RAM. -@end deffn This command notifies the memory manager that specified regions of RAM ought to be filtered out (usually, because they're damaged). This @@ -3291,6 +6592,13 @@ this page is to be filtered. This syntax makes it easy to represent patterns that are often result of memory damage, due to physical distribution of memory cells. +The command is similar to @command{cutmem} command. + +Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}). + This prevents removing EFI memory regions to potentially subvert the + security mechanisms provided by the UEFI secure boot. +@end deffn + @node blocklist @subsection blocklist @@ -3325,28 +6633,62 @@ will be displayed as a simple new line. Otherwise, the carriage return will be displayed as a control character (@samp{}) to make it easier to see when boot problems are caused by a file formatted using DOS-style line endings. + +Note: @command{cat} can be used to view the contents of devices using the +block list syntax (@pxref{Block list syntax}). However, it is not advised +to view binary data because it will try to decode UTF-8 strings, which can +lead to some bytes missing or added in the output. Instead, use the +@command{hexdump} command (@pxref{hexdump}). @end deffn -@node chainloader -@subsection chainloader +@node clear +@subsection clear -@deffn Command chainloader [@option{--force}] file -Load @var{file} as a chain-loader. Like any other file loaded by the -filesystem code, it can use the blocklist notation (@pxref{Block list -syntax}) to grab the first sector of the current partition with @samp{+1}. -If you specify the option @option{--force}, then load @var{file} forcibly, -whether it has a correct signature or not. This is required when you want to -load a defective boot loader, such as SCO UnixWare 7.1. +@deffn Command clear +Clear the screen. +@end deffn + + +@node cmosclean +@subsection cmosclean + +@deffn Command cmosclean byte:bit +Clear value of bit in CMOS at location @var{byte}:@var{bit}. This command +is available only on platforms that support CMOS. +@end deffn + + +@node cmosdump +@subsection cmosdump + +@deffn Dump CMOS contents +Dump full CMOS contents as hexadecimal values. This command is available only +on platforms that support CMOS. +@end deffn + + +@node cmostest +@subsection cmostest + +@deffn Command cmostest byte:bit +Test value of bit in CMOS at location @var{byte}:@var{bit}. Exit status +is zero if bit is set, non zero otherwise. This command is available only +on platforms that support CMOS. @end deffn @node cmp @subsection cmp -@deffn Command cmp file1 file2 -Compare the file @var{file1} with the file @var{file2}. If they differ -in size, print the sizes like this: +@deffn Command cmp [@option{-v}] file1 file2 +Compare the file @var{file1} with the file @var{file2}. If they are completely +identical, @code{$?} will be set to 0. Otherwise, if the files are not identical, +@code{$?} will be set to a nonzero value. + +By default nothing will be output. If the @option{-v} is used, verbose mode is +enabled. In this mode when when the files differ in size, print the sizes like +this: @example Differ in size: 0x1234 [foo], 0x4321 [bar] @@ -3359,7 +6701,6 @@ bytes like this: Differ at the offset 777: 0xbe [foo], 0xef [bar] @end example -If they are completely identical, nothing will be printed. @end deffn @@ -3368,19 +6709,24 @@ If they are completely identical, nothing will be printed. @deffn Command configfile file Load @var{file} as a configuration file. If @var{file} defines any menu -entries, then show a menu containing them immediately. +entries, then show a menu containing them immediately. Any environment +variable changes made by the commands in @var{file} will not be preserved +after @command{configfile} returns. @end deffn @node cpuid @subsection cpuid -@deffn Command cpuid [-l] +@deffn Command cpuid [-l] [-p] Check for CPU features. This command is only available on x86 systems. With the @option{-l} option, return true if the CPU supports long mode (64-bit). +With the @option{-p} option, return true if the CPU supports Physical +Address Extension (PAE). + If invoked without options, this command currently behaves as if it had been invoked with @option{-l}. This may change in the future. @end deffn @@ -3389,10 +6735,86 @@ invoked with @option{-l}. This may change in the future. @node crc @subsection crc -@deffn Command crc file -Display the CRC32 checksum of @var{file}. +@deffn Command crc arg @dots{} +Alias for @code{hashsum --hash crc32 arg @dots{}}. See command @command{hashsum} +(@pxref{hashsum}) for full description. @end deffn +@node cryptocheck +@subsection cryptocheck + +@deffn Command cryptocheck [ @option{--quiet} ] device +Check if a given diskfilter device is backed by encrypted devices +(@pxref{cryptomount} for additional information). + +The command examines all backing devices, physical volumes, of a specified +logical volume, like LVM2, and fails when at least one of them is unencrypted. + +The option @option{--quiet} can be given to suppress the output. +@end deffn + +@node cryptomount +@subsection cryptomount + +@deffn Command cryptomount [ [@option{-p} password] | [@option{-k} keyfile [@option{-O} keyoffset] [@option{-S} keysize] ] | [@option{-P} protector] ] [@option{-H} file] device|@option{-u} uuid|@option{-a}|@option{-b} +Setup access to encrypted device. A passphrase will be requested interactively, +if neither the @option{-p} nor @option{-k} options are given. The option +@option{-p} can be used to supply a passphrase (useful for scripts). +Alternatively the @option{-k} option can be used to supply a keyfile with +options @option{-O} and @option{-S} optionally supplying the offset and size, +respectively, of the key data in the given key file. Besides the keyfile, +the key can be stored in a key protector, and option @option{-P} configures +specific key protector, e.g. tpm2, to retrieve the key from. +The @option{-H} options can be used to supply cryptomount backends with an +alternative header file (aka detached header). Not all backends have headers +nor support alternative header files (currently only LUKS1 and LUKS2 support them). +Argument @var{device} configures specific grub device +(@pxref{Naming convention}); option @option{-u} @var{uuid} configures device +with specified @var{uuid}; option @option{-a} configures all detected encrypted +devices; option @option{-b} configures all geli containers that have boot flag set. + +Devices are not allowed to be given as key files nor as detached header files. +However, this limitation can be worked around by using blocklist syntax. So +for instance, @code{(hd1,gpt2)} can not be used, but @code{(hd1,gpt2)0+} will +achieve the desired result. + +GRUB supports devices encrypted using LUKS, LUKS2 and geli. Note that necessary +modules (@var{luks}, @var{luks2} and @var{geli}) have to be loaded manually +before this command can be used. For LUKS2 only the PBKDF2 key derivation +function is supported, as Argon2 is not yet supported. + +Successfully decrypted disks are named as (cryptoX) and have increasing numeration +suffix for each new decrypted disk. If the encrypted disk hosts some higher level +of abstraction (like LVM2 or MDRAID) it will be created under a separate device +namespace in addition to the cryptodisk namespace. + +Support for plain encryption mode (plain dm-crypt) is provided via separate +@command{@pxref{plainmount}} command. + +On the EFI platform, GRUB tries to erase master keys from memory when the cryptodisk +module is unloaded or the command @command{exit} is executed. All secrets remain in +memory when the command @command{chainloader} is issued, because execution can +return to GRUB on the EFI platform. +@end deffn + +@node cutmem +@subsection cutmem + +@deffn Command cutmem from[K|M|G] to[K|M|G] +Remove any memory regions in specified range. + +This command notifies the memory manager that specified regions of RAM ought to +be filtered out. This remains in effect after a payload kernel has been loaded +by GRUB, as long as the loaded kernel obtains its memory map from GRUB. Kernels +that support this include Linux, GNU Mach, the kernel of FreeBSD and Multiboot +kernels in general. + +The command is similar to @command{badram} command. + +Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}). + This prevents removing EFI memory regions to potentially subvert the + security mechanisms provided by the UEFI secure boot. +@end deffn @node date @subsection date @@ -3407,6 +6829,34 @@ hour, minute, and second unchanged. @end deffn +@node devicetree +@subsection devicetree + +@deffn Command devicetree file +Load a device tree blob (.dtb) from a filesystem, for later use by a Linux +kernel. Does not perform merging with any device tree supplied by firmware, +but rather replaces it completely. + +Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}). + This is done to prevent subverting various security mechanisms. +@end deffn + +@node distrust +@subsection distrust + +@deffn Command distrust pubkey_id +Remove public key @var{pubkey_id} from GRUB's keyring of trusted keys. +@var{pubkey_id} is the last four bytes (eight hexadecimal digits) of +the GPG v4 key id, which is also the output of @command{list_trusted} +(@pxref{list_trusted}). Outside of GRUB, the key id can be obtained +using @code{gpg --fingerprint}). +These keys are used to validate signatures when environment variable +@code{check_signatures} is set to @code{enforce} +(@pxref{check_signatures}), and by some invocations of +@command{verify_detached} (@pxref{verify_detached}). @xref{Using +digital signatures}, for more information. +@end deffn + @node drivemap @subsection drivemap @@ -3430,6 +6880,8 @@ For example: @example drivemap -s (hd0) (hd1) @end example + +NOTE: Only available on i386-pc. @end deffn @@ -3476,6 +6928,56 @@ character will print that character. @end deffn +@node efitextmode +@subsection efitextmode + +@deffn Command efitextmode [min | max | | ] +When used with no arguments displays all available text output modes. The +set mode determines the columns and rows of the text display when in +text mode. An asterisk, @samp{*}, will be at the end of the line of the +currently set mode. + +If given a single parameter, it must be @samp{min}, @samp{max}, or a mode +number given by the listing when run with no arguments. These arguments set +the mode to the minimum, maximum, and particular mode respectively. + +Otherwise, the command must be given two numerical arguments specifying the +columns and rows of the desired mode. Specifying a columns and rows +combination that corresponds to no supported mode, will return error, but +otherwise have no effect. + +By default GRUB will start in whatever mode the EFI firmware defaults to. +There are firmwares known to set up the default mode such that output +behaves strangely, for example the cursor in the GRUB shell never reaches +the bottom of the screen or, when typing characters at the prompt, +characters from previous command output are overwritten. Setting the mode +may fix this. + +The EFI specification says that mode 0 must be available and have +columns and rows of 80 and 25 respectively. Mode 1 may be defined and if +so must have columns and rows of 80 and 50 respectively. Any other modes +may have columns and rows arbitrarily defined by the firmware. This means +that a mode with columns and rows of 100 and 31 on one firmware may be +a different mode number on a different firmware or not exist at all. +Likewise, mode number 2 on one firmware may have a different number of +columns and rows than mode 2 on a different firmware. So one should not +rely on a particular mode number or a mode of a certain number of columns +and rows existing on all firmwares, except for mode 0. + +Note: This command is only available on EFI platforms and is similar to +EFI shell "mode" command. +@end deffn + + +@node eval +@subsection eval + +@deffn Command eval string ... +Concatenate arguments together using single space as separator and evaluate +result as sequence of GRUB commands. +@end deffn + + @node export @subsection export @@ -3494,6 +6996,141 @@ such as @code{if} and @code{while} (@pxref{Shell-like scripting}). @end deffn +@node fdtdump +@subsection fdtdump + +@deffn Command fdtdump @ + [@option{--prop} @var{prop}] @ + [@option{--set} @var{variable}] +Retrieve device tree information. + +The @command{fdtdump} command returns the value of a property in the device +tree provided by the firmware. The @option{--prop} option determines which +property to select. + +The default action is to print the value of the requested field to the console, +but a variable name can be specified with @option{--set} to store the value +instead of printing it. + +For example, this will store and then display the model string. + +@example +fdtdump --prop model --set machine_model +echo $machine_model +@end example +@end deffn + + +@node file +@subsection file + +@deffn Command file is_file_type filename + +The @command{file} command tests whether the provided @var{filename} is the +type provided by @var{is_file_type}. When the @command{file} is of type +@var{is_file_type} this command will return 0, otherwise it will return +non-zero (no output is provided to the terminal). + +@var{is_file_type} may be one of the following options: +@itemize @bullet +@item +@option{--is-i386-xen-pae-domu} Check if @var{filename} can be booted as i386 +PAE Xen unprivileged guest kernel +@item +@option{--is-x86_64-xen-domu} Check if @var{filename} can be booted as x86_64 +Xen unprivileged guest kernel +@item +@option{--is-x86-xen-dom0} Check if @var{filename} can be used as Xen x86 +privileged guest kernel +@item +@option{--is-x86-multiboot} Check if @var{filename} can be used as x86 +multiboot kernel +@item +@option{--is-x86-multiboot2} Check if @var{filename} can be used as x86 +multiboot2 kernel +@item +@option{--is-arm-linux} Check if @var{filename} is ARM Linux +@item +@option{--is-arm64-linux} Check if @var{filename} is ARM64 Linux +@item +@option{--is-ia64-linux} Check if @var{filename} is IA64 Linux +@item +@option{--is-mips-linux} Check if @var{filename} is MIPS Linux +@item +@option{--is-mipsel-linux} Check if @var{filename} is MIPSEL Linux +@item +@option{--is-sparc64-linux} Check if @var{filename} is SPARC64 Linux +@item +@option{--is-powerpc-linux} Check if @var{filename} is POWERPC Linux +@item +@option{--is-x86-linux} Check if @var{filename} is x86 Linux +@item +@option{--is-x86-linux32} Check if @var{filename} is x86 Linux supporting +32-bit protocol +@item +@option{--is-x86-kfreebsd} Check if @var{filename} is x86 kFreeBSD +@item +@option{--is-i386-kfreebsd} Check if @var{filename} is i386 kFreeBSD +@item +@option{--is-x86_64-kfreebsd} Check if @var{filename} is x86_64 kFreeBSD +@item +@option{--is-x86-knetbsd} Check if @var{filename} is x86 kNetBSD +@item +@option{--is-i386-knetbsd} Check if @var{filename} is i386 kNetBSD +@item +@option{--is-x86_64-knetbsd} Check if @var{filename} is x86_64 kNetBSD +@item +@option{--is-i386-efi} Check if @var{filename} is i386 EFI file +@item +@option{--is-x86_64-efi} Check if @var{filename} is x86_64 EFI file +@item +@option{--is-ia64-efi} Check if @var{filename} is IA64 EFI file +@item +@option{--is-arm64-efi} Check if @var{filename} is ARM64 EFI file +@item +@option{--is-arm-efi} Check if @var{filename} is ARM EFI file +@item +@option{--is-riscv32-efi} Check if @var{filename} is RISC-V 32bit EFI file +@item +@option{--is-riscv64-efi} Check if @var{filename} is RISC-V 64bit EFI file +@item +@option{--is-hibernated-hiberfil} Check if @var{filename} is hiberfil.sys in +hibernated state +@item +@option{--is-x86_64-xnu} Check if @var{filename} is x86_64 XNU (Mac OS X kernel) +@item +@option{--is-i386-xnu} Check if @var{filename} is i386 XNU (Mac OS X kernel) +@item +@option{--is-xnu-hibr} Check if @var{filename} is XNU (Mac OS X kernel) +hibernated image +@item +@option{--is-x86-bios-bootsector} Check if @var{filename} is BIOS bootsector +@end itemize +@end deffn + + +@node fwsetup +@subsection fwsetup + +@deffn Command fwsetup [@option{--is-supported}] +Reboot into the firmware setup menu. If @option{--is-supported} option is +specified, instead check whether the firmware supports a setup menu and +exit successfully if so. +@end deffn + + +@node gdbinfo +@subsection gdbinfo + +@deffn Command gdbinfo +Output text to be used as a GDB command for a GDB session using the gdb_grub +script and attached to a running GRUB instance. The GDB command that is +output will tell GDB how to load debugging symbols to their proper runtime +address. Currently this is only available for EFI platforms. See the Debugging +in the developer documentation for more information. +@end deffn + + @node gettext @subsection gettext @@ -3529,10 +7166,34 @@ type are omitted, then the partition will be inactive. @node halt @subsection halt -@deffn Command halt @option{--no-apm} -The command halts the computer. If the @option{--no-apm} option -is specified, no APM BIOS call is performed. Otherwise, the computer -is shut down using APM. +@deffn Command halt [@option{--no-apm}] +The command halts the computer. On the i386-pc target, the @option{--no-apm} +option, or short @option{-n}, is specified, no APM BIOS call is performed. +Otherwise, the computer is shut down using APM on that target. +@end deffn + + +@node hashsum +@subsection hashsum + +@deffn Command hashsum @option{--hash} hash @option{--keep-going} @option{--uncompress} @option{--check} file [@option{--prefix} dir]|file @dots{} +Compute or verify file hashes. Hash type is selected with option @option{--hash}. +Supported hashes are: @samp{adler32}, @samp{crc64}, @samp{crc32}, +@samp{crc32rfc1510}, @samp{crc24rfc2440}, @samp{md4}, @samp{md5}, +@samp{ripemd160}, @samp{sha1}, @samp{sha224}, @samp{sha256}, @samp{sha512}, +@samp{sha384}, @samp{tiger192}, @samp{tiger}, @samp{tiger2}, @samp{whirlpool}. +Option @option{--uncompress} uncompresses files before computing hash. + +When list of files is given, hash of each file is computed and printed, +followed by file name, each file on a new line. + +When option @option{--check} is given, it points to a file that contains +list of @var{hash name} pairs in the same format as used by UNIX +@command{md5sum} command. Option @option{--prefix} +may be used to give directory where files are located. Hash verification +stops after the first mismatch was found unless option @option{--keep-going} +was given. The exit code @code{$?} is set to 0 if hash verification +is successful. If it fails, @code{$?} is set to a nonzero value. @end deffn @@ -3549,27 +7210,22 @@ about each of the commands whose names begin with those @var{patterns}. @end deffn -@node initrd -@subsection initrd +@node hexdump +@subsection hexdump -@deffn Command initrd file -Load an initial ramdisk for a Linux kernel image, and set the appropriate -parameters in the Linux setup area in memory. This may only be used after -the @command{linux} command (@pxref{linux}) has been run. See also -@ref{GNU/Linux}. -@end deffn +@deffn Command hexdump [--skip offset] [--length len] FILE_OR_DEVICE +Show raw contents of a file or memory. When option @option{--skip} is given, +@samp{offset} number of bytes are skipped from the start of the device or +file given. And @option{--length} allows specifying a maximum number of bytes +to be shown. +If given the special device named @samp{(mem)}, then the @samp{offset} given to +@option{--skip} is treated as the address of a memory location to dump from. -@node initrd16 -@subsection initrd16 +Note: The dumping of RAM memory (by the (mem) argument) is not allowed when +when lockdown is enforced (@pxref{Lockdown}). The dumping of disk or file +data is allowed when lockdown is enforced. -@deffn Command initrd16 file -Load an initial ramdisk for a Linux kernel image to be booted in 16-bit -mode, and set the appropriate parameters in the Linux setup area in memory. -This may only be used after the @command{linux16} command (@pxref{linux16}) -has been run. See also @ref{GNU/Linux}. - -This command is only available on x86 systems. @end deffn @@ -3595,69 +7251,79 @@ only if checking key modifier status is supported. @end deffn -@node linux -@subsection linux - -@deffn Command linux file @dots{} -Load a Linux kernel image from @var{file}. The rest of the line is passed -verbatim as the @dfn{kernel command-line}. Any initrd must be reloaded -after using this command (@pxref{initrd}). - -On x86 systems, the kernel will be booted using the 32-bit boot protocol. -Note that this means that the @samp{vga=} boot option will not work; if you -want to set a special video mode, you will need to use GRUB commands such as -@samp{set gfxpayload=1024x768} or @samp{set gfxpayload=keep} (to keep the -same mode as used in GRUB) instead. GRUB can automatically detect some uses -of @samp{vga=} and translate them to appropriate settings of -@samp{gfxpayload}. The @command{linux16} command (@pxref{linux16}) avoids -this restriction. -@end deffn - - -@node linux16 -@subsection linux16 - -@deffn Command linux16 file @dots{} -Load a Linux kernel image from @var{file} in 16-bit mode. The rest of the -line is passed verbatim as the @dfn{kernel command-line}. Any initrd must -be reloaded after using this command (@pxref{initrd16}). - -The kernel will be booted using the traditional 16-bit boot protocol. As -well as bypassing problems with @samp{vga=} described in @ref{linux}, this -permits booting some other programs that implement the Linux boot protocol -for the sake of convenience. - -This command is only available on x86 systems. -@end deffn - - @node list_env @subsection list_env -@deffn Command list_env [@option{-f} file] +@deffn Command list_env [@option{--file} file] List all variables in the environment block file. @xref{Environment block}. -The @option{-f} option overrides the default location of the environment -block. +The @option{--file} option overrides the default location of the +environment block. @end deffn +@node list_trusted +@subsection list_trusted + +@deffn Command list_trusted +List all public keys trusted by GRUB for validating signatures. +The output is in GPG's v4 key fingerprint format (i.e., the output of +@code{gpg --fingerprint}). The least significant four bytes (last +eight hexadecimal digits) can be used as an argument to +@command{distrust} (@pxref{distrust}). +@xref{Using digital signatures}, for more information about uses for +these keys. +@end deffn @node load_env @subsection load_env -@deffn Command load_env [@option{-f} file] +@deffn Command load_env [@option{--file} file] [@option{--skip-sig}] [whitelisted_variable_name] @dots{} Load all variables from the environment block file into the environment. @xref{Environment block}. -The @option{-f} option overrides the default location of the environment +The @option{--file} option overrides the default location of the environment block. + +The @option{--skip-sig} option skips signature checking even when the +value of environment variable @code{check_signatures} is set to +@code{enforce} (@pxref{check_signatures}). + +If one or more variable names are provided as arguments, they are +interpreted as a whitelist of variables to load from the environment +block file. Variables set in the file but not present in the +whitelist are ignored. + +The @option{--skip-sig} option should be used with care, and should +always be used in concert with a whitelist of acceptable variables +whose values should be set. Failure to employ a carefully constructed +whitelist could result in reading a malicious value into critical +environment variables from the file, such as setting +@code{check_signatures=no}, modifying @code{prefix} to boot from an +unexpected location or not at all, etc. + +When used with care, @option{--skip-sig} and the whitelist enable an +administrator to configure a system to boot only signed +configurations, but to allow the user to select from among multiple +configurations, and to enable ``one-shot'' boot attempts and +``savedefault'' behavior. @xref{Using digital signatures}, for more +information. +@end deffn + + +@node loadfont +@subsection loadfont + +@deffn Command loadfont file @dots{} +Load specified font files. Unless absolute pathname is given, @var{file} +is assumed to be in directory @samp{$prefix/fonts} with +suffix @samp{.pf2} appended. @xref{Theme file format,,Fonts}. @end deffn @node loopback @subsection loopback -@deffn Command loopback [@option{-d}] device file +@deffn Command loopback [@option{-d}] [@option{-D}] device file Make the device named @var{device} correspond to the contents of the filesystem image in @var{file}. For example: @@ -3666,6 +7332,9 @@ loopback loop0 /path/to/image ls (loop0)/ @end example +Specifying the @option{-D} option allows the loopback file to be tranparently +decompressed if there is an appropriate decompressor loaded. + With the @option{-d} option, delete a device previously created using this command. @end deffn @@ -3680,13 +7349,76 @@ List devices or files. With no arguments, print all devices known to GRUB. If the argument is a device name enclosed in parentheses (@pxref{Device -syntax}), then list all files at the root directory of that device. +syntax}), then print the name of the filesystem of that device. If the argument is a directory given as an absolute file name (@pxref{File name syntax}), then list the contents of that directory. @end deffn +@node lsfonts +@subsection lsfonts + +@deffn Command lsfonts +List loaded fonts. +@end deffn + + +@node lsmod +@subsection lsmod + +@deffn Command lsmod +Show list of loaded modules. +@end deffn + +@node md5sum +@subsection md5sum + +@deffn Command md5sum arg @dots{} +Alias for @code{hashsum --hash md5 arg @dots{}}. See command @command{hashsum} +(@pxref{hashsum}) for full description. +@end deffn + +@node module +@subsection module + +@deffn Command module [--nounzip] file [arguments] +Load a module for multiboot kernel image. The rest of the +line is passed verbatim as the module command line. +@end deffn + +@node multiboot +@subsection multiboot + +@deffn Command multiboot [--quirk-bad-kludge] [--quirk-modules-after-kernel] file @dots{} +Load a multiboot kernel image from @var{file}. The rest of the +line is passed verbatim as the @dfn{kernel command-line}. Any module must +be reloaded after using this command (@pxref{module}). + +Some kernels have known problems. You need to specify --quirk-* for those. +--quirk-bad-kludge is a problem seen in several products that they include +loading kludge information with invalid data in ELF file. GRUB prior to 0.97 +and some custom builds preferred ELF information while 0.97 and GRUB 2 +use kludge. Use this option to ignore kludge. +Known affected systems: old Solaris, SkyOS. + +--quirk-modules-after-kernel is needed for kernels which load at relatively +high address e.g. 16MiB mark and can't cope with modules stuffed between +1MiB mark and beginning of the kernel. +Known afftected systems: VMWare. +@end deffn + +@node nativedisk +@subsection nativedisk + +@deffn Command nativedisk +Switch from firmware disk drivers to native ones. +Really useful only on platforms where both +firmware and native disk drives are available. +Currently i386-pc, i386-efi, i386-ieee1275 and +x86_64-efi. +@end deffn + @node normal @subsection normal @@ -3744,7 +7476,7 @@ range 0-0xFF (prefix with @samp{0x} to enter it in hexadecimal). When enabled, this hides the selected partition by setting the @dfn{hidden} bit in its partition type code; when disabled, unhides the selected partition by clearing this bit. This is useful only when booting DOS or -Wwindows and multiple primary FAT partitions exist in one disk. See also +Windows and multiple primary FAT partitions exist in one disk. See also @ref{DOS/Windows}. @end table @end deffn @@ -3769,10 +7501,81 @@ to generate password hashes. @xref{Security}. @end deffn +@node plainmount +@subsection plainmount + +@deffn Command plainmount device @option{-c} cipher @option{-s} key size [@option{-h} hash] +[@option{-S} sector size] [@option{-p} password] [@option{-u} uuid] +[[@option{-d} keyfile] [@option{-O} keyfile offset]] + + +Setup access to the encrypted device in plain mode. Offset of the encrypted +data at the device is specified in terms of 512 byte sectors using the blocklist +syntax and loopback device. The following example shows how to specify 1MiB +offset: + +@example +loopback node (hd0,gpt1)2048+ +plainmount node @var{...} +@end example + +The @command{plainmount} command can be used to open LUKS encrypted volume +if its master key and parameters (key size, cipher, offset, etc) are known. + +There are two ways to specify a password: a keyfile and a secret passphrase. +The keyfile path parameter has higher priority than the secret passphrase +parameter and is specified with the option @option{-d}. Password data obtained +from keyfiles is not hashed and is used directly as a cipher key. An optional +offset of password data in the keyfile can be specified with the option +@option{-O} or directly with the option @option{-d} and GRUB blocklist syntax, +if the keyfile data can be accessed from a device and is 512 byte aligned. +The following example shows both methods to specify password data in the +keyfile at offset 1MiB: + +@example +plainmount -d (hd0,gpt1)2048+ @var{...} +plainmount -d (hd0,gpt1)+ -O 1048576 @var{...} +@end example + +If no keyfile is specified then the password is set to the string specified +by option @option{-p} or is requested interactively from the console. In both +cases the provided password is hashed with the algorithm specified by the +option @option{-h}. This option is mandatory if no keyfile is specified, but +it can be set to @samp{plain} which means that no hashing is done and such +password is used directly as a key. + +Cipher @option{-c} and keysize @option{-s} options specify the cipher algorithm +and the key size respectively and are mandatory options. Cipher must be specified +with the mode separated by a dash (for example, @samp{aes-xts-plain64}). Key size +option @option{-s} is the key size of the cipher in bits, not to be confused with +the offset of the key data in a keyfile specified with the @option{-O} option. It +must not exceed 1024 bits, so a 32 byte key would be specified as 256 bits + +The optional parameter @option{-S} specifies encrypted device sector size. It +must be at least 512 bytes long (default value) and a power of 2. @footnote{Current +implementation of cryptsetup supports only 512/1024/2048/4096 byte sectors}. +Disk sector size is configured when creating the encrypted volume. Attempting +to decrypt volumes with a different sector size than it was created with will +not result in an error, but will decrypt to random bytes and thus prevent +accessing the volume (in some cases the filesystem driver can detect the presence +of a filesystem, but nevertheless will refuse to mount it). + +By default new plainmount devices will be given a UUID starting with +'109fea84-a6b7-34a8-4bd1-1c506305a401' where the last digits are incremented +by one for each plainmounted device beyond the first up to 2^10 devices. + +All encryption arguments (cipher, hash, key size, disk offset and disk sector +size) must match the parameters used to create the volume. If any of them does +not match the actual arguments used during the initial encryption, plainmount +will create virtual device with the garbage data and GRUB will report unknown +filesystem for such device. +@end deffn + + @node play @subsection play -@deffn Command play file | tempo [pitch1 duration1] [pitch2 duration2] ... +@deffn Command play file | tempo [pitch1 duration1] [pitch2 duration2] @dots{} Plays a tune If the argument is a file name (@pxref{File name syntax}), play the tune @@ -3788,23 +7591,43 @@ a rest. @end deffn -@node pxe_unload -@subsection pxe_unload +@node probe +@subsection probe -@deffn Command pxe_unload -Unload the PXE environment (@pxref{Network}). +@deffn Command probe [@option{--set} var] @option{--driver}|@option{--partmap}|@option{--fs}|@option{--fs-uuid}|@option{--label}|@option{--part-uuid} device +Retrieve device information. If option @option{--set} is given, assign result +to variable @var{var}, otherwise print information on the screen. -This command is only available on PC BIOS systems. +The option @option{--part-uuid} is currently only implemented for MSDOS and GPT formatted disks. +@end deffn + + +@node rdmsr +@subsection rdmsr + +@deffn Command: rdmsr 0xADDR [-v VARNAME] +Read a model-specific register at address 0xADDR. If the parameter +@option{-v} is used and an environment variable @var{VARNAME} is +given, set that environment variable to the value that was read. + +Please note that on SMP systems, reading from a MSR that has a +scope per hardware thread, implies that the value that is returned +only applies to the particular cpu/core/thread that runs the command. + +Also, if you specify a reserved or unimplemented MSR address, it will +cause a general protection exception (which is not currently being handled) +and the system will reboot. @end deffn @node read @subsection read -@deffn Command read [var] +@deffn Command read [-s] [var] Read a line of input from the user. If an environment variable @var{var} is given, set that environment variable to the line of input that was read, -with no terminating newline. +with no terminating newline. If the parameter @option{-s} is used, enable +silent mode where input is not printed to the terminal. @end deffn @@ -3816,15 +7639,45 @@ Reboot the computer. @end deffn +@node regexp +@subsection regexp + +@deffn Command regexp [@option{--set} [number:]var] regexp string +Test if regular expression @var{regexp} matches @var{string}. Supported +regular expressions are POSIX.2 Extended Regular Expressions. If option +@option{--set} is given, store @var{number}th matched subexpression in +variable @var{var}. Subexpressions are numbered in order of their opening +parentheses starting from @samp{1}. @var{number} defaults to @samp{1}. +@end deffn + + +@node rmmod +@subsection rmmod + +@deffn Command rmmod module +Remove a loaded @var{module}. +@end deffn + + @node save_env @subsection save_env -@deffn Command save_env [@option{-f} file] var @dots{} +@deffn Command save_env [@option{--file} file] var @dots{} Save the named variables from the environment to the environment block file. @xref{Environment block}. -The @option{-f} option overrides the default location of the environment +The @option{--file} option overrides the default location of the environment block. + +This command will operate successfully even when environment variable +@code{check_signatures} is set to @code{enforce} +(@pxref{check_signatures}), since it writes to disk and does not alter +the behavior of GRUB based on any contents of disk that have been +read. It is possible to modify a digitally signed environment block +file from within GRUB using this command, such that its signature will +no longer be valid on subsequent boots. Care should be taken in such +advanced configurations to avoid rendering the system +unbootable. @xref{Using digital signatures}, for more information. @end deffn @@ -3833,21 +7686,42 @@ block. @deffn Command search @ [@option{--file}|@option{--label}|@option{--fs-uuid}] @ - [@option{--set} [var]] [@option{--no-floppy}] name + [@option{--set} [var]] [@option{--no-floppy}|@option{--efidisk-only}|@option{--cryptodisk-only}] @ + name Search devices by file (@option{-f}, @option{--file}), filesystem label (@option{-l}, @option{--label}), or filesystem UUID (@option{-u}, @option{--fs-uuid}). -If the @option{--set} option is used, the first device found is set as the -value of environment variable @var{var}. The default variable is +If the (@option{-s}, @option{--set}) option is used, the first device found is +set as the value of environment variable @var{var}. The default variable is @samp{root}. -The @option{--no-floppy} option prevents searching floppy devices, which can -be slow. +The (@option{-n}, @option{--no-floppy}) option prevents searching floppy +devices, which can be slow. + +The (@option{--efidisk-only}) option prevents searching any other devices then +EFI disks. This is typically used when chainloading to local EFI partition. + +The (@option{--cryptodisk-only}) option prevents searching any devices other +than encrypted disks. This is typically used when booting from an encrypted +file system to ensure that no code gets executed from an unencrypted device +having the same filesystem UUID or label. + +This option implicitly invokes the command @command{cryptocheck}, if it is +available (@pxref{cryptocheck} for additional information). The @samp{search.file}, @samp{search.fs_label}, and @samp{search.fs_uuid} commands are aliases for @samp{search --file}, @samp{search --label}, and @samp{search --fs-uuid} respectively. + +Also hints as to which device may be the most likely to contain the item +searched for may be given via the (@option{-h}, @option{--hint}) option with +a device name as an argument. If the argument ends with a comma, then partitions +on the device are also searched. Furthermore, platform specific hints may be +given via the options @option{--hint-ieee1275}, @option{--hint-bios}, +@option{--hint-baremetal}, @option{--hint-efi}, and @option{--hint-arc}. When +specified, these options take an argument and operate like @option{--hint}, but +only on the specified platform. @end deffn @@ -3867,7 +7741,9 @@ Insert keystrokes into the keyboard buffer when booting. Sometimes an operating system or chainloaded boot loader requires particular keys to be pressed: for example, one might need to press a particular key to enter "safe mode", or when chainloading another boot loader one might send -keystrokes to it to navigate its menu. +keystrokes to it to navigate its menu. + +Note: This command is currently only available on the i386-pc target. You may provide up to 16 keystrokes (the length of the BIOS keyboard buffer). Keystroke names may be upper-case or lower-case letters, digits, @@ -4004,10 +7880,273 @@ This command is only available on PC BIOS systems. @deffn Command set [envvar=value] Set the environment variable @var{envvar} to @var{value}. If invoked with no -arguments, print all environment variables with their values. +arguments, print all environment variables with their values. For the list of +environment variables currently used by GRUB itself see the relevant section +@pxref{Environment}. @end deffn +@node sha1sum +@subsection sha1sum + +@deffn Command sha1sum arg @dots{} +Alias for @code{hashsum --hash sha1 arg @dots{}}. See command @command{hashsum} +(@pxref{hashsum}) for full description. +@end deffn + + +@node sha256sum +@subsection sha256sum + +@deffn Command sha256sum arg @dots{} +Alias for @code{hashsum --hash sha256 arg @dots{}}. See command @command{hashsum} +(@pxref{hashsum}) for full description. +@end deffn + + +@node sha512sum +@subsection sha512sum + +@deffn Command sha512sum arg @dots{} +Alias for @code{hashsum --hash sha512 arg @dots{}}. See command @command{hashsum} +(@pxref{hashsum}) for full description. +@end deffn + + +@node sleep +@subsection sleep + +@deffn Command sleep [@option{--verbose}] [@option{--interruptible}] count +Sleep for @var{count} seconds. If option @option{--interruptible} is given, +allow pressing @key{ESC}, @key{F4} or holding down @key{SHIFT} to interrupt +sleep. With @option{--verbose} show countdown of remaining seconds. Exit code +is set to 0 if timeout expired and to 1 if timeout was interrupted using any +of the mentioned keys. +@end deffn + + +@node smbios +@subsection smbios + +@deffn Command smbios @ + [@option{--type} @var{type}] @ + [@option{--handle} @var{handle}] @ + [@option{--match} @var{match}] @ + (@option{--get-byte} | @option{--get-word} | @option{--get-dword} | @ + @option{--get-qword} | @option{--get-string} | @option{--get-uuid}) @ + @var{offset} @ + [@option{--set} @var{variable}] +Retrieve SMBIOS information. + +The @command{smbios} command returns the value of a field in an SMBIOS +structure. The following options determine which structure to select. + +@itemize @bullet +@item +Specifying @option{--type} will select structures with a matching +@var{type}. The type can be any integer from 0 to 255. +@item +Specifying @option{--handle} will select structures with a matching +@var{handle}. The handle can be any integer from 0 to 65535. +@item +Specifying @option{--match} will select structure number @var{match} in the +filtered list of structures; e.g. @code{smbios --type 4 --match 2} will select +the second Process Information (Type 4) structure. The list is always ordered +the same as the hardware's SMBIOS table. The match number must be a positive +integer. If unspecified, the first matching structure will be selected. +@end itemize + +The remaining options determine which field in the selected SMBIOS structure to +return. Only one of these options may be specified at a time. + +@itemize @bullet +@item +When given @option{--get-byte}, return the value of the byte +at @var{offset} bytes into the selected SMBIOS structure. +It will be formatted as an unsigned decimal integer. +@item +When given @option{--get-word}, return the value of the word (two bytes) +at @var{offset} bytes into the selected SMBIOS structure. +It will be formatted as an unsigned decimal integer. +@item +When given @option{--get-dword}, return the value of the dword (four bytes) +at @var{offset} bytes into the selected SMBIOS structure. +It will be formatted as an unsigned decimal integer. +@item +When given @option{--get-qword}, return the value of the qword (eight bytes) +at @var{offset} bytes into the selected SMBIOS structure. +It will be formatted as an unsigned decimal integer. +@item +When given @option{--get-string}, return the string with its index found +at @var{offset} bytes into the selected SMBIOS structure. +@item +When given @option{--get-uuid}, return the value of the UUID (sixteen bytes) +at @var{offset} bytes into the selected SMBIOS structure. +It will be formatted as lower-case hyphenated hexadecimal digits, with the +first three fields as little-endian, and the rest printed byte-by-byte. +@end itemize + +The default action is to print the value of the requested field to the console, +but a variable name can be specified with @option{--set} to store the value +instead of printing it. + +For example, this will store and then display the system manufacturer's name. + +@example +smbios --type 1 --get-string 4 --set system_manufacturer +echo $system_manufacturer +@end example +@end deffn + + +@node source +@subsection source + +@deffn Command source file +Read @var{file} as a configuration file, as if its contents had been +incorporated directly into the sourcing file. Unlike @command{configfile} +(@pxref{configfile}), this executes the contents of @var{file} without +changing context: any environment variable changes made by the commands in +@var{file} will be preserved after @command{source} returns, and the menu +will not be shown immediately. +@end deffn + + +@node test +@subsection test + +@deffn Command test expression +Evaluate @var{expression} and return zero exit status if result is true, +non zero status otherwise. + +@var{expression} is one of: + +@table @asis +@item @var{string1} @code{==} @var{string2} +the strings are equal +@item @var{string1} @code{!=} @var{string2} +the strings are not equal +@item @var{string1} @code{<} @var{string2} +@var{string1} is lexicographically less than @var{string2} +@item @var{string1} @code{<=} @var{string2} +@var{string1} is lexicographically less or equal than @var{string2} +@item @var{string1} @code{>} @var{string2} +@var{string1} is lexicographically greater than @var{string2} +@item @var{string1} @code{>=} @var{string2} +@var{string1} is lexicographically greater or equal than @var{string2} +@item @var{integer1} @code{-eq} @var{integer2} +@var{integer1} is equal to @var{integer2} +@item @var{integer1} @code{-ge} @var{integer2} +@var{integer1} is greater than or equal to @var{integer2} +@item @var{integer1} @code{-gt} @var{integer2} +@var{integer1} is greater than @var{integer2} +@item @var{integer1} @code{-le} @var{integer2} +@var{integer1} is less than or equal to @var{integer2} +@item @var{integer1} @code{-lt} @var{integer2} +@var{integer1} is less than @var{integer2} +@item @var{integer1} @code{-ne} @var{integer2} +@var{integer1} is not equal to @var{integer2} +@item @var{prefix}@var{integer1} @code{-pgt} @var{prefix}@var{integer2} +@var{integer1} is greater than @var{integer2} after stripping off common non-numeric @var{prefix}. +@item @var{prefix}@var{integer1} @code{-plt} @var{prefix}@var{integer2} +@var{integer1} is less than @var{integer2} after stripping off common non-numeric @var{prefix}. +@item @var{file1} @code{-nt} @var{file2} +@var{file1} is newer than @var{file2} (modification time). Optionally numeric @var{bias} may be directly appended to @code{-nt} in which case it is added to the first file modification time. +@item @var{file1} @code{-ot} @var{file2} +@var{file1} is older than @var{file2} (modification time). Optionally numeric @var{bias} may be directly appended to @code{-ot} in which case it is added to the first file modification time. +@item @code{-d} @var{file} +@var{file} exists and is a directory +@item @code{-e} @var{file} +@var{file} exists +@item @code{-f} @var{file} +@var{file} exists and is not a directory +@item @code{-s} @var{file} +@var{file} exists and has a size greater than zero +@item @code{-n} @var{string} +the length of @var{string} is nonzero +@item @var{string} +@var{string} is equivalent to @code{-n @var{string}} +@item @code{-z} @var{string} +the length of @var{string} is zero +@item @code{(} @var{expression} @code{)} +@var{expression} is true +@item @code{!} @var{expression} +@var{expression} is false +@item @var{expression1} @code{-a} @var{expression2} +both @var{expression1} and @var{expression2} are true +@item @var{expression1} @var{expression2} +both @var{expression1} and @var{expression2} are true. This syntax is not POSIX-compliant and is not recommended. +@item @var{expression1} @code{-o} @var{expression2} +either @var{expression1} or @var{expression2} is true +@end table +@end deffn + +@node tpm2_key_protector_init +@subsection tpm2_key_protector_init + +@deffn Command tpm2_key_protector_init [@option{--mode} | @option{-m} mode] | [@option{--pcrs} | @option{-p} pcrlist] | [@option{--bank} | @option{-b} pcrbank] | [ [@option{--tpm2key} | @option{-T} tpm2key_file] | [@option{--keyfile} | @option{-k} keyfile] ] | [@option{--srk} | @option{-s} handle] | [@option{--asymmetric} | @option{-a} srk_type] | [@option{--nvindex} | @option{-n} nv_index] +Initialize the TPM2 key protector to unseal the key for the @command{cryptomount} +(@pxref{cryptomount}) command. There are two supported modes, +SRK(@kbd{srk}) and NV index(@kbd{nv}), to be specified by the option +@option{-m}. The default mode is SRK. The main difference between SRK mode +and NV index mode is the storage of the sealed key. For SRK mode, the sealed +key is stored in a file while NV index mode stores the sealed key in the +non-volatile memory inside TPM with a given NV index. + +The @option{-p} and @option{-b} options are used to supply the PCR list and +bank that the key is sealed with. The PCR list is a comma-separated list, e.g., +'0,2,4,7,9', to represent the involved PCRs, and the default is '7'. The PCR +bank is chosen by selecting a hash algorithm. The current supported PCR banks +are SHA1, SHA256, SHA384, and SHA512, and the default is SHA256. + +Some options are only available for the specific mode. The SRK-specific +options are @option{-T}, @option{-k}, @option{-a}, and @option{-s}. On the +other hand, the NV index-specific option is @option{-n}. + +The key file for SRK mode can be supplied with either @option{-T} or +@option{-k}. Those two options were used to distinguish the file formats but +are same now. There are two supported file formats: raw format and TPM 2.0 +Key File format. When using the key file in the raw format, the @option{-p} +and @option{-b} options are necessary for the non-default PCR list or bank. +On the other hand, when using the key file in TPM 2.0 Key File format, the +the parameters for the TPM commands are written in the file, and there is no +need to set the PCR list(@option{-p}) and bank(@option{-b}). In general, +TPM 2.0 Key File format is preferred due to the simplified GRUB command +options and the authorized policy support + +Besides the key file, there are two options, @option{-a} and @option{-s}, to +tweak the TPM Storage Root Key (SRK). The SRK can be either created at +runtime or stored in the non-volatile memory. When creating SRK at runtime, +GRUB provides the SRK template to the TPM to create the key. There are two SRK +templates for the @option{-a} option, ECC and RSA, and the default is ECC. +If the SRK is stored in a specific handle, e.g. @code{0x81000001}, the +@option{-s} option can be used to set the handle to notify GRUB to load +the SRK from the given handle. + +The only NV index-specific option is the @option{-n} option which is used to +set the NV index containing the sealed key. Then GRUB can load the sealed +key and unseal it with the given PCR list and bank. +@end deffn + +@node tpm2_key_protector_clear +@subsection tpm2_key_protector_clear + +@deffn Command tpm2_key_protector_clear +Clear the TPM2 key protector if previously initialized. +@end deffn + +@node tpm2_dump_pcr +@subsection tpm2_dump_pcr + +@deffn Command tpm2_dump_pcr [@var{bank}] +Print all PCRs of the specified TPM 2.0 @var{bank}. The supported banks are +@samp{sha1}, @samp{sha256}, @samp{sha384}, and @samp{sha512}. If @var{bank} +is not specified, @samp{sha256} is chosen by default. + +Since GRUB measures every command into PCR 8, invoking @command{tpm2_dump_pcr} +also extends PCR 8, so PCR 8 will not be a stable value in GRUB shell. +@end deffn + @node true @subsection true @@ -4016,6 +8155,22 @@ Do nothing, successfully. This is mainly useful in control constructs such as @code{if} and @code{while} (@pxref{Shell-like scripting}). @end deffn +@node trust +@subsection trust + +@deffn Command trust [@option{--skip-sig}] pubkey_file +Read public key from @var{pubkey_file} and add it to GRUB's internal +list of trusted public keys. These keys are used to validate digital +signatures when environment variable @code{check_signatures} is set to +@code{enforce}. Note that if @code{check_signatures} is set to +@code{enforce} when @command{trust} executes, then @var{pubkey_file} +must itself be properly signed. The @option{--skip-sig} option can be +used to disable signature-checking when reading @var{pubkey_file} +itself. It is expected that @option{--skip-sig} is useful for testing +and manual booting. @xref{Using digital signatures}, for more +information. +@end deffn + @node unset @subsection unset @@ -4025,23 +8180,388 @@ Unset the environment variable @var{envvar}. @end deffn -@node uppermem -@subsection uppermem +@ignore +@node vbeinfo +@subsection vbeinfo + +@deffn Command vbeinfo [[WxH]xD] +Alias for command @command{videoinfo} (@pxref{videoinfo}). It is available +only on PC BIOS platforms. +@end deffn +@end ignore + + +@node verify_detached +@subsection verify_detached + +@deffn Command verify_detached [@option{--skip-sig}] file signature_file [pubkey_file] +Verifies a GPG-style detached signature, where the signed file is +@var{file}, and the signature itself is in file @var{signature_file}. +Optionally, a specific public key to use can be specified using +@var{pubkey_file}. When environment variable @code{check_signatures} +is set to @code{enforce}, then @var{pubkey_file} must itself be +properly signed by an already-trusted key. An unsigned +@var{pubkey_file} can be loaded by specifying @option{--skip-sig}. +If @var{pubkey_file} is omitted, then public keys from GRUB's trusted keys +(@pxref{list_trusted}, @pxref{trust}, and @pxref{distrust}) are +tried. + +Exit code @code{$?} is set to 0 if the signature validates +successfully. If validation fails, it is set to a non-zero value. +@xref{Using digital signatures}, for more information. +@end deffn + +@node videoinfo +@subsection videoinfo + +@deffn Command videoinfo [[WxH]xD] +List available video modes. If resolution is given, show only matching modes. +@end deffn + +@node wrmsr +@subsection wrmsr + +@deffn Command: wrmsr 0xADDR 0xVALUE +Write a 0xVALUE to a model-specific register at address 0xADDR. + +Please note that on SMP systems, writing to a MSR that has a scope +per hardware thread, implies that the value that is written +only applies to the particular cpu/core/thread that runs the command. + +Also, if you specify a reserved or unimplemented MSR address, it will +cause a general protection exception (which is not currently being handled) +and the system will reboot. + +Note: The command is not allowed when lockdown is enforced (@pxref{Lockdown}). + This is done to prevent subverting various security mechanisms. +@end deffn + +@node Networking commands +@section Networking commands + +@menu +* net_add_addr:: Add a network address +* net_add_dns:: Add a DNS server +* net_add_route:: Add routing entry +* net_bootp:: Perform a bootp/DHCP autoconfiguration +* net_del_addr:: Remove IP address from interface +* net_del_dns:: Remove a DNS server +* net_del_route:: Remove a route entry +* net_dhcp:: Perform a DHCP autoconfiguration +* net_get_dhcp_option:: Retrieve DHCP options +* net_ipv6_autoconf:: Perform IPv6 autoconfiguration +* net_ls_addr:: List interfaces +* net_ls_cards:: List network cards +* net_ls_dns:: List DNS servers +* net_ls_routes:: List routing entries +* net_nslookup:: Perform a DNS lookup +* net_set_vlan:: Set vlan id on an interface +@end menu + + +@node net_add_addr +@subsection net_add_addr + +@deffn Command net_add_addr @var{interface} @var{card} @var{address} +Configure additional network @var{interface} with @var{address} on a +network @var{card}. @var{address} can be either IP in dotted decimal notation, +or symbolic name which is resolved using DNS lookup. If successful, this command +also adds local link routing entry to the default subnet of @var{address} +with name @var{interface}@samp{:local} via @var{interface}. +@end deffn + + +@node net_add_dns +@subsection net_add_dns + +@deffn Command net_add_dns @var{server} +Resolve @var{server} IP address and add to the list of DNS servers used during +name lookup. +@end deffn + + +@node net_add_route +@subsection net_add_route + +@deffn Command net_add_route @var{shortname} @var{ip}[/@var{prefix}] [@var{interface} | @samp{gw} @var{gateway}] +Add route to network with address @var{ip} as modified by @var{prefix} via +either local @var{interface} or @var{gateway}. @var{prefix} is optional and +defaults to 32 for IPv4 address and 128 for IPv6 address. Route is identified +by @var{shortname} which can be used to remove it (@pxref{net_del_route}). +@end deffn + + +@node net_bootp +@subsection net_bootp + +@deffn Command net_bootp [@var{card}] +Alias for net_dhcp, for compatibility with older Grub versions. Will perform +the same DHCP handshake with potential fallback to BOOTP as the net_dhcp +command (@pxref{net_dhcp}). + +@end deffn + + +@node net_del_addr +@subsection net_del_addr + +@deffn Command net_del_addr @var{interface} +Remove configured @var{interface} with associated address. +@end deffn + + +@node net_del_dns +@subsection net_del_dns + +@deffn Command net_del_dns @var{address} +Remove @var{address} from list of servers used during name lookup. +@end deffn + + +@node net_del_route +@subsection net_del_route + +@deffn Command net_del_route @var{shortname} +Remove route entry identified by @var{shortname}. +@end deffn + + +@node net_dhcp +@subsection net_dhcp + +@deffn Command net_dhcp [@var{card}] +Perform configuration of @var{card} using DHCP protocol. If no card name +is specified, try to configure all existing cards. +Falls back to the BOOTP protocol, if needed. If configuration was +successful, interface with name @var{card}@samp{:dhcp} and configured +address is added to @var{card}. +@comment If server provided gateway information in +@comment DHCP ACK packet, it is added as route entry with the name @var{card}@samp{:dhcp:gw}. +Additionally the following DHCP options are recognized and processed: + +@table @samp +@item 1 (Subnet Mask) +Used to calculate network local routing entry for interface @var{card}@samp{:dhcp}. +@item 3 (Router) +Adds default route entry with the name @var{card}@samp{:dhcp:default} via gateway +from DHCP option. Note that only option with single route is accepted. +@item 6 (Domain Name Server) +Adds all servers from option value to the list of servers used during name resolution. +@item 12 (Host Name) +Sets environment variable @samp{net_}@var{}@samp{_dhcp_hostname} +(@pxref{net_@var{}_hostname}) to the value of option. +@item 15 (Domain Name) +Sets environment variable @samp{net_}@var{}@samp{_dhcp_domain} +(@pxref{net_@var{}_domain}) to the value of option. +@item 17 (Root Path) +Sets environment variable @samp{net_}@var{}@samp{_dhcp_rootpath} +(@pxref{net_@var{}_rootpath}) to the value of option. +@item 18 (Extensions Path) +Sets environment variable @samp{net_}@var{}@samp{_dhcp_extensionspath} +(@pxref{net_@var{}_extensionspath}) to the value of option. +@item 66 (TFTP Server Name) +Sets environment variable @samp{net_}@var{}@samp{_dhcp_server_name} +(@pxref{net_@var{}_dhcp_server_name}) to the value of option. +@item 67 (Filename) +Sets environment variable @samp{net_}@var{}@samp{_boot_file} +(@pxref{net_@var{}_boot_file}) to the value of option. +@end table + +@end deffn + + +@node net_get_dhcp_option +@subsection net_get_dhcp_option + +@deffn Command net_get_dhcp_option @var{var} @var{interface} @var{number} @var{type} +Request DHCP option @var{number} of @var{type} via @var{interface}. @var{type} +can be one of @samp{string}, @samp{number} or @samp{hex}. If option is found, +assign its value to variable @var{var}. Values of types @samp{number} and @samp{hex} +are converted to string representation. +@end deffn + + +@node net_ipv6_autoconf +@subsection net_ipv6_autoconf + +@deffn Command net_ipv6_autoconf [@var{card}] +Perform IPv6 autoconfiguration by adding to the @var{card} interface with name +@var{card}@samp{:link} and link local MAC-based address. If no card is specified, +perform autoconfiguration for all existing cards. +@end deffn + + +@node net_ls_addr +@subsection net_ls_addr + +@deffn Command net_ls_addr +List all configured interfaces with their MAC and IP addresses. +@end deffn + + +@node net_ls_cards +@subsection net_ls_cards + +@deffn Command net_ls_cards +List all detected network cards with their MAC address. +@end deffn + + +@node net_ls_dns +@subsection net_ls_dns + +@deffn Command net_ls_dns +List addresses of DNS servers used during name lookup. +@end deffn + + +@node net_ls_routes +@subsection net_ls_routes + +@deffn Command net_ls_routes +List routing entries. +@end deffn + + +@node net_nslookup +@subsection net_nslookup + +@deffn Command net_nslookup @var{name} [@var{server}] +Resolve address of @var{name} using DNS server @var{server}. If no server +is given, use default list of servers. +@end deffn + + +@node net_set_vlan +@subsection net_set_vlan + +@deffn Command net_set_vlan @var{interface} @var{vlanid} +Set the 802.1Q VLAN identifier on @var{interface} to @var{vlanid}. For example, +to set the VLAN identifier on interface @samp{efinet1} to @samp{100}: + +@example +net_set_vlan efinet1 100 +@end example + +The VLAN identifier can be removed by setting it to @samp{0}: + +@example +net_set_vlan efinet1 0 +@end example +@end deffn + + +@node Undocumented commands +@section Commands currently undocumented +Unfortunately, not all GRUB commands are documented at this time due to +developer resource constraints. One way to contribute back to the GRUB +project would be to help document these commands, and submit patches or +ideas to the mailing list. The following is a (most likely incomplete) +list of undocumented or poorly documented commands and not all of them +are allowed for all platforms. Running the command help from within the +GRUB shell may provide more information on parameters and usage. + +@itemize @bullet +@item @command{all_functional_test} - Run all functional tests. +@item @command{backtrace} - Print backtrace. +@item @command{boottime} - Show boot time statistics. +@item @command{cacheinfo} - Get disk cache info. +@item @command{cbmemc} - Show CBMEM console content. +@item @command{cmosset} - Set bit at BYTE:BIT in CMOS. +@item @command{coreboot_boottime} - Show coreboot boot time statistics. +@item @command{dump} - Show memory contents. +@item @command{efiemu_loadcore} - Load and initialize EFI emulator. +@item @command{efiemu_prepare} - Finalize loading of EFI emulator. +@item @command{efiemu_unload} - Unload EFI emulator. +@item @command{exit} - Exit from GRUB. +@item @command{extract_entries_configfile} - Load another config file but take only menu entries. +@item @command{extract_entries_source} - Load another config file without changing context but take only menu entries. +@item @command{extract_legacy_entries_configfile} - Parse legacy config in new context taking only menu entries +@item @command{extract_legacy_entries_source} - Parse legacy config in same context taking only menu entries +@item @command{extract_syslinux_entries_configfile} - Execute syslinux config in new context taking only menu entries +@item @command{extract_syslinux_entries_source} - Execute syslinux config in same context taking only menu entries +@item @command{fakebios} - Create BIOS-like structures for backward compatibility with existing OS. +@item @command{fix_video} - Fix video problem. +@item @command{fpswa} - Display FPSWA version. +@item @command{functional_test} - Run all loaded functional tests. +@item @command{gdbstub_break} - Break into GDB +@item @command{gdbstub} - Start GDB stub on given port +@item @command{gdbstub_stop} - Stop GDB stub +@item @command{hdparm} - Get/set ATA disk parameters. +@item @command{hexdump_random} - Hexdump random data. +@item @command{inb} - Read 8-bit value from PORT. +@item @command{inl} - Read 32-bit value from PORT. +@item @command{inw} - Read 16-bit value from PORT. +@item @command{jpegtest} - Tests loading of JPEG bitmap. +@item @command{keymap} - Load a keyboard layout. +@item @command{legacy_check_password} - Simulate grub-legacy `password' command in menu entry mode +@item @command{legacy_configfile} - Parse legacy config in new context +@item @command{legacy_password} - Simulate grub-legacy `password' command +@item @command{legacy_source} - Parse legacy config in same context +@item @command{loadbios} - Load BIOS dump. +@item @command{lsacpi} - Show ACPI information. +@item @command{lsapm} - Show APM information. +@item @command{lscoreboot} - List coreboot tables. +@item @command{lsdev} - List devices. +@item @command{lsefi} - Display EFI handles. +@item @command{lsefimmap} - Display EFI memory map. +@item @command{lsefisystab} - Display EFI system tables. +@item @command{lsmmap} - List memory map provided by firmware. +@item @command{lspci} - List PCI devices. +@item @command{lssal} - Display SAL system table. +@item @command{lsspd} - Print Memory information. +@item @command{macppcbless} - Bless DIR of HFS or HFS+ partition for PPC macs. +@item @command{mactelbless} - Bless FILE of HFS or HFS+ partition for intel macs. +@item @command{net_set_vlan} - Set an interface's vlan id. +@item @command{outb} - Write 8-bit VALUE to PORT. +@item @command{outl} - Write 32-bit VALUE to PORT. +@item @command{outw} - Write 16-bit VALUE to PORT. +@item @command{pcidump} - Show raw dump of the PCI configuration space. +@item @command{pngtest} - Tests loading of PNG bitmap. +@item @command{read_byte} - Read 8-bit value from ADDR. +@item @command{read_dword} - Read 32-bit value from ADDR. +@item @command{read_word} - Read 16-bit value from ADDR. +@item @command{setpci} - Manipulate PCI devices. +@item @command{suspend} - Return to IEEE1275 prompt. +@item @command{syslinux_configfile} - Execute syslinux config in new context +@item @command{syslinux_source} - Execute syslinux config in same context +@item @command{test_blockarg} - Print and execute block argument., 0 +@item @command{testload} - Load the same file in multiple ways. +@item @command{testspeed} - Test file read speed. +@item @command{tgatest} - Tests loading of TGA bitmap. +@item @command{time} - Measure time used by COMMAND +@item @command{tr} - Translate SET1 characters to SET2 in STRING. +@item @command{usb} - Test USB support. +@item @command{vbeinfo} - List available video modes. If resolution is given show only modes matching it. +@item @command{vbetest} - Test video subsystem. +@item @command{videotest} - Test video subsystem in mode WxH. +@item @command{write_byte} - Write 8-bit VALUE to ADDR. +@item @command{write_dword} - Write 32-bit VALUE to ADDR. +@item @command{write_word} - Write 16-bit VALUE to ADDR. +@item @command{xen_cat} - List Xen storage. +@item @command{xen_ls} - List Xen storage. +@item @command{xnu_devprop_load} - Load `device-properties' dump. +@item @command{xnu_uuid} - Transform 64-bit UUID to format suitable for XNU. If -l is given keep it lowercase as done by blkid. +@item @command{zfs-bootfs} - Print ZFS-BOOTFSOBJ or store it into VARIABLE +@item @command{zfsinfo} - Print ZFS info about DEVICE. +@item @command{zfskey} - Import ZFS wrapping key stored in FILE. +@end itemize -This command is not yet implemented for GRUB 2, although it is planned. @node Internationalisation -@chapter Charset +@chapter Internationalisation + +@section Charset GRUB uses UTF-8 internally other than in rendering where some GRUB-specific appropriate representation is used. All text files (including config) are assumed to be encoded in UTF-8. -@chapter Filesystems +@section Filesystems NTFS, JFS, UDF, HFS+, exFAT, long filenames in FAT, Joliet part of ISO9660 are treated as UTF-16 as per specification. AFS and BFS are read as UTF-8, again according to specification. BtrFS, cpio, tar, squash4, minix, -minix2, minix3, ROMFS, ReiserFS, XFS, ext2, ext3, ext4, FAT (short names), -RockRidge part of ISO9660, nilfs2, UFS1, UFS2 and ZFS are assumed +minix2, minix3, ROMFS, ReiserFS, XFS, EROFS, ext2, ext3, ext4, FAT (short names), +F2FS, RockRidge part of ISO9660, nilfs2, UFS1, UFS2 and ZFS are assumed to be UTF-8. This might be false on systems configured with legacy charset but as long as the charset used is superset of ASCII you should be able to access ASCII-named files. And it's recommended to configure your system to use @@ -4070,32 +8590,41 @@ treated as distinct from u+combining diaresis. This however means that in order to access file on HFS+ its name must be specified in normalisation form D. On normalized ZFS subvolumes filenames out of normalisation are inaccessible. -@chapter Output terminal +@section Output terminal Firmware output console ``console'' on ARC and IEEE1275 are limited to ASCII. + BIOS firmware console and VGA text are limited to ASCII and some pseudographics. + None of above mentioned is appropriate for displaying international and any unsupported character is replaced with question mark except pseudographics -which we attempt to approximate with ASCII. EFI console on the other hand -nominally supports UTF-16 but actual language coverage depends on firmware and -may be very limited. The encoding used on serial can be chosen with -@command{terminfo} as either ASCII, UTF-8 or ``visual UTF-8''. Last one is -against the specification but results in correct rendering of right-to-left -on some readers which don't have own bidi implementation. When using gfxterm -or gfxmenu GRUB itself is responsible for rendering the text. In this case -GRUB is limited by loaded fonts. If fonts contain all required characters -then bidirectional text, cursive variants and combining marks other than -enclosing, half (e.g. left half tilde or combining overline) and double ones. -Ligatures aren't supported though. This should cover European, Middle Eastern -(if you don't mind lack of lam-alif ligature in Arabic) and East Asian scripts. -Notable unsupported scripts are Brahmic family and derived as well as -Mongolian, Tifinagh, Korean Jamo (precomposed characters have no problem) -and tonal writing (2e5-2e9). GRUB also ignores deprecated (as specified -in Unicode) characters (e.g. tags). GRUB also doesn't handle so called -``annotation characters'' If you can complete either of -two lists or, better, propose a patch to improve rendering, please contact -developper team. +which we attempt to approximate with ASCII. -@chapter Input terminal +EFI console on the other hand nominally supports UTF-16 but actual language +coverage depends on firmware and may be very limited. + +The encoding used on serial can be chosen with @command{terminfo} as +either ASCII, UTF-8 or ``visual UTF-8''. Last one is against the specification +but results in correct rendering of right-to-left on some readers which don't +have own bidi implementation. + +On emu GRUB checks if charset is UTF-8 and uses it if so and uses ASCII +otherwise. + +When using gfxterm or gfxmenu GRUB itself is responsible for rendering the +text. In this case GRUB is limited by loaded fonts. If fonts contain all +required characters then bidirectional text, cursive variants and combining +marks other than enclosing, half (e.g. left half tilde or combining overline) +and double ones. Ligatures aren't supported though. This should cover European, +Middle Eastern (if you don't mind lack of lam-alif ligature in Arabic) and +East Asian scripts. Notable unsupported scripts are Brahmic family and +derived as well as Mongolian, Tifinagh, Korean Jamo (precomposed characters +have no problem) and tonal writing (2e5-2e9). GRUB also ignores deprecated +(as specified in Unicode) characters (e.g. tags). GRUB also doesn't handle so +called ``annotation characters'' If you can complete either of +two lists or, better, propose a patch to improve rendering, please contact +developer team. + +@section Input terminal Firmware console on BIOS, IEEE1275 and ARC doesn't allow you to enter non-ASCII characters. EFI specification allows for such but author is unaware of any actual implementations. Serial input is currently limited for latin1 (unlikely @@ -4105,15 +8634,15 @@ So no dead keys or advanced input method. Also there is no keymap change hotkey. In practice it makes difficult to enter any text using non-Latin alphabet. Moreover all current input consumers are limited to ASCII. -@chapter Gettext +@section Gettext GRUB supports being translated. For this you need to have language *.mo files in $prefix/locale, load gettext module and set ``lang'' variable. -@chapter Regexp -Regexps work on unicode characters, however no attempt at checking cannonical +@section Regexp +Regexps work on unicode characters, however no attempt at checking canonical equivalence has been made. Moreover the classes like [:alpha:] match only ASCII subset. -@chapter Other +@section Other Currently GRUB always uses YEAR-MONTH-DAY HOUR:MINUTE:SECOND [WEEKDAY] 24-hour datetime format but weekdays are translated. GRUB always uses the decimal number format with [0-9] as digits and . as @@ -4123,20 +8652,33 @@ matched as binary. Similar behaviour is for matching OSBundleRequired. Since IEEE1275 aliases and OSBundleRequired don't contain any non-ASCII it should never be a problem in practice. Case-sensitive identifiers are matched as raw strings, no canonical -equivalence check is performed. Case-insenstive identifiers are matched +equivalence check is performed. Case-insensitive identifiers are matched as RAW but additionally [a-z] is equivalent to [A-Z]. GRUB-defined identifiers use only ASCII and so should user-defined ones. Identifiers containing non-ASCII may work but aren't supported. Only the ASCII space characters (space U+0020, tab U+000b, CR U+000d and LF U+000a) are recognised. Other unicode space characters aren't a valid field separator. -@command{test} tests <, >, <=, >=, -pgt and -plt compare the strings in the +@command{test} (@pxref{test}) tests <, >, <=, >=, -pgt and -plt compare the strings in the lexicographical order of unicode codepoints, replicating the behaviour of test from coreutils. environment variables and commands are listed in the same order. @node Security -@chapter Authentication and authorisation +@chapter Security + +@menu +* Authentication and authorisation:: Users and access control +* Using digital signatures:: Booting digitally signed code +* UEFI secure boot and shim:: Booting digitally signed PE files +* Secure Boot Advanced Targeting:: Embedded information for generation number based revocation +* Measured Boot:: Measuring boot components +* Lockdown:: Lockdown when booting on a secure setup +* TPM2 key protector:: Managing disk key with TPM2 key protector +@end menu + +@node Authentication and authorisation +@section Authentication and authorisation in GRUB By default, the boot loader interface is accessible to anyone with physical access to the console: anyone can select and edit any menu entry, and anyone @@ -4161,10 +8703,15 @@ In order to enable authentication support, the @samp{superusers} environment variable must be set to a list of usernames, separated by any of spaces, commas, semicolons, pipes, or ampersands. Superusers are permitted to use the GRUB command line, edit menu entries, and execute any menu entry. If -@samp{superusers} is set, then use of the command line is automatically -restricted to superusers. +@samp{superusers} is set, then use of the command line and editing of menu +entries are automatically restricted to superusers. Setting @samp{superusers} +to empty string effectively disables both access to CLI and editing of menu +entries. Building a grub image with @samp{--disable-cli} option will also +disable access to CLI and editing of menu entries, as well as disabling rescue +mode. Note: The environment variable needs to be exported to also affect the +section defined by the @samp{submenu} command (@pxref{submenu}). -Other users may be given access to specific menu entries by giving a list of +Other users may be allowed to execute specific menu entries by giving a list of usernames (as above) using the @option{--users} option to the @samp{menuentry} command (@pxref{menuentry}). If the @option{--unrestricted} option is used for a menu entry, then that entry is unrestricted. @@ -4203,6 +8750,618 @@ generating configuration files with authentication. You can use adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2} commands. +@node Using digital signatures +@section Using digital signatures in GRUB + +GRUB's @file{core.img} can optionally provide enforcement that all files +subsequently read from disk are covered by a valid digital signature. +This document does @strong{not} cover how to ensure that your +platform's firmware (e.g., Coreboot) validates @file{core.img}. + +If environment variable @code{check_signatures} +(@pxref{check_signatures}) is set to @code{enforce}, then every +attempt by the GRUB @file{core.img} to load another file @file{foo} +implicitly invokes @code{verify_detached foo foo.sig} +(@pxref{verify_detached}). @code{foo.sig} must contain a valid +digital signature over the contents of @code{foo}, which can be +verified with a public key currently trusted by GRUB +(@pxref{list_trusted}, @pxref{trust}, and @pxref{distrust}). If +validation fails, then file @file{foo} cannot be opened. This failure +may halt or otherwise impact the boot process. + +An initial trusted public key can be embedded within the GRUB @file{core.img} +using the @code{--pubkey} option to @command{grub-install} +(@pxref{Invoking grub-install}). + +GRUB uses GPG-style detached signatures (meaning that a file +@file{foo.sig} will be produced when file @file{foo} is signed), and +currently supports the DSA and RSA signing algorithms. A signing key +can be generated as follows: + +@example +gpg --gen-key +@end example + +An individual file can be signed as follows: + +@example +gpg --detach-sign /path/to/file +@end example + +For successful validation of all of GRUB's subcomponents and the +loaded OS kernel, they must all be signed. One way to accomplish this +is the following (after having already produced the desired +@file{grub.cfg} file, e.g., by running @command{grub-mkconfig} +(@pxref{Invoking grub-mkconfig}): + +@example +@group +# Edit /dev/shm/passphrase.txt to contain your signing key's passphrase +for i in `find /boot -name "*.cfg" -or -name "*.lst" -or \ + -name "*.mod" -or -name "vmlinuz*" -or -name "initrd*" -or \ + -name "grubenv"`; +do + gpg --batch --detach-sign --passphrase-fd 0 $i < \ + /dev/shm/passphrase.txt +done +shred /dev/shm/passphrase.txt +@end group +@end example + +See also: @ref{check_signatures}, @ref{verify_detached}, @ref{trust}, +@ref{list_trusted}, @ref{distrust}, @ref{load_env}, @ref{save_env}. + +Note that internally signature enforcement is controlled by setting +the environment variable @code{check_signatures} equal to +@code{enforce}. Passing one or more @code{--pubkey} options to +@command{grub-mkimage} implicitly defines @code{check_signatures} +equal to @code{enforce} in @file{core.img} prior to processing any +configuration files. + +Note that signature checking does @strong{not} prevent an attacker +with (serial, physical, ...) console access from dropping manually to +the GRUB console and executing: + +@example +set check_signatures=no +@end example + +To prevent this, password-protection (@pxref{Authentication and +authorisation}) is essential. Note that even with GRUB password +protection, GRUB itself cannot prevent someone with physical access to +the machine from altering that machine's firmware (e.g., Coreboot +or BIOS) configuration to cause the machine to boot from a different +(attacker-controlled) device. GRUB is at best only one link in a +secure boot chain. + +@node UEFI secure boot and shim +@section UEFI secure boot and shim support + +The GRUB works with UEFI secure boot and the shim. This functionality is +provided by the shim_lock verifier. It is built into the @file{core.img} and is +registered if the UEFI secure boot is enabled. The @samp{shim_lock} variable is +set to @samp{y} when shim_lock verifier is registered. If it is desired to use +UEFI secure boot without shim, one can disable shim_lock by disabling shim +verification with MokSbState UEFI variable or by building grub image with +@samp{--disable-shim-lock} option. + +All GRUB modules not stored in the @file{core.img}, OS kernels, ACPI tables, +Device Trees, etc. have to be signed, e.g, using PGP. Additionally, the commands +that can be used to subvert the UEFI secure boot mechanism, such as @command{iorw} +and @command{memrw} will not be available when the UEFI secure boot is enabled. +This is done for security reasons and are enforced by the GRUB Lockdown mechanism +(@pxref{Lockdown}). + +@node Secure Boot Advanced Targeting +@section Embedded information for generation number based revocation + +The Secure Boot Advanced Targeting (SBAT) is a mechanism to allow the revocation +of components in the boot path by using generation numbers embedded into the EFI +binaries. The SBAT metadata is located in an .sbat data section that has set of +UTF-8 strings as comma-separated values (CSV). See +@uref{https://github.com/rhboot/shim/blob/main/SBAT.md} for more details. + +To add a data section containing the SBAT information into the binary, the +@option{--sbat} option of @command{grub-mkimage} command should be used. The content +of a CSV file, encoded with UTF-8, is copied as is to the .sbat data section into +the generated EFI binary. The CSV file can be stored anywhere on the file system. + +@example +grub-mkimage -O x86_64-efi -o grubx64.efi -p '(tftp)/grub' --sbat sbat.csv efinet tftp +@end example + +@node Measured Boot +@section Measuring boot components + +If the tpm module is loaded and the platform has a Trusted Platform Module +installed, GRUB will log each command executed and each file loaded into the +TPM event log and extend the PCR values in the TPM correspondingly. All events +will be logged into the PCR described below with a type of EV_IPL and an +event description as described below. + +@multitable @columnfractions 0.3 0.1 0.6 +@headitem Event type @tab PCR @tab Description +@item Command +@tab 8 +@tab All executed commands (including those from configuration files) will be +logged and measured as entered with a prefix of ``grub_cmd: `` +@item Kernel command line +@tab 8 +@tab Any command line passed to a kernel will be logged and measured as entered +with a prefix of ``kernel_cmdline: '' +@item Module command line +@tab 8 +@tab Any command line passed to a kernel module will be logged and measured as +entered with a prefix of ``module_cmdline: `` +@item Files +@tab 9 +@tab Any file read by GRUB will be logged and measured with a descriptive text +corresponding to the filename. +@end multitable + +GRUB will not measure its own @file{core.img} - it is expected that firmware +will carry this out. GRUB will also not perform any measurements until the +tpm module is loaded. As such it is recommended that the tpm module be built +into @file{core.img} in order to avoid a potential gap in measurement between +@file{core.img} being loaded and the tpm module being loaded. + +Measured boot is currently only supported on EFI and IBM IEEE1275 PowerPC +platforms. + +@node Lockdown +@section Lockdown when booting on a secure setup + +The GRUB can be locked down when booted on a secure boot environment, for example +if the UEFI secure boot is enabled. On a locked down configuration, the GRUB will +be restricted and some operations/commands cannot be executed. This also includes +limiting which filesystems are supported to those thought to be more robust and +widely used within GRUB. + +The filesystems currently allowed in lockdown mode include: +@itemize @bullet +@item BtrFS +@item cpio +@item exFAT +@item Enhanced Read-Only File System (EROFS) +@item Linux ext2/ext3/ext4 +@item F2FS +@item DOS FAT12/FAT16/FAT32 +@item HFS+ +@item ISO9660 +@item Squash4 +@item tar +@item XFS +@item ZFS +@end itemize + +The filesystems currently not allowed in lockdown mode include: +@itemize @bullet +@item Amiga Fast FileSystem (AFFS) +@item AtheOS File System (AFS) +@item Bee File System (BFS) +@item Coreboot File System (CBFS) +@item Hierarchical File System (HFS) +@item Journaled File System (JFS) +@item Minix filesystem +@item New Implementation of Log filesystem (nilfs2) +@item Windows New Technology File System (NTFS) +@item ReiserFS +@item Read-Only Memory File System (ROMFS) +@item Amiga Smart File System (SFS) +@item Universal Disk Format (UDF) +@item Unix File System (UFS) +@end itemize + +The @samp{lockdown} variable is set to @samp{y} when the GRUB is locked down. +Otherwise it does not exist. + +@node TPM2 key protector +@section TPM2 key protector in GRUB + +TPM2 key protector extends measured boot to unlock the encrypted partition +without user intervention. It uses the TPM Storage Root Key (SRK) to seal +the disk key with a given set of PCR values. If the system state matches, +i.e. PCR values match the sealed PCR set, TPM2 key protector unseals the +disk key for @command{cryptomount} (@pxref{cryptomount}) to unlock the +encrypted partition. In case the unsealed key fails to unlock the +partition, @command{cryptomount} falls back to the passphrase prompt. + +Please note that TPM2 key protector uses the SRK in the owner hierarchy +@emph{without} authorization. If the owner hierarchy is password-protected, +TPM2 key protector may fail to unseal the key due to the absence of the +password. For the systems that already enable the password protection for the +owner hierarchy, the following command removes the password protection with +the existing password. + +@example +# @kbd{tpm2_changeauth -c owner -p password} +@end example + +There are two supported modes to store the sealed key, SRK and NV index. +The details will be addressed in later sections. + +TPM2 key protector is currently only supported on EFI and EMU platforms. + +@subsection TPM PCR usage + +Since TPM2 key protector relies on PCRs to check the system state, it is +important to decide which PCRs to seal the key with. The following table +lists uses of PCRs and the measured objects on EFI platforms. + +@multitable @columnfractions 0.1 0.2 0.7 +@headitem PCR @tab Used by @tab Measured Objects +@item 0 +@tab Firmware +@tab Core system firmware executable code +@item 1 +@tab Firmware +@tab Core system firmware data/host platform configuration; typically +contains serial and model numbers +@item 2 +@tab Firmware +@tab Extended or pluggable executable code; includes option ROMs on +pluggable hardware +@item 3 +@tab Firmware +@tab Extended or pluggable firmware data; includes information about +pluggable hardware +@item 4 +@tab Firmware +@tab Boot loader and additional drivers; binaries and extensions loaded +by the boot loader +@item 5 +@tab Firmware +@tab GPT/Partition table +@item 7 +@tab Firmware +@tab SecureBoot state +@item 8 +@tab GRUB +@tab Commands and kernel command line +@item 9 +@tab GRUB +@tab All files read (including kernel image) +@item 9 +@tab Linux Kernel +@tab All passed initrds (when the new LOAD_FILE2 initrd protocol is used) +@item 10 +@tab Linux Kernel +@tab Protection of the IMA measurement log +@item 14 +@tab shim +@tab “MOK†certificates and hashes +@end multitable + +PCR 0, 2, 4, and 7 can be used to check the integrity of the firmware code +and bootloaders. PCR 8 and 9 are useful to check the file and data processed +by GRUB. PCRs 10, 11, 12, 13, and 15 are controlled by the operating system, +so those PCRs are usually still in the initial state when GRUB is running. + +In general, it is nice to include PCR 0, 2, 4, and 7 to ensure the integrity +of the firmware and bootloaders. For PCR 8 and 9, a sophisticated tool is +required to examine the GRUB configuration files and the files to be loaded +to calculate the correct PCR values. + +Please note that PCRs are sensitive to any change, so an update of a component +could invalidate the sealed key, due to the so-called PCR brittleness. For the +bootloader update, PCR 4 may be affected. This can be mitigated by extracting +the events from the TPM event log and predict the value with the updated +bootloader binary. On the other hand, it is difficult to predict PCR 0~7 after +a firmware update since the content of the code and the order of drivers may +not follow the TPM event log from the previous firmware version, so it is +necessary to reboot the system to update the measurement results of PCR 0~7 +and seal or sign the sealed key again. + +Reference: @url{https://uapi-group.org/specifications/specs/linux_tpm_pcr_registry/, Linux TPM PCR Registry} + +@subsection Setting up the extra disk key + +Instead of using the existing password, it is recommended to seal a new +random disk key and use the existing password for recovery. + +Here are the sample commands to create a 128 random bytes key file and +enroll the key into the target partition (sda2). + +@example +# @kbd{dd if=/dev/urandom of=luks.key bs=1 count=128} +# @kbd{cryptsetup luksAddKey /dev/sda2 luks.key --pbkdf=pbkdf2 --hash=sha512} +@end example + +@subsection SRK mode + +To unlock the partition with SRK mode, assume that the sealed key is in +@file{(hd0,gpt1)/efi/grub/sealed.tpm}, the following GRUB commands +unseal the disk key with SRK mode and supply it to @command{cryptomount}. + +@example +grub> @kbd{tpm2_key_protector_init -T (hd0,gpt1)/efi/grub/sealed.tpm} +grub> @kbd{cryptomount -u -P tpm2} +@end example + +There are two programs to create the sealed key for SRK mode: @command{grub-protect} +and @command{pcr-oracle} (@url{https://github.com/okirch/pcr-oracle}). + +The following sample command uses @command{grub-protect} to seal the random +key, @file{luks.key}, with PCR 0, 2, 4 and 7 in TPM 2.0 Key File format. + +@example +@group +# @kbd{grub-protect --action=add \ + --protector=tpm2 \ + --tpm2-pcrs=0,2,4,7 \ + --tpm2key \ + --tpm2-keyfile=luks.key \ + --tpm2-outfile=/boot/efi/efi/grub/sealed.tpm} +@end group +@end example + +@command{grub-protect} only seals the key with the current PCR values. +Therefore, when a boot component, such as shim or GRUB, is updated, it is +necessary to reboot the system to update the measurement results and seal +the key again. That means the random disk key has to be stored in cleartext +for the next key sealing. Besides this, the measurement result of some PCRs +may differ between boot time and OS runtime. For example, PCR 9 measures the +files loaded by GRUB including the Linux kernel and initrd. To unlock the disk +containing the kernel and initrd, the key has to be sealed with PCR 9 value +before loading the kernel and initrd. However, PCR 9 changes after GRUB +loading the kernel and initrd, so PCR 9 at OS runtime cannot be used directly +for key sealing. + +To solve these problems, @command{pcr-oracle} takes a different approach. It +reads the TPM eventlog and predicts the PCR values. Besides, +@command{pcr-oracle} also supports ``authorized policy'' which allows the +PCR policy to be updated with a valid signature, so that the user only seals +the random disk key once. If at some later time the PCR values change due to +an update of the system firmware, bootloader, or config file, the user just +needs to update the signature of the PCR policy. + +To seal the key with the authorized policy, the first thing is to generate +the RSA policy key, @file{policy-key.pem}, and the authorized policy file, +@file{authorized.policy}. In this example, PCR 0, 2, 4, 7 and 9 are chosen +for key sealing. + +@example +@group +# @kbd{pcr-oracle --rsa-generate-key \ + --private-key policy-key.pem \ + --auth authorized.policy \ + create-authorized-policy 0,2,4,7,9} +@end group +@end example + +Then, we seal the random disk key, @file{luks.key}, with the authorized +policy file and save the sealed key in @file{sealed.key}. + +@example +@group +# @kbd{pcr-oracle --key-format tpm2.0 \ + --auth authorized.policy \ + --input luks.key \ + --output sealed.key \ + seal-secret} +@end group +@end example + +Since we now have the sealed key, we can remove the random disk key file +@file{luks.key}. + +The last step is to sign the predicted PCR policy and save the final key +file, @file{sealed.tpm}. + +@example +@group +# @kbd{pcr-oracle --key-format tpm2.0 \ + --private-key policy-key.pem \ + --from eventlog \ + --stop-event "grub-file=grub.cfg" \ + --after \ + --input sealed.key \ + --output /boot/efi/efi/grub/sealed.tpm \ + sign 0,2,4,7,9} +@end group +@end example + +Here we also set a stop event for the prediction. With +@kbd{--stop-event grub-file=grub.cfg --after}, @command{pcr-oracle} stops +the calculation of PCR values right after GRUB loads @file{grub.cfg}. + +When/After the shim or GRUB are updated, it only requires to run the last +@command{pcr-oracle} command to update the predicted PCR policy. + +@subsection NV index mode + +Instead of storing the sealed key in a file, NV index mode uses the TPM +non-volatile memory to store the sealed key and could be useful when accessing +the file is not possible. + +However, the Linux root user must be careful who she/he gives access to the +TPM (tss group) since those users will also be able to modify the NV index +that's holding the key. + +There are two types of TPM handles supported by NV index mode: persistent +handle and NV index handle. + +@subsubsection Persistent handle + +The range of persistent handles is from @kbd{0x81000000} to @kbd{0x81FFFFFF}. +The persistent handle is designed to make TPM objects persistent through +power cycles, and only TPM objects, such as RSA or EC keys, are accepted. +Thus, only the raw format is supported by persistent handles. The following +shows the @command{grub-protect} command to seal the disk key @file{luks.key} +into the persistent handle @kbd{0x81000000} with the PCRs @kbd{0,2,4,7}. + +@example +@group +# @kbd{grub-protect \ + --protector=tpm2 \ + --action=add \ + --tpm2-bank=sha256 \ + --tpm2-pcrs=0,2,4,7 \ + --tpm2-keyfile=luks.key \ + --tpm2-nvindex=0x81000000} +@end group +@end example + +To unseal the key, we have to specify the mode @kbd{nv}, the persistent handle +@kbd{0x81000000}, and the PCRs @kbd{0,2,4,7} for the @command{tpm2_key_protector_init} +command. + +@example +grub> @kbd{tpm2_key_protector_init --mode=nv --nvindex=0x81000000 --pcrs=0,2,4,7} +grub> @kbd{cryptomount -u --protector tpm2} +@end example + +If the key in the persistent handle becomes unwanted, the following +@command{grub-protect} command removes the specified persistent handle +@kbd{0x81000000}. + +@example +@group +# @kbd{grub-protect \ + --protector=tpm2 \ + --action=remove \ + --tpm2-evict \ + --tpm2-nvindex=0x81000000} +@end group +@end example + +@subsubsection NV index handle + +The range of NV index handles is from @kbd{0x1000000} to @kbd{0x1FFFFFF}. +Unlike the persistent handle, the NV index handle allows user-defined data, +so it can easily support both the TPM 2.0 Key File format as well as the raw +format. + +The following @kbd{grub-protect} command seals the disk key @file{luks.key} +into the NV index handle @kbd{0x1000000} with the PCRs @kbd{0,2,4,7} while +using the TPM 2.0 Key File format. + +@example +@group +# @kbd{grub-protect \ + --protector=tpm2 \ + --action=add \ + --tpm2key \ + --tpm2-bank=sha256 \ + --tpm2-pcrs=0,2,4,7 \ + --tpm2-keyfile=luks.key \ + --tpm2-nvindex=0x1000000} +@end group +@end example + +Furthermore, it is also possible to insert an existing key file, +@file{sealed.tpm}, into a specific NV index handle using the following +tpm2-tools (@url{https://github.com/tpm2-software/tpm2-tools}) commands. + +@example +@group +# @kbd{tpm2_nvdefine -C o \ + -a "ownerread|ownerwrite" \ + -s $(stat -c %s sealed.tpm) \ + 0x1000000} +@end group +# @kbd{tpm2_nvwrite -C o -i sealed.tpm 0x1000000} +@end example + +When unsealing the key in TPM 2.0 Key File format, only the mode @kbd{nv} +and the NV index handle @kbd{0x1000000} have to be specified for the +@command{tpm2_key_protector_init} command. + +@example +grub> @kbd{tpm2_key_protector_init --mode=nv --nvindex=0x1000000} +grub> @kbd{cryptomount -u --protector tpm2} +@end example + +The following @command{grub-protect} command allows to remove the specified +NV index handle @kbd{0x1000000}. + +@example +@group +# @kbd{grub-protect \ + --protector=tpm2 \ + --action=remove \ + --tpm2-evict \ + --tpm2-nvindex=0x1000000} +@end group +@end example + +@subsection Setting up software TPM for EMU platform + +In order to test TPM2 key protector and TPM2 Software Stack (TSS2), it is +useful to set up a software TPM (swtpm) instance and run the commands on the +EMU platform. + +Here are the commands to start a swtpm instance which provides a character +device interface. To store the TPM states, the directory, @file{swtpm-state}, +is created before the @command{swtpm} command. All the messages are stored +in @file{swtpm.log} including the name of the character device. + +@example +# @kbd{mkdir swtpm-state} +@group +# @kbd{swtpm chardev --vtpm-proxy --tpmstate dir=swtpm-state \ + --tpm2 --ctrl type=unixio,path="swtpm-state/ctrl" \ + --flags startup-clear --daemon > swtpm.log} +@end group +@end example + +Then, we extract the name of the character device from @file{swtpm.log} and +save it to the variable, @samp{tpm2dev}. + +@example +# @kbd{tpm2dev=$(grep "New TPM device" swtpm.log | cut -d' ' -f 4)} +@end example + +Now we can start @kbd{grub-emu} with @kbd{--tpm-device $tpm2dev} to interact +with the swtpm instance. + +@example +# @kbd{grub-emu --tpm-device $tpm2dev} +@end example + +On the host, the tpm2-tools commands can interact with the swtpm instance by +setting @samp{TPM2TOOLS_TCTI}. + +@example +# @kbd{export TPM2TOOLS_TCTI="device:$tpm2dev"} +@end example + +When the test is done, use @kbd{swtpm_ioctl} to send the shutdown +command through the swtpm control channel. + +@example +# @kbd{swtpm_ioctl -s --unix swtpm-state/ctrl} +@end example + +@subsection Command line and menuentry editor protection + +The TPM key protector provides full disk encryption support on servers or +virtual machine images, meanwhile keeping the boot process unattended. This +prevents service disruptions by eliminating the need for manual password input +during startup, improving system uptime and continuity. It is achieved by TPM, +which verifies the integrity of boot components by checking cryptographic +hashes against securely stored values, to confirm the disks are unlocked in a +trusted state. + +However, for users to access the system interactively, some form of +authentication is still required, as the disks are not unlocked by an +authorized user. This raised concerns about using an unprotected +@samp{command-line interface} (@pxref{Command-line interface}), as anyone could +execute commands to access decrypted data. To address this issue, the LUKS +password is used to ensure that only authorized users are granted access to the +interface. Additionally, the @samp{menu entry editor} (@pxref{Menu entry +editor}) is also safeguarded by the LUKS password, as modifying a boot entry is +effectively the same as altering the @file{grub.cfg} file read from encrypted +files. + +It is worth mentioning that the built-in password support, as described in +@samp{Authentication and Authorization in GRUB} (@pxref{Authentication and +authorisation}), can also be used to protect the command-line interface from +unauthorized access. However, it is not recommended to rely on this approach as +it is an optional step. Setting it up requires additional manual intervention, +which increases the risk of password leakage during the process. Moreover, the +superuser list must be well maintained, and the password used cannot be +synchronized with LUKS key rotation. @node Platform limitations @chapter Platform limitations @@ -4211,17 +9370,25 @@ GRUB2 is designed to be portable and is actually ported across platforms. We try to keep all platforms at the level. Unfortunately some platforms are better supported than others. This is detailed in current and 2 following sections. +All platforms have an artificially GRUB imposed disk size restriction of 1 EiB. +In some cases, larger disk sizes can be used, but access will not be allowed +beyond 1 EiB. + +LUKS2 devices with size larger than 16 EiB are currently not supported. They +can not be created as crypto devices by cryptomount, so can not even be +partially read from. LUKS have no limitations other than those imposed by the +format. + ARC platform is unable to change datetime (firmware doesn't seem to provide a function for it). EMU has similar limitation. -ARC platform no serial port is available. -EMU has similar limitation. +On EMU platform no serial port is available. Console charset refers only to firmware-assisted console. gfxterm is always Unicode (see Internationalisation section for its limitations). Serial is configurable to UTF-8 or ASCII (see Internationalisation). In case of qemu -and coreboot ports the refered console is vga_text. Loongson always uses +and coreboot ports the referred console is vga_text. Loongson always uses gfxterm. Most limited one is ASCII. CP437 provides additionally pseudographics. @@ -4230,11 +9397,8 @@ by national encoding compatible only in pseudographics. Unicode is the most versatile charset which supports many languages. However the actual console may be much more limited depending on firmware -On BIOS network is supported only if the image is loaded through network. -On sparc64 GRUB is unable to determine which server it was booted from. - -On platforms not having direct serial support (as indicated in the line serial) -you can still redirect firmware console to serial if it allows so. +On BIOS, network is supported only if the image is loaded through network. +On sparc64, GRUB is unable to determine which server it was booted from. Direct ATA/AHCI support allows to circumvent various firmware limitations but isn't needed for normal operation except on baremetal ports. @@ -4243,10 +9407,13 @@ AT keyboard support allows keyboard layout remapping and support for keys not available through firmware. It isn't needed for normal operation except baremetal ports. +Speaker allows morse and spkmodem communication. + USB support provides benefits similar to ATA (for USB disks) or AT (for USB keyboards). In addition it allows USBserial. Chainloading refers to the ability to load another bootloader through the same protocol +and on some platforms, like EFI, allow that bootloader to return to the GRUB. Hints allow faster disk discovery by already knowing in advance which is the disk in question. On some platforms hints are correct unless you move the disk between boots. @@ -4257,6 +9424,16 @@ BadRAM is the ability to mark some of the RAM as ``bad''. Note: due to protocol limitations mips-loongson (with Linux protocol) and mips-qemu_mips can use only memory up to first hole. +Bootlocation is ability of GRUB to automatically detect where it boots from. +``disk'' means the detection is limited to detecting the disk with partition +being discovered on install time. ``partition'' means that disk and partiton +can be automatically discovered. ``file'' means that boot image file name as +well as disk and partition can be discovered. For consistency, default install ignores +partition and relies solely on disk detection. If no bootlocation discovery is available +or boot and grub-root disks are different, UUID is used instead. On ARC if no device +to install to is specified, UUID is used instead as well. + + @multitable @columnfractions .20 .20 .20 .20 .20 @item @tab BIOS @tab Coreboot @tab Multiboot @tab Qemu @item video @tab yes @tab yes @tab yes @tab yes @@ -4264,14 +9441,18 @@ and mips-qemu_mips can use only memory up to first hole. @item network @tab yes (*) @tab no @tab no @tab no @item ATA/AHCI @tab yes @tab yes @tab yes @tab yes @item AT keyboard @tab yes @tab yes @tab yes @tab yes +@item Speaker @tab yes @tab yes @tab yes @tab yes @item USB @tab yes @tab yes @tab yes @tab yes @item chainloader @tab local @tab yes @tab yes @tab no @item cpuid @tab partial @tab partial @tab partial @tab partial +@item rdmsr @tab partial @tab partial @tab partial @tab partial +@item wrmsr @tab partial @tab partial @tab partial @tab partial @item hints @tab guess @tab guess @tab guess @tab guess @item PCI @tab yes @tab yes @tab yes @tab yes @item badram @tab yes @tab yes @tab yes @tab yes @item compression @tab always @tab pointless @tab no @tab no @item exit @tab yes @tab no @tab no @tab no +@item bootlocation @tab disk @tab no @tab no @tab no @end multitable @multitable @columnfractions .20 .20 .20 .20 .20 @@ -4281,14 +9462,18 @@ and mips-qemu_mips can use only memory up to first hole. @item network @tab yes @tab yes @tab yes @tab yes @item ATA/AHCI @tab yes @tab yes @tab yes @tab no @item AT keyboard @tab yes @tab yes @tab yes @tab no +@item Speaker @tab yes @tab yes @tab yes @tab no @item USB @tab yes @tab yes @tab yes @tab no @item chainloader @tab local @tab local @tab no @tab local @item cpuid @tab partial @tab partial @tab partial @tab no +@item rdmsr @tab partial @tab partial @tab partial @tab no +@item wrmsr @tab partial @tab partial @tab partial @tab no @item hints @tab guess @tab guess @tab good @tab guess @item PCI @tab yes @tab yes @tab yes @tab no @item badram @tab yes @tab yes @tab no @tab yes @item compression @tab no @tab no @tab no @tab no @item exit @tab yes @tab yes @tab yes @tab yes +@item bootlocation @tab file @tab file @tab file, ignored @tab file @end multitable @multitable @columnfractions .20 .20 .20 .20 .20 @@ -4298,31 +9483,39 @@ and mips-qemu_mips can use only memory up to first hole. @item network @tab no @tab yes (*) @tab yes @tab no @item ATA/AHCI @tab yes @tab no @tab no @tab no @item AT keyboard @tab yes @tab no @tab no @tab no +@item Speaker @tab no @tab no @tab no @tab no @item USB @tab yes @tab no @tab no @tab no @item chainloader @tab yes @tab no @tab no @tab no @item cpuid @tab no @tab no @tab no @tab no +@item rdmsr @tab no @tab no @tab no @tab no +@item wrmsr @tab no @tab no @tab no @tab no @item hints @tab good @tab good @tab good @tab no @item PCI @tab yes @tab no @tab no @tab no @item badram @tab yes (*) @tab no @tab no @tab no @item compression @tab configurable @tab no @tab no @tab configurable @item exit @tab no @tab yes @tab yes @tab yes +@item bootlocation @tab no @tab partition @tab file @tab file (*) @end multitable @multitable @columnfractions .20 .20 .20 .20 .20 -@item @tab MIPS qemu @tab emu -@item video @tab no @tab yes -@item console charset @tab CP437 @tab ASCII -@item network @tab no @tab yes -@item ATA/AHCI @tab yes @tab no -@item AT keyboard @tab yes @tab no -@item USB @tab N/A @tab yes -@item chainloader @tab yes @tab no -@item cpuid @tab no @tab no -@item hints @tab guess @tab no -@item PCI @tab no @tab no -@item badram @tab yes (*) @tab no -@item compression @tab configurable @tab no -@item exit @tab no @tab yes +@item @tab MIPS qemu @tab emu @tab xen +@item video @tab no @tab yes @tab no +@item console charset @tab CP437 @tab Unicode (*) @tab ASCII +@item network @tab no @tab yes @tab no +@item ATA/AHCI @tab yes @tab no @tab no +@item AT keyboard @tab yes @tab no @tab no +@item Speaker @tab no @tab no @tab no +@item USB @tab N/A @tab yes @tab no +@item chainloader @tab yes @tab no @tab yes +@item cpuid @tab no @tab no @tab yes +@item rdmsr @tab no @tab no @tab yes +@item wrmsr @tab no @tab no @tab yes +@item hints @tab guess @tab no @tab no +@item PCI @tab no @tab no @tab no +@item badram @tab yes (*) @tab no @tab no +@item compression @tab configurable @tab no @tab no +@item exit @tab no @tab yes @tab no +@item bootlocation @tab no @tab file @tab no @end multitable @node Platform-specific operations @@ -4338,14 +9531,15 @@ Information retrieval: @itemize @item mipsel-loongson: lsspd @item mips-arc: lsdev -@item efi: lsefisystab, lssal, lsefimmap +@item efi: lsefisystab, lssal, lsefimmap, lsefi @item i386-pc: lsapm +@item i386-coreboot: lscoreboot, coreboot_boottime, cbmemc @item acpi-enabled (i386-pc, i386-coreboot, i386-multiboot, *-efi): lsacpi @end itemize Workarounds for platform-specific issues: @itemize -@item i386-efi/x86_64-efi: loadbios, fixvideo +@item i386-efi/x86_64-efi: loadbios, fakebios, fix_video @item acpi-enabled (i386-pc, i386-coreboot, i386-multiboot, *-efi): acpi (override ACPI tables) @item i386-pc: drivemap @@ -4357,10 +9551,10 @@ Advanced operations for power users: @item x86: iorw (direct access to I/O ports) @end itemize -Miscelaneous: +Miscellaneous: @itemize @item cmos (x86-*, ieee1275, mips-qemu_mips, mips-loongson): cmostest - (used on some laptops to check for special power-on key) + (used on some laptops to check for special power-on key), cmosclean @item i386-pc: play @end itemize @@ -4375,10 +9569,10 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item Plan9 @tab yes @tab no (1) @item Freedos @tab yes @tab no (1) @item FreeBSD bootloader @tab yes @tab crashes (1) -@item 32-bit kFreeBSD @tab yes @tab crashes (2,6) -@item 64-bit kFreeBSD @tab yes @tab crashes (2,6) +@item 32-bit kFreeBSD @tab yes @tab crashes (5) +@item 64-bit kFreeBSD @tab yes @tab crashes (5) @item 32-bit kNetBSD @tab yes @tab crashes (1) -@item 64-bit kNetBSD @tab yes @tab crashes (2) +@item 64-bit kNetBSD @tab yes @tab crashes @item 32-bit kOpenBSD @tab yes @tab yes @item 64-bit kOpenBSD @tab yes @tab yes @item Multiboot @tab yes @tab yes @@ -4389,9 +9583,9 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item 64-bit Linux (modern protocol) @tab yes @tab yes @item 32-bit XNU @tab yes @tab ? @item 64-bit XNU @tab yes @tab ? -@item 32-bit EFI chainloader @tab no (3) @tab no (3) -@item 64-bit EFI chainloader @tab no (3) @tab no (3) -@item Appleloader @tab no (3) @tab no (3) +@item 32-bit EFI chainloader @tab no (2) @tab no (2) +@item 64-bit EFI chainloader @tab no (2) @tab no (2) +@item Appleloader @tab no (2) @tab no (2) @end multitable @multitable @columnfractions .50 .22 .22 @@ -4401,8 +9595,8 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item Plan9 @tab no (1) @tab no (1) @item FreeDOS @tab no (1) @tab no (1) @item FreeBSD bootloader @tab crashes (1) @tab crashes (1) -@item 32-bit kFreeBSD @tab crashes (6) @tab crashes (6) -@item 64-bit kFreeBSD @tab crashes (6) @tab crashes (6) +@item 32-bit kFreeBSD @tab crashes (5) @tab crashes (5) +@item 64-bit kFreeBSD @tab crashes (5) @tab crashes (5) @item 32-bit kNetBSD @tab crashes (1) @tab crashes (1) @item 64-bit kNetBSD @tab yes @tab yes @item 32-bit kOpenBSD @tab yes @tab yes @@ -4415,9 +9609,9 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item 64-bit Linux (modern protocol) @tab yes @tab yes @item 32-bit XNU @tab ? @tab ? @item 64-bit XNU @tab ? @tab ? -@item 32-bit EFI chainloader @tab no (3) @tab no (3) -@item 64-bit EFI chainloader @tab no (3) @tab no (3) -@item Appleloader @tab no (3) @tab no (3) +@item 32-bit EFI chainloader @tab no (2) @tab no (2) +@item 64-bit EFI chainloader @tab no (2) @tab no (2) +@item Appleloader @tab no (2) @tab no (2) @end multitable @multitable @columnfractions .50 .22 .22 @@ -4440,9 +9634,9 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item 32-bit Linux (modern protocol) @tab yes @tab yes @item 64-bit Linux (modern protocol) @tab yes @tab yes @item 32-bit XNU @tab yes @tab yes -@item 64-bit XNU @tab yes (5) @tab yes -@item 32-bit EFI chainloader @tab yes @tab no (4) -@item 64-bit EFI chainloader @tab no (4) @tab yes +@item 64-bit XNU @tab yes (4) @tab yes +@item 32-bit EFI chainloader @tab yes @tab no (3) +@item 64-bit EFI chainloader @tab no (3) @tab yes @item Appleloader @tab yes @tab yes @end multitable @@ -4453,8 +9647,8 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item Plan9 @tab no (1) @item FreeDOS @tab no (1) @item FreeBSD bootloader @tab crashes (1) -@item 32-bit kFreeBSD @tab crashes (6) -@item 64-bit kFreeBSD @tab crashes (6) +@item 32-bit kFreeBSD @tab crashes (5) +@item 64-bit kFreeBSD @tab crashes (5) @item 32-bit kNetBSD @tab crashes (1) @item 64-bit kNetBSD @tab ? @item 32-bit kOpenBSD @tab ? @@ -4467,14 +9661,13 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item 64-bit Linux (modern protocol) @tab ? @item 32-bit XNU @tab ? @item 64-bit XNU @tab ? -@item 32-bit EFI chainloader @tab no (3) -@item 64-bit EFI chainloader @tab no (3) -@item Appleloader @tab no (3) +@item 32-bit EFI chainloader @tab no (2) +@item 64-bit EFI chainloader @tab no (2) +@item Appleloader @tab no (2) @end multitable @enumerate @item Requires BIOS -@item Crashes because the memory at 0x0-0x1000 isn't available @item EFI only @item 32-bit and 64-bit EFI have different structures and work in different CPU modes so it's not possible to chainload 32-bit bootloader on 64-bit platform and vice-versa @item Some modules may need to be disabled @@ -4484,7 +9677,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel PowerPC, IA64 and Sparc64 ports support only Linux. MIPS port supports Linux and multiboot2. -@chapter Boot tests +@section Boot tests As you have seen in previous chapter the support matrix is pretty big and some of the configurations are only rarely used. To ensure the quality bootchecks are available for all x86 targets except EFI chainloader, Appleloader and XNU. All x86 platforms have bootcheck facility except ieee1275. Multiboot, multiboot2, BIOS chainloader, ntldr and freebsd-bootloader boot targets are tested only with a fake kernel images. Only Linux is tested among the payloads using Linux protocols. @@ -4492,7 +9685,7 @@ Following variables must be defined: @multitable @columnfractions .30 .65 @item GRUB_PAYLOADS_DIR @tab directory containing the required kernels -@item GRUB_CBFSTOOL @tab cbfstoll from Coreboot package (for coreboot platform only) +@item GRUB_CBFSTOOL @tab cbfstool from Coreboot package (for coreboot platform only) @item GRUB_COREBOOT_ROM @tab empty Coreboot ROM @item GRUB_QEMU_OPTS @tab additional options to be supplied to QEMU @end multitable @@ -4517,6 +9710,7 @@ Required files are: @menu * GRUB only offers a rescue shell:: +* Firmware stalls instead of booting GRUB:: @end menu @@ -4582,17 +9776,45 @@ Installing to the whole disk device is normally more robust. @item Check that GRUB actually knows how to read from the device and file system containing @file{/boot/grub}. It will not be able to read from encrypted -devices, nor from file systems for which support has not yet been added to -GRUB. +devices with unsupported encryption scheme, nor from file systems for which +support has not yet been added to GRUB. @end itemize -@node Invoking grub-install -@chapter Invoking grub-install +@node Firmware stalls instead of booting GRUB +@section Firmware stalls instead of booting GRUB -The program @command{grub-install} installs GRUB on your drive using -@command{grub-mkimage} and (on some platforms) @command{grub-setup}. You -must specify the device name on which you want to install GRUB, like this: +The EFI implementation of some older MacBook laptops stalls when it gets +presented a grub-mkrescue ISO image for x86_64-efi target on an USB stick. +Affected are models of year 2010 or earlier. Workaround is to zeroize the +bytes 446 to 461 of the EFI partition, where mformat has put a partition table +entry which claims partition start at block 0. This change will not hamper +bootability on other machines. + + +@node User-space utilities +@chapter User-space utilities + +@menu +* Invoking grub-install:: How to use the GRUB installer +* Invoking grub-mkconfig:: Generate a GRUB configuration file +* Invoking grub-mkpasswd-pbkdf2:: + Generate GRUB password hashes +* Invoking grub-mkrelpath:: Make system path relative to its root +* Invoking grub-mkrescue:: Make a GRUB rescue image +* Invoking grub-mount:: Mount a file system using GRUB +* Invoking grub-probe:: Probe device information for GRUB +* Invoking grub-protect:: Protect a disk key with a key protector +* Invoking grub-script-check:: Check GRUB script file for syntax errors +@end menu + + +@node Invoking grub-install +@section Invoking grub-install + +The program @command{grub-install} generates a GRUB core image using +@command{grub-mkimage} and installs it on your system. You must specify the +device name on which you want to install GRUB, like this: @example grub-install @var{install_device} @@ -4638,11 +9860,23 @@ mounted on Recheck the device map, even if @file{/boot/grub/device.map} already exists. You should use this option whenever you add/remove a disk into/from your computer. + +@item --no-rs-codes +By default on x86 BIOS systems, @command{grub-install} will use some +extra space in the bootloader embedding area for Reed-Solomon +error-correcting codes. This enables GRUB to still boot successfully +if some blocks are corrupted. The exact amount of protection offered +is dependent on available space in the embedding area. R sectors of +redundancy can tolerate up to R/2 corrupted sectors. This +redundancy may be cumbersome if attempting to cryptographically +validate the contents of the bootloader embedding area, or in more +modern systems with GPT-style partition tables (@pxref{BIOS +installation}) where GRUB does not reside in any unpartitioned space +outside of the MBR. Disable the Reed-Solomon codes with this option. @end table - @node Invoking grub-mkconfig -@chapter Invoking grub-mkconfig +@section Invoking grub-mkconfig The program @command{grub-mkconfig} generates a configuration file for GRUB (@pxref{Simple configuration}). @@ -4668,7 +9902,7 @@ it to standard output. @node Invoking grub-mkpasswd-pbkdf2 -@chapter Invoking grub-mkpasswd-pbkdf2 +@section Invoking grub-mkpasswd-pbkdf2 The program @command{grub-mkpasswd-pbkdf2} generates password hashes for GRUB (@pxref{Security}). @@ -4695,8 +9929,35 @@ Length of the salt. Defaults to 64. @end table +@node Invoking grub-mkrelpath +@section Invoking grub-mkrelpath + +The program @command{grub-mkrelpath} makes a file system path relative to +the root of its containing file system. For instance, if @file{/usr} is a +mount point, then: + +@example +$ @kbd{grub-mkrelpath /usr/share/grub/unicode.pf2} +@samp{/share/grub/unicode.pf2} +@end example + +This is mainly used internally by other GRUB utilities such as +@command{grub-mkconfig} (@pxref{Invoking grub-mkconfig}), but may +occasionally also be useful for debugging. + +@command{grub-mkrelpath} accepts the following options: + +@table @option +@item --help +Print a summary of the command-line options and exit. + +@item --version +Print the version number of GRUB and exit. +@end table + + @node Invoking grub-mkrescue -@chapter Invoking grub-mkrescue +@section Invoking grub-mkrescue The program @command{grub-mkrescue} generates a bootable GRUB rescue image (@pxref{Making a GRUB bootable CD-ROM}). @@ -4753,8 +10014,95 @@ built-in default. @end table +@node Invoking grub-mount +@section Invoking grub-mount + +The program @command{grub-mount} performs a read-only mount of any file +system or file system image that GRUB understands, using GRUB's file system +drivers via FUSE. (It is only available if FUSE development files were +present when GRUB was built.) This has a number of uses: + +@itemize @bullet +@item +It provides a convenient way to check how GRUB will view a file system at +boot time. You can use normal command-line tools to compare that view with +that of your operating system, making it easy to find bugs. + +@item +It offers true read-only mounts. Linux does not have these for journalling +file systems, because it will always attempt to replay the journal at mount +time; while you can temporarily mark the block device read-only to avoid +this, that causes the mount to fail. Since GRUB intentionally contains no +code for writing to file systems, it can easily provide a guaranteed +read-only mount mechanism. + +@item +It allows you to examine any file system that GRUB understands without +needing to load additional modules into your running kernel, which may be +useful in constrained environments such as installers. + +@item +Since it can examine file system images (contained in regular files) just as +easily as file systems on block devices, you can use it to inspect any file +system image that GRUB understands with only enough privileges to use FUSE, +even if nobody has yet written a FUSE module specifically for that file +system type. +@end itemize + +Using @command{grub-mount} is normally as simple as: + +@example +grub-mount /dev/sda1 /mnt +@end example + +@command{grub-mount} must be given one or more images and a mount point as +non-option arguments (if it is given more than one image, it will treat them +as a RAID set), and also accepts the following options: + +@table @option +@item --help +Print a summary of the command-line options and exit. + +@item --version +Print the version number of GRUB and exit. + +@item -C +@itemx --crypto +Mount encrypted devices, prompting for a passphrase if necessary. + +@item -d @var{string} +@itemx --debug=@var{string} +Show debugging output for conditions matching @var{string}. + +@item -K prompt|@var{file} +@itemx --zfs-key=prompt|@var{file} +Load a ZFS encryption key. If you use @samp{prompt} as the argument, +@command{grub-mount} will read a passphrase from the terminal; otherwise, it +will read key material from the specified file. + +@item -r @var{device} +@itemx --root=@var{device} +Set the GRUB root device to @var{device}. You do not normally need to set +this; @command{grub-mount} will automatically set the root device to the +root of the supplied file system. + +If @var{device} is just a number, then it will be treated as a partition +number within the supplied image. This means that, if you have an image of +an entire disk in @file{disk.img}, then you can use this command to mount +its second partition: + +@example +grub-mount -r 2 disk.img mount-point +@end example + +@item -v +@itemx --verbose +Print verbose messages. +@end table + + @node Invoking grub-probe -@chapter Invoking grub-probe +@section Invoking grub-probe The program @command{grub-probe} probes device information for a given path or device. @@ -4839,6 +10187,268 @@ Print verbose messages. @end table +@node Invoking grub-protect +@section Invoking grub-protect + +The program @command{grub-protect} protects a disk encryption key with +a specified key protector. + +@table @option +@item --help +Print a summary of the command-line options and exit. + +@item --version +Print the version number of GRUB and exit. + +@item -a add|remove +@itemx --action=add|remove +Add or remove a key protector to or from a key. + +@item -p @var{protector} +@itemx --protector=@var{protector} +Set the key protector. Currently, @samp{tpm2} is the only supported key +protector. + +@item --tpm2-asymmetric=@var{type} +Choose the the type of SRK. The valid options are @samp{RSA} (@samp{RSA2048}) +and @samp{ECC} (@samp{ECC_NIST_P256}).(default: @samp{ECC}) + +@item --tpm2-bank=@var{alg} +Choose bank of PCRs used to authorize key release: @samp{SHA1}, @samp{SHA256}, +@samp{SHA384}, or @samp{SHA512}. (default: @samp{SHA256}) + +@item --tpm2-device=@var{device} +Set the path to the TPM2 device. (default: @samp{/dev/tpm0}) + +@item --tpm2-evict +Evict a previously persisted SRK from the TPM, if any. + +@item --tpm2-keyfile=@var{file} +Set the path to a file that contains the cleartext key to protect. + +@item --tpm2-outfile=@var{file} +Set the path to the file that will contain the key after sealing +(must be accessible to GRUB during boot). + +@item --tpm2-pcrs=@var{pcrs} +Set a comma-separated list of PCRs used to authorize key release e.g., @samp{7,11}. +Please be aware that PCR 0~7 are used by the firmware and the measurement result +may change after a firmware update (for baremetal systems) or a package +(OVMF/SLOF) update in the VM host. This may lead to the failure of key +unsealing. (default: @samp{7}) + +@item --tpm2-srk=@var{handle} +Set the SRK handle, e.g. @samp{0x81000000}, if the SRK is to be made persistent. + +@item --tpm2-nvindex=@var{handle} +Set the handle, e.g. @samp{0x81000000} or @samp{0x1000000}, for NV index mode. + +@item --tpm2key +Use TPM 2.0 Key File format. + +@end table + +@subsection 'Add' action + +Before sealing the key, please check the TPM PCR usage +(@pxref{TPM2 key protector, TPM PCR usage}) to choose a proper set of PCRs. + +Assume that there is a key file, @file{luks.key}, to be sealed with PCR 0, 2, +4, and 7, and here is the @command{grub-protect} command to create the sealed +key file: + +@example +@group +# @kbd{grub-protect --action=add \ + --protector=tpm2 \ + --tpm2-pcrs=0,2,4,7 \ + --tpm2key \ + --tpm2-keyfile=luks.key \ + --tpm2-outfile=/boot/efi/efi/grub/sealed.tpm} +@end group +@end example + +Then, GRUB can unlock the target partition with the following commands: + +@example +grub> @kbd{tpm2_key_protector_init -T (hd0,gpt1)/efi/grub/sealed.tpm} +grub> @kbd{cryptomount -u -P tpm2} +@end example + +Besides writing the PCR-sealed key into a file, @command{grub-protect} can +write the sealed key into TPM non-volatile memory. Here is the +@command{grub-protect} command to write the sealed key into the NV index +handle @samp{0x1000000}. + +@example +@group +# @kbd{grub-protect --action=add \ + --protector=tpm2 \ + --tpm2-pcrs=0,2,4,7 \ + --tpm2key \ + --tpm2-keyfile=luks.key \ + --tpm2-nvindex=0x1000000} +@end group +@end example + +Later, GRUB can fetch the key from @samp{0x1000000}. + +@example +grub> @kbd{tpm2_key_protector_init --mode=nv --nvindex=0x1000000} +grub> @kbd{cryptomount -u -P tpm2} +@end example + +In most of cases, the user only needs to create the key with the `add' action. +If auto-unlocking is unwanted, just remove the file and the +@command{tpm2_key_protector_init} command and invoke the @command{cryptomount} +command without @kbd{-P tpm2}. + +@subsection 'Remove' action + +The `remove' action is used to remove the handles for NV index mode and the +persistent SRK. + +@subsubsection Handles for NV index mode + +There are two types of TPM handles supported by NV index mode: persistent +handles and NV index handles, and @command{tpm2_getcap} can be used to +check the existing handles. + +To display the list of existing persistent handles: + +@example +@group +# @kbd{tpm2_getcap handles-persistent} +- 0x81000000 +@end group +@end example + +Similarly, to display the list of existing NV index handles: + +@example +@group +# @kbd{tpm2_getcap handles-nv-index} +- 0x1000000 +@end group +@end example + +If the sealed key at an NV index handle is not needed anymore, the user can +remove the handle with @kbd{--tpm2-nvindex} and @kbd{--tpm2-evict}. For +example, this command removes the data from NV index @samp{0x1000000}: + +@example +@group +# @kbd{grub-protect --action=remove \ + --protector=tpm2 \ + --tpm2-evict \ + --tpm2-nvindex 0x1000000} \ +@end group +@end example + +@subsubsection Persistent SRK + +There are two supported SRKs in @command{grub-protect}: @samp{RSA} and @samp{ECC}. +Due to slower key generation, some users of the @samp{RSA} SRK may prefer +making it persistent so that the TPM can skip the SRK generation when GRUB tries +to unseal the key. + +The available persistent handles can be checked with @command{tpm2_getcap}. + +@example +@group +# @kbd{tpm2_getcap properties-variable} +... +TPM2_PT_HR_PERSISTENT: 0x0 +TPM2_PT_HR_PERSISTENT_AVAIL: 0x41 +... +@end group +@end example + +In this system, there is no persistent handle. A TPM handle is an unsigned +32-bit integer, and the persistent handles starts with @samp{0x81}. Here +we choose the well-known persistent handle: @samp{0x81000000}. + +@example +@group +# @kbd{grub-protect --action=add \ + --protector=tpm2 \ + --tpm2-pcrs=0,2,4,7 \ + --tpm2-asymmetric=RSA \ + --tpm2-srk=0x81000000 \ + --tpm2key \ + --tpm2-keyfile=luks.key \ + --tpm2-outfile=/boot/efi/efi/grub/sealed.tpm} +@end group +@end example + +The additional @kbd{--tpm2-asymmetric=RSA} and @kbd{--tpm2-srk=0x81000000} +options are used to make the key sealed with the RSA SRK and store the SRK +in @samp{0x81000000}. + +For the @command{tpm2_key_protector_init} command, the additional @kbd{-s 0x81000000} +informs the TPM2 key protector to fetch the SRK from @samp{0x81000000}. + +@example +grub> @kbd{tpm2_key_protector_init -s 0x81000000 -T (hd0,gpt1)/efi/grub/sealed.tpm} +grub> @kbd{cryptomount -u -P tpm2} +@end example + +After making the SRK handle persistent, we can check the status of the +persistent handles with @command{tpm2_getcap}. + +@example +@group +# @kbd{tpm2_getcap properties-variable} +... +TPM2_PT_HR_PERSISTENT: 0x1 +TPM2_PT_HR_PERSISTENT_AVAIL: 0x40 +... +# @kbd{tpm2_getcap handles-persistent} +- 0x81000000 +@end group +@end example + +The sealed key can be removed once the user does not want to use the TPM2 key +protector anymore. Here is the command to remove the persistent SRK handle +(@samp{0x81000000}) with @kbd{--tpm2-srk} and @kbd{--tpm2-evict}. + +@example +@group +# @kbd{grub-protect --action=remove \ + --protector=tpm2 \ + --tpm2-srk 0x81000000 \ + --tpm2-evict} +@end group +@end example + + +@node Invoking grub-script-check +@section Invoking grub-script-check + +The program @command{grub-script-check} takes a GRUB script file +(@pxref{Shell-like scripting}) and checks it for syntax errors, similar to +commands such as @command{sh -n}. It may take a @var{path} as a non-option +argument; if none is supplied, it will read from standard input. + +@example +grub-script-check /boot/grub/grub.cfg +@end example + +@command{grub-script-check} accepts the following options: + +@table @option +@item --help +Print a summary of the command-line options and exit. + +@item --version +Print the version number of GRUB and exit. + +@item -v +@itemx --verbose +Print each line of input after reading it. +@end table + + @node Obtaining and Building GRUB @appendix How to obtain and build GRUB @@ -4876,8 +10486,8 @@ just do: @end group @end example -Also, the latest version is available using Bazaar. See -@uref{http://www.gnu.org/software/grub/grub-download.en.html} for more +Also, the latest version is available using Git. See +@uref{http://www.gnu.org/software/grub/grub-download.html} for more information. @node Reporting bugs diff --git a/docs/man/grub-bios-setup.h2m b/docs/man/grub-bios-setup.h2m index eebe3ef38..ac6ede362 100644 --- a/docs/man/grub-bios-setup.h2m +++ b/docs/man/grub-bios-setup.h2m @@ -1,5 +1,5 @@ [NAME] -grub-setup \- set up a device to boot using GRUB +grub-bios-setup \- set up a device to boot using GRUB [SEE ALSO] .BR grub-install (8), .BR grub-mkimage (1), diff --git a/docs/man/grub-file.h2m b/docs/man/grub-file.h2m new file mode 100644 index 000000000..e09bb4d31 --- /dev/null +++ b/docs/man/grub-file.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-file \- check file type diff --git a/docs/man/grub-glue-efi.h2m b/docs/man/grub-glue-efi.h2m new file mode 100644 index 000000000..c1c6ded49 --- /dev/null +++ b/docs/man/grub-glue-efi.h2m @@ -0,0 +1,4 @@ +[NAME] +grub-glue-efi \- generate a fat binary for EFI +[DESCRIPTION] +grub-glue-efi processes ia32 and amd64 EFI images and glues them according to Apple format. diff --git a/docs/man/grub-install.h2m b/docs/man/grub-install.h2m index 2de371a3f..8cbbc87a0 100644 --- a/docs/man/grub-install.h2m +++ b/docs/man/grub-install.h2m @@ -3,5 +3,4 @@ grub-install \- install GRUB to a device [SEE ALSO] .BR grub-mkconfig (8), .BR grub-mkimage (1), -.BR grub-setup (8), .BR grub-mkrescue (1) diff --git a/docs/man/grub-macbless.h2m b/docs/man/grub-macbless.h2m new file mode 100644 index 000000000..0197c0087 --- /dev/null +++ b/docs/man/grub-macbless.h2m @@ -0,0 +1,4 @@ +[NAME] +grub-macbless \- bless a mac file/directory +[SEE ALSO] +.BR grub-install (1) diff --git a/docs/man/grub-mkdevicemap.h2m b/docs/man/grub-mkdevicemap.h2m deleted file mode 100644 index 3ef8e9712..000000000 --- a/docs/man/grub-mkdevicemap.h2m +++ /dev/null @@ -1,4 +0,0 @@ -[NAME] -grub-mkdevicemap \- generate a GRUB device map file automatically -[SEE ALSO] -.BR grub-install (8) diff --git a/docs/man/grub-mkimage.h2m b/docs/man/grub-mkimage.h2m index ca08b0c5c..f0fbc2bb1 100644 --- a/docs/man/grub-mkimage.h2m +++ b/docs/man/grub-mkimage.h2m @@ -2,6 +2,5 @@ grub-mkimage \- make a bootable image of GRUB [SEE ALSO] .BR grub-install (8), -.BR grub-setup (8), .BR grub-mkrescue (1), .BR grub-mknetdir (8) diff --git a/docs/man/grub-protect.h2m b/docs/man/grub-protect.h2m new file mode 100644 index 000000000..ecf1c9eab --- /dev/null +++ b/docs/man/grub-protect.h2m @@ -0,0 +1,4 @@ +[NAME] +grub-protect \- protect a disk key with a key protector +[DESCRIPTION] +grub-protect helps to protect a disk encryption key with a specified key protector. diff --git a/docs/man/grub-render-label.h2m b/docs/man/grub-render-label.h2m new file mode 100644 index 000000000..50ae5247c --- /dev/null +++ b/docs/man/grub-render-label.h2m @@ -0,0 +1,3 @@ +[NAME] +grub-render-label \- generate a .disk_label for Apple Macs. + diff --git a/docs/man/grub-sparc64-setup.h2m b/docs/man/grub-sparc64-setup.h2m index eebe3ef38..18f803a50 100644 --- a/docs/man/grub-sparc64-setup.h2m +++ b/docs/man/grub-sparc64-setup.h2m @@ -1,5 +1,5 @@ [NAME] -grub-setup \- set up a device to boot using GRUB +grub-sparc64-setup \- set up a device to boot using GRUB [SEE ALSO] .BR grub-install (8), .BR grub-mkimage (1), diff --git a/docs/man/grub-syslinux2cfg.h2m b/docs/man/grub-syslinux2cfg.h2m new file mode 100644 index 000000000..ad25c8ab7 --- /dev/null +++ b/docs/man/grub-syslinux2cfg.h2m @@ -0,0 +1,4 @@ +[NAME] +grub-syslinux2cfg \- transform syslinux config into grub.cfg +[SEE ALSO] +.BR grub-menulst2cfg (8) diff --git a/docs/osdetect.cfg b/docs/osdetect.cfg new file mode 100644 index 000000000..47455601d --- /dev/null +++ b/docs/osdetect.cfg @@ -0,0 +1,331 @@ +# Sample GRUB script to autodetect operating systems +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB 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 GRUB. If not, see . + +set saved_root=$root + +function freebsd_ufs_variants { + set device=$1 + set fstype=$2 + set uuid=$3 + + menuentry "FreeBSD (on $fstype $device)" $device $uuid { + set root=$2 + set uuid=$3 + + freebsd /boot/kernel/kernel + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + set FreeBSD.vfs.root.mountfrom=ufs:ufsid/$uuid + frebsd_loadenv /boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (single)" $device $uuid { + set root=$2 + set uuid=$3 + + freebsd /boot/kernel/kernel --single + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + set FreeBSD.vfs.root.mountfrom=ufs:ufsid/$uuid + frebsd_loadenv /boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (verbose)" $device $uuid { + set root=$2 + set uuid=$3 + + freebsd /boot/kernel/kernel --verbose + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + set FreeBSD.vfs.root.mountfrom=ufs:ufsid/$uuid + frebsd_loadenv /boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (without ACPI)" $device $uuid { + set root=$2 + set uuid=$3 + + freebsd /boot/kernel/kernel --verbose + unset FreeBSD.acpi_load + set FreeBSD.hint.acpi.0.disabled=1 + set FreeBSD.loader.acpi_disabled_by_user=1 + set FreeBSD.vfs.root.mountfrom=ufs:ufsid/$uuid + frebsd_loadenv /boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (safe mode)" $device $uuid { + set root=$2 + set uuid=$3 + + freebsd /boot/kernel/kernel --verbose + unset FreeBSD.acpi_load + set FreeBSD.hint.acpi.0.disabled=1 + set FreeBSD.loader.acpi_disabled_by_user=1 + set FreeBSD.hint.apic.0.disabled=1 + set FreeBSD.hw.ata.ata_dma=0 + set FreeBSD.hw.ata.atapi_dma=0 + set FreeBSD.hw.ata.wc=0 + set FreeBSD.hw.eisa_slots=0 + set FreeBSD.hint.kbdmux.0.disabled=1 + set FreeBSD.vfs.root.mountfrom=ufs:ufsid/$uuid + frebsd_loadenv /boot/device.hints + } +} + +function freebsd_zfs_variants { + set device=$1 + set fstype=zfs + + menuentry "FreeBSD (on $fstype $device)" $device { + set root=$2 + + freebsd /@/boot/kernel/kernel + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + freebsd_module_elf /@/boot/kernel/opensolaris.ko + freebsd_module_elf /@/boot/kernel/zfs.ko + freebsd_module /@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache + probe -l -s name $root + set FreeBSD.vfs.root.mountfrom=zfs:$name + freebsd_loadenv /@/boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (single)" $device { + set root=$2 + + freebsd /@/boot/kernel/kernel --single + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + freebsd_module_elf /@/boot/kernel/opensolaris.ko + freebsd_module_elf /@/boot/kernel/zfs.ko + freebsd_module /@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache + probe -l -s name $root + set FreeBSD.vfs.root.mountfrom=zfs:$name + freebsd_loadenv /@/boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (verbose)" $device { + set root=$2 + + freebsd /@/boot/kernel/kernel --verbose + set FreeBSD.acpi_load=YES + set FreeBSD.hint.acpi.0.disabled=0 + freebsd_module_elf /@/boot/kernel/opensolaris.ko + freebsd_module_elf /@/boot/kernel/zfs.ko + freebsd_module /@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache + probe -l -s name $root + set FreeBSD.vfs.root.mountfrom=zfs:$name + freebsd_loadenv /@/boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (without ACPI)" $device { + set root=$2 + + freebsd /@/boot/kernel/kernel --verbose + unset FreeBSD.acpi_load + set FreeBSD.hint.acpi.0.disabled=1 + set FreeBSD.loader.acpi_disabled_by_user=1 + freebsd_module_elf /@/boot/kernel/opensolaris.ko + freebsd_module_elf /@/boot/kernel/zfs.ko + freebsd_module /@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache + probe -l -s name $root + set FreeBSD.vfs.root.mountfrom=zfs:$name + freebsd_loadenv /@/boot/device.hints + } + + menuentry "FreeBSD (on $fstype $device) (safe mode)" $device { + set root=$2 + + freebsd /@/boot/kernel/kernel --verbose + unset FreeBSD.acpi_load + set FreeBSD.hint.acpi.0.disabled=1 + set FreeBSD.loader.acpi_disabled_by_user=1 + set FreeBSD.hint.apic.0.disabled=1 + set FreeBSD.hw.ata.ata_dma=0 + set FreeBSD.hw.ata.atapi_dma=0 + set FreeBSD.hw.ata.wc=0 + set FreeBSD.hw.eisa_slots=0 + set FreeBSD.hint.kbdmux.0.disabled=1 + freebsd_module_elf /@/boot/kernel/opensolaris.ko + freebsd_module_elf /@/boot/kernel/zfs.ko + freebsd_module /@/boot/zfs/zpool.cache type=/boot/zfs/zpool.cache + probe -l -s name $root + set FreeBSD.vfs.root.mountfrom=zfs:$name + freebsd_loadenv /@/boot/device.hints + } +} + +insmod regexp +for dev in (*); do + # $device: parenthesis removed from $dev + regexp -s device '\((.*)\)' $dev + # $fstype: filesystem type identified + probe -s fstype -f $dev + # uuid: filesystem UUID + probe -s uuid -u $dev + + if test -f ($device)/isolinux/isolinux.cfg ; then + menuentry "ISOLINUX config (on $device)" $device { + set root=$2 + syslinux_configfile -i /isolinux/isolinux.cfg + } + fi + if test -f ($device)/bootmgr -a -f ($device)/boot/bcd; then + menuentry "Windows Vista bootmgr (on $device)" $device { + set root=$2 + chainloader +1 + } + elif test -f ($device)/ntldr -a \ + -e ($device)/ntdetect.com -a -f ($device)/boot.ini; then + menuentry "Windows NT/2000/XP loader (on $device)" $device { + set root=$2 + regexp -s devnum 'hd([0-9]+)' $root + if test "$devnum" != "0"; then + drivemap -s hd0 $root + fi + chainloader +1 + } + elif test -f ($device)/windows/win.com; then + menuentry "Windows 98/ME (on $device)" $device { + set root=$2 + regexp -s devnum 'hd([0-9]+)' $root + if test "$devnum" != "0"; then + drivemap -s hd0 $root + fi + chainloader +1 + } + elif test -f ($device)/io.sys -a -f ($device)/command.com; then + menuentry "MS-DOS (on $device)" $device { + set root=$2 + regexp -s devnum 'hd([0-9]+)' $root + if test "$devnum" != "0"; then + drivemap -s hd0 $root + fi + chainloader +1 + } + elif test -f ($device)/kernel.sys; then + menuentry "FreeDOS (on $device)" $device { + set root=$2 + regexp -s type '([fh])d[0-9]+' $root + regexp -s devnum '[fh]d([0-9]+)' $root + if test $type = 'h' -a "$devnum" != "0"; then + drivemap -s hd0 $root + fi + chainloader +1 + } + elif test "$fstype" = ufs1 -o "$fstype" = ufs2 -a \ + -e ($device)/boot/kernel/kernel -a \ + -e ($device)/boot/device.hints; then + + freebsd_ufs_variants $device $fstype $uuid + + elif test "$fstype" = zfs -a \ + -e ($device)/@/boot/kernel/kernel -a \ + -e ($device)/@/boot/device.hints; then + + freebsd_zfs_variants $device + + elif test "$fstype" = hfsplus -a -f ($device)/mach_kernel; then + menuentry "Mac OS X/Darwin" $device $uuid { + set root=$2 + set uuid=$3 + + insmod vbe + do_resume=0 + if [ /var/vm/sleepimage -nt10 / ]; then + if xnu_resume /var/vm/sleepimage; then + do_resume=1 + fi + fi + if [ $do_resume = 1 ]; then + xnu_uuid $uuid uuid + if [ -f /Extra/DSDT.aml ]; then + acpi -e /Extra/DSDT.aml + fi + xnu_kernel /mach_kernel boot-uuid=${uuid} rd=*uuid + if [ /System/Library/Extensions.mkext -nt /System/Library/Extensions ]; then + xnu_mkext /System/Library/Extensions.mkext + else + xnu_mkext /System/Library/Extensions + fi + if [ -f /Extra/Extensions.mkext ]; then + xnu_mkext /Extra/Extensions.mkext + fi + if [ -d /Extra/Extensions ]; then + xnu_kextdir /Extra/Extensions + fi + if [ -f /Extra/devtree.txt ]; then + xnu_devtree /Extra/devtree.txt + fi + if [ -f /Extra/splash.jpg ]; then + insmod jpeg + xnu_splash /Extra/splash.jpg + fi + if [ -f /Extra/splash.png ]; then + insmod png + xnu_splash /Extra/splash.png + fi + if [ -f /Extra/splash.tga ]; then + insmod tga + xnu_splash /Extra/splash.tga + fi + fi + } + else + set root=$device + for file in /boot/vmlinuz-* /boot/linux-*; do + if test -f $file; then + regexp -s version '/boot/vmlinuz-(.*)' $file + regexp -s version '/boot/linux-(.*)' $file + + menuentry "Linux $file" $device $uuid $file $version { + set root=$2 + set uuid=$3 + set kernel=$4 + set version=$5 + + linux $kernel root=UUID=$uuid ro + if test -f /boot/initrd-$version.img; then + initrd /boot/initrd-$version.img + elif test -f /boot/initrd.img-$version; then + initrd /boot/initrd.img-$version + elif test -f /boot/initrd-$version; then + initrd /boot/initrd-$version + fi + } + + menuentry "Linux $file (single)" $device $uuid $file $version { + set root=$2 + set uuid=$3 + set kernel=$4 + set version=$5 + + linux $kernel root=UUID=$uuid ro single + if test -f /boot/initrd-$version.img; then + initrd /boot/initrd-$version.img + elif test -f /boot/initrd.img-$version; then + initrd /boot/initrd.img-$version + elif test -f /boot/initrd-$version; then + initrd /boot/initrd-$version + fi + } + fi + done + fi +done + +set root=$saved_root diff --git a/gentpl.py b/gentpl.py index 13a60816f..d8c6965d8 100644 --- a/gentpl.py +++ b/gentpl.py @@ -1,6 +1,6 @@ #! /usr/bin/python # GRUB -- GRand Unified Bootloader -# Copyright (C) 2010,2011 Free Software Foundation, Inc. +# Copyright (C) 2010,2011,2012,2013 Free Software Foundation, Inc. # # GRUB is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -15,31 +15,49 @@ # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . +from __future__ import print_function + +__metaclass__ = type + +from optparse import OptionParser +import re + # -# This is the python script used to generate Makefile.tpl +# This is the python script used to generate Makefile.*.am # GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275", "x86_64_efi", + "i386_xen", "x86_64_xen", "i386_xen_pvh", "mips_loongson", "sparc64_ieee1275", "powerpc_ieee1275", "mips_arc", "ia64_efi", - "mips_qemu_mips" ] + "mips_qemu_mips", "arm_uboot", "arm_efi", "arm64_efi", + "arm_coreboot", "loongarch64_efi", "riscv32_efi", "riscv64_efi" ] GROUPS = {} GROUPS["common"] = GRUB_PLATFORMS[:] # Groups based on CPU -GROUPS["i386"] = [ "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275" ] -GROUPS["x86_64"] = [ "x86_64_efi" ] -GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"] -GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ] -GROUPS["sparc64"] = [ "sparc64_ieee1275" ] -GROUPS["powerpc"] = [ "powerpc_ieee1275" ] +GROUPS["i386"] = [ "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", "i386_multiboot", "i386_ieee1275" ] +GROUPS["x86_64"] = [ "x86_64_efi" ] +GROUPS["x86"] = GROUPS["i386"] + GROUPS["x86_64"] +GROUPS["mips"] = [ "mips_loongson", "mips_qemu_mips", "mips_arc" ] +GROUPS["sparc64"] = [ "sparc64_ieee1275" ] +GROUPS["powerpc"] = [ "powerpc_ieee1275" ] +GROUPS["arm"] = [ "arm_uboot", "arm_efi", "arm_coreboot" ] +GROUPS["arm64"] = [ "arm64_efi" ] +GROUPS["loongarch64"] = [ "loongarch64_efi" ] +GROUPS["riscv32"] = [ "riscv32_efi" ] +GROUPS["riscv64"] = [ "riscv64_efi" ] # Groups based on firmware -GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi" ] +GROUPS["efi"] = [ "i386_efi", "x86_64_efi", "ia64_efi", "arm_efi", "arm64_efi", + "loongarch64_efi", "riscv32_efi", "riscv64_efi" ] GROUPS["ieee1275"] = [ "i386_ieee1275", "sparc64_ieee1275", "powerpc_ieee1275" ] +GROUPS["uboot"] = [ "arm_uboot" ] +GROUPS["xen"] = [ "i386_xen", "x86_64_xen" ] +GROUPS["coreboot"] = [ "i386_coreboot", "arm_coreboot" ] # emu is a special case so many core functionality isn't needed on this platform GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") @@ -47,21 +65,30 @@ GROUPS["noemu"] = GRUB_PLATFORMS[:]; GROUPS["noemu"].remove("emu") # Groups based on hardware features GROUPS["cmos"] = GROUPS["x86"][:] + ["mips_loongson", "mips_qemu_mips", "sparc64_ieee1275", "powerpc_ieee1275"] -GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi") +GROUPS["cmos"].remove("i386_efi"); GROUPS["cmos"].remove("x86_64_efi"); GROUPS["pci"] = GROUPS["x86"] + ["mips_loongson"] -GROUPS["usb"] = GROUPS["pci"] +GROUPS["usb"] = GROUPS["pci"] + ["arm_coreboot"] # If gfxterm is main output console integrate it into kernel -GROUPS["videoinkernel"] = ["mips_loongson", "mips_qemu_mips"] +GROUPS["videoinkernel"] = ["mips_loongson", "i386_coreboot", "arm_coreboot" ] GROUPS["videomodules"] = GRUB_PLATFORMS[:]; for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i) # Similar for terminfo -GROUPS["terminfoinkernel"] = ["mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["ieee1275"]; +GROUPS["terminfoinkernel"] = [ "emu", "mips_loongson", "mips_arc", "mips_qemu_mips", "i386_xen_pvh" ] + GROUPS["xen"] + GROUPS["ieee1275"] + GROUPS["uboot"]; GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) -# Miscelaneous groups schedulded to disappear in future +# Flattened Device Trees (FDT) +GROUPS["fdt"] = [ "arm64_efi", "arm_uboot", "arm_efi", "loongarch64_efi", "riscv32_efi", "riscv64_efi" ] + +# Needs software helpers for division +# Must match GRUB_DIVISION_IN_SOFTWARE in misc.h +GROUPS["softdiv"] = GROUPS["arm"] + ["ia64_efi"] + GROUPS["riscv32"] +GROUPS["no_softdiv"] = GRUB_PLATFORMS[:] +for i in GROUPS["softdiv"]: GROUPS["no_softdiv"].remove(i) + +# Miscellaneous groups scheduled to disappear in future GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"] GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc") @@ -89,81 +116,410 @@ for platform in GRUB_PLATFORMS: # insert in the middle RMAP[platform] = smaller + [ k ] + bigger +# +# Input +# + +# We support a subset of the AutoGen definitions file syntax. Specifically, +# compound names are disallowed; some preprocessing directives are +# disallowed (though #if/#endif are allowed; note that, like AutoGen, #if +# skips everything to the next #endif regardless of the value of the +# conditional); and shell-generated strings, Scheme-generated strings, and +# here strings are disallowed. + +class AutogenToken: + (autogen, definitions, eof, var_name, other_name, string, number, + semicolon, equals, comma, lbrace, rbrace, lbracket, rbracket) = range(14) + +class AutogenState: + (init, need_def, need_tpl, need_semi, need_name, have_name, need_value, + need_idx, need_rbracket, indx_name, have_value, done) = range(12) + +class AutogenParseError(Exception): + def __init__(self, message, path, line): + super(AutogenParseError, self).__init__(message) + self.path = path + self.line = line + + def __str__(self): + return ( + super(AutogenParseError, self).__str__() + + " at file %s line %d" % (self.path, self.line)) + +class AutogenDefinition(list): + def __getitem__(self, key): + try: + return super(AutogenDefinition, self).__getitem__(key) + except TypeError: + for name, value in self: + if name == key: + return value + + def __contains__(self, key): + for name, value in self: + if name == key: + return True + return False + + def get(self, key, default): + for name, value in self: + if name == key: + return value + else: + return default + + def find_all(self, key): + for name, value in self: + if name == key: + yield value + +class AutogenParser: + def __init__(self): + self.definitions = AutogenDefinition() + self.def_stack = [("", self.definitions)] + self.curdef = None + self.new_name = None + self.cur_path = None + self.cur_line = 0 + + @staticmethod + def is_unquotable_char(c): + return (ord(c) in range(ord("!"), ord("~") + 1) and + c not in "#,;<=>[\\]`{}?*'\"()") + + @staticmethod + def is_value_name_char(c): + return c in ":^-_" or c.isalnum() + + def error(self, message): + raise AutogenParseError(message, self.cur_file, self.cur_line) + + def read_tokens(self, f): + data = f.read() + end = len(data) + offset = 0 + while offset < end: + while offset < end and data[offset].isspace(): + if data[offset] == "\n": + self.cur_line += 1 + offset += 1 + if offset >= end: + break + c = data[offset] + if c == "#": + offset += 1 + try: + end_directive = data.index("\n", offset) + directive = data[offset:end_directive] + offset = end_directive + except ValueError: + directive = data[offset:] + offset = end + name, value = directive.split(None, 1) + if name == "if": + try: + end_if = data.index("\n#endif", offset) + new_offset = end_if + len("\n#endif") + self.cur_line += data[offset:new_offset].count("\n") + offset = new_offset + except ValueError: + self.error("#if without matching #endif") + else: + self.error("Unhandled directive '#%s'" % name) + elif c == "{": + yield AutogenToken.lbrace, c + offset += 1 + elif c == "=": + yield AutogenToken.equals, c + offset += 1 + elif c == "}": + yield AutogenToken.rbrace, c + offset += 1 + elif c == "[": + yield AutogenToken.lbracket, c + offset += 1 + elif c == "]": + yield AutogenToken.rbracket, c + offset += 1 + elif c == ";": + yield AutogenToken.semicolon, c + offset += 1 + elif c == ",": + yield AutogenToken.comma, c + offset += 1 + elif c in ("'", '"'): + s = [] + while True: + offset += 1 + if offset >= end: + self.error("EOF in quoted string") + if data[offset] == "\n": + self.cur_line += 1 + if data[offset] == "\\": + offset += 1 + if offset >= end: + self.error("EOF in quoted string") + if data[offset] == "\n": + self.cur_line += 1 + # Proper escaping unimplemented; this can be filled + # out if needed. + s.append("\\") + s.append(data[offset]) + elif data[offset] == c: + offset += 1 + break + else: + s.append(data[offset]) + yield AutogenToken.string, "".join(s) + elif c == "/": + offset += 1 + if data[offset] == "*": + offset += 1 + try: + end_comment = data.index("*/", offset) + new_offset = end_comment + len("*/") + self.cur_line += data[offset:new_offset].count("\n") + offset = new_offset + except ValueError: + self.error("/* without matching */") + elif data[offset] == "/": + try: + offset = data.index("\n", offset) + except ValueError: + pass + elif (c.isdigit() or + (c == "-" and offset < end - 1 and + data[offset + 1].isdigit())): + end_number = offset + 1 + while end_number < end and data[end_number].isdigit(): + end_number += 1 + yield AutogenToken.number, data[offset:end_number] + offset = end_number + elif self.is_unquotable_char(c): + end_name = offset + while (end_name < end and + self.is_value_name_char(data[end_name])): + end_name += 1 + if end_name < end and self.is_unquotable_char(data[end_name]): + while (end_name < end and + self.is_unquotable_char(data[end_name])): + end_name += 1 + yield AutogenToken.other_name, data[offset:end_name] + offset = end_name + else: + s = data[offset:end_name] + if s.lower() == "autogen": + yield AutogenToken.autogen, s + elif s.lower() == "definitions": + yield AutogenToken.definitions, s + else: + yield AutogenToken.var_name, s + offset = end_name + else: + self.error("Invalid input character '%s'" % c) + yield AutogenToken.eof, None + + def do_need_name_end(self, token): + if len(self.def_stack) > 1: + self.error("Definition blocks were left open") + + def do_need_name_var_name(self, token): + self.new_name = token + + def do_end_block(self, token): + if len(self.def_stack) <= 1: + self.error("Too many close braces") + new_name, parent_def = self.def_stack.pop() + parent_def.append((new_name, self.curdef)) + self.curdef = parent_def + + def do_empty_val(self, token): + self.curdef.append((self.new_name, "")) + + def do_str_value(self, token): + self.curdef.append((self.new_name, token)) + + def do_start_block(self, token): + self.def_stack.append((self.new_name, self.curdef)) + self.curdef = AutogenDefinition() + + def do_indexed_name(self, token): + self.new_name = token + + def read_definitions_file(self, f): + self.curdef = self.definitions + self.cur_line = 0 + state = AutogenState.init + + # The following transition table was reduced from the Autogen + # documentation: + # info -f autogen -n 'Full Syntax' + transitions = { + AutogenState.init: { + AutogenToken.autogen: (AutogenState.need_def, None), + }, + AutogenState.need_def: { + AutogenToken.definitions: (AutogenState.need_tpl, None), + }, + AutogenState.need_tpl: { + AutogenToken.var_name: (AutogenState.need_semi, None), + AutogenToken.other_name: (AutogenState.need_semi, None), + AutogenToken.string: (AutogenState.need_semi, None), + }, + AutogenState.need_semi: { + AutogenToken.semicolon: (AutogenState.need_name, None), + }, + AutogenState.need_name: { + AutogenToken.autogen: (AutogenState.need_def, None), + AutogenToken.eof: (AutogenState.done, self.do_need_name_end), + AutogenToken.var_name: ( + AutogenState.have_name, self.do_need_name_var_name), + AutogenToken.rbrace: ( + AutogenState.have_value, self.do_end_block), + }, + AutogenState.have_name: { + AutogenToken.semicolon: ( + AutogenState.need_name, self.do_empty_val), + AutogenToken.equals: (AutogenState.need_value, None), + AutogenToken.lbracket: (AutogenState.need_idx, None), + }, + AutogenState.need_value: { + AutogenToken.var_name: ( + AutogenState.have_value, self.do_str_value), + AutogenToken.other_name: ( + AutogenState.have_value, self.do_str_value), + AutogenToken.string: ( + AutogenState.have_value, self.do_str_value), + AutogenToken.number: ( + AutogenState.have_value, self.do_str_value), + AutogenToken.lbrace: ( + AutogenState.need_name, self.do_start_block), + }, + AutogenState.need_idx: { + AutogenToken.var_name: ( + AutogenState.need_rbracket, self.do_indexed_name), + AutogenToken.number: ( + AutogenState.need_rbracket, self.do_indexed_name), + }, + AutogenState.need_rbracket: { + AutogenToken.rbracket: (AutogenState.indx_name, None), + }, + AutogenState.indx_name: { + AutogenToken.semicolon: ( + AutogenState.need_name, self.do_empty_val), + AutogenToken.equals: (AutogenState.need_value, None), + }, + AutogenState.have_value: { + AutogenToken.semicolon: (AutogenState.need_name, None), + AutogenToken.comma: (AutogenState.need_value, None), + }, + } + + for code, token in self.read_tokens(f): + if code in transitions[state]: + state, handler = transitions[state][code] + if handler is not None: + handler(token) + else: + self.error( + "Parse error in state %s: unexpected token '%s'" % ( + state, token)) + if state == AutogenState.done: + break + + def read_definitions(self, path): + self.cur_file = path + with open(path) as f: + self.read_definitions_file(f) + +defparser = AutogenParser() + +# +# Output +# + +outputs = {} + +def output(s, section=''): + if s == "": + return + outputs.setdefault(section, []) + outputs[section].append(s) + +def write_output(section=''): + for s in outputs.get(section, []): + print(s, end='') + # # Global variables # -GVARS = set() def gvar_add(var, value): - GVARS.add(var) - return var + " += " + value + "\n" - -def global_variable_initializers(): - r = "" - for var in sorted(GVARS): - r += var + " ?= \n" - return r + output(var + " += " + value + "\n") # # Per PROGRAM/SCRIPT variables # -def vars_init(*var_list): - r = "[+ IF (if (not (assoc-ref seen-vars (get \".name\"))) \"seen\") +]" - r += "[+ (out-suspend \"v\") +]" - for var in var_list: - r += var + " = \n" - r += "[+ (out-resume \"v\") +]" - r += "[+ (set! seen-vars (assoc-set! seen-vars (get \".name\") 0)) +]" - r += "[+ ENDIF +]" - return first_time(r) +seen_vars = set() + +def vars_init(defn, *var_list): + name = defn['name'] + + if name not in seen_target and name not in seen_vars: + for var in var_list: + output(var + " = \n", section='decl') + seen_vars.add(name) def var_set(var, value): - return var + " = " + value + "\n" + output(var + " = " + value + "\n") def var_add(var, value): - return var + " += " + value + "\n" + output(var + " += " + value + "\n") # -# Autogen constructs +# Variable names and rules # -def set_canonical_name_suffix(suffix): return "[+ % name `export cname=$(echo %s" + suffix + " | sed -e 's/[^0-9A-Za-z@_]/_/g')` +]" -def cname(): return "[+ % name `echo $cname` +]" +canonical_name_re = re.compile(r'[^0-9A-Za-z@_]') +canonical_name_suffix = "" + +def set_canonical_name_suffix(suffix): + global canonical_name_suffix + canonical_name_suffix = suffix + +def cname(defn): + return canonical_name_re.sub('_', defn['name'] + canonical_name_suffix) def rule(target, source, cmd): if cmd[0] == "\n": - return "\n" + target + ": " + source + cmd.replace("\n", "\n\t") + "\n" + output("\n" + target + ": " + source + cmd.replace("\n", "\n\t") + "\n") else: - return "\n" + target + ": " + source + "\n\t" + cmd.replace("\n", "\n\t") + "\n" + output("\n" + target + ": " + source + "\n\t" + cmd.replace("\n", "\n\t") + "\n") # -# Template for keys with platform names as values, for example: +# Handle keys with platform names as values, for example: # # kernel = { # nostrip = emu; # ... # } # -def if_platform_tagged(platform, tag, snippet_if, snippet_else=None): - r = "" - r += "[+ IF " + tag + " defined +]" - r += "[+ FOR " + tag + " +][+ CASE " + tag + " +]" - for group in RMAP[platform]: - r += "[+ = \"" + group + "\" +]" + snippet_if +def platform_tagged(defn, platform, tag): + for value in defn.find_all(tag): + for group in RMAP[platform]: + if value == group: + return True + return False - if snippet_else != None: r += "[+ * +]" + snippet_else - r += "[+ ESAC +][+ ENDFOR +]" - - if snippet_else == None: - r += "[+ ENDIF +]" - return r - - r += "[+ ELSE +]" + snippet_else + "[+ ENDIF +]" - return r +def if_platform_tagged(defn, platform, tag, snippet_if, snippet_else=None): + if platform_tagged(defn, platform, tag): + return snippet_if + elif snippet_else is not None: + return snippet_else # -# Template for tagged values +# Handle tagged values # # module = { # extra_dist = ... @@ -171,11 +527,14 @@ def if_platform_tagged(platform, tag, snippet_if, snippet_else=None): # ... # }; # -def foreach_value(tag, closure): - return "[+ FOR " + tag + " +]" + closure("[+ ." + tag + " +]") + "[+ ENDFOR +]" +def foreach_value(defn, tag, closure): + r = [] + for value in defn.find_all(tag): + r.append(closure(value)) + return ''.join(r) # -# Template for handling best matched values for a platform, for example: +# Handle best matched values for a platform, for example: # # module = { # cflags = '-Wall'; @@ -183,34 +542,21 @@ def foreach_value(tag, closure): # ... # } # -def foreach_platform_specific_value(platform, suffix, nonetag, closure): - r = "" +def foreach_platform_specific_value(defn, platform, suffix, nonetag, closure): + r = [] for group in RMAP[platform]: - gtag = group + suffix - - if group == RMAP[platform][0]: - r += "[+ IF " + gtag + " +]" - else: - r += "[+ ELIF " + gtag + " +]" - - r += "[+ FOR " + gtag + " +]" + closure("[+ ." + gtag + " +]") + "[+ ENDFOR +]" - r += "[+ ELSE +][+ FOR " + nonetag + " +]" + closure("[+ ." + nonetag + " +]") + "[+ ENDFOR +][+ ENDIF +]" - return r + values = list(defn.find_all(group + suffix)) + if values: + for value in values: + r.append(closure(value)) + break + else: + for value in defn.find_all(nonetag): + r.append(closure(value)) + return ''.join(r) # -# Returns autogen code that defines an autogen macro using the -# definition given in the 'snippet'. -# -def define_autogen_macro(name, snippet): - r = "" - r += "[+ DEFINE " + name + " +]" - r += snippet - r += "[+ ENDDEF +]\n" - return r - -# -# Template for handling values from sum of all groups for a platform, -# for example: +# Handle values from sum of all groups for a platform, for example: # # module = { # common = kern/misc.c; @@ -218,18 +564,21 @@ def define_autogen_macro(name, snippet): # ... # } # -def foreach_platform_value (platform, suffix, closure): - r = "" +def foreach_platform_value(defn, platform, suffix, closure): + r = [] for group in RMAP[platform]: - gtag = group + suffix + for value in defn.find_all(group + suffix): + r.append(closure(value)) + r.sort() + return ''.join(r) - r += "[+ IF " + gtag + " +]" - r += "[+ FOR " + gtag + " +]" + closure("[+ ." + gtag + " +]") + "[+ ENDFOR +]" - r += "[+ ENDIF +]" - return r +def platform_conditional(platform, closure): + output("\nif COND_" + platform + "\n") + closure(platform) + output("endif\n") # -# Template for gaurding with platform specific "enable" keys, for example: +# Handle guarding with platform-specific "enable" keys, for example: # # module = { # name = pci; @@ -244,20 +593,17 @@ def foreach_platform_value (platform, suffix, closure): # enable = i386_coreboot; # }; # -def foreach_enabled_platform(closure): - r = "[+ IF - enable undefined +]" - for platform in GRUB_PLATFORMS: - r += "\nif COND_" + platform + "\n" + closure(platform) + "endif\n" - r += "[+ ELSE +]" - for platform in GRUB_PLATFORMS: - x = "\nif COND_" + platform + "\n" + closure(platform) + "endif\n" - r += if_platform_tagged(platform, "enable", x) - r += "[+ ENDIF +]" - return r +def foreach_enabled_platform(defn, closure): + if 'enable' in defn: + for platform in GRUB_PLATFORMS: + if platform_tagged(defn, platform, "enable"): + platform_conditional(platform, closure) + else: + for platform in GRUB_PLATFORMS: + platform_conditional(platform, closure) # -# Template for gaurding with platform specific automake conditionals, -# for example: +# Handle guarding with platform-specific automake conditionals, for example: # # module = { # name = usb; @@ -267,352 +613,303 @@ def foreach_enabled_platform(closure): # enable = emu; # enable = i386; # enable = mips_loongson; -# emu_condition = COND_GRUB_EMU_USB; +# emu_condition = COND_GRUB_EMU_SDL; # }; # -def define_macro_for_platform_conditionals_if_statement(p): - return define_autogen_macro( - "if_" + p + "_conditionals", - foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "if " + cond + "\n")) -def define_macro_for_platform_conditionals_endif_statement(p): - return define_autogen_macro( - "endif_" + p + "_conditionals", - foreach_platform_specific_value(platform, "_condition", "condition", lambda cond: "endif " + cond + "\n")) -def under_platform_specific_conditionals(platform, snippet): - r = "[+ if_" + platform + "_conditionals +]" - r += snippet - r += "[+ endif_" + platform + "_conditionals +]" - return r +def under_platform_specific_conditionals(defn, platform, closure): + output(foreach_platform_specific_value(defn, platform, "_condition", "condition", lambda cond: "if " + cond + "\n")) + closure(defn, platform) + output(foreach_platform_specific_value(defn, platform, "_condition", "condition", lambda cond: "endif " + cond + "\n")) -def platform_specific_values(platform, suffix, nonetag): - return foreach_platform_specific_value(platform, suffix, nonetag, +def platform_specific_values(defn, platform, suffix, nonetag): + return foreach_platform_specific_value(defn, platform, suffix, nonetag, lambda value: value + " ") -def platform_values(platform, suffix): - return foreach_platform_value(platform, suffix, lambda value: value + " ") +def platform_values(defn, platform, suffix): + return foreach_platform_value(defn, platform, suffix, lambda value: value + " ") -def extra_dist(): - return foreach_value("extra_dist", lambda value: value + " ") +def extra_dist(defn): + return foreach_value(defn, "extra_dist", lambda value: value + " ") -def define_macro_for_platform_sources(p): - return define_autogen_macro( - "get_" + p + "_sources", - platform_values(p, "")) -def define_macro_for_platform_nodist_sources(p): - return define_autogen_macro( - "get_" + p + "_nodist_sources", - platform_values(p, "_nodist")) -def define_macro_for_platform_dependencies(p): - return define_autogen_macro( - "get_" + p + "_dependencies", - platform_values(p, "dependencies", "_dependencies")) -def platform_sources(p): return "[+ get_" + p + "_sources +]" -def platform_nodist_sources(p): return "[+ get_" + p + "_nodist_sources +]" -def platform_dependencies(p): return "[+ get_" + p + "_dependencies +]" +def extra_dep(defn): + return foreach_value(defn, "depends", lambda value: value + " ") -# -# Returns Autogen code which defines the autogen macros that collect -# platform specific values for cflags, ldflags, etc. tags. -# -def define_macro_for_platform_startup(p): - return define_autogen_macro( - "get_" + p + "_startup", - platform_specific_values(p, "_startup", "startup")) -def define_macro_for_platform_cflags(p): - return define_autogen_macro( - "get_" + p + "_cflags", - platform_specific_values(p, "_cflags", "cflags")) -def define_macro_for_platform_ldadd(p): - return define_autogen_macro( - "get_" + p + "_ldadd", - platform_specific_values(p, "_ldadd", "ldadd")) -def define_macro_for_platform_ldflags(p): - return define_autogen_macro( - "get_" + p + "_ldflags", - platform_specific_values(p, "_ldflags", "ldflags")) -def define_macro_for_platform_cppflags(p): - return define_autogen_macro( - "get_" + p + "_cppflags", - platform_specific_values(p, "_cppflags", "cppflags")) -def define_macro_for_platform_ccasflags(p): - return define_autogen_macro( - "get_" + p + "_ccasflags", - platform_specific_values(p, "_ccasflags", "ccasflags")) -def define_macro_for_platform_stripflags(p): - return define_autogen_macro( - "get_" + p + "_stripflags", - platform_specific_values(p, "_stripflags", "stripflags")) -def define_macro_for_platform_objcopyflags(p): - return define_autogen_macro( - "get_" + p + "_objcopyflags", - platform_specific_values(p, "_objcopyflags", "objcopyflags")) -# -# Autogen calls to invoke the above macros. -# -def platform_startup(p): return "[+ get_" + p + "_startup +]" -def platform_ldadd(p): return "[+ get_" + p + "_ldadd +]" -def platform_cflags(p): return "[+ get_" + p + "_cflags +]" -def platform_ldflags(p): return "[+ get_" + p + "_ldflags +]" -def platform_cppflags(p): return "[+ get_" + p + "_cppflags +]" -def platform_ccasflags(p): return "[+ get_" + p + "_ccasflags +]" -def platform_stripflags(p): return "[+ get_" + p + "_stripflags +]" -def platform_objcopyflags(p): return "[+ get_" + p + "_objcopyflags +]" +def platform_sources(defn, p): return platform_values(defn, p, "_head") + platform_values(defn, p, "") +def platform_nodist_sources(defn, p): return platform_values(defn, p, "_nodist") + +def platform_startup(defn, p): return platform_specific_values(defn, p, "_startup", "startup") +def platform_ldadd(defn, p): return platform_specific_values(defn, p, "_ldadd", "ldadd") +def platform_dependencies(defn, p): return platform_specific_values(defn, p, "_dependencies", "dependencies") +def platform_cflags(defn, p): return platform_specific_values(defn, p, "_cflags", "cflags") +def platform_ldflags(defn, p): return platform_specific_values(defn, p, "_ldflags", "ldflags") +def platform_cppflags(defn, p): return platform_specific_values(defn, p, "_cppflags", "cppflags") +def platform_ccasflags(defn, p): return platform_specific_values(defn, p, "_ccasflags", "ccasflags") +def platform_stripflags(defn, p): return platform_specific_values(defn, p, "_stripflags", "stripflags") +def platform_objcopyflags(defn, p): return platform_specific_values(defn, p, "_objcopyflags", "objcopyflags") # # Emit snippet only the first time through for the current name. # -def first_time(snippet): - r = "[+ IF (if (not (assoc-ref seen-target (get \".name\"))) \"seen\") +]" - r += snippet - r += "[+ ENDIF +]" - return r +seen_target = set() -def module(platform): - r = set_canonical_name_suffix(".module") +def first_time(defn, snippet): + if defn['name'] not in seen_target: + return snippet + return '' - r += gvar_add("platform_PROGRAMS", "[+ name +].module") - r += gvar_add("MODULE_FILES", "[+ name +].module$(EXEEXT)") +def is_platform_independent(defn): + if 'enable' in defn: + return False + for suffix in [ "", "_head", "_nodist" ]: + template = platform_values(defn, GRUB_PLATFORMS[0], suffix) + for platform in GRUB_PLATFORMS[1:]: + if template != platform_values(defn, platform, suffix): + return False - r += var_set(cname() + "_SOURCES", platform_sources(platform) + " ## platform sources") - r += var_set("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform) + " ## platform nodist sources") - r += var_set(cname() + "_LDADD", platform_ldadd(platform)) - r += var_set(cname() + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_MODULE) " + platform_cflags(platform)) - r += var_set(cname() + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_MODULE) " + platform_ldflags(platform)) - r += var_set(cname() + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_MODULE) " + platform_cppflags(platform)) - r += var_set(cname() + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_MODULE) " + platform_ccasflags(platform)) - # r += var_set(cname() + "_DEPENDENCIES", platform_dependencies(platform) + " " + platform_ldadd(platform)) + for suffix in [ "startup", "ldadd", "dependencies", "cflags", "ldflags", "cppflags", "ccasflags", "stripflags", "objcopyflags", "condition" ]: + template = platform_specific_values(defn, GRUB_PLATFORMS[0], "_" + suffix, suffix) + for platform in GRUB_PLATFORMS[1:]: + if template != platform_specific_values(defn, platform, "_" + suffix, suffix): + return False + for tag in [ "nostrip" ]: + template = platform_tagged(defn, GRUB_PLATFORMS[0], tag) + for platform in GRUB_PLATFORMS[1:]: + if template != platform_tagged(defn, platform, tag): + return False - r += gvar_add("EXTRA_DIST", extra_dist()) - r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") - r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") + return True - r += gvar_add("MOD_FILES", "[+ name +].mod") - r += gvar_add("MARKER_FILES", "[+ name +].marker") - r += gvar_add("CLEANFILES", "[+ name +].marker") - r += """ -[+ name +].marker: $(""" + cname() + """_SOURCES) $(nodist_""" + cname() + """_SOURCES) - $(TARGET_CPP) -DGRUB_LST_GENERATOR $(CPPFLAGS_MARKER) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(""" + cname() + """_CPPFLAGS) $(CPPFLAGS) $^ > $@.new || (rm -f $@; exit 1) - grep 'MARKER' $@.new > $@; rm -f $@.new -""" - return r +def module(defn, platform): + name = defn['name'] + set_canonical_name_suffix(".module") -def kernel(platform): - r = set_canonical_name_suffix(".exec") - r += gvar_add("platform_PROGRAMS", "[+ name +].exec") - r += var_set(cname() + "_SOURCES", platform_startup(platform)) - r += var_add(cname() + "_SOURCES", platform_sources(platform)) - r += var_set("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform) + " ## platform nodist sources") - r += var_set(cname() + "_LDADD", platform_ldadd(platform)) - r += var_set(cname() + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_KERNEL) " + platform_cflags(platform)) - r += var_set(cname() + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_KERNEL) " + platform_ldflags(platform)) - r += var_set(cname() + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) " + platform_cppflags(platform)) - r += var_set(cname() + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_KERNEL) " + platform_ccasflags(platform)) - r += var_set(cname() + "_STRIPFLAGS", "$(AM_STRIPFLAGS) $(STRIPFLAGS_KERNEL) " + platform_stripflags(platform)) - # r += var_set(cname() + "_DEPENDENCIES", platform_dependencies(platform) + " " + platform_ldadd(platform)) + gvar_add("platform_PROGRAMS", name + ".module") + gvar_add("MODULE_FILES", name + ".module$(EXEEXT)") - r += gvar_add("EXTRA_DIST", extra_dist()) - r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") - r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") + var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform) + " ## platform sources") + var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + " ## platform nodist sources") + var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform)) + var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_MODULE) " + platform_cflags(defn, platform)) + var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_MODULE) " + platform_ldflags(defn, platform)) + var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_MODULE) " + platform_cppflags(defn, platform)) + var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_MODULE) " + platform_ccasflags(defn, platform)) + var_set(cname(defn) + "_DEPENDENCIES", "$(TARGET_OBJ2ELF) " + platform_dependencies(defn, platform)) - r += gvar_add("platform_DATA", "[+ name +].img") - r += gvar_add("CLEANFILES", "[+ name +].img") - r += rule("[+ name +].img", "[+ name +].exec$(EXEEXT)", - if_platform_tagged(platform, "nostrip", -"""if test x$(USE_APPLE_CC_FIXES) = xyes; then \ - $(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -wd1106 -nu -nd $< $@; \ + gvar_add("dist_noinst_DATA", extra_dist(defn)) + gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)") + gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)") + + gvar_add("MOD_FILES", name + ".mod") + gvar_add("MARKER_FILES", name + ".marker") + gvar_add("CLEANFILES", name + ".marker") + + for dep in defn.find_all("depends"): + gvar_add("EXTRA_DEPS", "depends " + name + " " + dep + ":") + + output(""" +""" + name + """.marker: $(""" + cname(defn) + """_SOURCES) $(nodist_""" + cname(defn) + """_SOURCES) + $(TARGET_CPP) -DGRUB_LST_GENERATOR $(CPPFLAGS_MARKER) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(""" + cname(defn) + """_CPPFLAGS) $(CPPFLAGS) $^ > $@.new || (rm -f $@; exit 1) + grep 'MARKER' $@.new | grep -v '^#' > $@; rm -f $@.new +""") + +def kernel(defn, platform): + name = defn['name'] + set_canonical_name_suffix(".exec") + gvar_add("platform_PROGRAMS", name + ".exec") + var_set(cname(defn) + "_SOURCES", platform_startup(defn, platform)) + var_add(cname(defn) + "_SOURCES", platform_sources(defn, platform)) + var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + " ## platform nodist sources") + var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform)) + var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_KERNEL) " + platform_cflags(defn, platform)) + var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_KERNEL) " + platform_ldflags(defn, platform)) + var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) " + platform_cppflags(defn, platform)) + var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_KERNEL) " + platform_ccasflags(defn, platform)) + var_set(cname(defn) + "_STRIPFLAGS", "$(AM_STRIPFLAGS) $(STRIPFLAGS_KERNEL) " + platform_stripflags(defn, platform)) + var_set(cname(defn) + "_DEPENDENCIES", "$(TARGET_OBJ2ELF)") + + gvar_add("dist_noinst_DATA", extra_dist(defn)) + gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)") + gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)") + + gvar_add("platform_DATA", name + ".img") + gvar_add("CLEANFILES", name + ".img") + rule(name + ".img", name + ".exec$(EXEEXT)", + if_platform_tagged(defn, platform, "nostrip", +"""if test x$(TARGET_APPLE_LINKER) = x1; then \ + $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -wd1106 -nu -nd $< $@; \ elif test ! -z '$(TARGET_OBJ2ELF)'; then \ - cp $< $@.bin; $(TARGET_OBJ2ELF) $@.bin && cp $@.bin $@ || (rm -f $@.bin; exit 1); \ + $(TARGET_OBJ2ELF) $< $@ || (rm -f $@; exit 1); \ else cp $< $@; fi""", -"""if test x$(USE_APPLE_CC_FIXES) = xyes; then \ - $(STRIP) $(""" + cname() + """) -o $@.bin $<; \ - $(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -wd1106 -nu -nd $@.bin $@; \ -else """ + "$(STRIP) $(" + cname() + "_STRIPFLAGS) -o $@ $<; \ +"""if test x$(TARGET_APPLE_LINKER) = x1; then \ + $(TARGET_STRIP) -S -x $(""" + cname(defn) + """) -o $@.bin $<; \ + $(TARGET_OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -ed2022 -ed2016 -wd1106 -nu -nd $@.bin $@; \ + rm -f $@.bin; \ + elif test ! -z '$(TARGET_OBJ2ELF)'; then \ + """ + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@.bin $< && \ + $(TARGET_OBJ2ELF) $@.bin $@ || (rm -f $@; rm -f $@.bin; exit 1); \ + rm -f $@.bin; \ +else """ + "$(TARGET_STRIP) $(" + cname(defn) + "_STRIPFLAGS) -o $@ $<; \ fi""")) - return r -def image(platform): - r = set_canonical_name_suffix(".image") - r += gvar_add("platform_PROGRAMS", "[+ name +].image") - r += var_set(cname() + "_SOURCES", platform_sources(platform)) - r += var_set("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform) + "## platform nodist sources") - r += var_set(cname() + "_LDADD", platform_ldadd(platform)) - r += var_set(cname() + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_IMAGE) " + platform_cflags(platform)) - r += var_set(cname() + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_IMAGE) " + platform_ldflags(platform)) - r += var_set(cname() + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_IMAGE) " + platform_cppflags(platform)) - r += var_set(cname() + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_IMAGE) " + platform_ccasflags(platform)) - r += var_set(cname() + "_OBJCOPYFLAGS", "$(OBJCOPYFLAGS_IMAGE) " + platform_objcopyflags(platform)) - # r += var_set(cname() + "_DEPENDENCIES", platform_dependencies(platform) + " " + platform_ldadd(platform)) +def image(defn, platform): + name = defn['name'] + set_canonical_name_suffix(".image") + gvar_add("platform_PROGRAMS", name + ".image") + var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform)) + var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform) + "## platform nodist sources") + var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform)) + var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_IMAGE) " + platform_cflags(defn, platform)) + var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_IMAGE) " + platform_ldflags(defn, platform)) + var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_IMAGE) " + platform_cppflags(defn, platform)) + var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_IMAGE) " + platform_ccasflags(defn, platform)) + var_set(cname(defn) + "_OBJCOPYFLAGS", "$(OBJCOPYFLAGS_IMAGE) " + platform_objcopyflags(defn, platform)) + # var_set(cname(defn) + "_DEPENDENCIES", platform_dependencies(defn, platform) + " " + platform_ldadd(defn, platform)) - r += gvar_add("EXTRA_DIST", extra_dist()) - r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") - r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") + gvar_add("dist_noinst_DATA", extra_dist(defn)) + gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)") + gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)") - r += gvar_add("platform_DATA", "[+ name +].img") - r += gvar_add("CLEANFILES", "[+ name +].img") - r += rule("[+ name +].img", "[+ name +].image$(EXEEXT)", """ -if test x$(USE_APPLE_CC_FIXES) = xyes; then \ + gvar_add("platform_DATA", name + ".img") + gvar_add("CLEANFILES", name + ".img") + rule(name + ".img", name + ".image$(EXEEXT)", """ +if test x$(TARGET_APPLE_LINKER) = x1; then \ $(MACHO2IMG) $< $@; \ else \ - $(OBJCOPY) $(""" + cname() + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn -R .note.gnu.gold-version $< $@; \ + $(TARGET_OBJCOPY) $(""" + cname(defn) + """_OBJCOPYFLAGS) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .MIPS.abiflags -R .reginfo -R .rel.dyn -R .note.gnu.gold-version -R .note.gnu.property -R .ARM.exidx -R .interp $< $@; \ fi """) - return r -def library(platform): - r = set_canonical_name_suffix("") +def library(defn, platform): + name = defn['name'] + set_canonical_name_suffix("") - r += vars_init(cname() + "_SOURCES", - "nodist_" + cname() + "_SOURCES", - cname() + "_CFLAGS", - cname() + "_CPPFLAGS", - cname() + "_CCASFLAGS") - # cname() + "_DEPENDENCIES") + vars_init(defn, + cname(defn) + "_SOURCES", + "nodist_" + cname(defn) + "_SOURCES", + cname(defn) + "_CFLAGS", + cname(defn) + "_CPPFLAGS", + cname(defn) + "_CCASFLAGS") + # cname(defn) + "_DEPENDENCIES") - r += first_time(gvar_add("noinst_LIBRARIES", "[+ name +]")) - r += var_add(cname() + "_SOURCES", platform_sources(platform)) - r += var_add("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform)) - r += var_add(cname() + "_CFLAGS", first_time("$(AM_CFLAGS) $(CFLAGS_LIBRARY) ") + platform_cflags(platform)) - r += var_add(cname() + "_CPPFLAGS", first_time("$(AM_CPPFLAGS) $(CPPFLAGS_LIBRARY) ") + platform_cppflags(platform)) - r += var_add(cname() + "_CCASFLAGS", first_time("$(AM_CCASFLAGS) $(CCASFLAGS_LIBRARY) ") + platform_ccasflags(platform)) - # r += var_add(cname() + "_DEPENDENCIES", platform_dependencies(platform) + " " + platform_ldadd(platform)) + if name not in seen_target: + gvar_add("noinst_LIBRARIES", name) + var_add(cname(defn) + "_SOURCES", platform_sources(defn, platform)) + var_add("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform)) + var_add(cname(defn) + "_CFLAGS", first_time(defn, "$(AM_CFLAGS) $(CFLAGS_LIBRARY) ") + platform_cflags(defn, platform)) + var_add(cname(defn) + "_CPPFLAGS", first_time(defn, "$(AM_CPPFLAGS) $(CPPFLAGS_LIBRARY) ") + platform_cppflags(defn, platform)) + var_add(cname(defn) + "_CCASFLAGS", first_time(defn, "$(AM_CCASFLAGS) $(CCASFLAGS_LIBRARY) ") + platform_ccasflags(defn, platform)) + # var_add(cname(defn) + "_DEPENDENCIES", platform_dependencies(defn, platform) + " " + platform_ldadd(defn, platform)) - r += gvar_add("EXTRA_DIST", extra_dist()) - r += first_time(gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)")) - r += first_time(gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)")) - return r + gvar_add("dist_noinst_DATA", extra_dist(defn)) + if name not in seen_target: + gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)") + gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)") -def installdir(default="bin"): - return "[+ IF installdir +][+ installdir +][+ ELSE +]" + default + "[+ ENDIF +]" +def installdir(defn, default="bin"): + return defn.get('installdir', default) -def manpage(): - r = "if COND_MAN_PAGES\n" - r += gvar_add("man_MANS", "[+ name +].[+ mansection +]\n") - r += rule("[+ name +].[+ mansection +]", "[+ name +]", """ -chmod a+x [+ name +] -PATH=$(builddir):$$PATH pkgdatadir=$(builddir) $(HELP2MAN) --section=[+ mansection +] -i $(top_srcdir)/docs/man/[+ name +].h2m -o $@ [+ name +] +def manpage(defn, adddeps): + name = defn['name'] + mansection = defn['mansection'] + + output("if COND_MAN_PAGES\n") + gvar_add("man_MANS", name + "." + mansection) + rule(name + "." + mansection, name + " " + adddeps, """ +chmod a+x """ + name + """ +PATH=$(builddir):$$PATH pkgdatadir=$(builddir) $(HELP2MAN) --section=""" + mansection + """ -i $(top_srcdir)/docs/man/""" + name + """.h2m -o $@ """ + name + """ """) - r += gvar_add("CLEANFILES", "[+ name +].[+ mansection +]") - r += "endif\n" - return r + gvar_add("CLEANFILES", name + "." + mansection) + output("endif\n") -def program(platform, test=False): - r = set_canonical_name_suffix("") +def program(defn, platform, test=False): + name = defn['name'] + set_canonical_name_suffix("") - r += "[+ IF testcase defined +]" - r += gvar_add("check_PROGRAMS", "[+ name +]") - r += gvar_add("TESTS", "[+ name +]") - r += "[+ ELSE +]" - r += var_add(installdir() + "_PROGRAMS", "[+ name +]") - r += "[+ IF mansection +]" + manpage() + "[+ ENDIF +]" - r += "[+ ENDIF +]" + if 'testcase' in defn: + gvar_add("check_PROGRAMS_" + defn['testcase'], name) + else: + var_add(installdir(defn) + "_PROGRAMS", name) + if 'mansection' in defn: + manpage(defn, "") - r += var_set(cname() + "_SOURCES", platform_sources(platform)) - r += var_set("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform)) - r += var_set(cname() + "_LDADD", platform_ldadd(platform)) - r += var_set(cname() + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_PROGRAM) " + platform_cflags(platform)) - r += var_set(cname() + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_PROGRAM) " + platform_ldflags(platform)) - r += var_set(cname() + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_PROGRAM) " + platform_cppflags(platform)) - r += var_set(cname() + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_PROGRAM) " + platform_ccasflags(platform)) - # r += var_set(cname() + "_DEPENDENCIES", platform_dependencies(platform) + " " + platform_ldadd(platform)) + var_set(cname(defn) + "_SOURCES", platform_sources(defn, platform)) + var_set("nodist_" + cname(defn) + "_SOURCES", platform_nodist_sources(defn, platform)) + var_set(cname(defn) + "_LDADD", platform_ldadd(defn, platform)) + var_set(cname(defn) + "_CFLAGS", "$(AM_CFLAGS) $(CFLAGS_PROGRAM) " + platform_cflags(defn, platform)) + var_set(cname(defn) + "_LDFLAGS", "$(AM_LDFLAGS) $(LDFLAGS_PROGRAM) " + platform_ldflags(defn, platform)) + var_set(cname(defn) + "_CPPFLAGS", "$(AM_CPPFLAGS) $(CPPFLAGS_PROGRAM) " + platform_cppflags(defn, platform)) + var_set(cname(defn) + "_CCASFLAGS", "$(AM_CCASFLAGS) $(CCASFLAGS_PROGRAM) " + platform_ccasflags(defn, platform)) + # var_set(cname(defn) + "_DEPENDENCIES", platform_dependencies(defn, platform) + " " + platform_ldadd(defn, platform)) - r += gvar_add("EXTRA_DIST", extra_dist()) - r += gvar_add("BUILT_SOURCES", "$(nodist_" + cname() + "_SOURCES)") - r += gvar_add("CLEANFILES", "$(nodist_" + cname() + "_SOURCES)") - return r + gvar_add("dist_noinst_DATA", extra_dist(defn)) + gvar_add("BUILT_SOURCES", "$(nodist_" + cname(defn) + "_SOURCES)") + gvar_add("CLEANFILES", "$(nodist_" + cname(defn) + "_SOURCES)") -def data(platform): - r = gvar_add("EXTRA_DIST", platform_sources(platform)) - r += gvar_add("EXTRA_DIST", extra_dist()) - r += var_add(installdir() + "_DATA", platform_sources(platform)) - return r +def data(defn, platform): + var_add("dist_" + installdir(defn) + "_DATA", platform_sources(defn, platform)) + gvar_add("dist_noinst_DATA", extra_dist(defn)) -def script(platform): - r = "[+ IF testcase defined +]" - r += gvar_add("check_SCRIPTS", "[+ name +]") - r += gvar_add ("TESTS", "[+ name +]") - r += "[+ ELSE +]" - r += var_add(installdir() + "_SCRIPTS", "[+ name +]") - r += "[+ IF mansection +]" + manpage() + "[+ ENDIF +]" - r += "[+ ENDIF +]" +def transform_data(defn, platform): + name = defn['name'] - r += rule("[+ name +]", platform_sources(platform) + " $(top_builddir)/config.status", """ -$(top_builddir)/config.status --file=$@:$< -chmod a+x [+ name +] + var_add(installdir(defn) + "_DATA", name) + + rule(name, "$(top_builddir)/config.status " + platform_sources(defn, platform) + platform_dependencies(defn, platform), """ +(for x in """ + platform_sources(defn, platform) + """; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:- +chmod a+x """ + name + """ """) - r += gvar_add("CLEANFILES", "[+ name +]") - r += gvar_add("dist_noinst_DATA", platform_sources(platform)) - return r + gvar_add("CLEANFILES", name) + gvar_add("EXTRA_DIST", extra_dist(defn)) + gvar_add("dist_noinst_DATA", platform_sources(defn, platform)) + +def script(defn, platform): + name = defn['name'] + + if 'testcase' in defn: + gvar_add("check_SCRIPTS_" + defn['testcase'], name) + else: + var_add(installdir(defn) + "_SCRIPTS", name) + if 'mansection' in defn: + manpage(defn, "grub-mkconfig_lib") + + rule(name, "$(top_builddir)/config.status " + platform_sources(defn, platform) + platform_dependencies(defn, platform), """ +(for x in """ + platform_sources(defn, platform) + """; do cat $(srcdir)/"$$x"; done) | $(top_builddir)/config.status --file=$@:- +chmod a+x """ + name + """ +""") + + gvar_add("CLEANFILES", name) + gvar_add("EXTRA_DIST", extra_dist(defn)) + gvar_add("dist_noinst_DATA", platform_sources(defn, platform)) def rules(target, closure): - # Create association lists for the benefit of first_time and vars_init. - r = "[+ (define seen-target '()) +]" - r += "[+ (define seen-vars '()) +]" - # Most output goes to a diversion. This allows us to emit variable - # initializations before everything else. - r += "[+ (out-push-new) +]" + seen_target.clear() + seen_vars.clear() - r += "[+ FOR " + target + " +]" - r += foreach_enabled_platform( - lambda p: under_platform_specific_conditionals(p, closure(p))) - # Remember that we've seen this target. - r += "[+ (set! seen-target (assoc-set! seen-target (get \".name\") 0)) +]" - r += "[+ ENDFOR +]" - r += "[+ (out-pop #t) +]" - return r + for defn in defparser.definitions.find_all(target): + if is_platform_independent(defn): + under_platform_specific_conditionals(defn, GRUB_PLATFORMS[0], closure) + else: + foreach_enabled_platform( + defn, + lambda p: under_platform_specific_conditionals(defn, p, closure)) + # Remember that we've seen this target. + seen_target.add(defn['name']) -def module_rules(): - return rules("module", module) +parser = OptionParser(usage="%prog DEFINITION-FILES") +_, args = parser.parse_args() -def kernel_rules(): - return rules("kernel", kernel) +for arg in args: + defparser.read_definitions(arg) -def image_rules(): - return rules("image", image) +rules("module", module) +rules("kernel", kernel) +rules("image", image) +rules("library", library) +rules("program", program) +rules("script", script) +rules("data", data) +rules("transform_data", transform_data) -def library_rules(): - return rules("library", library) - -def program_rules(): - return rules("program", program) - -def script_rules(): - return rules("script", script) - -def data_rules(): - return rules("data", data) - -a = module_rules() -b = kernel_rules() -c = image_rules() -d = library_rules() -e = program_rules() -f = script_rules() -g = data_rules() -z = global_variable_initializers() - -print ("[+ AutoGen5 template +]\n") -for p in GRUB_PLATFORMS: - print (define_macro_for_platform_sources(p)) - print (define_macro_for_platform_nodist_sources(p)) - # print define_macro_for_platform_dependencies(p) - - print (define_macro_for_platform_startup(p)) - print (define_macro_for_platform_cflags(p)) - print (define_macro_for_platform_ldadd(p)) - print (define_macro_for_platform_ldflags(p)) - print (define_macro_for_platform_cppflags(p)) - print (define_macro_for_platform_ccasflags(p)) - print (define_macro_for_platform_stripflags(p)) - print (define_macro_for_platform_objcopyflags(p)) - - print (define_macro_for_platform_conditionals_if_statement(p)) - print (define_macro_for_platform_conditionals_endif_statement(p)) -# print z # initializer for all vars -print (a) -print (b) -print (c) -print (d) -print (e) -print (f) -print (g) +write_output(section='decl') +write_output() diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 7dc25197c..e50db8106 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -7,12 +7,8 @@ include $(top_srcdir)/conf/Makefile.common CC=$(TARGET_CC) CPP=$(TARGET_CC) CCAS=$(TARGET_CC) - -if COND_GRUB_MKFONT -if COND_HAVE_FONT_SOURCE -TARGET_CFLAGS += -DUSE_ASCII_FAILBACK=1 -DHAVE_UNIFONT_WIDTHSPEC=1 -endif -endif +RANLIB=$(TARGET_RANLIB) +STRIP=$(TARGET_STRIP) MACHO2IMG=$(top_builddir)/grub-macho2img @@ -30,25 +26,28 @@ CFLAGS_LIBRARY += $(CFLAGS_PLATFORM) -fno-builtin CPPFLAGS_LIBRARY += $(CPPFLAGS_PLATFORM) CCASFLAGS_LIBRARY += $(CCASFLAGS_PLATFORM) +build-grub-pep2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=64 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pep2elf\" $^ +CLEANFILES += build-grub-pep2elf$(BUILD_EXEEXT) + +build-grub-pe2elf$(BUILD_EXEEXT): $(top_srcdir)/util/grub-pe2elf.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_TARGET_WORDSIZE=32 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-pe2elf\" $^ +CLEANFILES += build-grub-pe2elf$(BUILD_EXEEXT) + # gentrigtables -gentrigtables: gentrigtables.c - $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(CPPFLAGS) $< -lm -CLEANFILES += gentrigtables +gentrigtables$(BUILD_EXEEXT): gentrigtables.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) $< $(BUILD_LIBM) +CLEANFILES += gentrigtables$(BUILD_EXEEXT) + +build-grub-module-verifier$(BUILD_EXEEXT): $(top_srcdir)/util/grub-module-verifier.c $(top_srcdir)/util/grub-module-verifier32.c $(top_srcdir)/util/grub-module-verifier64.c $(top_srcdir)/grub-core/kern/emu/misc.c $(top_srcdir)/util/misc.c + $(BUILD_CC) -o $@ -I$(top_srcdir)/include $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $(BUILD_LDFLAGS) -DGRUB_BUILD=1 -DGRUB_UTIL=1 -DGRUB_BUILD_PROGRAM_NAME=\"build-grub-module-verifier\" $^ +CLEANFILES += build-grub-module-verifier$(BUILD_EXEEXT) # trigtables.c -trigtables.c: gentrigtables gentrigtables.c $(top_srcdir)/configure.ac - $(builddir)/gentrigtables > $@ +trigtables.c: gentrigtables$(BUILD_EXEEXT) gentrigtables.c $(top_srcdir)/configure.ac + ./gentrigtables$(BUILD_EXEEXT) > $@ CLEANFILES += trigtables.c -gensm712: video/sm712.c - $(BUILD_CC) -DGENINIT -o $@ -I$(top_builddir) -I$(top_builddir)/include -I$(top_srcdir)/include $(CPPFLAGS) $< -CLEANFILES += gensm712 - -# trigtables.c -sm712_start.S: gensm712 video/sm712.c $(top_srcdir)/configure.ac - $(builddir)/gensm712 > $@ -CLEANFILES += sm712_start.S - # XXX Use Automake's LEX & YACC support grub_script.tab.h: script/parser.y $(YACC) -d -p grub_script_yy -b grub_script $< @@ -60,12 +59,9 @@ grub_script.yy.h: script/yylex.l $(LEX) -o grub_script.yy.c --header-file=grub_script.yy.h $< grub_script.yy.c: grub_script.yy.h -rs_decoder.S: $(srcdir)/lib/reed_solomon.c +rs_decoder.h: $(srcdir)/lib/reed_solomon.c $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -Os -I$(top_builddir) -S -DSTANDALONE -o $@ $< -g0 -mregparm=3 -ffreestanding -kern/i386/pc/startup.S: $(builddir)/rs_decoder.S -boot/mips/loongson/fwstart.S: $(builddir)/sm712_start.S - CLEANFILES += grub_script.yy.c grub_script.yy.h include $(srcdir)/Makefile.core.am @@ -75,6 +71,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/disk.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dl.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/sb.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/env_private.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/err.h @@ -83,64 +80,120 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fs.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i18n.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/kernel.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/list.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lockdown.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/misc.h +if COND_emu +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt-emu.h +else +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/compiler-rt.h +endif KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/parser.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/partition.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/key_protector.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/stack_protector.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/verify.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h if COND_i386_pc KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +endif + +if COND_i386_xen_pvh +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/int.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/xen.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/xen/hypercall.h endif if COND_i386_efi +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h endif if COND_i386_coreboot -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/coreboot/lbio.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h endif if COND_i386_multiboot -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/i386/pc/int.h +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h endif if COND_i386_qemu KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h endif if COND_i386_ieee1275 +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/alloc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h +endif + +if COND_i386_xen +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/xen.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/xen/hypercall.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h +endif + +if COND_x86_64_xen +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/xen.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/x86_64/xen/hypercall.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h endif if COND_x86_64_efi +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/tsc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pmtimer.h endif if COND_ia64_efi KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h endif if COND_mips @@ -150,18 +203,12 @@ endif if COND_mips_arc KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arc/arc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h endif if COND_mips_qemu_mips KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h @@ -173,12 +220,10 @@ if COND_mips_loongson KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/time.h -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h @@ -197,6 +242,7 @@ endif if COND_powerpc_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/alloc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h @@ -210,15 +256,72 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h endif +if COND_arm_uboot +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/uboot.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/uboot/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/lib/arg.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h +endif + +if COND_arm_coreboot +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video_fb.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/gfxterm.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdt.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/dma.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/coreboot/kernel.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/fdtbus.h +endif + +if COND_arm_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/arm/system.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + +if COND_arm64_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + +if COND_loongarch64_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + +if COND_riscv32_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + +if COND_riscv64_efi +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/efi.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/efi/disk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/acpi.h +endif + if COND_emu KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/export.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/net.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostdisk.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/hostfile.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/exec.h if COND_GRUB_EMU_SDL KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h endif -if COND_GRUB_EMU_USB -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libusb.h +if COND_GRUB_EMU_SDL2 +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h endif if COND_GRUB_EMU_PCI KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libpciaccess.h @@ -235,7 +338,7 @@ BUILT_SOURCES += symlist.h symlist.c: symlist.h gensymlist.sh $(TARGET_CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS_KERNEL) $(CPPFLAGS) -DGRUB_SYMBOL_GENERATOR=1 symlist.h > symlist.p || (rm -f symlist.p; exit 1) - cat symlist.p | /bin/sh $(srcdir)/gensymlist.sh $(top_builddir)/config.h $(KERNEL_HEADER_FILES) >$@ || (rm -f $@; exit 1) + cat symlist.p | $(SHELL) $(srcdir)/gensymlist.sh $(top_builddir)/config.h $(KERNEL_HEADER_FILES) >$@ || (rm -f $@; exit 1) rm -f symlist.p CLEANFILES += symlist.c BUILT_SOURCES += symlist.c @@ -263,12 +366,12 @@ grub_emu-grub_emu_init.$(OBJEXT):grub_emu_init.h kern/emu/grub_emu_dyn-main.$(OBJEXT):grub_emu_init.h grub_emu_dyn-grub_emu_init.$(OBJEXT):grub_emu_init.h -grub_emu_init.h: genemuinitheader.sh $(MOD_FILES) - rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinitheader.sh $(NM) > $@ +grub_emu_init.h: genemuinitheader.sh $(MODULE_FILES) + rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinitheader.sh $(TARGET_NM) > $@ CLEANFILES += grub_emu_init.h -grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MOD_FILES) - rm -f $@; echo $(MOD_FILES) | sh $(srcdir)/genemuinit.sh $(NM) > $@ +grub_emu_init.c: grub_emu_init.h genemuinit.sh $(MODULE_FILES) + rm -f $@; echo $(MODULE_FILES) | sh $(srcdir)/genemuinit.sh $(TARGET_NM) > $@ CLEANFILES += grub_emu_init.c endif @@ -289,8 +392,10 @@ command.lst: $(MARKER_FILES) b=`basename $$pp .marker`; \ sed -n \ -e "/EXTCOMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \ + -e "/EXTCOMMAND_LOCKDOWN_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \ -e "/P1COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/*\1: $$b/;p;}" \ - -e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \ + -e "/COMMAND_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" \ + -e "/COMMAND_LOCKDOWN_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/\1: $$b/;p;}" $$pp; \ done) | sort -u > $@ platform_DATA += command.lst CLEANFILES += command.lst @@ -315,6 +420,16 @@ terminal.lst: $(MARKER_FILES) platform_DATA += terminal.lst CLEANFILES += terminal.lst +fdt.lst: $(MARKER_FILES) + (for pp in $^; do \ + b=`basename $$pp .marker`; \ + sed -n \ + -e "/FDT_DRIVER_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $$b/;p;}" \ + -e "/FDT_DRIVER_LIST_MARKER *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $$b/;p;}" $$pp; \ + done) | sort -u > $@ +platform_DATA += fdt.lst +CLEANFILES += fdt.lst + parttool.lst: $(MARKER_FILES) (for pp in $^; do \ b=`basename $$pp .marker`; \ @@ -340,8 +455,11 @@ crypto.lst: $(srcdir)/lib/libgcrypt-grub/cipher/crypto.lst platform_DATA += crypto.lst CLEANFILES += crypto.lst -syminfo.lst: gensyminfo.sh kernel_syms.lst $(MODULE_FILES) - cat kernel_syms.lst > $@.new +extra_deps.lst: + @echo $(EXTRA_DEPS) | sed "s/\s*:\s*/\n/g" > $@ + +syminfo.lst: gensyminfo.sh kernel_syms.lst extra_deps.lst $(MODULE_FILES) + cat kernel_syms.lst extra_deps.lst > $@.new for m in $(MODULE_FILES); do \ sh $< $$m >> $@.new || exit 1; \ done @@ -349,11 +467,11 @@ syminfo.lst: gensyminfo.sh kernel_syms.lst $(MODULE_FILES) # generate global module dependencies list moddep.lst: syminfo.lst genmoddep.awk video.lst - cat $< | sort | awk -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1) + cat $< | sort | $(AWK) -f $(srcdir)/genmoddep.awk > $@ || (rm -f $@; exit 1) platform_DATA += moddep.lst -CLEANFILES += config.log syminfo.lst moddep.lst +CLEANFILES += config.log syminfo.lst moddep.lst extra_deps.lst -$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) +$(MOD_FILES): %.mod : genmod.sh moddep.lst %.module$(EXEEXT) build-grub-module-verifier$(BUILD_EXEEXT) TARGET_OBJ2ELF=@TARGET_OBJ2ELF@ sh $^ $@ platform_DATA += $(MOD_FILES) platform_DATA += modinfo.sh @@ -361,43 +479,44 @@ CLEANFILES += $(MOD_FILES) if COND_ENABLE_EFIEMU efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF) - -rm -f $@; \ - if test "x$(TARGET_APPLE_CC)" = x1; then \ - $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -DELF32 -DAPPLE_CC -m32 -Wall -Werror -nostdlib -O2 -c -o $@.bin $< || exit 1; \ - $(OBJCONV) -felf32 -nu -nd $@.bin $@ || exit 1; \ - rm -f $@.bin; \ + -rm -f $@ + -rm -f $@.bin + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m32 -Wall -Werror -nostdlib -static -O2 -c -o $@.bin $< + if test "x$(TARGET_APPLE_LINKER)" = x1; then \ + $(TARGET_OBJCONV) -felf32 -nu -nd $@.bin $@ || exit 1; \ + rm -f $@.bin ; \ + elif test ! -z "$(TARGET_OBJ2ELF)"; then \ + $(TARGET_OBJ2ELF) $@.bin || (rm -f $@.bin; exit 1); \ + mv $@.bin $@ ; \ else \ - $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -DELF32 -m32 -Wall -Werror -nostdlib -O2 -c -o $@ $< || exit 1; \ - if test ! -z "$(TARGET_OBJ2ELF)"; then $(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi; \ + mv $@.bin $@ ; \ fi +# Link format -arch,x86_64 means Apple linker efiemu64_c.o: efiemu/runtime/efiemu.c - if test "x$(TARGET_APPLE_CC)" = x1; then \ - $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -DELF64 -DAPPLE_CC=1 -m64 -nostdlib -Wall -Werror -mno-red-zone -c -o $@ $< || exit 1; \ - else \ - $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -DELF64 -m64 -nostdlib -Wall -Werror -O2 -mcmodel=large -mno-red-zone -c -o $@ $< || exit 1; \ - fi + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m64 -nostdlib -Wall -Werror -O2 -mcmodel=large -mno-red-zone -c -o $@ $< efiemu64_s.o: efiemu/runtime/efiemu.S - -rm -f $@ - if test "x$(TARGET_APPLE_CC)" = x1; then \ - $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -DELF64 -DAPPLE_CC=1 -m64 -Wall -Werror -nostdlib -O2 -mno-red-zone -c -o $@ $< || exit 1; \ - else \ - $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -DELF64 -m64 -Wall -Werror -nostdlib -O2 -mcmodel=large -mno-red-zone -c -o $@ $< || exit 1; \ - fi + $(TARGET_CC) $(DEFS) $(INCLUDES) $(CPPFLAGS_EFIEMU) $(CPPFLAGS_DEFAULT) -m64 -Wall -Werror -nostdlib -O2 -mcmodel=large -mno-red-zone -c -o $@ $< efiemu64.o: efiemu64_c.o efiemu64_s.o $(TARGET_OBJ2ELEF) - -rm -f $@; \ - if test "x$(TARGET_APPLE_CC)" = x1; then \ - rm -f $@.bin; \ - $(TARGET_CC) -m64 -Wl,-r -nostdlib -o $@.bin $^ || exit 1; \ - $(OBJCONV) -felf64 -nu -nd $@.bin $@ || exit 1; \ + -rm -f $@ + -rm -f $@.bin + $(TARGET_CC) -m64 $(EFIEMU64_LINK_FORMAT) -nostdlib -static -Wl,-r -o $@.bin $^ + if test "x$(EFIEMU64_LINK_FORMAT)" = x-arch,x86_64; then \ + $(TARGET_OBJCONV) -felf64 -nu -nd $@.bin $@ || exit 1; \ rm -f $@.bin; \ else \ - $(TARGET_CC) -m64 -nostdlib -Wl,-r -o $@ $^ || exit 1; \ - if test ! -z "$(TARGET_OBJ2ELF)"; then $(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi; \ + mv $@.bin $@ ; \ fi platform_DATA += efiemu32.o efiemu64.o CLEANFILES += efiemu32.o efiemu64.o efiemu64_c.o efiemu64_s.o endif + +windowsdir=$(top_builddir)/$(PACKAGE)-$(VERSION)-for-windows +windowsdir: $(PROGRAMS) $(starfield_DATA) $(platform_DATA) + test -d $(windowsdir)/$(target_cpu)-$(platform) || mkdir $(windowsdir)/$(target_cpu)-$(platform) + for x in $(platform_DATA); do \ + cp -fp $$x $(windowsdir)/$(target_cpu)-$(platform)/$$x; \ + done diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 39e77a450..f70e02e69 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1,75 +1,124 @@ AutoGen definitions Makefile.tpl; -script = { +transform_data = { installdir = noinst; name = gensyminfo.sh; common = gensyminfo.sh.in; }; -script = { +transform_data = { installdir = noinst; name = genmod.sh; common = genmod.sh.in; }; -script = { +transform_data = { installdir = noinst; name = modinfo.sh; common = modinfo.sh.in; }; -script = { +transform_data = { installdir = platform; - name = gmodule.pl; - common = gmodule.pl.in; + name = gdb_helper.py; + common = gdb_helper.py.in; }; -script = { +transform_data = { installdir = platform; name = gdb_grub; common = gdb_grub.in; }; +transform_data = { + installdir = platform; + name = grub.chrp; + common = boot/powerpc/grub.chrp.in; + enable = powerpc_ieee1275; +}; + +transform_data = { + installdir = platform; + name = bootinfo.txt; + common = boot/powerpc/bootinfo.txt.in; + enable = powerpc_ieee1275; +}; + kernel = { name = kernel; nostrip = emu; - emu_ldflags = '-Wl,-r,-d'; - i386_efi_ldflags = '-Wl,-r,-d'; + emu_ldflags = '-Wl,-r'; + i386_efi_cflags = '-fshort-wchar'; + i386_efi_ldflags = '-Wl,-r'; i386_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; - x86_64_efi_ldflags = '-Wl,-r,-d'; + x86_64_efi_cflags = '-fshort-wchar'; + x86_64_efi_ldflags = '-Wl,-r'; x86_64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; - ia64_efi_cflags = '-fno-builtin -fpic -minline-int-divide-max-throughput'; - ia64_efi_ldflags = '-Wl,-r,-d'; + ia64_efi_cflags = '-fshort-wchar -fno-builtin -fpic -minline-int-divide-max-throughput'; + ia64_efi_ldflags = '-Wl,-r'; ia64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + arm_efi_cflags = '-fshort-wchar'; + arm_efi_ldflags = '-Wl,-r'; + arm_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + + arm64_efi_cflags = '-fshort-wchar'; + arm64_efi_ldflags = '-Wl,-r'; + arm64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; + + loongarch64_efi_cflags = '-fshort-wchar'; + loongarch64_efi_ldflags = '-Wl,-r'; + loongarch64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; + + riscv32_efi_cflags = '-fshort-wchar'; + riscv32_efi_ldflags = '-Wl,-r'; + riscv32_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; + + riscv64_efi_cflags = '-fshort-wchar'; + riscv64_efi_ldflags = '-Wl,-r'; + riscv64_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version -R .eh_frame'; + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; - i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)'; - i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; + i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; + i386_coreboot_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_coreboot_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; + i386_multiboot_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_multiboot_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x9000'; + i386_ieee1275_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_ieee1275_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x10000'; + i386_xen_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_xen_ldflags = '$(TARGET_IMG_BASE_LDOPT),0'; + x86_64_xen_ldflags = '$(TARGET_IMG_LDFLAGS)'; + x86_64_xen_ldflags = '$(TARGET_IMG_BASE_LDOPT),0'; + i386_xen_pvh_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_xen_pvh_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x100000'; - ldadd = '$(LDADD_KERNEL)'; - - i386_coreboot_ldflags = '-Wl,-Ttext=0x8200'; - i386_multiboot_ldflags = '-Wl,-Ttext=0x8200'; - i386_ieee1275_ldflags = '-Wl,-Ttext=0x10000'; mips_loongson_ldflags = '-Wl,-Ttext,0x80200000'; powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; - mips_arc_ldflags = '-Wl,-Ttext,0x8bd00000'; + mips_arc_ldflags = '-Wl,-Ttext,$(TARGET_LINK_ADDR)'; mips_qemu_mips_ldflags = '-Wl,-Ttext,0x80200000'; - mips_loongson_cppflags = '-DUSE_ASCII_FAILBACK'; + mips_arc_cppflags = '-DGRUB_DECOMPRESSOR_LINK_ADDR=$(TARGET_DECOMPRESSOR_LINK_ADDR)'; i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; emu_cflags = '$(CFLAGS_GNULIB)'; emu_cppflags = '$(CPPFLAGS_GNULIB)'; + arm_uboot_ldflags = '-Wl,-r'; + arm_uboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; + arm_coreboot_ldflags = '-Wl,-r'; + arm_coreboot_stripflags = '--strip-unneeded -K start -R .note -R .comment -R .note.gnu.gold-version'; i386_pc_startup = kern/i386/pc/startup.S; i386_efi_startup = kern/i386/efi/startup.S; x86_64_efi_startup = kern/x86_64/efi/startup.S; + i386_xen_startup = kern/i386/xen/startup.S; + x86_64_xen_startup = kern/x86_64/xen/startup.S; + i386_xen_pvh_startup = kern/i386/xen/startup_pvh.S; i386_qemu_startup = kern/i386/qemu/startup.S; i386_ieee1275_startup = kern/i386/ieee1275/startup.S; i386_coreboot_startup = kern/i386/coreboot/startup.S; @@ -77,7 +126,15 @@ kernel = { mips_startup = kern/mips/startup.S; sparc64_ieee1275_startup = kern/sparc64/ieee1275/crt0.S; powerpc_ieee1275_startup = kern/powerpc/ieee1275/startup.S; + arm_uboot_startup = kern/arm/startup.S; + arm_coreboot_startup = kern/arm/startup.S; + arm_efi_startup = kern/arm/efi/startup.S; + arm64_efi_startup = kern/arm64/efi/startup.S; + loongarch64_efi_startup = kern/loongarch64/efi/startup.S; + riscv32_efi_startup = kern/riscv/efi/startup.S; + riscv64_efi_startup = kern/riscv/efi/startup.S; + common = kern/buffer.c; common = kern/command.c; common = kern/corecmd.c; common = kern/device.c; @@ -95,14 +152,15 @@ kernel = { common = kern/rescue_parser.c; common = kern/rescue_reader.c; common = kern/term.c; + common = kern/verifiers.c; + noemu = kern/compiler-rt.c; noemu = kern/mm.c; noemu = kern/time.c; noemu = kern/generic/millisleep.c; noemu_nodist = symlist.c; - i386_pc = kern/generic/rtc_get_time_ms.c; mips = kern/generic/rtc_get_time_ms.c; ieee1275 = disk/ieee1275/ofdisk.c; @@ -113,57 +171,127 @@ kernel = { ieee1275 = term/ieee1275/console.c; ieee1275 = kern/ieee1275/init.c; + uboot = disk/uboot/ubootdisk.c; + uboot = kern/uboot/uboot.c; + uboot = kern/uboot/init.c; + uboot = kern/uboot/hw.c; + uboot = term/uboot/console.c; + arm_uboot = kern/arm/uboot/init.c; + arm_uboot = kern/arm/uboot/uboot.S; + + arm_coreboot = kern/arm/coreboot/init.c; + arm_coreboot = kern/arm/coreboot/timer.c; + arm_coreboot = kern/arm/coreboot/coreboot.S; + arm_coreboot = lib/fdt.c; + arm_coreboot = bus/fdt.c; + arm_coreboot = term/ps2.c; + arm_coreboot = term/arm/pl050.c; + arm_coreboot = term/arm/cros.c; + arm_coreboot = term/arm/cros_ec.c; + arm_coreboot = bus/spi/rk3288_spi.c; + arm_coreboot = commands/keylayouts.c; + arm_coreboot = kern/arm/coreboot/dma.c; + terminfoinkernel = term/terminfo.c; terminfoinkernel = term/tparm.c; terminfoinkernel = commands/extcmd.c; terminfoinkernel = lib/arg.c; + softdiv = lib/division.c; + i386 = kern/i386/dl.c; + i386_xen = kern/i386/dl.c; + i386_xen_pvh = kern/i386/dl.c; - i386_coreboot_multiboot_qemu = kern/i386/coreboot/init.c; + i386_coreboot = kern/i386/coreboot/init.c; + i386_multiboot = kern/i386/coreboot/init.c; + i386_qemu = kern/i386/qemu/init.c; i386_coreboot_multiboot_qemu = term/i386/pc/vga_text.c; - - i386_coreboot_multiboot_qemu = term/i386/vga_common.c; - i386_pc = term/i386/vga_common.c; - - x86 = kern/i386/pit.c; + coreboot = video/coreboot/cbfb.c; efi = disk/efi/efidisk.c; efi = kern/efi/efi.c; + efi = kern/efi/debug.c; efi = kern/efi/init.c; efi = kern/efi/mm.c; efi = term/efi/console.c; + efi = kern/acpi.c; + efi = kern/efi/acpi.c; + efi = kern/efi/sb.c; + efi = kern/lockdown.c; + i386_coreboot = kern/i386/pc/acpi.c; + i386_multiboot = kern/i386/pc/acpi.c; + i386_coreboot = kern/acpi.c; + i386_multiboot = kern/acpi.c; + + x86 = kern/i386/tsc.c; + x86 = kern/i386/tsc_pit.c; + i386_efi = kern/i386/efi/tsc.c; + x86_64_efi = kern/i386/efi/tsc.c; + i386_efi = kern/i386/tsc_pmtimer.c; + i386_coreboot = kern/i386/tsc_pmtimer.c; + x86_64_efi = kern/i386/tsc_pmtimer.c; - i386_efi = kern/i386/tsc.c; i386_efi = kern/i386/efi/init.c; i386_efi = bus/pci.c; - x86_64_efi = kern/i386/tsc.c; - x86_64_efi = kern/x86_64/dl.c; - x86_64_efi = kern/x86_64/efi/callwrap.S; + x86_64 = kern/x86_64/dl.c; + x86_64_xen = kern/x86_64/dl.c; x86_64_efi = kern/i386/efi/init.c; x86_64_efi = bus/pci.c; + xen = kern/i386/tsc.c; + xen = kern/i386/xen/tsc.c; + x86_64_xen = kern/x86_64/xen/hypercall.S; + i386_xen = kern/i386/xen/hypercall.S; + xen = kern/xen/init.c; + xen = term/xen/console.c; + xen = disk/xen/xendisk.c; + xen = commands/boot.c; + + i386_xen_pvh = commands/boot.c; + i386_xen_pvh = disk/xen/xendisk.c; + i386_xen_pvh = kern/i386/tsc.c; + i386_xen_pvh = kern/i386/xen/tsc.c; + i386_xen_pvh = kern/i386/xen/pvh.c; + i386_xen_pvh = kern/xen/init.c; + i386_xen_pvh = term/xen/console.c; + ia64_efi = kern/ia64/efi/startup.S; ia64_efi = kern/ia64/efi/init.c; ia64_efi = kern/ia64/dl.c; ia64_efi = kern/ia64/dl_helper.c; + ia64_efi = kern/ia64/cache.c; + + arm_efi = kern/arm/efi/init.c; + arm_efi = kern/efi/fdt.c; + + arm64_efi = kern/arm64/efi/init.c; + arm64_efi = kern/efi/fdt.c; + + loongarch64_efi = kern/loongarch64/efi/init.c; + loongarch64_efi = kern/efi/fdt.c; + + riscv32_efi = kern/riscv/efi/init.c; + riscv32_efi = kern/efi/fdt.c; + + riscv64_efi = kern/riscv/efi/init.c; + riscv64_efi = kern/efi/fdt.c; i386_pc = kern/i386/pc/init.c; i386_pc = kern/i386/pc/mmap.c; - i386_pc = kern/i386/tsc.c; i386_pc = term/i386/pc/console.c; i386_qemu = bus/pci.c; i386_qemu = kern/vga_init.c; i386_qemu = kern/i386/qemu/mmap.c; - i386_qemu = kern/i386/tsc.c; - i386_coreboot = kern/i386/coreboot/mmap.c; - i386_coreboot = kern/i386/tsc.c; + coreboot = kern/coreboot/mmap.c; + i386_coreboot = kern/i386/coreboot/cbtable.c; + coreboot = kern/coreboot/cbtable.c; + arm_coreboot = kern/arm/coreboot/cbtable.c; i386_multiboot = kern/i386/multiboot_mmap.c; - i386_multiboot = kern/i386/tsc.c; mips = kern/mips/cache.S; mips = kern/mips/dl.c; @@ -173,9 +301,10 @@ kernel = { mips_qemu_mips = term/ns8250.c; mips_qemu_mips = term/serial.c; mips_qemu_mips = term/at_keyboard.c; + mips_qemu_mips = term/ps2.c; + mips_qemu_mips = commands/boot.c; mips_qemu_mips = commands/keylayouts.c; mips_qemu_mips = term/i386/pc/vga_text.c; - mips_qemu_mips = term/i386/vga_common.c; mips_qemu_mips = kern/vga_init.c; mips_arc = kern/mips/arc/init.c; @@ -188,26 +317,60 @@ kernel = { mips_loongson = bus/pci.c; mips_loongson = kern/mips/loongson/init.c; mips_loongson = term/at_keyboard.c; + mips_loongson = term/ps2.c; + mips_loongson = commands/boot.c; mips_loongson = term/serial.c; mips_loongson = video/sm712.c; mips_loongson = video/sis315pro.c; mips_loongson = video/radeon_fuloong2e.c; + mips_loongson = video/radeon_yeeloong3a.c; extra_dist = video/sm712_init.c; extra_dist = video/sis315_init.c; mips_loongson = commands/keylayouts.c; powerpc_ieee1275 = kern/powerpc/cache.S; powerpc_ieee1275 = kern/powerpc/dl.c; + powerpc_ieee1275 = kern/powerpc/compiler-rt.S; sparc64_ieee1275 = kern/sparc64/cache.S; sparc64_ieee1275 = kern/sparc64/dl.c; sparc64_ieee1275 = kern/sparc64/ieee1275/ieee1275.c; + sparc64_ieee1275 = disk/ieee1275/obdisk.c; + + arm = kern/arm/dl.c; + arm = kern/arm/dl_helper.c; + arm = kern/arm/cache_armv6.S; + arm = kern/arm/cache_armv7.S; + extra_dist = kern/arm/cache.S; + arm = kern/arm/cache.c; + arm = kern/arm/compiler-rt.S; + + arm64 = kern/arm64/cache.c; + arm64 = kern/arm64/cache_flush.S; + arm64 = kern/arm64/dl.c; + arm64 = kern/arm64/dl_helper.c; + + loongarch64 = kern/loongarch64/cache.c; + loongarch64 = kern/loongarch64/cache_flush.S; + loongarch64 = kern/loongarch64/dl.c; + loongarch64 = kern/loongarch64/dl_helper.c; + + riscv32 = kern/riscv/cache.c; + riscv32 = kern/riscv/cache_flush.S; + riscv32 = kern/riscv/dl.c; + + riscv64 = kern/riscv/cache.c; + riscv64 = kern/riscv/cache_flush.S; + riscv64 = kern/riscv/dl.c; emu = disk/host.c; - emu = gnulib/progname.c; - emu = gnulib/error.c; emu = kern/emu/cache_s.S; emu = kern/emu/hostdisk.c; + emu = osdep/unix/hostdisk.c; + emu = osdep/exec.c; + extra_dist = osdep/unix/exec.c; + emu = osdep/devmapper/hostdisk.c; + emu = osdep/hostdisk.c; emu = kern/emu/hostfs.c; emu = kern/emu/main.c; emu = kern/emu/argp_common.c; @@ -215,23 +378,31 @@ kernel = { emu = kern/emu/mm.c; emu = kern/emu/time.c; emu = kern/emu/cache.c; - emu = term/emu/console.c; + emu = osdep/emuconsole.c; + extra_dist = osdep/unix/emuconsole.c; + extra_dist = osdep/windows/emuconsole.c; + emu = osdep/dl.c; + extra_dist = osdep/unix/dl.c; + extra_dist = osdep/windows/dl.c; + emu = osdep/sleep.c; + emu = osdep/init.c; + emu = osdep/emunet.c; + extra_dist = osdep/linux/emunet.c; + extra_dist = osdep/basic/emunet.c; + emu = osdep/cputime.c; + extra_dist = osdep/unix/cputime.c; + extra_dist = osdep/windows/cputime.c; videoinkernel = term/gfxterm.c; videoinkernel = font/font.c; videoinkernel = font/font_cmd.c; videoinkernel = io/bufio.c; - videoinkernel = video/bitmap.c; - videoinkernel = video/bitmap_scale.c; - videoinkernel = video/colors.c; videoinkernel = video/fb/fbblit.c; videoinkernel = video/fb/fbfill.c; videoinkernel = video/fb/fbutil.c; videoinkernel = video/fb/video_fb.c; videoinkernel = video/video.c; - videoinkernel = commands/boot.c; - extra_dist = kern/i386/int.S; extra_dist = kern/i386/realmode.S; extra_dist = boot/i386/pc/lzma_decode.S; @@ -245,9 +416,9 @@ program = { emu = kern/emu/full.c; emu_nodist = grub_emu_init.c; - ldadd = 'kernel.img$(EXEEXT)'; + ldadd = 'kernel.exec$(EXEEXT)'; ldadd = '$(MODULE_FILES)'; - ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(SDL2_LIBS) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; enable = emu; }; @@ -258,8 +429,8 @@ program = { emu = kern/emu/lite.c; emu_nodist = symlist.c; - ldadd = 'kernel.img$(EXEEXT)'; - ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; + ldadd = 'kernel.exec$(EXEEXT)'; + ldadd = 'lib/gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(SDL2_LIBS) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; enable = emu; }; @@ -277,8 +448,14 @@ image = { i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),$(GRUB_BOOT_MACHINE_LINK_ADDR)'; i386_qemu_ccasflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; - sparc64_ieee1275_objcopyflags = '-O a.out-sunos-big'; - sparc64_ieee1275_ldflags = ' -Wl,-Ttext=0x4000'; + /* The entry point for a.out binaries on sparc64 starts + at 0x4000. Since we are writing the 32 bytes long a.out + header in the assembly code ourselves, we need to tell + the linker to adjust the start of the text segment to + 0x4000 - 0x20 = 0x3fe0. + */ + sparc64_ieee1275_ldflags = ' -Wl,-Ttext=0x3fe0'; + sparc64_ieee1275_objcopyflags = '-O binary'; objcopyflags = '-O binary'; enable = i386_pc; @@ -286,12 +463,36 @@ image = { enable = sparc64_ieee1275; }; +image = { + name = boot_hybrid; + i386_pc = boot/i386/pc/boot.S; + + cppflags = '-DHYBRID_BOOT=1'; + + i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; + + objcopyflags = '-O binary'; + enable = i386_pc; +}; + image = { name = cdboot; + i386_pc = boot/i386/pc/cdboot.S; i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00'; + + sparc64_ieee1275 = boot/sparc64/ieee1275/boot.S; + + /* See comment for sparc64_ieee1275_ldflags above. */ + sparc64_ieee1275_ldflags = ' -Wl,-Ttext=0x3fe0'; + sparc64_ieee1275_objcopyflags = '-O binary'; + sparc64_ieee1275_cppflags = '-DCDBOOT=1'; + objcopyflags = '-O binary'; + + enable = sparc64_ieee1275; enable = i386_pc; }; @@ -335,43 +536,38 @@ image = { image = { name = xz_decompress; - mips = boot/mips/startup_raw.S; + mips_head = boot/mips/startup_raw.S; common = boot/decompressor/minilib.c; common = boot/decompressor/xz.c; common = lib/xzembed/xz_dec_bcj.c; common = lib/xzembed/xz_dec_lzma2.c; common = lib/xzembed/xz_dec_stream.c; + common = kern/compiler-rt.c; cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -DGRUB_EMBED_DECOMPRESSOR=1'; objcopyflags = '-O binary'; - mips_loongson_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; - mips_qemu_mips_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; - mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x8bc00000'; - ldadd = '-lgcc'; - cflags = '-Wno-unreachable-code -static-libgcc'; + mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)'; + cflags = '-Wno-unreachable-code'; enable = mips; }; image = { name = none_decompress; - mips = boot/mips/startup_raw.S; + mips_head = boot/mips/startup_raw.S; common = boot/decompressor/none.c; cppflags = '-DGRUB_EMBED_DECOMPRESSOR=1'; objcopyflags = '-O binary'; - mips_loongson_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; - mips_qemu_mips_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; - mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x8bc00000'; - ldadd = '-lgcc'; - cflags = '-static-libgcc'; + mips_ldflags = '-Wl,-Ttext,$(TARGET_DECOMPRESSOR_LINK_ADDR)'; enable = mips; }; image = { name = lzma_decompress; i386_pc = boot/i386/pc/startup_raw.S; + i386_pc_nodist = rs_decoder.h; objcopyflags = '-O binary'; ldflags = '$(TARGET_IMG_LDFLAGS) $(TARGET_IMG_BASE_LDOPT),0x8200'; @@ -382,7 +578,7 @@ image = { name = fwstart; mips_loongson = boot/mips/loongson/fwstart.S; objcopyflags = '-O binary'; - ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; + ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; enable = mips_loongson; }; @@ -390,10 +586,16 @@ image = { name = fwstart_fuloong2f; mips_loongson = boot/mips/loongson/fuloong2f.S; objcopyflags = '-O binary'; - ldflags = '-static-libgcc -lgcc -Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; + ldflags = '-Wl,-N,-S,-Ttext,0xbfc00000,-Bstatic'; enable = mips_loongson; }; +module = { + name = disk; + common = lib/disk.c; + extra_dist = kern/disk_common.c; +}; + module = { name = trig; common_nodist = trigtables.c; @@ -406,13 +608,6 @@ module = { enable = x86; }; -module = { - name = libusb; - emu = bus/usb/emu/usb.c; - enable = emu; - condition = COND_GRUB_EMU_USB; -}; - module = { name = lsspd; mips_loongson = commands/mips/loongson/lsspd.c; @@ -427,12 +622,6 @@ module = { enable = usb; }; -module = { - name = emuusb; - common = bus/usb/usb.c; - condition = COND_GRUB_EMU_USB; -}; - module = { name = usbserial_common; common = bus/usb/serial/common.c; @@ -451,10 +640,16 @@ module = { enable = usb; }; +module = { + name = usbserial_usbdebug; + common = bus/usb/serial/usbdebug_late.c; + enable = usb; +}; + module = { name = uhci; common = bus/usb/uhci.c; - enable = x86; + enable = pci; }; module = { @@ -466,12 +661,16 @@ module = { module = { name = ehci; common = bus/usb/ehci.c; + arm_coreboot = bus/usb/ehci-fdt.c; + pci = bus/usb/ehci-pci.c; enable = pci; + enable = arm_coreboot; }; module = { name = pci; common = bus/pci.c; + i386_ieee1275 = bus/i386/ieee1275/pci.c; enable = i386_pc; enable = i386_ieee1275; @@ -479,11 +678,21 @@ module = { enable = i386_multiboot; }; +module = { + name = nativedisk; + common = commands/nativedisk.c; + + enable = x86; + enable = mips_loongson; + enable = mips_qemu_mips; +}; + module = { name = emupci; common = bus/emu/pci.c; common = commands/lspci.c; + enable = emu; condition = COND_GRUB_EMU_PCI; }; @@ -494,17 +703,27 @@ module = { enable = mips_arc; }; -library = { - name = libgnulib.a; - common = gnulib/regex.c; - cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; - cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; +module = { + name = lsxen; + common = commands/xen/lsxen.c; + + enable = xen; }; module = { name = cmostest; common = commands/i386/cmostest.c; enable = cmos; + enable = i386_efi; + enable = x86_64_efi; +}; + +module = { + name = cmosdump; + common = commands/i386/cmosdump.c; + enable = cmos; + enable = i386_efi; + enable = x86_64_efi; }; module = { @@ -513,11 +732,44 @@ module = { enable = x86; }; +module = { + name = cbtable; + common = kern/i386/coreboot/cbtable.c; + common = kern/coreboot/cbtable.c; + enable = i386_pc; + enable = i386_efi; + enable = i386_qemu; + enable = i386_multiboot; + enable = i386_ieee1275; + enable = x86_64_efi; +}; + +module = { + name = cbtime; + common = commands/i386/coreboot/cb_timestamps.c; + enable = x86; +}; + +module = { + name = cbls; + common = commands/i386/coreboot/cbls.c; + enable = x86; +}; + +module = { + name = cbmemc; + common = term/i386/coreboot/cbmemc.c; + enable = x86; +}; + module = { name = regexp; common = commands/regexp.c; common = commands/wildcard.c; - ldadd = libgnulib.a; + common = lib/gnulib/malloc/dynarray_finalize.c; + common = lib/gnulib/malloc/dynarray_emplace_enlarge.c; + common = lib/gnulib/malloc/dynarray_resize.c; + common = lib/gnulib/regex.c; cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB)'; }; @@ -526,10 +778,8 @@ module = { name = acpi; common = commands/acpi.c; - efi = commands/efi/acpi.c; - i386_pc = commands/i386/pc/acpi.c; - i386_coreboot = commands/i386/pc/acpi.c; - i386_multiboot = commands/i386/pc/acpi.c; + i386_pc = kern/acpi.c; + i386_pc = kern/i386/pc/acpi.c; enable = efi; enable = i386_pc; @@ -572,6 +822,24 @@ module = { enable = efi; }; +module = { + name = lsefi; + common = commands/efi/lsefi.c; + enable = efi; +}; + +module = { + name = efifwsetup; + efi = commands/efi/efifwsetup.c; + enable = efi; +}; + +module = { + name = efitextmode; + efi = commands/efi/efitextmode.c; + enable = efi; +}; + module = { name = blocklist; common = commands/blocklist.c; @@ -581,7 +849,19 @@ module = { name = boot; common = commands/boot.c; i386_pc = lib/i386/pc/biosnum.c; - enable = videomodules; + enable = x86; + enable = emu; + enable = sparc64_ieee1275; + enable = powerpc_ieee1275; + enable = mips_arc; + enable = ia64_efi; + enable = arm_efi; + enable = arm64_efi; + enable = arm_uboot; + enable = arm_coreboot; + enable = loongarch64_efi; + enable = riscv32_efi; + enable = riscv64_efi; }; module = { @@ -601,8 +881,11 @@ module = { module = { name = cpuid; - x86 = commands/i386/cpuid.c; + common = commands/i386/cpuid.c; enable = x86; + enable = i386_xen_pvh; + enable = i386_xen; + enable = x86_64_xen; }; module = { @@ -623,6 +906,11 @@ module = { common = commands/echo.c; }; +module = { + name = eval; + common = commands/eval.c; +}; + module = { name = extcmd; common = commands/extcmd.c; @@ -654,22 +942,28 @@ module = { i386_multiboot = lib/i386/halt.c; i386_coreboot = lib/i386/halt.c; i386_qemu = lib/i386/halt.c; + xen = lib/xen/halt.c; + i386_xen_pvh = lib/xen/halt.c; efi = lib/efi/halt.c; ieee1275 = lib/ieee1275/halt.c; emu = lib/emu/halt.c; + uboot = lib/dummy/halt.c; + arm_coreboot = lib/dummy/halt.c; }; module = { name = reboot; i386 = lib/i386/reboot.c; i386 = lib/i386/reboot_trampoline.S; - ia64_efi = lib/efi/reboot.c; - x86_64_efi = lib/efi/reboot.c; powerpc_ieee1275 = lib/ieee1275/reboot.c; sparc64_ieee1275 = lib/ieee1275/reboot.c; mips_arc = lib/mips/arc/reboot.c; mips_loongson = lib/mips/loongson/reboot.c; mips_qemu_mips = lib/mips/qemu_mips/reboot.c; + xen = lib/xen/reboot.c; + i386_xen_pvh = lib/xen/reboot.c; + uboot = lib/uboot/reboot.c; + arm_coreboot = lib/dummy/reboot.c; common = commands/reboot.c; }; @@ -678,10 +972,16 @@ module = { common = commands/hashsum.c; }; +module = { + name = pgp; + common = commands/pgp.c; + cflags = '$(CFLAGS_POSIX)'; + cppflags = '-I$(srcdir)/lib/posix_wrap'; +}; + module = { name = hdparm; common = commands/hdparm.c; - common = lib/hexdump.c; enable = pci; enable = mips_qemu_mips; }; @@ -763,6 +1063,18 @@ module = { enable = x86; }; +module = { + name = spkmodem; + x86 = term/spkmodem.c; + enable = x86; +}; + +module = { + name = morse; + x86 = term/morse.c; + enable = x86; +}; + module = { name = probe; common = commands/probe.c; @@ -800,11 +1112,32 @@ module = { enable = pci; }; +module = { + name = pcidump; + common = commands/pcidump.c; + enable = pci; +}; + module = { name = sleep; common = commands/sleep.c; }; +module = { + name = smbios; + + common = commands/smbios.c; + efi = commands/efi/smbios.c; + i386_pc = commands/i386/pc/smbios.c; + i386_coreboot = commands/i386/pc/smbios.c; + i386_multiboot = commands/i386/pc/smbios.c; + + enable = efi; + enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; +}; + module = { name = suspend; ieee1275 = commands/ieee1275/suspend.c; @@ -818,6 +1151,13 @@ module = { enable = powerpc_ieee1275; }; +module = { + name = tpm; + common = commands/tpm.c; + ieee1275 = commands/ieee1275/ibmvtpm.c; + enable = powerpc_ieee1275; +}; + module = { name = terminal; common = commands/terminal.c; @@ -869,10 +1209,32 @@ module = { common = disk/cryptodisk.c; }; +module = { + name = plainmount; + common = disk/plainmount.c; +}; + +module = { + name = json; + common = lib/json/json.c; +}; + +module = { + name = afsplitter; + common = disk/AFSplitter.c; +}; + module = { name = luks; common = disk/luks.c; - common = disk/AFSplitter.c; +}; + +module = { + name = luks2; + common = disk/luks2.c; + common = lib/gnulib/base64.c; + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/json'; }; module = { @@ -920,6 +1282,11 @@ module = { common = disk/raid6_recover.c; }; +module = { + name = key_protector; + common = disk/key_protector.c; +}; + module = { name = scsi; common = disk/scsi.c; @@ -1007,6 +1374,11 @@ module = { enable = videomodules; }; +module = { + name = procfs; + common = fs/proc.c; +}; + module = { name = affs; common = fs/affs.c; @@ -1022,12 +1394,37 @@ module = { common = fs/bfs.c; }; +module = { + name = zstd; + common = lib/zstd/debug.c; + common = lib/zstd/entropy_common.c; + common = lib/zstd/error_private.c; + common = lib/zstd/fse_decompress.c; + common = lib/zstd/huf_decompress.c; + common = lib/zstd/module.c; + common = lib/zstd/xxhash.c; + common = lib/zstd/zstd_common.c; + common = lib/zstd/zstd_decompress.c; + cflags = '$(CFLAGS_POSIX) -Wno-undef'; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/zstd'; +}; + module = { name = btrfs; common = fs/btrfs.c; common = lib/crc.c; cflags = '$(CFLAGS_POSIX) -Wno-undef'; - cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H'; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -I$(srcdir)/lib/zstd -DMINILZO_HAVE_CONFIG_H'; +}; + +module = { + name = archelp; + common = fs/archelp.c; +}; + +module = { + name = cbfs; + common = fs/cbfs.c; }; module = { @@ -1050,6 +1447,11 @@ module = { common = fs/odc.c; }; +module = { + name = erofs; + common = fs/erofs.c; +}; + module = { name = ext2; common = fs/ext2.c; @@ -1065,6 +1467,11 @@ module = { common = fs/exfat.c; }; +module = { + name = f2fs; + common = fs/f2fs.c; +}; + module = { name = fshelp; common = fs/fshelp.c; @@ -1080,6 +1487,11 @@ module = { common = fs/hfsplus.c; }; +module = { + name = hfspluscomp; + common = fs/hfspluscomp.c; +}; + module = { name = iso9660; common = fs/iso9660.c; @@ -1172,6 +1584,11 @@ module = { common = fs/ufs.c; }; +module = { + name = ufs1_be; + common = fs/ufs_be.c; +}; + module = { name = ufs2; common = fs/ufs2.c; @@ -1186,8 +1603,10 @@ module = { name = zfs; common = fs/zfs/zfs.c; common = fs/zfs/zfs_lzjb.c; + common = fs/zfs/zfs_lz4.c; common = fs/zfs/zfs_sha256.c; common = fs/zfs/zfs_fletcher.c; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/zstd'; }; module = { @@ -1200,6 +1619,11 @@ module = { common = fs/zfs/zfsinfo.c; }; +module = { + name = macbless; + common = commands/macbless.c; +}; + module = { name = pxe; i386_pc = net/drivers/i386/pc/pxe.c; @@ -1214,7 +1638,6 @@ module = { module = { name = gfxmenu; common = gfxmenu/gfxmenu.c; - common = gfxmenu/model.c; common = gfxmenu/view.c; common = gfxmenu/font.c; common = gfxmenu/icon_manager.c; @@ -1241,6 +1664,11 @@ module = { common = io/gzio.c; }; +module = { + name = offsetio; + common = io/offset.c; +}; + module = { name = bufio; common = io/bufio.c; @@ -1250,6 +1678,8 @@ module = { module = { name = elf; common = kern/elf.c; + + extra_dist = kern/elfXX.c; }; module = { @@ -1270,15 +1700,29 @@ module = { x86 = lib/i386/relocator16.S; x86 = lib/i386/relocator32.S; x86 = lib/i386/relocator64.S; + i386_xen_pvh = lib/i386/relocator16.S; + i386_xen_pvh = lib/i386/relocator32.S; + i386_xen_pvh = lib/i386/relocator64.S; i386 = lib/i386/relocator_asm.S; + i386_xen_pvh = lib/i386/relocator_asm.S; x86_64 = lib/x86_64/relocator_asm.S; + i386_xen = lib/i386/relocator_asm.S; + x86_64_xen = lib/x86_64/relocator_asm.S; x86 = lib/i386/relocator.c; + x86 = lib/i386/relocator_common_c.c; + i386_xen_pvh = lib/i386/relocator.c; + i386_xen_pvh = lib/i386/relocator_common_c.c; ieee1275 = lib/ieee1275/relocator.c; efi = lib/efi/relocator.c; mips = lib/mips/relocator_asm.S; mips = lib/mips/relocator.c; powerpc = lib/powerpc/relocator_asm.S; powerpc = lib/powerpc/relocator.c; + xen = lib/xen/relocator.c; + i386_xen = lib/i386/xen/relocator.S; + x86_64_xen = lib/x86_64/xen/relocator.S; + xen = lib/i386/relocator_common_c.c; + x86_64_efi = lib/x86_64/efi/relocator.c; extra_dist = lib/i386/relocator_common.S; extra_dist = kern/powerpc/cache_flush.S; @@ -1286,19 +1730,25 @@ module = { enable = mips; enable = powerpc; enable = x86; + enable = i386_xen_pvh; + enable = xen; }; module = { name = datetime; + common = lib/datetime.c; cmos = lib/cmos_datetime.c; efi = lib/efi/datetime.c; + uboot = lib/dummy/datetime.c; + arm_coreboot = lib/dummy/datetime.c; sparc64_ieee1275 = lib/ieee1275/datetime.c; powerpc_ieee1275 = lib/ieee1275/datetime.c; sparc64_ieee1275 = lib/ieee1275/cmos.c; powerpc_ieee1275 = lib/ieee1275/cmos.c; + xen = lib/xen/datetime.c; + i386_xen_pvh = lib/xen/datetime.c; mips_arc = lib/arc/datetime.c; - enable = noemu; }; module = { @@ -1311,6 +1761,10 @@ module = { extra_dist = lib/powerpc/setjmp.S; extra_dist = lib/ia64/setjmp.S; extra_dist = lib/ia64/longjmp.S; + extra_dist = lib/arm/setjmp.S; + extra_dist = lib/arm64/setjmp.S; + extra_dist = lib/riscv/setjmp.S; + extra_dist = lib/loongarch64/setjmp.S; }; module = { @@ -1340,9 +1794,8 @@ module = { module = { name = linux16; - i386_pc = loader/i386/pc/linux.c; - i386_pc = lib/cmdline.c; - enable = i386_pc; + common = loader/i386/pc/linux.c; + enable = x86; }; module = { @@ -1351,6 +1804,14 @@ module = { enable = i386_pc; }; + +module = { + name = truecrypt; + i386_pc = loader/i386/pc/truecrypt.c; + enable = i386_pc; +}; + + module = { name = freedos; i386_pc = loader/i386/pc/freedos.c; @@ -1370,6 +1831,7 @@ module = { common = loader/multiboot.c; common = loader/multiboot_mbi2.c; enable = x86; + enable = i386_xen_pvh; enable = mips; }; @@ -1377,34 +1839,92 @@ module = { name = multiboot; common = loader/multiboot.c; x86 = loader/i386/multiboot_mbi.c; + i386_xen_pvh = loader/i386/multiboot_mbi.c; extra_dist = loader/multiboot_elfxx.c; enable = x86; + enable = i386_xen_pvh; +}; + +module = { + name = xen_boot; + arm64 = loader/arm64/xen_boot.c; + enable = arm64; }; module = { name = linux; x86 = loader/i386/linux.c; + i386_xen_pvh = loader/i386/linux.c; + xen = loader/i386/xen.c; i386_pc = lib/i386/pc/vesa_modes_table.c; + i386_xen_pvh = lib/i386/pc/vesa_modes_table.c; mips = loader/mips/linux.c; powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; ia64_efi = loader/ia64/efi/linux.c; + arm_coreboot = loader/arm/linux.c; + arm_efi = loader/efi/linux.c; + arm_uboot = loader/arm/linux.c; + arm64 = loader/efi/linux.c; + loongarch64 = loader/efi/linux.c; + riscv32 = loader/efi/linux.c; + riscv64 = loader/efi/linux.c; + i386_efi = loader/efi/linux.c; + x86_64_efi = loader/efi/linux.c; + emu = loader/emu/linux.c; + common = loader/linux.c; common = lib/cmdline.c; - enable = noemu; +}; + +module = { + name = fdt; + efi = loader/efi/fdt.c; + common = lib/fdt.c; + enable = fdt; }; module = { name = xnu; x86 = loader/xnu_resume.c; x86 = loader/i386/xnu.c; - x86 = loader/macho32.c; - x86 = loader/macho64.c; - x86 = loader/macho.c; x86 = loader/xnu.c; - x86 = loader/lzss.c; + /* Code is pretty generic but relies on RNG which + is available only on few platforms. It's not a + big deal as xnu needs ACPI anyway and we have + RNG on all platforms with ACPI. + */ + enable = i386_multiboot; + enable = i386_coreboot; + enable = i386_pc; + enable = i386_efi; + enable = x86_64_efi; +}; + +module = { + name = random; + x86 = lib/i386/random.c; + common = lib/random.c; + + i386_multiboot = kern/i386/tsc_pmtimer.c; + i386_coreboot = kern/i386/tsc_pmtimer.c; + i386_pc = kern/i386/tsc_pmtimer.c; + + enable = i386_multiboot; + enable = i386_coreboot; + enable = i386_pc; + enable = i386_efi; + enable = x86_64_efi; +}; + +module = { + name = macho; + + common = loader/macho.c; + common = loader/macho32.c; + common = loader/macho64.c; + common = loader/lzss.c; extra_dist = loader/machoXX.c; - enable = x86; }; module = { @@ -1419,6 +1939,7 @@ module = { efi = loader/efi/chainloader.c; i386_pc = loader/i386/pc/chainloader.c; i386_coreboot = loader/i386/coreboot/chainloader.c; + i386_coreboot = lib/LzmaDec.c; enable = i386_pc; enable = i386_coreboot; enable = efi; @@ -1429,6 +1950,8 @@ module = { common = mmap/mmap.c; x86 = mmap/i386/uppermem.c; x86 = mmap/i386/mmap.c; + i386_xen_pvh = mmap/i386/uppermem.c; + i386_xen_pvh = mmap/i386/mmap.c; i386_pc = mmap/i386/pc/mmap.c; i386_pc = mmap/i386/pc/mmap_helper.S; @@ -1438,7 +1961,13 @@ module = { mips = mmap/mips/uppermem.c; enable = x86; + enable = i386_xen_pvh; enable = ia64_efi; + enable = arm_efi; + enable = arm64_efi; + enable = loongarch64_efi; + enable = riscv32_efi; + enable = riscv64_efi; enable = mips; }; @@ -1451,7 +1980,6 @@ module = { common = normal/autofs.c; common = normal/color.c; common = normal/completion.c; - common = normal/datetime.c; common = normal/menu.c; common = normal/menu_entry.c; common = normal/menu_text.c; @@ -1460,6 +1988,7 @@ module = { common = normal/term.c; common = normal/context.c; common = normal/charset.c; + common = lib/getline.c; common = script/main.c; common = script/script.c; @@ -1479,7 +2008,7 @@ module = { extra_dist = script/yylex.l; extra_dist = script/parser.y; - cflags = '$(CFLAGS_POSIX) -Wno-redundant-decls'; + cflags = '$(CFLAGS_POSIX) -Wno-redundant-decls -Wno-unused-but-set-variable'; cppflags = '$(CPPFLAGS_POSIX)'; }; @@ -1533,6 +2062,11 @@ module = { common = partmap/sunpc.c; }; +module = { + name = part_dfly; + common = partmap/dfly.c; +}; + module = { name = msdospart; common = parttool/msdospart.c; @@ -1541,6 +2075,7 @@ module = { module = { name = at_keyboard; common = term/at_keyboard.c; + common = term/ps2.c; enable = x86; }; @@ -1550,15 +2085,24 @@ module = { enable = videomodules; }; +module = { + name = gfxterm_background; + common = term/gfxterm_background.c; +}; + module = { name = serial; common = term/serial.c; x86 = term/ns8250.c; + x86 = term/ns8250-spcr.c; ieee1275 = term/ieee1275/serial.c; + mips_arc = term/arc/serial.c; efi = term/efi/serial.c; + x86 = term/pci/serial.c; enable = terminfomodule; enable = ieee1275; + enable = mips_arc; }; module = { @@ -1584,17 +2128,21 @@ module = { name = vga; common = video/i386/pc/vga.c; enable = i386_pc; - enable = i386_coreboot; - enable = i386_multiboot; }; module = { name = vga_text; common = term/i386/pc/vga_text.c; - common = term/i386/vga_common.c; enable = i386_pc; }; +module = { + name = mda_text; + common = term/i386/pc/mda_text.c; + enable = i386_pc; + enable = i386_coreboot_multiboot_qemu; +}; + module = { name = video_cirrus; x86 = video/cirrus.c; @@ -1611,6 +2159,10 @@ module = { name = functional_test; common = tests/lib/functional_test.c; common = tests/lib/test.c; + common = tests/checksums.h; + common = tests/video_checksum.c; + common = tests/fake_input.c; + common = video/capture.c; }; module = { @@ -1618,16 +2170,107 @@ module = { common = tests/example_functional_test.c; }; +module = { + name = strtoull_test; + common = tests/strtoull_test.c; +}; + +module = { + name = setjmp_test; + common = tests/setjmp_test.c; +}; + +module = { + name = signature_test; + common = tests/signature_test.c; + common = tests/signatures.h; +}; + +module = { + name = sleep_test; + common = tests/sleep_test.c; +}; + +module = { + name = xnu_uuid_test; + common = tests/xnu_uuid_test.c; +}; + +module = { + name = pbkdf2_test; + common = tests/pbkdf2_test.c; +}; + +module = { + name = legacy_password_test; + common = tests/legacy_password_test.c; + enable = i386_pc; + enable = i386_xen_pvh; + enable = i386_efi; + enable = x86_64_efi; + enable = emu; + enable = xen; +}; + +module = { + name = div; + common = lib/division.c; + enable = no_softdiv; +}; + +module = { + name = div_test; + common = tests/div_test.c; +}; + +module = { + name = mul_test; + common = tests/mul_test.c; +}; + +module = { + name = shift_test; + common = tests/shift_test.c; +}; + +module = { + name = cmp_test; + common = tests/cmp_test.c; +}; + +module = { + name = ctz_test; + common = tests/ctz_test.c; +}; + +module = { + name = bswap_test; + common = tests/bswap_test.c; +}; + +module = { + name = videotest_checksum; + common = tests/videotest_checksum.c; +}; + +module = { + name = gfxterm_menu; + common = tests/gfxterm_menu.c; +}; + +module = { + name = cmdline_cat_test; + common = tests/cmdline_cat_test.c; +}; + module = { name = bitmap; common = video/bitmap.c; - enable = videomodules; }; module = { name = bitmap_scale; common = video/bitmap_scale.c; - enable = videomodules; }; module = { @@ -1662,8 +2305,6 @@ module = { name = vbe; common = video/i386/pc/vbe.c; enable = i386_pc; - enable = i386_coreboot; - enable = i386_multiboot; }; module = { @@ -1678,10 +2319,14 @@ module = { module = { name = video; common = video/video.c; - common = video/colors.c; enable = videomodules; }; +module = { + name = video_colors; + common = video/colors.c; +}; + module = { name = ieee1275_fb; ieee1275 = video/ieee1275.c; @@ -1695,6 +2340,14 @@ module = { condition = COND_GRUB_EMU_SDL; }; +module = { + name = sdl; + emu = video/emu/sdl.c; + enable = emu; + condition = COND_GRUB_EMU_SDL2; + cflags = '$(SDL2_CFLAGS)'; +}; + module = { name = datehook; common = hook/datehook.c; @@ -1731,6 +2384,12 @@ module = { enable = ieee1275; }; +module = { + name = ubootnet; + common = net/drivers/uboot/ubootnet.c; + enable = uboot; +}; + module = { name = efinet; common = net/drivers/efi/efinet.c; @@ -1748,8 +2407,22 @@ module = { common = commands/legacycfg.c; common = lib/legacy_parse.c; emu = lib/i386/pc/vesa_modes_table.c; + i386_efi = lib/i386/pc/vesa_modes_table.c; + x86_64_efi = lib/i386/pc/vesa_modes_table.c; + xen = lib/i386/pc/vesa_modes_table.c; + enable = i386_pc; + enable = i386_xen_pvh; + enable = i386_efi; + enable = x86_64_efi; enable = emu; + enable = xen; +}; + +module = { + name = syslinuxcfg; + common = lib/syslinux_parse.c; + common = commands/syslinuxcfg.c; }; module = { @@ -1783,8 +2456,14 @@ module = { module = { name = backtrace; x86 = lib/i386/backtrace.c; + i386_xen_pvh = lib/i386/backtrace.c; + i386_xen = lib/i386/backtrace.c; + x86_64_xen = lib/i386/backtrace.c; common = lib/backtrace.c; enable = x86; + enable = i386_xen_pvh; + enable = i386_xen; + enable = x86_64_xen; }; module = { @@ -1796,7 +2475,7 @@ module = { module = { name = keylayouts; common = commands/keylayouts.c; - enable = videomodules; + enable = x86; }; module = { @@ -1815,6 +2494,12 @@ module = { condition = COND_ENABLE_CACHE_STATS; }; +module = { + name = boottime; + common = commands/boottime.c; + condition = COND_ENABLE_BOOT_TIME_STATS; +}; + module = { name = adler32; common = lib/adler32.c; @@ -1825,6 +2510,36 @@ module = { common = lib/crc64.c; }; +module = { + name = mpi; + common = lib/libgcrypt-grub/mpi/mpiutil.c; + common = lib/libgcrypt-grub/mpi/mpi-bit.c; + common = lib/libgcrypt-grub/mpi/mpi-add.c; + common = lib/libgcrypt-grub/mpi/mpi-mul.c; + common = lib/libgcrypt-grub/mpi/mpi-mod.c; + common = lib/libgcrypt-grub/mpi/mpi-gcd.c; + common = lib/libgcrypt-grub/mpi/mpi-div.c; + common = lib/libgcrypt-grub/mpi/mpi-cmp.c; + common = lib/libgcrypt-grub/mpi/mpi-inv.c; + common = lib/libgcrypt-grub/mpi/mpi-pow.c; + common = lib/libgcrypt-grub/mpi/mpi-mpow.c; + common = lib/libgcrypt-grub/mpi/mpih-lshift.c; + common = lib/libgcrypt-grub/mpi/mpih-mul.c; + common = lib/libgcrypt-grub/mpi/mpih-mul1.c; + common = lib/libgcrypt-grub/mpi/mpih-mul2.c; + common = lib/libgcrypt-grub/mpi/mpih-mul3.c; + common = lib/libgcrypt-grub/mpi/mpih-add1.c; + common = lib/libgcrypt-grub/mpi/mpih-sub1.c; + common = lib/libgcrypt-grub/mpi/mpih-div.c; + common = lib/libgcrypt-grub/mpi/mpicoder.c; + common = lib/libgcrypt-grub/mpi/mpih-rshift.c; + common = lib/libgcrypt-grub/mpi/mpi-inline.c; + common = lib/libgcrypt_wrap/mem.c; + + cflags = '$(CFLAGS_GCRY) -Wno-redundant-decls -Wno-sign-compare'; + cppflags = '$(CPPFLAGS_GCRY)'; +}; + module = { name = all_video; common = lib/fake_module.c; @@ -1840,3 +2555,117 @@ module = { enable = i386; }; +module = { + name = testspeed; + common = commands/testspeed.c; +}; + +module = { + name = tpm; + common = commands/tpm.c; + efi = commands/efi/tpm.c; + enable = efi; +}; + +module = { + name = tss2; + common = lib/tss2/buffer.c; + common = lib/tss2/tss2_mu.c; + common = lib/tss2/tpm2_cmd.c; + common = lib/tss2/tss2.c; + efi = lib/efi/tcg2.c; + emu = lib/tss2/tcg2_emu.c; + powerpc_ieee1275 = lib/ieee1275/tcg2.c; + enable = efi; + enable = emu; + enable = powerpc_ieee1275; + cppflags = '-I$(srcdir)/lib/tss2'; +}; + +module = { + name = tpm2_key_protector; + common = commands/tpm2_key_protector/args.c; + common = commands/tpm2_key_protector/module.c; + common = commands/tpm2_key_protector/tpm2key.c; + common = commands/tpm2_key_protector/tpm2key_asn1_tab.c; + /* The plaform support of tpm2_key_protector depends on the tcg2 implementation in tss2. */ + enable = efi; + enable = emu; + enable = powerpc_ieee1275; + cppflags = '-I$(srcdir)/lib/tss2 -I$(srcdir)/lib/libtasn1-grub'; +}; + +module = { + name = tr; + common = commands/tr.c; +}; + +module = { + name = progress; + common = lib/progress.c; +}; + +module = { + name = file; + common = commands/file.c; + common = commands/file32.c; + common = commands/file64.c; + extra_dist = commands/fileXX.c; + common = loader/i386/xen_file.c; + common = loader/i386/xen_file32.c; + common = loader/i386/xen_file64.c; + extra_dist = loader/i386/xen_fileXX.c; +}; +module = { + name = rdmsr; + common = commands/i386/rdmsr.c; + enable = x86; +}; +module = { + name = wrmsr; + common = commands/i386/wrmsr.c; + enable = x86; +}; + +module = { + name = memtools; + common = commands/memtools.c; + condition = COND_MM_DEBUG; +}; + +module = { + name = bli; + efi = commands/bli.c; + enable = efi; + depends = part_gpt; +}; + +module = { + name = asn1; + common = lib/libtasn1-grub/lib/decoding.c; + common = lib/libtasn1-grub/lib/coding.c; + common = lib/libtasn1-grub/lib/element.c; + common = lib/libtasn1-grub/lib/structure.c; + common = lib/libtasn1-grub/lib/parser_aux.c; + common = lib/libtasn1-grub/lib/gstr.c; + common = lib/libtasn1-grub/lib/errors.c; + common = lib/libtasn1_wrap/wrap.c; + cflags = '$(CFLAGS_POSIX) $(CFLAGS_GNULIB)'; + /* -Wno-type-limits comes from configure.ac of libtasn1 */ + cppflags = '$(CPPFLAGS_POSIX) $(CPPFLAGS_GNULIB) -I$(srcdir)/lib/libtasn1-grub -I$(srcdir)/lib/libtasn1-grub/lib -Wno-type-limits'; +}; + +module = { + name = asn1_test; + common = tests/asn1/tests/CVE-2018-1000654.c; + common = tests/asn1/tests/object-id-decoding.c; + common = tests/asn1/tests/object-id-encoding.c; + common = tests/asn1/tests/octet-string.c; + common = tests/asn1/tests/reproducers.c; + common = tests/asn1/tests/Test_overflow.c; + common = tests/asn1/tests/Test_simple.c; + common = tests/asn1/tests/Test_strings.c; + common = tests/asn1/asn1_test.c; + cflags = '-Wno-uninitialized'; + cppflags = '-I$(srcdir)/lib/libtasn1-grub -I$(srcdir)/tests/asn1/'; +}; diff --git a/grub-core/boot/decompressor/minilib.c b/grub-core/boot/decompressor/minilib.c index 94edfd561..fc46ee07b 100644 --- a/grub-core/boot/decompressor/minilib.c +++ b/grub-core/boot/decompressor/minilib.c @@ -21,7 +21,7 @@ #include void * -memset (void *s, int c, grub_size_t len) +grub_memset (void *s, int c, grub_size_t len) { grub_uint8_t *ptr; for (ptr = s; len; ptr++, len--) @@ -68,15 +68,6 @@ grub_memcmp (const void *s1, const void *s2, grub_size_t n) return 0; } -int memcmp (const void *s1, const void *s2, grub_size_t n) - __attribute__ ((alias ("grub_memcmp"))); - -void *memmove (void *dest, const void *src, grub_size_t n) - __attribute__ ((alias ("grub_memmove"))); - -void *memcpy (void *dest, const void *src, grub_size_t n) - __attribute__ ((alias ("grub_memmove"))); - void *grub_decompressor_scratch; void diff --git a/grub-core/boot/i386/pc/boot.S b/grub-core/boot/i386/pc/boot.S index 314f14016..2bd0b2d28 100644 --- a/grub-core/boot/i386/pc/boot.S +++ b/grub-core/boot/i386/pc/boot.S @@ -28,6 +28,86 @@ #define MSG(x) movw $x, %si; call LOCAL(message) #define ERR(x) movw $x, %si; jmp LOCAL(error_message) + .macro floppy +part_start: + +LOCAL(probe_values): + .byte 36, 18, 15, 9, 0 + +LOCAL(floppy_probe): + pushw %dx +/* + * Perform floppy probe. + */ +#ifdef __APPLE__ + LOCAL(probe_values_minus_one) = LOCAL(probe_values) - 1 + movw MACRO_DOLLAR(LOCAL(probe_values_minus_one)), %si +#else + movw MACRO_DOLLAR(LOCAL(probe_values)) - 1, %si +#endif + +LOCAL(probe_loop): + /* reset floppy controller INT 13h AH=0 */ + xorw %ax, %ax + int MACRO_DOLLAR(0x13) + + incw %si + movb (%si), %cl + + /* if number of sectors is 0, display error and die */ + testb %cl, %cl + jnz 1f + +/* + * Floppy disk probe failure. + */ + MSG(fd_probe_error_string) + jmp LOCAL(general_error) + +/* "Floppy" */ +fd_probe_error_string: .asciz "Floppy" + +1: + /* perform read */ + movw MACRO_DOLLAR(GRUB_BOOT_MACHINE_BUFFER_SEG), %bx + movw %bx, %es + xorw %bx, %bx + movw MACRO_DOLLAR(0x201), %ax + movb MACRO_DOLLAR(0), %ch + movb MACRO_DOLLAR(0), %dh + int MACRO_DOLLAR(0x13) + + /* if error, jump to "LOCAL(probe_loop)" */ + jc LOCAL(probe_loop) + + /* %cl is already the correct value! */ + movb MACRO_DOLLAR(1), %dh + movb MACRO_DOLLAR(79), %ch + + jmp LOCAL(final_init) + .endm + + .macro scratch + + /* scratch space */ +mode: + .byte 0 +disk_address_packet: +sectors: + .long 0 +heads: + .long 0 +cylinders: + .word 0 +sector_start: + .byte 0 +head_start: + .byte 0 +cylinder_start: + .word 0 + /* more space... */ + .endm + .file "boot.S" .text @@ -51,47 +131,66 @@ start: jmp LOCAL(after_BPB) nop /* do I care about this ??? */ +#ifdef HYBRID_BOOT + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + + nop + nop + nop + nop + nop + nop + nop + nop + + nop + nop + jmp LOCAL(after_BPB) +#else /* * This space is for the BIOS parameter block!!!! Don't change * the first jump, nor start the code anywhere but right after * this area. */ - . = _start + GRUB_BOOT_MACHINE_BPB_START - . = _start + 4 - - /* scratch space */ -mode: - .byte 0 -disk_address_packet: -sectors: - .long 0 -heads: - .long 0 -cylinders: - .word 0 -sector_start: - .byte 0 -head_start: - .byte 0 -cylinder_start: - .word 0 - /* more space... */ - - . = _start + GRUB_BOOT_MACHINE_BPB_END + .org GRUB_BOOT_MACHINE_BPB_START + .org 4 +#endif +#ifdef HYBRID_BOOT + floppy +#else + scratch +#endif + .org GRUB_BOOT_MACHINE_BPB_END /* * End of BIOS parameter block. */ -kernel_address: +LOCAL(kernel_address): .word GRUB_BOOT_MACHINE_KERNEL_ADDR - . = _start + GRUB_BOOT_MACHINE_KERNEL_SECTOR -kernel_sector: - .long 1, 0 +#ifndef HYBRID_BOOT + .org GRUB_BOOT_MACHINE_KERNEL_SECTOR +LOCAL(kernel_sector): + .long 1 +LOCAL(kernel_sector_high): + .long 0 +#endif - . = _start + GRUB_BOOT_MACHINE_BOOT_DRIVE + .org GRUB_BOOT_MACHINE_BOOT_DRIVE boot_drive: .byte 0xff /* the disk to load kernel from */ /* 0xff means use the boot drive */ @@ -109,7 +208,7 @@ LOCAL(after_BPB): * possible boot drive. If GRUB is installed into a floppy, * this does nothing (only jump). */ - . = _start + GRUB_BOOT_MACHINE_DRIVE_CHECK + .org GRUB_BOOT_MACHINE_DRIVE_CHECK boot_drive_check: jmp 3f /* grub-setup may overwrite this jump */ testb $0x80, %dl @@ -176,7 +275,7 @@ real_start: andw $1, %cx jz LOCAL(chs_mode) -lba_mode: +LOCAL(lba_mode): xorw %ax, %ax movw %ax, 4(%si) @@ -191,9 +290,9 @@ lba_mode: movw $0x0010, (%si) /* the absolute address */ - movl kernel_sector, %ebx + movl LOCAL(kernel_sector), %ebx movl %ebx, 8(%si) - movl kernel_sector + 4, %ebx + movl LOCAL(kernel_sector_high), %ebx movl %ebx, 12(%si) /* the segment of buffer address */ @@ -226,11 +325,12 @@ LOCAL(chs_mode): int $0x13 jnc LOCAL(final_init) + popw %dx /* * The call failed, so maybe use the floppy probe instead. */ - testb $GRUB_BOOT_MACHINE_BIOS_HD_FLAG, %dl - jz LOCAL(floppy_probe) + testb %dl, %dl + jnb LOCAL(floppy_probe) /* Nope, we definitely have a hard disk, and we're screwed. */ ERR(hd_probe_error_string) @@ -261,13 +361,13 @@ LOCAL(final_init): setup_sectors: /* load logical sector start (top half) */ - movl kernel_sector + 4, %eax + movl LOCAL(kernel_sector_high), %eax orl %eax, %eax jnz LOCAL(geometry_error) /* load logical sector start (bottom half) */ - movl kernel_sector, %eax + movl LOCAL(kernel_sector), %eax /* zero %edx */ xorl %edx, %edx @@ -352,7 +452,7 @@ LOCAL(copy_buffer): popa /* boot kernel */ - jmp *(kernel_address) + jmp *(LOCAL(kernel_address)) /* END OF MAIN LOOP */ @@ -410,7 +510,14 @@ LOCAL(message): * number here. */ - . = _start + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC +#ifdef HYBRID_BOOT + .org 0x1b0 +LOCAL(kernel_sector): + .long 1 +LOCAL(kernel_sector_high): + .long 0 +#endif + .org GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC nt_magic: .long 0 .word 0 @@ -419,62 +526,17 @@ nt_magic: * This is where an MBR would go if on a hard disk. The code * here isn't even referenced unless we're on a floppy. Kinda * sneaky, huh? - */ + */ - . = _start + GRUB_BOOT_MACHINE_PART_START -part_start: + .org GRUB_BOOT_MACHINE_PART_START -probe_values: - .byte 36, 18, 15, 9, 0 - -LOCAL(floppy_probe): -/* - * Perform floppy probe. - */ - - movw $probe_values - 1, %si - -LOCAL(probe_loop): - /* reset floppy controller INT 13h AH=0 */ - xorw %ax, %ax - int $0x13 - - incw %si - movb (%si), %cl - - /* if number of sectors is 0, display error and die */ - cmpb $0, %cl - jne 1f - -/* - * Floppy disk probe failure. - */ - MSG(fd_probe_error_string) - jmp LOCAL(general_error) - -/* "Floppy" */ -fd_probe_error_string: .asciz "Floppy" - -1: - /* perform read */ - movw $GRUB_BOOT_MACHINE_BUFFER_SEG, %bx - movw %bx, %es - xorw %bx, %bx - movw $0x201, %ax - movb $0, %ch - movb $0, %dh - int $0x13 - - /* if error, jump to "LOCAL(probe_loop)" */ - jc LOCAL(probe_loop) - - /* %cl is already the correct value! */ - movb $1, %dh - movb $79, %ch - - jmp LOCAL(final_init) - - . = _start + GRUB_BOOT_MACHINE_PART_END +#ifndef HYBRID_BOOT + floppy +#else + scratch +#endif + .org GRUB_BOOT_MACHINE_PART_END + /* the last 2 bytes in the sector 0 contain the signature */ .word GRUB_BOOT_MACHINE_SIGNATURE diff --git a/grub-core/boot/i386/pc/cdboot.S b/grub-core/boot/i386/pc/cdboot.S index d939835a9..de4f80929 100644 --- a/grub-core/boot/i386/pc/cdboot.S +++ b/grub-core/boot/i386/pc/cdboot.S @@ -43,7 +43,7 @@ _start: LOCAL(next): jmp 1f - . = start + 8 + .org 8 bi_pvd: .long 0 /* LBA of primary volume descriptor. */ @@ -93,11 +93,12 @@ LOCAL(read_cdrom): pushw $CDBLK_LENG /* Block number. */ + incl %esi pushl %eax pushl %esi /* Buffer address. */ - pushw $((DATA_ADDR - 0x400)>> 4) + pushw $((DATA_ADDR - 0x200)>> 4) pushl %eax pushw $0x10 @@ -167,6 +168,6 @@ err_noboot_msg: err_cdfail_msg: .ascii "cdrom read fails\0" - . = start + 0x1FF + .org 0x7FF .byte 0 diff --git a/grub-core/boot/i386/pc/diskboot.S b/grub-core/boot/i386/pc/diskboot.S index d030a14c9..c1addc0df 100644 --- a/grub-core/boot/i386/pc/diskboot.S +++ b/grub-core/boot/i386/pc/diskboot.S @@ -37,8 +37,8 @@ start: _start: /* - * _start is loaded at 0x2000 and is jumped to with - * CS:IP 0:0x2000 in kernel. + * _start is loaded at 0x8000 and is jumped to with + * CS:IP 0:0x8000 in kernel. */ /* @@ -362,7 +362,7 @@ LOCAL(message): .word 0 .word 0 - . = _start + 0x200 - GRUB_BOOT_MACHINE_LIST_SIZE + .org 0x200 - GRUB_BOOT_MACHINE_LIST_SIZE LOCAL(firstlist): /* this label has to be before the first list entry!!! */ /* fill the first data listing with the default */ blocklist_default_start: diff --git a/grub-core/boot/i386/pc/lnxboot.S b/grub-core/boot/i386/pc/lnxboot.S index e4bc8b425..2dda0e06b 100644 --- a/grub-core/boot/i386/pc/lnxboot.S +++ b/grub-core/boot/i386/pc/lnxboot.S @@ -41,7 +41,7 @@ data_start: xorl %ebp, %ebp jmp LOCAL(linux_next) - . = data_start + 0x1F1 + .org 0x1F1 setup_sects: .byte CODE_SECTORS @@ -207,6 +207,10 @@ real_code_2: 2: call LOCAL(move_memory) + movb %dh, %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 2) + movb (reg_edx + 2 - start), %dh + movb %dh, %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + 1) + movb $0xFF, %dh ljmp $(DATA_ADDR >> 4), $0 @@ -288,4 +292,4 @@ LOCAL(fail): err_int15_msg: .ascii "move memory fails\0" - . = _start + CODE_SECTORS * 512 + .org (CODE_SECTORS * 512 + 512) diff --git a/grub-core/boot/i386/pc/pxeboot.S b/grub-core/boot/i386/pc/pxeboot.S index 446bfc781..b695b24d0 100644 --- a/grub-core/boot/i386/pc/pxeboot.S +++ b/grub-core/boot/i386/pc/pxeboot.S @@ -38,5 +38,5 @@ start: /* This region is a junk. Do you say that this is wasteful? But I like that the memory layout of the body is consistent among different kernels rather than scamping just for 1.5KB. */ - . = _start + 0x8200 - 0x7C00 - 0x200 - 1 + .org 0x8200 - 0x7C00 - 0x200 - 1 .byte 0 diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S index 81c0bc457..28974821e 100644 --- a/grub-core/boot/i386/pc/startup_raw.S +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -50,23 +50,23 @@ LOCAL (base): * This is a special data area. */ - . = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE + .org GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE LOCAL(compressed_size): .long 0 - . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE + .org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE LOCAL(uncompressed_size): .long 0 - . = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY + .org GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY reed_solomon_redundancy: .long 0 - . = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH + .org GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH .short (LOCAL(reed_solomon_part) - _start) /* * This is the area for all of the special variables. */ - . = _start + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE + .org GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE LOCAL(boot_dev): .byte 0xFF, 0xFF, 0xFF LOCAL(boot_drive): @@ -89,18 +89,17 @@ LOCAL (codestart): sti /* we're safe again */ /* save the boot drive */ - ADDR32 movb %dl, LOCAL(boot_drive) + movb %dl, LOCAL(boot_drive) /* reset disk system (%ah = 0) */ int $0x13 /* transition to protected mode */ - DATA32 call real_to_prot + calll real_to_prot /* The ".code32" directive takes GAS out of 16-bit mode. */ .code32 - incl %eax cld call grub_gate_a20 @@ -119,12 +118,21 @@ LOCAL (codestart): #include "../../../kern/i386/realmode.S" -#include +/* + * + * This is a workaround for clang adding a section containing only .addrsig + * Since clang itself is unable to assemble this pseudo-opcode, just replace + * it with .text + * + */ +#define addrsig text +#include +#undef addrsig .text /* - * grub_gate_a20(int on) + * grub_gate_a20(void) * * Gate address-line 20 for high memory. * @@ -134,12 +142,10 @@ LOCAL (codestart): */ grub_gate_a20: - movl %eax, %edx - gate_a20_test_current_state: /* first of all, test if already in a good state */ call gate_a20_check_state - cmpb %al, %dl + testb %al, %al jnz gate_a20_try_bios ret @@ -149,18 +155,15 @@ gate_a20_try_bios: call prot_to_real .code16 - movw $0x2400, %ax - testb %dl, %dl - jz 1f - incw %ax -1: int $0x15 + movw $0x2401, %ax + int $0x15 - DATA32 call real_to_prot + calll real_to_prot .code32 popl %ebp call gate_a20_check_state - cmpb %al, %dl + testb %al, %al jnz gate_a20_try_system_control_port_a ret @@ -172,20 +175,13 @@ gate_a20_try_system_control_port_a: /* fourth, try the system control port A */ inb $0x92 andb $(~0x03), %al - testb %dl, %dl - jz 6f orb $0x02, %al -6: outb $0x92 + outb $0x92 - /* When turning off Gate A20, do not check the state strictly, - because a failure is not fatal usually, and Gate A20 is always - on some modern machines. */ - testb %dl, %dl - jz 7f call gate_a20_check_state - cmpb %al, %dl + testb %al, %al jnz gate_a20_try_keyboard_controller -7: ret + ret gate_a20_flush_keyboard_buffer: inb $0x64 @@ -211,11 +207,8 @@ gate_a20_try_keyboard_controller: andb $0x02, %al jnz 4b - movb $0xdd, %al - testb %dl, %dl - jz 5f - orb $0x02, %al -5: outb $0x60 + movb $0xdf, %al + outb $0x60 call gate_a20_flush_keyboard_buffer /* output a dummy command (USB keyboard hack) */ @@ -224,7 +217,7 @@ gate_a20_try_keyboard_controller: call gate_a20_flush_keyboard_buffer call gate_a20_check_state - cmpb %al, %dl + testb %al, %al /* everything failed, so restart from the beginning */ jnz gate_a20_try_bios ret @@ -234,7 +227,7 @@ gate_a20_check_state: movl $100, %ecx 1: call 3f - cmpb %al, %dl + testb %al, %al jz 2f loop 1b 2: @@ -263,9 +256,8 @@ gate_a20_check_state: pushl %ebx addl $0x100000, %ebx movb (%ebx), %ch - /* this result is 1 if A20 is on or 0 if it is off */ + /* this result is 0 if A20 is on or 1 if it is off */ subb %ch, %al - xorb $1, %al /* restore the original */ popl %ebx movb %cl, (%ebx) diff --git a/grub-core/boot/i386/qemu/boot.S b/grub-core/boot/i386/qemu/boot.S index 97aeab9e6..8c3a1db71 100644 --- a/grub-core/boot/i386/qemu/boot.S +++ b/grub-core/boot/i386/qemu/boot.S @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -32,7 +31,7 @@ _start: jmp 1f - . = _start + GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR + .org GRUB_BOOT_I386_QEMU_CORE_ENTRY_ADDR VARIABLE(grub_core_entry_addr) .long 0 1: @@ -49,10 +48,17 @@ VARIABLE(grub_core_entry_addr) /* Transition to protected mode. We use pushl to force generation of a flat return address. */ pushl $1f - DATA32 jmp real_to_prot + jmp real_to_prot .code32 1: - movl grub_core_entry_addr, %edx + /* Ensure A20 is enabled. We're in qemu, so control port A works + and there is no need to wait since there is no real logic, it's + all emulated. */ + inb $0x92 + andb $(~0x03), %al + orb $0x02, %al + outb $0x92 + movl EXT_C(grub_core_entry_addr), %edx jmp *%edx #include "../../../kern/i386/realmode.S" @@ -60,9 +66,9 @@ VARIABLE(grub_core_entry_addr) /* Intel, in its infinite wisdom, decided to put the i8086 entry point *right here* and this is why we need this kludge. */ - . = GRUB_BOOT_MACHINE_SIZE - 16 + .org GRUB_BOOT_MACHINE_SIZE - 16 .code16 jmp _start - . = GRUB_BOOT_MACHINE_SIZE + .org GRUB_BOOT_MACHINE_SIZE diff --git a/grub-core/boot/mips/loongson/fwstart.S b/grub-core/boot/mips/loongson/fwstart.S index ec57be6a1..28c634614 100644 --- a/grub-core/boot/mips/loongson/fwstart.S +++ b/grub-core/boot/mips/loongson/fwstart.S @@ -63,18 +63,18 @@ __start: This way we don't need to sacrifice a register for it. */ retry_cs5536: /* We have only one bus (0). Function is 0. */ - lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) - lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE) + lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR_2F) + lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE_2F) lui $t3, %hi(GRUB_CS5536_PCIID) addiu $t3, $t3, %lo(GRUB_CS5536_PCIID) ori $t4, $zero, 1 1: - andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1) + andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES_2F) - 1) /* In case of failure try again. CS5536 may be slow to come up. */ beql $t4, $zero, retry_cs5536 nop - sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) - lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1) + sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR_2F) ($t0) + lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE_2F) + GRUB_PCI_REG_PCI_ID) ($t1) bnel $t2, $t3, 1b sll $t4, $t4, 1 @@ -86,9 +86,9 @@ retry_cs5536: move $a0, $t4 #endif - lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE) + lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE_2F) li $t1, GRUB_CS5536_MSR_MAILBOX_CONFIG_ENABLED - sw $t1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_CONFIG) ($t0) + sw $t1, (%lo(GRUB_MACHINE_PCI_CONFSPACE_2F) + GRUB_CS5536_MSR_MAILBOX_CONFIG) ($t0) /* Set GPIO LBAR. */ lui $a0, %hi(GRUB_CS5536_MSR_GPIO_BAR) @@ -121,21 +121,21 @@ retry_cs5536: bal message addiu $a0, $a0, %lo(smbus_enabled) - lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS) + lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_SMBUS) /* Disable SMB. */ - sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0) + sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0) /* Disable interrupts. */ - sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1) ($t0) + sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1) ($t0) /* Set as master. */ - sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_ADDR) ($t0) + sb $zero, %lo(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_ADDR) ($t0) /* Launch SMBus controller at slowest speed possible. */ ori $t1, $zero, 0xff - sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0) - sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0) + sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL3) ($t0) + sb $t1, %lo(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL2) ($t0) /* Yeeloong and Fuloong2f have only one memory slot. */ /* Output first byte on serial for debugging. */ @@ -162,7 +162,7 @@ retry_cs5536: b continue - . = start + GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START + .org GRUB_CPU_LOONGSON_FLASH_TLB_REFILL - GRUB_CPU_LOONGSON_FLASH_START tlb_refill: mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC mfc0 $s2, GRUB_CPU_LOONGSON_COP0_BADVADDR @@ -196,13 +196,13 @@ tlb_refill: b fatal addiu $a0, $a0, %lo(unhandled_tlb_refill) - . = start + GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START + .org GRUB_CPU_LOONGSON_FLASH_CACHE_ERROR - GRUB_CPU_LOONGSON_FLASH_START cache_error: lui $a0, %hi(unhandled_cache_error) b fatal addiu $a0, $a0, %lo(unhandled_cache_error) - . = start + GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START + .org GRUB_CPU_LOONGSON_FLASH_OTHER_EXCEPTION - GRUB_CPU_LOONGSON_FLASH_START other_exception: mfc0 $s0, GRUB_CPU_LOONGSON_COP0_CAUSE mfc0 $s1, GRUB_CPU_LOONGSON_COP0_EPC @@ -237,8 +237,8 @@ other_exception: addiu $a0, $a0, %lo(unhandled_exception) gpio_init: - lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO) - addiu $t0, $t0, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_CS5536_LBAR_GPIO) + lui $t0, %hi(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_GPIO) + addiu $t0, $t0, %lo(GRUB_MACHINE_PCI_IO_BASE_2F + GRUB_CS5536_LBAR_GPIO) lui $t1, %hi (gpio_dump) addiu $t1, $t1, %lo (gpio_dump) @@ -344,7 +344,7 @@ printhex: nop srl $t1, $a0, 28 addiu $t1, $t1, -10 - blt $t1, $zero, 2f + bltz $t1, 2f sll $a0, $a0, 4 addiu $t1, $t1, 'A'-10-'0' 2: addiu $t1, $t1, '0'+10 @@ -368,18 +368,18 @@ self: Clobbered: $t0 */ wrmsr: - lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE) - sw $a0, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_ADDR) ($t0) - sw $a1, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA0) ($t0) + lui $t0, %hi(GRUB_MACHINE_PCI_CONFSPACE_2F) + sw $a0, (%lo(GRUB_MACHINE_PCI_CONFSPACE_2F) + GRUB_CS5536_MSR_MAILBOX_ADDR) ($t0) + sw $a1, (%lo(GRUB_MACHINE_PCI_CONFSPACE_2F) + GRUB_CS5536_MSR_MAILBOX_DATA0) ($t0) jr $ra - sw $a2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_CS5536_MSR_MAILBOX_DATA1) ($t0) + sw $a2, (%lo(GRUB_MACHINE_PCI_CONFSPACE_2F) + GRUB_CS5536_MSR_MAILBOX_DATA1) ($t0) /* Wait for SMBus data or empty transmitter. */ /* In: $a0 = exception handler. Out: none. Clobbered: $t0, $t1 */ smbus_wait: 1: - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE) - lb $t0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE) ($t0) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE_2F) + lb $t0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_STATUS + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) andi $t1, $t0, GRUB_CS5536_SMB_REG_STATUS_SDAST bne $t1, $zero, return nop @@ -398,55 +398,55 @@ read_spd: move $t2, $a0 move $t3, $ra lui $a0, %hi(read_spd_fail) - addiu $a0, $a0, %hi(read_spd_fail) + addiu $a0, $a0, %lo(read_spd_fail) /* Send START. */ - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) - lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) + lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START bal smbus_wait - sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) /* Send device address. */ - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) sll $t1, $a1, 1 bal smbus_wait - sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) /* Send ACK. */ - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) - lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) + lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_ACK - sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) /* Send byte address. */ - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) bal smbus_wait - sb $t2, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) + sb $t2, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) /* Send START. */ - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) - lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) + lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_START bal smbus_wait - sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) /* Send device address. */ - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) sll $t1, $a1, 1 ori $t1, $t1, 1 bal smbus_wait - sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) /* Send STOP. */ - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) - lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) + lb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) ori $t1, $t1, GRUB_CS5536_SMB_REG_CTRL1_STOP bal smbus_wait - sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE) ($t0) + sb $t1, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_CTRL1 + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) - lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) - lb $v0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE) ($t0) + lui $t0, %hi(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) + lb $v0, %lo(GRUB_CS5536_LBAR_SMBUS + GRUB_CS5536_SMB_REG_DATA + GRUB_MACHINE_PCI_IO_BASE_2F) ($t0) jr $t3 andi $v0, $v0, 0xff read_spd_fail: @@ -547,7 +547,7 @@ gpio_dump: #endif gpio_dump_end: - .p2align + .p2align 3 write_dumpreg: ld $t2, 0($t6) @@ -754,140 +754,3 @@ continue: #endif cached_continue: -#ifndef FULOONG2F - /* We have to init video early enough or watchdog will reboot us. */ - - /* Setup PCI controller. */ - - lui $t0, %hi (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) - lui $t1, %hi(0x8000000c) - addiu $t1, $t1, %lo(0x8000000c) - - sw $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) ($t0) - li $t1, 0xffffffff - sw $t1, %lo (GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) ($t0) - - li $t0, GRUB_MACHINE_PCI_CONTROLLER_HEADER - li $t1, (GRUB_PCI_COMMAND_PARITY_ERROR | GRUB_PCI_COMMAND_BUS_MASTER \ - | GRUB_PCI_COMMAND_MEM_ENABLED) - sh $t0, GRUB_PCI_REG_COMMAND ($t1) - li $t1, ((1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) \ - | GRUB_PCI_STATUS_FAST_B2B_CAPABLE \ - | GRUB_PCI_STATUS_66MHZ_CAPABLE \ - | GRUB_PCI_STATUS_CAPABILITIES) - sh $t0, GRUB_PCI_REG_STATUS ($t1) - li $t0, 0xff - sw $t0, GRUB_PCI_REG_CACHELINE ($t1) - lui $t1, %hi(0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 \ - | GRUB_PCI_ADDR_MEM_PREFETCH) - addiu $t1, $t1, %lo(0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 \ - | GRUB_PCI_ADDR_MEM_PREFETCH) - sw $t0, GRUB_PCI_REG_ADDRESS_REG0 ($t1) - sw $zero, GRUB_PCI_REG_ADDRESS_REG1 ($t1) - - /* Find video. */ - /* $t4 chooses device in priority encoding. */ - /* Resulting value is kept in GRUB_MACHINE_PCI_CONF_CTRL_REG. - This way we don't need to sacrifice a register for it. */ -retry_sm712: - /* We have only one bus (0). Function is 0. */ - lui $t0, %hi(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) - lui $t1, %hi(GRUB_MACHINE_PCI_CONFSPACE) - lui $t3, %hi(GRUB_SM712_PCIID) - addiu $t3, $t3, %lo(GRUB_SM712_PCIID) - ori $t4, $zero, 1 -1: - andi $t4, $t4, ((1 << GRUB_PCI_NUM_DEVICES) - 1) - /* In case of failure try again. SM712 may be slow to come up. */ - beql $t4, $zero, retry_sm712 - nop - sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) - lw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_PCI_ID) ($t1) - bnel $t2, $t3, 1b - sll $t4, $t4, 1 - - /* FIXME: choose address dynamically if needed. */ -#define SM712_MAP 0x04000000 - - lui $t2, %hi(SM712_MAP) - sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) - sw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_ADDRESS_REG0) ($t1) - - /* Set latency. */ - li $t2, 0x8 - sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) - sw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_CACHELINE) ($t1) - - /* Enable address spaces. */ - li $t2, 0x7 - sw $t4, %lo(GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) ($t0) - sw $t2, (%lo(GRUB_MACHINE_PCI_CONFSPACE) + GRUB_PCI_REG_COMMAND) ($t1) - - lui $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX) - li $t2, 0x18 - sb $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX)($t3) - - lui $t3, %hi(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA) - li $t2, 0x11 - sb $t2, %lo(GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA)($t3) - - li $t2, ((((SM712_MAP & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK) \ - >> GRUB_MACHINE_PCI_WIN_SHIFT) \ - & GRUB_MACHINE_PCI_WIN_MASK)) - lui $t3, %hi(0xbfe00110) - addiu $t3, $t3, %lo(0xbfe00110) - sw $t2, 0 ($t3) - li $t2, (GRUB_MACHINE_PCI_WIN1_ADDR \ - | (SM712_MAP & GRUB_MACHINE_PCI_WIN_OFFSET_MASK)) - - lui $t3, %hi(GRUB_SM712_REG_BASE) - addiu $t3, $t3, %lo(GRUB_SM712_REG_BASE) - addu $t2, $t2, $t3 - lui $t0, %hi(init_table - 0x20000000) - addiu $t0, $t0, %lo(init_table - 0x20000000) - lui $t1, %hi(init_table_end - 0x20000000) - addiu $t1, $t1, %lo(init_table_end - 0x20000000) - li $t5, 0x80 - addiu $t6, $t2, 0x3c0 - -table_cont: - lb $t3, 0($t0) - andi $t5, $t3, 0x80 - andi $t3, $t3, 0x7f - addu $t3, $t3, $t6 - lb $t4, 1($t0) - - bne $zero, $t5, 1f - addiu $t0, $t0, 2 - b 2f - sb $t4, 0($t3) -1: - lb $t4, 0($t3) -2: - bne $t0, $t1, table_cont - nop - - lui $t3, %hi(0x40c000 - GRUB_SM712_REG_BASE) - addiu $t3, $t3, %lo(0x40c000 - GRUB_SM712_REG_BASE) - addu $t1, $t2, $t3 - sw $zero, 0xc ($t1) - sw $zero, 0x40 ($t1) - li $t3, 0x20000 - sw $t3, 0x0 ($t1) - lui $t3, %hi(0x1020100) - addiu $t3, $t3, %lo(0x1020100) - sw $t3, 0x10 ($t1) - - li $t4, 0x16 - sb $t4, GRUB_VGA_IO_SR_INDEX($t2) - - lb $t4, GRUB_VGA_IO_SR_DATA($t2) - - b init_end - nop -init_table: -#include "sm712_start.S" -init_table_end: - .align 4 -init_end: -#endif diff --git a/grub-core/boot/mips/startup_raw.S b/grub-core/boot/mips/startup_raw.S index bbbc1dbec..6a81b3733 100644 --- a/grub-core/boot/mips/startup_raw.S +++ b/grub-core/boot/mips/startup_raw.S @@ -22,11 +22,13 @@ #include #include #include +#include #define BASE_ADDR 8 .extern __bss_start .extern _end +.extern _edata .globl __start, _start, start .set noreorder @@ -38,13 +40,13 @@ start: bal codestart nop base: - . = _start + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE + .org GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE compressed_size: .long 0 - . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE + .org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_SIZE uncompressed_size: .long 0 - . = _start + GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR + .org GRUB_DECOMPRESSOR_MACHINE_UNCOMPRESSED_ADDR uncompressed_addr: .long 0 codestart: @@ -117,50 +119,50 @@ parsestr: move $v0, $zero move $t3, $t1 3: - lb $t4, 0($t2) - lb $t5, 0($t3) + lb GRUB_ASM_T4, 0($t2) + lb GRUB_ASM_T5, 0($t3) addiu $t2, $t2, 1 addiu $t3, $t3, 1 - beq $t5, $zero, 1f + beq GRUB_ASM_T5, $zero, 1f nop - beq $t5, $t4, 3b + beq GRUB_ASM_T5, GRUB_ASM_T4, 3b nop - bne $t4, $zero, 1f + bne GRUB_ASM_T4, $zero, 1f nop addiu $t3, $t3, 0xffff digcont: - lb $t5, 0($t3) + lb GRUB_ASM_T5, 0($t3) /* Substract '0' from digit. */ - addiu $t5, $t5, 0xffd0 - bltz $t5, 1f + addiu GRUB_ASM_T5, GRUB_ASM_T5, 0xffd0 + bltz GRUB_ASM_T5, 1f nop - addiu $t4, $t5, 0xfff7 - bgtz $t4, 1f + addiu GRUB_ASM_T4, GRUB_ASM_T5, 0xfff7 + bgtz GRUB_ASM_T4, 1f nop /* Multiply $v0 by 10 with bitshifts. */ sll $v0, $v0, 1 - sll $t4, $v0, 2 - addu $v0, $v0, $t4 - addu $v0, $v0, $t5 + sll GRUB_ASM_T4, $v0, 2 + addu $v0, $v0, GRUB_ASM_T4 + addu $v0, $v0, GRUB_ASM_T5 addiu $t3, $t3, 1 b digcont nop 1: jr $ra nop -busclockstr: .asciiz "busclock=" -cpuclockstr: .asciiz "cpuclock=" -memsizestr: .asciiz "memsize=" -highmemsizestr: .asciiz "highmemsize=" -machtype_yeeloong_str1: .asciiz "machtype=8.9" -machtype_yeeloong_str2: .asciiz "machtype=lemote-yeeloong-" -machtype_fuloong2f_str: .asciiz "machtype=lemote-fuloong-2f" -machtype_fuloong2e_str: .asciiz "machtype=lemote-fuloong-2e" -pmon_yeeloong_str: .asciiz "PMON_VER=LM8" -pmon_fuloong2f_str: .asciiz "PMON_VER=LM6" -pmon_yeeloong_verstr: .asciiz "Version=LM8" -pmon_fuloong2f_verstr: .asciiz "Version=LM6" +busclockstr: .asciz "busclock=" +cpuclockstr: .asciz "cpuclock=" +memsizestr: .asciz "memsize=" +highmemsizestr: .asciz "highmemsize=" +machtype_yeeloong_str1: .asciz "machtype=8.9" +machtype_yeeloong_str2: .asciz "machtype=lemote-yeeloong-" +machtype_fuloong2f_str: .asciz "machtype=lemote-fuloong-2f" +machtype_fuloong2e_str: .asciz "machtype=lemote-fuloong-2e" +pmon_yeeloong_str: .asciz "PMON_VER=LM8" +pmon_fuloong2f_str: .asciz "PMON_VER=LM6" +pmon_yeeloong_verstr: .asciz "Version=LM8" +pmon_fuloong2f_verstr: .asciz "Version=LM6" .p2align 2 argdone: @@ -181,10 +183,10 @@ argdone: b argdone addiu $a1, $a1, 4 do_check: - lb $t4, 0($t7) - beq $t4, $zero, 1f + lb GRUB_ASM_T4, 0($t7) + beq GRUB_ASM_T4, $zero, 1f lb $t3, 0($t6) - bne $t3, $t4, 2f + bne $t3, GRUB_ASM_T4, 2f addiu $t6, $t6, 1 b do_check addiu $t7, $t7, 1 @@ -196,6 +198,21 @@ do_check: argfw: not $s7, $a2 cmdlinedone: +#endif +#ifdef GRUB_MACHINE_ARC + lui $t0, %hi(_start - 256) + addiu $t0, $t0, %lo(_start - 256) + addiu $t3, $t0, 255 + lw $t1, 0($a1) +1: + bne $t0, $t3, 2f + lb $t2, 0($t1) + move $t2, $zero +2: + sb $t2, 0($t0) + addiu $t0, $t0, 1 + bnez $t2, 1b + addiu $t1, $t1, 1 #endif /* Copy the decompressor. */ lui $t1, %hi(base) @@ -206,8 +223,8 @@ cmdlinedone: 1: beq $t1, $t3, 2f - lb $t4, 0($t2) - sb $t4, 0($t1) + lb GRUB_ASM_T4, 0($t2) + sb GRUB_ASM_T4, 0($t1) addiu $t1, $t1, 1 b 1b addiu $t2, $t2, 1 @@ -233,8 +250,9 @@ cmdlinedone: #include "../../kern/mips/cache_flush.S" /* Decompress the payload. */ - lui $a0, %hi(__bss_start) - addiu $a0, $a0, %lo(__bss_start) + lui $a0, %hi(_edata) + addiu $a0, $a0, %lo(_edata) + lui $t0, %hi(base) addiu $t0, $t0, %lo(base) subu $a0, $a0, $t0 @@ -250,13 +268,18 @@ cmdlinedone: */ move $s6, $a3 - lui $t0, %hi(EXT_C(grub_decompress_core)) - addiu $t0, $t0, %lo(EXT_C(grub_decompress_core)) + lui $t9, %hi(EXT_C(grub_decompress_core)) + addiu $t9, $t9, %lo(EXT_C(grub_decompress_core)) +#ifdef GRUB_MACHINE_ARC + lui $sp, %hi(_start - 512) + jalr $t9 + addiu $sp, $sp, %lo(_start - 512) +#else lui $sp, %hi(_start - 256) - jalr $t0 + jalr $t9 addiu $sp, $sp, %lo(_start - 256) - +#endif move $a0, $s1 move $a1, $s6 @@ -267,3 +290,11 @@ cmdlinedone: jr $t1 nop + /* Ensure that .data section is created. In code we suppose that _edata + is first location not in decompressor image. Strictly speaking it's + _edata only when .data is present and _etext otherwise. But checking + for .data presence would cost more in code than it is to ensure that + .data is created. + */ + .data + .long 0 diff --git a/grub-core/boot/powerpc/bootinfo.txt.in b/grub-core/boot/powerpc/bootinfo.txt.in new file mode 100644 index 000000000..bc831daa9 --- /dev/null +++ b/grub-core/boot/powerpc/bootinfo.txt.in @@ -0,0 +1,73 @@ + +@PACKAGE@ @VERSION@ +@PACKAGE@ @VERSION@ +boot &device;:\boot\grub\powerpc.elf + + +FF FF FF FF FF FF FF FF FF FF 92 6D 6D 6D 6D 6D 6D 6D 6D 6D DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 92 6D 92 92 92 DB FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF DB 6D 92 DB FF FF FF FF FF DB B6 FF FF 92 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 92 DB FF FF FF FF FF B6 6D 92 DB FF FF FF FF FF FF FF +FF FF FF FF FF FF 49 92 FF FF B6 B6 24 00 24 00 00 00 00 49 6D DB 6D 92 DB B6 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 6D DB 92 6D 24 49 92 6D 6D FF FF FF 92 6D FF FF FF FF FF FF +FF FF FF FF B6 49 DB FF FF 24 00 00 00 92 92 B6 FF DB DB FF DB B6 FF DB 92 49 DB FF FF FF FF FF FF FF FF FF FF FF FF FF DB 49 6D B6 FF 6D B6 6D 6D 92 24 24 00 00 24 6D FF FF 49 DB FF FF FF FF +FF FF FF B6 49 FF DB 49 24 00 49 6D B6 FF B6 92 6D 6D 6D 92 DB DB DB B6 6D 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D DB FF FF FF FF DB B6 B6 B6 FF DB 24 00 00 92 B6 FF 49 FF FF FF FF +FF FF DB 49 FF FF 49 00 00 24 FF FF 6D 49 92 DB FF FF FF DB 92 92 92 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 92 92 6D 6D B6 DB DB B6 6D 6D FF FF 24 00 00 DB FF 49 FF FF FF +FF FF 49 FF FF 49 00 00 6D DB DB 49 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 B6 24 00 24 DB DB 6D FF FF +FF B6 92 FF B6 00 00 24 FF DB 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 FF 00 00 49 FF 92 B6 FF +FF 6D FF FF 92 00 00 49 FF 6D FF FF FF FF FF FF FF FF FF FF FF FF FF B6 92 92 6D 6D 6D 6D DB FF FF FF FF FF FF B6 92 92 92 92 92 FF FF FF FF FF FF FF FF FF FF FF FF 6D FF 24 00 24 FF FF 6D FF +DB 92 FF DB 00 00 49 FF 92 DB FF FF FF FF FF FF FF FF FF FF FF DB 6D B6 FF FF FF FF FF FF 92 6D FF FF FF FF 6D B6 FF FF FF FF FF B6 B6 FF FF FF FF FF FF FF FF FF FF FF 92 DB 00 00 92 FF 92 DB +92 FF FF B6 00 00 6D FF 6D FF FF FF FF FF FF FF FF FF FF FF DB 6D FF FF FF 92 49 49 49 92 FF FF 49 DB DB 24 DB FF B6 49 49 92 FF FF DB 92 FF FF FF FF FF FF FF FF FF FF 92 FF 00 00 6D FF DB 92 +6D FF FF FF 00 00 49 92 DB FF FF FF FF FF FF FF FF FF FF DB 6D FF FF 6D 00 00 00 00 00 00 00 B6 FF 49 00 24 24 49 24 00 00 00 00 6D FF DB 92 FF FF FF FF FF FF FF FF FF DB B6 00 00 92 FF FF 6D +6D FF FF 24 00 00 DB 6D FF FF FF FF FF FF FF FF FF FF DB 6D FF DB 00 00 00 00 00 00 00 00 00 00 B6 FF DB B6 49 92 24 24 00 00 00 00 24 FF DB 92 FF FF FF FF FF FF FF FF FF 92 6D 00 00 DB FF 6D +6D FF FF 24 00 00 FF 6D FF FF FF FF FF FF FF FF FF FF 49 FF B6 00 00 00 00 00 00 00 00 00 00 00 00 92 FF FF 92 DB DB 24 24 00 00 00 00 24 FF 92 DB FF FF FF FF FF FF FF FF 92 92 00 00 FF FF 6D +6D FF FF B6 00 00 92 6D FF FF FF FF FF FF FF FF FF 49 FF DB 00 00 00 00 00 00 00 00 00 00 00 00 00 92 FF FF B6 B6 FF 92 24 00 00 00 00 00 49 FF 6D FF FF FF FF FF FF FF FF 92 24 00 49 FF FF 6D +6D FF FF 00 00 00 DB 6D FF FF FF FF FF FF FF FF 6D DB DB 00 00 00 00 00 00 00 00 00 00 00 00 00 00 92 FF FF DB B6 FF B6 49 00 00 00 00 00 00 6D FF 6D FF FF FF FF FF FF FF 92 92 00 00 DB FF 6D +6D FF FF DB 00 00 B6 6D FF FF FF FF FF FF FF 6D B6 FF 24 00 00 00 00 00 00 00 00 00 00 00 24 B6 DB 6D FF FF FF FF FF 6D 49 24 00 00 00 00 00 00 B6 DB B6 FF FF FF FF FF B6 DB 24 00 92 FF FF 6D +6D FF FF 6D 00 00 24 DB 92 FF FF FF FF FF 92 92 FF 49 00 00 00 00 00 49 B6 FF FF DB B6 DB FF FF FF B6 92 FF FF DB 92 FF FF FF 49 6D 92 24 00 00 00 DB B6 DB FF FF FF FF 6D FF 00 00 00 DB FF 6D +6D FF FF 92 24 00 49 FF 6D B6 FF FF FF 6D 92 FF 49 00 00 49 DB FF FF FF FF FF FF B6 FF FF FF FF FF FF B6 6D 92 92 FF FF FF FF 6D FF FF FF DB 24 00 24 FF 92 B6 FF FF 92 B6 FF 00 00 B6 FF FF 6D +92 FF FF FF 00 00 24 92 FF 92 6D 92 49 B6 DB 24 00 24 DB FF FF FF FF FF DB 92 24 00 FF FF FF FF 6D 6D FF FF FF 6D 6D FF FF B6 DB 6D FF FF FF FF 00 00 24 DB B6 6D 6D B6 DB 00 00 00 6D FF FF 6D +DB 92 FF DB 49 00 00 00 B6 FF FF DB FF 6D 00 00 6D FF FF FF FF FF FF FF 24 92 00 49 FF FF FF FF FF 6D B6 FF FF 6D 6D FF 6D 00 DB DB 92 FF FF FF DB 00 00 00 6D FF FF DB 6D 00 00 24 FF FF 92 DB +FF 49 FF FF 6D 00 00 00 24 49 B6 FF 24 00 00 6D FF FF FF FF FF FF FF 49 92 B6 00 DB FF FF DB DB FF FF B6 FF FF FF FF FF 00 49 DB FF 92 FF FF FF FF 92 00 00 00 24 6D 00 00 00 00 24 DB FF 49 FF +FF 92 B6 FF 92 49 00 00 00 00 00 24 00 00 00 FF FF FF FF FF FF FF 92 6D FF B6 DB FF DB B6 DB B6 B6 FF FF B6 FF FF FF DB 00 B6 DB FF 92 FF FF FF FF FF 24 00 00 00 00 00 00 00 00 B6 FF 92 B6 FF +FF FF 49 FF FF 49 24 00 00 00 00 00 00 00 B6 FF FF FF FF FF FF FF B6 FF FF FF FF FF FF FF FF FF 6D FF FF 6D FF FF FF DB 24 FF FF FF 92 FF FF FF FF FF 6D 00 00 00 00 00 00 00 DB FF FF 6D FF FF +FF FF DB 6D FF FF 6D 49 00 00 00 00 00 24 FF FF FF FF FF FF FF FF FF FF FF FF FF DB 6D 49 24 24 24 FF FF DB FF FF FF FF 24 24 00 00 92 FF FF FF FF FF DB 00 00 00 00 00 00 FF DB FF 6D FF FF FF +FF FF FF 92 B6 FF FF DB 49 24 00 00 00 92 FF FF FF FF FF FF FF FF FF DB FF FF FF 49 49 24 00 24 FF FF FF FF FF FF FF FF 49 6D 00 24 49 FF FF FF FF FF FF 49 00 24 6D 6D B6 FF FF 6D B6 FF FF FF +FF FF FF FF 6D B6 FF FF DB 92 B6 49 00 FF FF FF FF FF FF FF FF FF FF B6 FF FF FF 92 DB 92 00 24 FF FF FF FF FF FF FF FF FF 00 00 6D FF FF FF FF FF FF FF DB 00 6D DB FF FF FF 6D B6 FF FF FF FF +FF FF FF FF FF 92 6D FF FF FF FF B6 49 FF FF FF FF FF FF FF FF FF FF 6D FF FF FF FF B6 92 92 B6 B6 DB FF FF FF FF FF FF FF B6 6D 49 6D FF FF FF FF FF FF FF 92 24 FF FF B6 6D DB FF FF FF FF FF +FF FF FF FF FF FF DB 49 6D B6 FF 6D 92 FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF FF FF FF 92 FF FF FF FF FF FF FF FF 6D DB 92 FF FF FF FF FF FF FF FF 6D 49 6D DB FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF DB 92 49 00 FF FF FF FF FF FF FF FF FF FF 6D 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 92 6D FF FF FF FF FF FF FF DB 92 FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF FF DB 00 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 92 6D B6 FF FF FF FF FF FF 49 DB FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF FF FF 49 DB 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 6D FF 92 49 92 FF FF FF FF DB 49 DB FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF B6 49 FF FF FF FF FF FF FF FF 6D 92 FF 92 FF FF FF FF FF FF FF FF FF FF B6 6D 49 6D DB FF FF FF FF FF 6D 49 FF FF FF DB 6D 6D 92 92 6D 49 FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF FF 6D 92 FF FF FF DB FF FF FF FF FF FF FF FF 6D 6D FF FF FF 92 6D FF FF FF FF FF 49 92 B6 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF DB 24 92 FF FF FF FF FF FF FF FF FF FF FF FF FF 49 49 6D DB FF FF DB 6D B6 FF FF FF FF B6 B6 DB 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF 24 B6 FF FF FF FF B6 49 49 24 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF 00 49 FF DB DB FF FF FF B6 92 FF FF FF FF FF FF 92 DB FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF 24 B6 FF FF B6 24 00 6D DB FF 6D 92 FF FF FF FF FF FF FF FF FF FF FF FF FF 6D DB DB 00 00 24 FF FF FF FF B6 FF FF FF FF FF B6 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF B6 B6 DB B6 6D 49 49 92 FF FF FF B6 6D FF FF FF FF FF FF FF 92 92 FF FF FF FF FF FF FF 49 92 DB 49 FF FF FF FF FF FF FF FF FF 92 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF 92 24 49 49 6D FF 6D 92 FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF DB FF FF FF FF FF FF FF FF B6 FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 92 FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF B6 DB DB FF FF FF FF FF FF FF DB FF FF FF FF FF FF FF 6D 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 92 FF FF FF FF 24 92 FF FF FF FF FF FF FF FF FF FF 6D B6 FF FF FF FF FF FF FF FF FF FF FF FF FF DB 49 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF 6D B6 FF FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF B6 92 FF FF FF FF FF FF FF FF FF FF FF DB 6D 00 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF 6D 92 FF FF FF FF DB 49 FF FF FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF FF FF FF FF FF DB 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF 92 6D FF FF FF FF FF 00 24 DB FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF B6 49 FF FF FF FF FF FF 92 6D FF FF FF FF FF FF FF FF FF FF 6D B6 FF FF FF FF FF FF FF FF FF FF FF FF B6 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 FF FF FF FF FF FF FF 49 00 DB FF FF FF FF FF FF FF FF FF 6D 6D B6 DB DB DB 92 49 00 00 00 00 00 49 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF 49 DB FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF FF FF FF FF DB 6D 49 49 6D B6 DB FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 92 FF FF FF FF FF FF B6 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF DB 00 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 FF FF FF FF FF FF DB 6D 00 49 FF FF FF FF FF FF FF FF FF FF FF FF DB B6 92 6D 6D 6D 49 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 49 FF FF FF FF FF FF FF FF 49 00 92 FF FF FF FF FF FF FF FF 49 00 00 00 00 00 49 B6 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 6D FF FF FF FF FF FF FF FF 6D 6D FF B6 B6 FF FF FF FF FF FF 92 92 FF FF 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 B6 FF FF FF FF FF FF DB 00 DB 6D 00 B6 FF FF FF FF FF FF FF FF FF FF 24 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 DB FF FF FF FF FF 92 00 FF 24 00 00 49 FF FF FF FF FF FF FF FF FF B6 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 FF FF FF FF FF FF 49 24 24 00 00 6D FF FF FF FF FF FF FF DB FF DB 6D FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 FF FF FF FF FF FF 6D 00 24 24 24 FF FF FF FF FF FF DB B6 DB 49 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 00 B6 00 49 DB FF FF FF DB 24 6D 24 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 B6 6D 00 00 DB FF 6D 00 00 00 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 00 6D FF FF 00 00 DB 49 00 00 00 00 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 92 DB FF FF 6D 00 00 92 24 00 00 00 00 00 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B6 FF FF 00 6D 00 00 24 00 00 00 00 00 00 24 92 DB FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 6D DB 00 00 00 00 00 00 00 00 00 00 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 00 24 00 00 6D 00 00 00 B6 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF +FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF DB 49 92 6D 6D DB B6 92 92 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF + + + diff --git a/grub-core/boot/powerpc/grub.chrp.in b/grub-core/boot/powerpc/grub.chrp.in new file mode 100644 index 000000000..9b2218352 --- /dev/null +++ b/grub-core/boot/powerpc/grub.chrp.in @@ -0,0 +1,172 @@ + + +MacRISC MacRISC3 MacRISC4 + + +@PACKAGE@ @VERSION@ + + +3434 +00000000000000F781FB8181818181FBFAF500000000000000000000000000000000000000F6FAFAFAFA81F9F600000000000000 +0000000000F8FBF9F500F95656FCFB5656FBF800000000000000000000000000000000F5FAF9F5F7F600F6F6F9FAF70000000000 +000000F5FBFA0056FDFEFEFDFDFAAC81FB56568181560000000000000000000000F9F9F9F7FCFDFEFEFEFFFC81F656FA00000000 +0000F5AC2BF7FBFEFEFD2BF6568181F9F7F6F6F8FBF50000000000000000000000FAF700F600F5F7F7F6F7FEFFACF82BFB000000 +0000FC2BF5FEFFFFF5F7FC81F70000F7F9FAFAF8000000000000000000000000000056F9F9FAF9F7F7FA812BF7FFFF56F7FA0000 +005656F5FEFFAC2BF9FA000000000000000000000000000000000000000000000000000000000000000000FA56FAFEFEF8F9F700 +00FB00F7FFFF56F9F800000000000000000000F656FAFA56F50000000000F5F8F9F8F5000000000000000000F9F7FCFFFB00FB00 +F8F800ACFFACF6FA000000000000000000F6FA562BF5F5F781FA000000F9FA2B00F556F9F5000000000000000081F8FFFEF6562B +810000FFFFF9FAF500000000000000002B8100F5F9FCACFBF82BFBF6FCFAF6FAFC81F600FA2B000000000000002BF8FEFFF8F5FA +FA00F5FEFFFA8100000000000000002B8100F9FEFFFFFFFFFFFBF6FDFEACFDFEFFFFFFFBF581F600000000000000F9FEFFF700FA +FA00FBFFFEF6F900000000000000F6FB00FCFFFFFFFFFFFFFFFFFCF600FCF7ACFEFFFFFFFDF6810000000000000056F9FFAC00FA +FA00F6FFFFF856000000000000F5FBF5ACFFFFFFFFFFFFFFFFFFFF2B002BF8F5ACFFFFFFFFFDF6FA000000000000F9FCFF560081 +FA0081FFFFF8F9000000000000FBF6FBFFFFFFFFFFFFFFFFFFFFFFF800F55600FCFFFFFFFFFF81F8F80000000000F981FFAC0081 +FA0000FEFEF8FB0000000000812BFAFFFFFFFFFFFFFEFFFFFDF92BFA0000F6F981ACFEFFFFFFFF56F9F600000000F9FDFF2B0081 +FA00FAFFFF81812B000000FAF8F9FFFFFEACFBF80000F500000000F9F900562B0000FCF7F9ACFFFF2BF9F50000F9F6FEFFFB0081 +810000FCFFFBF6FB56F7FBF8F9FFFE5600000000F5FAAC000000F82BF6FAFBF800F556F80000F9FFFE2BFAFAFAF8FAFFFEF60081 +FAF6F5ACFFFFAC00F856F7ACFFFCF500000000FAFCFFFC00000056AC00F581F92BFEF9FAF6000081FFFFFBF6F62BFFFFACF6F6FA +F6FA00FAFFFFFFACFA56FFFFAC0000000000F6FD2BFEF6F5565600F5F800F60081FEF7F656000000FDFFFFFDFDFFFFFFAC0081F5 +0081F52BFDFFFFFFFFFFFFFFF60000000000FBF6F6F5F656F52BF900FA000000FCFAF5F656000000F7FFFFFFFFFFFFFDF7F68100 +00F6FB00F8FDFFFFFFFFFF810000000000F6F5000000F52B56F9FC00F7F70000FCF881FCF500000000FEFFFFFFFFAC5600FBF500 +000056F900F8ACFDFFFFFFF5000000000000002B0000FDFEFFFE560000F60000F9ACFFFE810000000081FFFEFDFAF800FAF70000 +000000FAF9002B56FAFDFC0000000000000000F80000FBF5FEFEF5000000000000ACFFFA2B0000000000FEFB2BF5008156000000 +00000000F9FBF600F6FBF800000000000000F7F8000000F9F9F9F82B0000000000F6ACACF70000000000F7FD2BFA812B00000000 +0000000000F681FCFBFD0000000000000000FBF6000000000000F52B000000000000F92B810000000000008181F6000000000000 +0000000000000000F6FC00000000000000F6FF0000000000000000000000000000000081FBFB2B00000000F7F900000000000000 +000000000000000000FC00000000000000FCFAF600000000000000000000000000000056ACF581FBF700000081FB000000000000 +0000000000000000FAF90000000000008156F5F8000000000000002BFBFCFBF800000000FD2B000056FB8181FBF8000000000000 +0000000000000000AC0000000000F5FBF90000F6000000000000F5AC56F6005681F50000F6ACFCFBF70000000000000000000000 +00000000000000F881000000F5FAFDFD00000000000000000000F7FEFA2B0000F581F70000000000810000000000000000000000 +000000000000F9FCF500FAFDACFAF5FD00000000000000000000F5ACF5FDFEFA0000F82B00000000810000000000000000000000 +000000000000FCF8F9AC81FD000000FD000000000000FAF7000000F50081F9FAF800000000000000FB0000000000000000000000 +000000000000FC81F956F5FD000000FD0000000000000000F800F5000000000056000000000000F7FB0000000000000000000000 +00000000000000000000F5AC000000ACF800000000000000F5FAF80000000000F50000000000F8ACF50000000000000000000000 +00000000000000000000F5AC000000F5AC000000000000000056F9000000000000000000F7ACFCF5000000000000000000000000 +00000000000000000000F5FD00000000AC000000000000000000FB0000000000000000F5F6F5FCF6000000000000000000000000 +0000000000000000000000FD00000000FBFDF600000000000000F8F900000000000000000000F5FB000000000000000000000000 +0000000000000000000000FDF500000000F9ACF800000000000000815600000000F656818181AC56000000000000000000000000 +000000000000000000000081F80000000000F9FC0000000000000000F9ACACACFCFBFAFA81FD2B00000000000000000000000000 +0000000000000000000000F7FB0000000000FBF70000000000000000000000000000000000FB0000000000000000000000000000 +000000000000000000000000ACF500000000F9FD56F5000000000000000000000000000000FB0000000000000000000000000000 +000000000000000000000000F8FA0000000000F6FEFEF5000000000000F55681FCACFDACFC560000000000000000000000000000 +00000000000000000000000000FBF600000000002BFCFA00F700000000F9FDFDFAFEF90000000000000000000000000000000000 +00000000000000000000000000F5FB0000000000F5FEF7ACAC0000000000000000FCF50000000000000000000000000000000000 +0000000000000000000000000000F6FA000000002BFF2BFFFFAC00000000000000F7FA0000000000000000000000000000000000 +000000000000000000000000000000F65600000000FAFEFFFFAC0000000000F800F6810000000000000000000000000000000000 +00000000000000000000000000000000F52B00000000F8FEFBFF5600000000FCFAACF60000000000000000000000000000000000 +0000000000000000000000000000000000000000000000F9FCFCFFFB00F8FEFFFDF5000000000000000000000000000000000000 +00000000000000000000000000000000000000000000F9FDF7F5FFFD56FFFFFFFD00000000000000000000000000000000000000 +00000000000000000000000000000000000000000000810000FBFFFFFBFFFFFFFFACF9F5F5000000000000000000000000000000 +0000000000000000000000000000000000000000000000F600FC81FFFEFFFFFFFFFFFE8100000000000000000000000000000000 +00000000000000000000000000000000000000000000000000F7F6FDFFFFFFFEFFFFACF500000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000F5FC81FC81FAFBF9F500000000000000000000000000000000 + +00000000000000F781FB8181818181FBFAF500000000000000000000000000000000000000F6FAFAFAFA81F9F600000000000000 +0000000000F8FBF9F500F95656FCFB5656FBF800000000000000000000000000000000F5FAF9F5F7F600F6F6F9FAF70000000000 +000000F5FBFA0056FDFEFEFDFDFAAC81FB56568181560000000000000000000000F9F9F9F7FCFDFEFEFEFFFC81F656FA00000000 +0000F5AC2BF7FBFEFEFD2BF6568181F9F7F6F6F8FBF50000000000000000000000FAF700F600F5F7F7F6F7FEFFACF82BFB000000 +0000FC2BF5FEFFFFF5F7FC81F70000F7F9FAFAF8000000000000000000000000000056F9F9FAF9F7F7FA812BF7FFFF56F7FA0000 +005656F5FEFFAC2BF9FA000000000000000000000000000000000000000000000000000000000000000000FA56FAFEFEF8F9F700 +00FB00F7FFFF56F9F800000000000000000000F656FAFA56F50000000000F5F8F9F8F5000000000000000000F9F7FCFFFB00FB00 +F8F800ACFFACF6FA000000000000000000F6FA562BF5F5F781FA000000F9FA2B00F556F9F5000000000000000081F8FFFEF6562B +810000FFFFF9FAF500000000000000002B8100F5F9FCACFBF82BFBF6FCFAF6FAFC81F600FA2B000000000000002BF8FEFFF8F5FA +FA00F5FEFFFA8100000000000000002B8100F9FEFFFFFFFFFFFBF6FDFEACFDFEFFFFFFFBF581F600000000000000F9FEFFF700FA +FA00FBFFFEF6F900000000000000F6FB00FCFFFFFFFFFFFFFFFFFCF600FCF7ACFEFFFFFFFDF6810000000000000056F9FFAC00FA +FA00F6FFFFF856000000000000F5FBF5ACFFFFFFFFFFFFFFFFFFFF2B002BF8F5ACFFFFFFFFFDF6FA000000000000F9FCFF560081 +FA0081FFFFF8F9000000000000FBF6FBFFFFFFFFFFFFFFFFFFFFFFF800F55600FCFFFFFFFFFF81F8F80000000000F981FFAC0081 +FA0000FEFEF8FB0000000000812BFAFFFFFFFFFFFFFEFFFFFDF92BFA0000F6F981ACFEFFFFFFFF56F9F600000000F9FDFF2B0081 +FA00FAFFFF81812B000000FAF8F9FFFFFEACFBF80000F500000000F9F900562B0000FCF7F9ACFFFF2BF9F50000F9F6FEFFFB0081 +810000FCFFFBF6FB56F7FBF8F9FFFE5600000000F5FAAC000000F82BF6FAFBF800F556F80000F9FFFE2BFAFAFAF8FAFFFEF60081 +FAF6F5ACFFFFAC00F856F7ACFFFCF500000000FAFCFFFC00000056AC00F581F92BFEF9FAF6000081FFFFFBF6F62BFFFFACF6F6FA +F6FA00FAFFFFFFACFA56FFFFAC0000000000F6FD2BFEF6F5565600F5F800F60081FEF7F656000000FDFFFFFDFDFFFFFFAC0081F5 +0081F52BFDFFFFFFFFFFFFFFF60000000000FBF6F6F5F656F52BF900FA000000FCFAF5F656000000F7FFFFFFFFFFFFFDF7F68100 +00F6FB00F8FDFFFFFFFFFF810000000000F6F5000000F52B56F9FC00F7F70000FCF881FCF500000000FEFFFFFFFFAC5600FBF500 +000056F900F8ACFDFFFFFFF5000000000000002B0000FDFEFFFE560000F60000F9ACFFFE810000000081FFFEFDFAF800FAF70000 +000000FAF9002B56FAFDFC0000000000000000F80000FBF5FEFEF5000000000000ACFFFA2B0000000000FEFB2BF5008156000000 +00000000F9FBF600F6FBF800000000000000F7F8000000F9F9F9F82B0000000000F6ACACF70000000000F7FD2BFA812B00000000 +0000000000F681FCFBFD0000000000000000FBF6000000000000F52B000000000000F92B810000000000008181F6000000000000 +0000000000000000F6FC00000000000000F6FF0000000000000000000000000000000081FBFB2B00000000F7F900000000000000 +000000000000000000FC00000000000000FCFAF600000000000000000000000000000056ACF581FBF700000081FB000000000000 +0000000000000000FAF90000000000008156F5F8000000000000002BFBFCFBF800000000FD2B000056FB8181FBF8000000000000 +0000000000000000AC0000000000F5FBF90000F6000000000000F5AC56F6005681F50000F6ACFCFBF70000000000000000000000 +00000000000000F881000000F5FAFDFD00000000000000000000F7FEFA2B0000F581F70000000000810000000000000000000000 +000000000000F9FCF500FAFDACFAF5FD00000000000000000000F5ACF5FDFEFA0000F82B00000000810000000000000000000000 +000000000000FCF8F9AC81FD000000FD000000000000FAF7000000F50081F9FAF800000000000000FB0000000000000000000000 +000000000000FC81F956F5FD000000FD0000000000000000F800F5000000000056000000000000F7FB0000000000000000000000 +00000000000000000000F5AC000000ACF800000000000000F5FAF80000000000F50000000000F8ACF50000000000000000000000 +00000000000000000000F5AC000000F5AC000000000000000056F9000000000000000000F7ACFCF5000000000000000000000000 +00000000000000000000F5FD00000000AC000000000000000000FB0000000000000000F5F6F5FCF6000000000000000000000000 +0000000000000000000000FD00000000FBFDF600000000000000F8F900000000000000000000F5FB000000000000000000000000 +0000000000000000000000FDF500000000F9ACF800000000000000815600000000F656818181AC56000000000000000000000000 +000000000000000000000081F80000000000F9FC0000000000000000F9ACACACFCFBFAFA81FD2B00000000000000000000000000 +0000000000000000000000F7FB0000000000FBF70000000000000000000000000000000000FB0000000000000000000000000000 +000000000000000000000000ACF500000000F9FD56F5000000000000000000000000000000FB0000000000000000000000000000 +000000000000000000000000F8FA0000000000F6FEFEF5000000000000F55681FCACFDACFC560000000000000000000000000000 +00000000000000000000000000FBF600000000002BFCFA00F700000000F9FDFDFAFEF90000000000000000000000000000000000 +00000000000000000000000000F5FB0000000000F5FEF7ACAC0000000000000000FCF50000000000000000000000000000000000 +0000000000000000000000000000F6FA000000002BFF2BFFFFAC00000000000000F7FA0000000000000000000000000000000000 +000000000000000000000000000000F65600000000FAFEFFFFAC0000000000F800F6810000000000000000000000000000000000 +00000000000000000000000000000000F52B00000000F8FEFBFF5600000000FCFAACF60000000000000000000000000000000000 +0000000000000000000000000000000000000000000000F9FCFCFFFB00F8FEFFFDF5000000000000000000000000000000000000 +00000000000000000000000000000000000000000000F9FDF7F5FFFD56FFFFFFFD00000000000000000000000000000000000000 +00000000000000000000000000000000000000000000810000FBFFFFFBFFFFFFFFACF9F5F5000000000000000000000000000000 +0000000000000000000000000000000000000000000000F600FC81FFFEFFFFFFFFFFFE8100000000000000000000000000000000 +00000000000000000000000000000000000000000000000000F7F6FDFFFFFFFEFFFFACF500000000000000000000000000000000 +000000000000000000000000000000000000000000000000000000F5FC81FC81FAFBF9F500000000000000000000000000000000 + +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + + +boot &device;:&partition;,\System\Library\CoreServices\grub.elf + + diff --git a/grub-core/boot/sparc64/ieee1275/boot.S b/grub-core/boot/sparc64/ieee1275/boot.S index f79699502..ff8a79d3b 100644 --- a/grub-core/boot/sparc64/ieee1275/boot.S +++ b/grub-core/boot/sparc64/ieee1275/boot.S @@ -21,6 +21,24 @@ .text .align 4 + /* + * We're writing the a.out header ourselves as newer + * upstream versions of binutils no longer support + * the a.out format on sparc64. + * + * The boot loader fits into 512 bytes with 32 bytes + * used for the a.out header, hence the text segment + * size is 512 - 32. There is no data segment and no + * code relocation, thus those fields remain zero. + */ + .word 0x1030107 /* Magic number. */ + .word 512 - GRUB_BOOT_AOUT_HEADER_SIZE /* Size of text segment. */ + .word 0 /* Size of initialized data. */ + .word 0 /* Size of uninitialized data. */ + .word 0 /* Size of symbol table || checksum. */ + .word _start /* Entry point. */ + .word 0 /* Size of text relocation. */ + .word 0 /* Size of data relocation. */ .globl _start _start: /* OF CIF entry point arrives in %o4 */ @@ -28,8 +46,9 @@ pic_base: call boot_continue mov %o4, CIF_REG +#ifndef CDBOOT /* The offsets to these locations are defined by the - * GRUB_BOOT_MACHINE_foo macros in include/grub/sparc/ieee1275/boot.h, + * GRUB_BOOT_MACHINE_foo macros in include/grub/sparc64/ieee1275/boot.h, * and grub-setup uses this to patch these next three values as needed. * * The boot_path will be the OF device path of the partition where the @@ -39,13 +58,27 @@ pic_base: * * After loading in that block we will execute it by jumping to the * load address plus the size of the prepended A.OUT header (32 bytes). + * + * Since this assembly code includes the 32 bytes long a.out header, + * we need to move the actual code entry point forward by the size + * of the a.out header, i.e. += GRUB_BOOT_AOUT_HEADER_SIZE. */ - . = _start + GRUB_BOOT_MACHINE_BOOT_DEVPATH + .org GRUB_BOOT_MACHINE_BOOT_DEVPATH + GRUB_BOOT_AOUT_HEADER_SIZE boot_path: - . = _start + GRUB_BOOT_MACHINE_KERNEL_BYTE + .org GRUB_BOOT_MACHINE_KERNEL_BYTE + GRUB_BOOT_AOUT_HEADER_SIZE boot_path_end: kernel_byte: .xword (2 << 9) kernel_address: .word GRUB_BOOT_MACHINE_KERNEL_ADDR +#else +#define boot_path (_start + 512 + SCRATCH_PAD_BOOT_SIZE) +#define boot_path_end (_start + 1024) +#include + + .org 8 + GRUB_BOOT_AOUT_HEADER_SIZE +kernel_byte: .xword (2 << 9) +kernel_size: .word 512 +kernel_address: .word GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS +#endif prom_finddev_name: .asciz "finddevice" prom_chosen_path: .asciz "/chosen" @@ -58,6 +91,10 @@ prom_seek_name: .asciz "seek" prom_read_name: .asciz "read" prom_exit_name: .asciz "exit" grub_name: .asciz "GRUB " +#ifdef CDBOOT +prom_close_name: .asciz "close" +#endif + #define GRUB_NAME_LEN 5 .align 4 @@ -129,7 +166,11 @@ prom_call: boot_continue: mov %o7, PIC_REG /* PIC base */ +#ifndef CDBOOT sethi %hi(SCRATCH_PAD_BOOT), %l1 /* OF argument slots */ +#else + GET_ABS(_start + 512, %l1) /* OF argument slots */ +#endif /* Find the /chosen node so we can fetch the stdout handle, * and thus perform console output. @@ -158,8 +199,10 @@ boot_continue: mov GRUB_NAME_LEN, %o3 GET_ABS(boot_path, %o3) +#ifndef CDBOOT ldub [%o3], %o1 brnz,pn %o1, bootpath_known +#endif /* getprop(chosen_node, "bootpath", &buffer, buffer_size) */ GET_ABS(prom_bootpath_name, %o2) @@ -194,13 +237,26 @@ bootpath_known: GET_ABS(prom_read_name, %o0) LDUW_ABS(kernel_address, 0x00, %o2) call prom_call_3_1_o1 +#ifdef CDBOOT + LDUW_ABS(kernel_size, 0x00, %o3) + + GET_ABS(prom_close_name, %o0) + mov 1, %g1 + mov 0, %o5 + call prom_call + mov BOOTDEV_REG, %o1 +#else mov 512, %o3 +#endif LDUW_ABS(kernel_address, 0x00, %o2) jmpl %o2, %o7 +#ifdef CDBOOT + mov CIF_REG, %o4 +#else nop - - . = _start + GRUB_BOOT_MACHINE_CODE_END +#endif + .org GRUB_BOOT_MACHINE_CODE_END /* the last 4 bytes in the sector 0 contain the signature */ .word GRUB_BOOT_MACHINE_SIGNATURE diff --git a/grub-core/boot/sparc64/ieee1275/diskboot.S b/grub-core/boot/sparc64/ieee1275/diskboot.S index e020f6221..35e02c1b6 100644 --- a/grub-core/boot/sparc64/ieee1275/diskboot.S +++ b/grub-core/boot/sparc64/ieee1275/diskboot.S @@ -136,7 +136,7 @@ lastlist: .word 0 .word 0 - . = _start + (0x200 - GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE) + .org (0x200 - GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE) blocklist_default_start: .word 0 .word 2 diff --git a/grub-core/bus/bonito.c b/grub-core/bus/bonito.c index 985608181..23b9a9915 100644 --- a/grub-core/bus/bonito.c +++ b/grub-core/bus/bonito.c @@ -21,56 +21,130 @@ #include static grub_uint32_t base_win[GRUB_MACHINE_PCI_NUM_WIN]; -static const grub_size_t sizes_win[GRUB_MACHINE_PCI_NUM_WIN] = - {GRUB_MACHINE_PCI_WIN1_SIZE, GRUB_MACHINE_PCI_WIN_SIZE, +static const grub_size_t sizes_win[GRUB_MACHINE_PCI_NUM_WIN] = + {GRUB_MACHINE_PCI_WIN1_SIZE, GRUB_MACHINE_PCI_WIN_SIZE, GRUB_MACHINE_PCI_WIN_SIZE}; /* Usage counters. */ static int usage_win[GRUB_MACHINE_PCI_NUM_WIN]; -static grub_addr_t addr_win[GRUB_MACHINE_PCI_NUM_WIN] = +static grub_addr_t addr_win[GRUB_MACHINE_PCI_NUM_WIN] = {GRUB_MACHINE_PCI_WIN1_ADDR, GRUB_MACHINE_PCI_WIN2_ADDR, GRUB_MACHINE_PCI_WIN3_ADDR}; +grub_bonito_type_t grub_bonito_type; + +static volatile void * +config_addr (grub_pci_address_t addr) +{ + if (grub_bonito_type == GRUB_BONITO_2F) + { + GRUB_MACHINE_PCI_CONF_CTRL_REG_2F = 1 << ((addr >> 11) & 0xf); + return (volatile void *) (GRUB_MACHINE_PCI_CONFSPACE_2F + | (addr & 0x07ff)); + } + else + { + + if (addr >> 16) + return (volatile void *) (GRUB_MACHINE_PCI_CONFSPACE_3A_EXT | addr); + else + return (volatile void *) (GRUB_MACHINE_PCI_CONFSPACE_3A | addr); + } +} + +grub_uint32_t +grub_pci_read (grub_pci_address_t addr) +{ + return *(volatile grub_uint32_t *) config_addr (addr); +} + +grub_uint16_t +grub_pci_read_word (grub_pci_address_t addr) +{ + return *(volatile grub_uint16_t *) config_addr (addr); +} + +grub_uint8_t +grub_pci_read_byte (grub_pci_address_t addr) +{ + return *(volatile grub_uint8_t *) config_addr (addr); +} + +void +grub_pci_write (grub_pci_address_t addr, grub_uint32_t data) +{ + *(volatile grub_uint32_t *) config_addr (addr) = data; +} + +void +grub_pci_write_word (grub_pci_address_t addr, grub_uint16_t data) +{ + *(volatile grub_uint16_t *) config_addr (addr) = data; +} + +void +grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data) +{ + *(volatile grub_uint8_t *) config_addr (addr) = data; +} + + static inline void -write_bases (void) +write_bases_2f (void) { int i; grub_uint32_t reg = 0; - for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) - reg |= (((base_win[i] >> GRUB_MACHINE_PCI_WIN_SHIFT) - & GRUB_MACHINE_PCI_WIN_MASK) + for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) + reg |= (((base_win[i] >> GRUB_MACHINE_PCI_WIN_SHIFT) + & GRUB_MACHINE_PCI_WIN_MASK) << (i * GRUB_MACHINE_PCI_WIN_MASK_SIZE)); - GRUB_MACHINE_PCI_IO_CTRL_REG = reg; + GRUB_MACHINE_PCI_IO_CTRL_REG_2F = reg; } volatile void * grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)), grub_addr_t base, grub_size_t size) { - int i; - grub_addr_t newbase; + if (grub_bonito_type == GRUB_BONITO_2F) + { + int i; + grub_addr_t newbase; - /* First try already used registers. */ - for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) - if (usage_win[i] && base_win[i] <= base - && base_win[i] + sizes_win[i] > base + size) - { - usage_win[i]++; - return (void *) - (addr_win[i] | (base & GRUB_MACHINE_PCI_WIN_OFFSET_MASK)); - } - /* Map new register. */ - newbase = base & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK; - for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) - if (!usage_win[i] && newbase <= base - && newbase + sizes_win[i] > base + size) - { - usage_win[i]++; - base_win[i] = newbase; - write_bases (); - return (void *) - (addr_win[i] | (base & GRUB_MACHINE_PCI_WIN_OFFSET_MASK)); - } - grub_fatal ("Out of PCI windows."); + /* First try already used registers. */ + for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) + if (usage_win[i] && base_win[i] <= base + && base_win[i] + sizes_win[i] > base + size) + { + usage_win[i]++; + return (void *) + (addr_win[i] | (base & GRUB_MACHINE_PCI_WIN_OFFSET_MASK)); + } + /* Map new register. */ + newbase = base & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK; + for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) + if (!usage_win[i] && newbase <= base + && newbase + sizes_win[i] > base + size) + { + usage_win[i]++; + base_win[i] = newbase; + write_bases_2f (); + return (void *) + (addr_win[i] | (base & GRUB_MACHINE_PCI_WIN_OFFSET_MASK)); + } + grub_fatal ("Out of PCI windows."); + } + else + { + int region = 0; + if (base >= 0x10000000 + && base + size <= 0x18000000) + region = 1; + if (base >= 0x1c000000 + && base + size <= 0x1f000000) + region = 2; + if (region == 0) + grub_fatal ("Attempt to map out of regions"); + return (void *) (0xa0000000 | base); + } } void * @@ -86,14 +160,17 @@ grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)), volatile void *mem, grub_size_t size __attribute__ ((unused))) { - int i; - for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) - if (usage_win[i] && addr_win[i] - == (((grub_addr_t) mem | 0x20000000) - & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK)) - { - usage_win[i]--; - return; - } - grub_fatal ("Tried to unmap not mapped region"); + if (grub_bonito_type == GRUB_BONITO_2F) + { + int i; + for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) + if (usage_win[i] && addr_win[i] + == (((grub_addr_t) mem | 0x20000000) + & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK)) + { + usage_win[i]--; + return; + } + grub_fatal ("Tried to unmap not mapped region"); + } } diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c index 9e7796ea1..cd0a45e58 100644 --- a/grub-core/bus/cs5536.c +++ b/grub-core/bus/cs5536.c @@ -29,28 +29,39 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Context for grub_cs5536_find. */ +struct grub_cs5536_find_ctx +{ + grub_pci_device_t *devp; + int found; +}; + +/* Helper for grub_cs5536_find. */ +static int +grub_cs5536_find_iter (grub_pci_device_t dev, grub_pci_id_t pciid, void *data) +{ + struct grub_cs5536_find_ctx *ctx = data; + + if (pciid == GRUB_CS5536_PCIID) + { + *ctx->devp = dev; + ctx->found = 1; + return 1; + } + return 0; +} + int grub_cs5536_find (grub_pci_device_t *devp) { - int found = 0; - auto int NESTED_FUNC_ATTR hook (grub_pci_device_t dev, - grub_pci_id_t pciid); + struct grub_cs5536_find_ctx ctx = { + .devp = devp, + .found = 0 + }; - int NESTED_FUNC_ATTR hook (grub_pci_device_t dev, - grub_pci_id_t pciid) - { - if (pciid == GRUB_CS5536_PCIID) - { - *devp = dev; - found = 1; - return 1; - } - return 0; - } + grub_pci_iterate (grub_cs5536_find_iter, &ctx); - grub_pci_iterate (hook); - - return found; + return ctx.found; } grub_uint64_t @@ -61,7 +72,7 @@ grub_cs5536_read_msr (grub_pci_device_t dev, grub_uint32_t addr) addr); ret = (grub_uint64_t) grub_pci_read (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_DATA0)); - ret |= (((grub_uint64_t) + ret |= (((grub_uint64_t) grub_pci_read (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_DATA1))) << 32); @@ -89,7 +100,7 @@ grub_cs5536_smbus_wait (grub_port_t smbbase) grub_uint8_t status; status = grub_inb (smbbase + GRUB_CS5536_SMB_REG_STATUS); if (status & GRUB_CS5536_SMB_REG_STATUS_SDAST) - return GRUB_ERR_NONE; + return GRUB_ERR_NONE; if (status & GRUB_CS5536_SMB_REG_STATUS_BER) return grub_error (GRUB_ERR_IO, "SM bus error"); if (status & GRUB_CS5536_SMB_REG_STATUS_NACK) @@ -111,8 +122,8 @@ grub_cs5536_read_spd_byte (grub_port_t smbbase, grub_uint8_t dev, smbbase + GRUB_CS5536_SMB_REG_CTRL1); /* Send device address. */ - err = grub_cs5536_smbus_wait (smbbase); - if (err) + err = grub_cs5536_smbus_wait (smbbase); + if (err) return err; grub_outb (dev << 1, smbbase + GRUB_CS5536_SMB_REG_DATA); @@ -128,8 +139,8 @@ grub_cs5536_read_spd_byte (grub_port_t smbbase, grub_uint8_t dev, grub_outb (addr, smbbase + GRUB_CS5536_SMB_REG_DATA); /* Send START. */ - err = grub_cs5536_smbus_wait (smbbase); - if (err) + err = grub_cs5536_smbus_wait (smbbase); + if (err) return err; grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1) | GRUB_CS5536_SMB_REG_CTRL1_START, @@ -150,7 +161,7 @@ grub_cs5536_read_spd_byte (grub_port_t smbbase, grub_uint8_t dev, smbbase + GRUB_CS5536_SMB_REG_CTRL1); err = grub_cs5536_smbus_wait (smbbase); - if (err) + if (err) return err; *res = grub_inb (smbbase + GRUB_CS5536_SMB_REG_DATA); @@ -187,8 +198,8 @@ grub_cs5536_init_smbus (grub_pci_device_t dev, grub_uint16_t divisor, grub_outb (((divisor >> 7) & 0xff), *smbbase + GRUB_CS5536_SMB_REG_CTRL3); grub_outb (((divisor << 1) & 0xfe) | GRUB_CS5536_SMB_REG_CTRL2_ENABLE, *smbbase + GRUB_CS5536_SMB_REG_CTRL2); - - return GRUB_ERR_NONE; + + return GRUB_ERR_NONE; } grub_err_t @@ -206,7 +217,7 @@ grub_cs5536_read_spd (grub_port_t smbbase, grub_uint8_t dev, if (b == 0) return grub_error (GRUB_ERR_IO, "no SPD found"); size = b; - + ((grub_uint8_t *) res)[0] = b; for (ptr = 1; ptr < size; ptr++) { @@ -299,7 +310,7 @@ grub_cs5536_init_geode (grub_pci_device_t dev) /* Initialise USB controller. */ /* FIXME: assign adresses dynamically. */ - grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE, + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE, GRUB_CS5536_MSR_USB_BASE_BUS_MASTER | GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE | 0x05024000); @@ -320,8 +331,9 @@ grub_cs5536_init_geode (grub_pci_device_t dev) { volatile grub_uint32_t *oc; - oc = grub_pci_device_map_range (dev, 0x05022000, - GRUB_CS5536_USB_OPTION_REGS_SIZE); + + oc = grub_absolute_pointer (grub_pci_device_map_range (dev, 0x05022000, + GRUB_CS5536_USB_OPTION_REGS_SIZE)); oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX] = (oc[GRUB_CS5536_USB_OPTION_REG_UOCMUX] diff --git a/grub-core/bus/emu/pci.c b/grub-core/bus/emu/pci.c index d1beb561d..267f2622d 100644 --- a/grub-core/bus/emu/pci.c +++ b/grub-core/bus/emu/pci.c @@ -32,7 +32,7 @@ grub_pci_make_address (grub_pci_device_t dev, int reg) } void -grub_pci_iterate (grub_pci_iteratefunc_t hook) +grub_pci_iterate (grub_pci_iteratefunc_t hook, void *hook_data) { struct pci_device_iterator *iter; struct pci_slot_match slot; @@ -43,7 +43,7 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) slot.func = PCI_MATCH_ANY; iter = pci_slot_match_iterator_create (&slot); while ((dev = pci_device_next (iter))) - hook (dev, dev->vendor_id | (dev->device_id << 16)); + hook (dev, dev->vendor_id | (dev->device_id << 16), hook_data); pci_iterator_destroy (iter); } @@ -55,7 +55,8 @@ grub_pci_device_map_range (grub_pci_device_t dev, grub_addr_t base, int err; err = pci_device_map_range (dev, base, size, PCI_DEV_MAP_FLAG_WRITABLE, &addr); if (err) - grub_util_error ("mapping 0x%x failed (error %d)\n", base, err); + grub_util_error ("mapping 0x%llx failed (error %d)", + (unsigned long long) base, err); return addr; } @@ -66,12 +67,12 @@ grub_pci_device_unmap_range (grub_pci_device_t dev, void *mem, pci_device_unmap_range (dev, mem, size); } -GRUB_MOD_INIT (pci) +GRUB_MOD_INIT (emupci) { pci_system_init (); } -GRUB_MOD_FINI (pci) +GRUB_MOD_FINI (emupci) { pci_system_cleanup (); } diff --git a/grub-core/bus/fdt.c b/grub-core/bus/fdt.c new file mode 100644 index 000000000..135da497b --- /dev/null +++ b/grub-core/bus/fdt.c @@ -0,0 +1,256 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2016 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include + +static const void *dtb; +static grub_size_t root_address_cells, root_size_cells; +/* Pointer to this symbol signals invalid mapping. */ +char grub_fdtbus_invalid_mapping[1]; + +struct grub_fdtbus_dev *devs; +struct grub_fdtbus_driver *drivers; + +int +grub_fdtbus_is_compatible (const char *compat_string, + const struct grub_fdtbus_dev *dev) +{ + grub_size_t compatible_size; + const char *compatible = grub_fdt_get_prop (dtb, dev->node, "compatible", + &compatible_size); + if (!compatible) + return 0; + const char *compatible_end = compatible + compatible_size; + while (compatible < compatible_end) + { + if (grub_strcmp (compat_string, compatible) == 0) + return 1; + compatible += grub_strlen (compatible) + 1; + } + return 0; +} + +static void +fdtbus_scan (struct grub_fdtbus_dev *parent) +{ + int node; + for (node = grub_fdt_first_node (dtb, parent ? parent->node : 0); node >= 0; + node = grub_fdt_next_node (dtb, node)) + { + struct grub_fdtbus_dev *dev; + struct grub_fdtbus_driver *driver; + dev = grub_zalloc (sizeof (*dev)); + if (!dev) + { + grub_print_error (); + return; + } + dev->node = node; + dev->next = devs; + dev->parent = parent; + devs = dev; + FOR_LIST_ELEMENTS(driver, drivers) + if (!dev->driver && grub_fdtbus_is_compatible (driver->compatible, dev)) + { + grub_dprintf ("fdtbus", "Attaching %s\n", driver->compatible); + if (driver->attach (dev) == GRUB_ERR_NONE) + { + grub_dprintf ("fdtbus", "Attached %s\n", driver->compatible); + dev->driver = driver; + break; + } + grub_print_error (); + } + fdtbus_scan (dev); + } +} + +void +grub_fdtbus_register (struct grub_fdtbus_driver *driver) +{ + struct grub_fdtbus_dev *dev; + grub_dprintf ("fdtbus", "Registering %s\n", driver->compatible); + grub_list_push (GRUB_AS_LIST_P (&drivers), + GRUB_AS_LIST (driver)); + for (dev = devs; dev; dev = dev->next) + if (!dev->driver && grub_fdtbus_is_compatible (driver->compatible, dev)) + { + grub_dprintf ("fdtbus", "Attaching %s (%p)\n", driver->compatible, dev); + if (driver->attach (dev) == GRUB_ERR_NONE) + { + grub_dprintf ("fdtbus", "Attached %s\n", driver->compatible); + dev->driver = driver; + } + grub_print_error (); + } +} + +void +grub_fdtbus_unregister (struct grub_fdtbus_driver *driver) +{ + grub_list_remove (GRUB_AS_LIST (driver)); + struct grub_fdtbus_dev *dev; + for (dev = devs; dev; dev = dev->next) + if (dev->driver == driver) + { + if (driver->detach) + driver->detach(dev); + dev->driver = 0; + } +} + +void +grub_fdtbus_init (const void *dtb_in, grub_size_t size) +{ + if (!dtb_in || grub_fdt_check_header (dtb_in, size) < 0) + grub_fatal ("invalid FDT"); + dtb = dtb_in; + const grub_uint32_t *prop = grub_fdt_get_prop (dtb, 0, "#address-cells", 0); + if (prop) + root_address_cells = grub_be_to_cpu32 (*prop); + else + root_address_cells = 1; + + prop = grub_fdt_get_prop (dtb, 0, "#size-cells", 0); + if (prop) + root_size_cells = grub_be_to_cpu32 (*prop); + else + root_size_cells = 1; + + fdtbus_scan (0); +} + +static int +get_address_cells (const struct grub_fdtbus_dev *dev) +{ + const grub_uint32_t *prop; + if (!dev) + return root_address_cells; + prop = grub_fdt_get_prop (dtb, dev->node, "#address-cells", 0); + if (prop) + return grub_be_to_cpu32 (*prop); + return 1; +} + +static int +get_size_cells (const struct grub_fdtbus_dev *dev) +{ + const grub_uint32_t *prop; + if (!dev) + return root_size_cells; + prop = grub_fdt_get_prop (dtb, dev->node, "#size-cells", 0); + if (prop) + return grub_be_to_cpu32 (*prop); + return 1; +} + +static grub_uint64_t +get64 (const grub_uint32_t *reg, grub_size_t cells) +{ + grub_uint64_t val = 0; + if (cells >= 1) + val = grub_be_to_cpu32 (reg[cells - 1]); + if (cells >= 2) + val |= ((grub_uint64_t) grub_be_to_cpu32 (reg[cells - 2])) << 32; + return val; +} + +static volatile void * +translate (const struct grub_fdtbus_dev *dev, const grub_uint32_t *reg) +{ + volatile void *ret; + const grub_uint32_t *ranges; + grub_size_t ranges_size, cells_per_mapping; + grub_size_t parent_address_cells, child_address_cells, child_size_cells; + grub_size_t nmappings, i; + if (dev == 0) + { + grub_uint64_t val; + val = get64 (reg, root_address_cells); + if (sizeof (void *) == 4 && (val >> 32)) + return grub_fdtbus_invalid_mapping; + return (void *) (grub_addr_t) val; + } + ranges = grub_fdt_get_prop (dtb, dev->node, "ranges", &ranges_size); + if (!ranges) + return grub_fdtbus_invalid_mapping; + if (ranges_size == 0) + return translate (dev->parent, reg); + parent_address_cells = get_address_cells (dev->parent); + child_address_cells = get_address_cells (dev); + child_size_cells = get_size_cells (dev); + cells_per_mapping = parent_address_cells + child_address_cells + child_size_cells; + nmappings = ranges_size / 4 / cells_per_mapping; + for (i = 0; i < nmappings; i++) + { + const grub_uint32_t *child_addr = &ranges[i * cells_per_mapping]; + const grub_uint32_t *parent_addr = child_addr + child_address_cells; + grub_uint64_t child_size = get64 (parent_addr + parent_address_cells, child_size_cells); + + if (child_address_cells > 2 && grub_memcmp (reg, child_addr, (child_address_cells - 2) * 4) != 0) + continue; + if (get64 (reg, child_address_cells) < get64 (child_addr, child_address_cells)) + continue; + + grub_uint64_t offset = get64 (reg, child_address_cells) - get64 (child_addr, child_address_cells); + if (offset >= child_size) + continue; + + ret = translate (dev->parent, parent_addr); + if (grub_fdtbus_is_mapping_valid (ret)) + ret = (volatile char *) ret + offset; + return ret; + } + return grub_fdtbus_invalid_mapping; +} + +volatile void * +grub_fdtbus_map_reg (const struct grub_fdtbus_dev *dev, int regno, grub_size_t *size) +{ + grub_size_t address_cells, size_cells; + address_cells = get_address_cells (dev->parent); + size_cells = get_size_cells (dev->parent); + const grub_uint32_t *reg = grub_fdt_get_prop (dtb, dev->node, "reg", 0); + if (size && size_cells) + *size = reg[(address_cells + size_cells) * regno + address_cells]; + if (size && !size_cells) + *size = 0; + return translate (dev->parent, reg + (address_cells + size_cells) * regno); +} + +const char * +grub_fdtbus_get_name (const struct grub_fdtbus_dev *dev) +{ + return grub_fdt_get_nodename (dtb, dev->node); +} + +const void * +grub_fdtbus_get_prop (const struct grub_fdtbus_dev *dev, + const char *name, + grub_uint32_t *len) +{ + return grub_fdt_get_prop (dtb, dev->node, name, len); +} + +const void * +grub_fdtbus_get_fdt (void) +{ + return dtb; +} diff --git a/grub-core/bus/i386/ieee1275/pci.c b/grub-core/bus/i386/ieee1275/pci.c new file mode 100644 index 000000000..1fd3b5610 --- /dev/null +++ b/grub-core/bus/i386/ieee1275/pci.c @@ -0,0 +1,42 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +volatile void * +grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)), + grub_addr_t base, + grub_size_t size) +{ + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_REAL_MODE)) + return (volatile void *) base; + if (grub_ieee1275_map (base, base, size, 7)) + grub_fatal ("couldn't map 0x%lx", base); + return (volatile void *) base; +} + +void +grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)), + volatile void *mem __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused))) +{ +} diff --git a/grub-core/bus/pci.c b/grub-core/bus/pci.c index 17dea30a1..c1ee9dc58 100644 --- a/grub-core/bus/pci.c +++ b/grub-core/bus/pci.c @@ -98,7 +98,7 @@ grub_pci_make_address (grub_pci_device_t dev, int reg) } void -grub_pci_iterate (grub_pci_iteratefunc_t hook) +grub_pci_iterate (grub_pci_iteratefunc_t hook, void *hook_data) { grub_pci_device_t dev; grub_pci_address_t addr; @@ -125,7 +125,7 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) continue; } - if (hook (dev, id)) + if (hook (dev, id, hook_data)) return; /* Probe only func = 0 if the device if not multifunction */ @@ -159,12 +159,12 @@ grub_pci_find_capability (grub_pci_device_t dev, grub_uint8_t cap) pos &= ~3; - addr = grub_pci_make_address (dev, pos); + addr = grub_pci_make_address (dev, pos); id = grub_pci_read_byte (addr); if (id == 0xff) break; - + if (id == cap) return pos; pos++; diff --git a/grub-core/bus/spi/rk3288_spi.c b/grub-core/bus/spi/rk3288_spi.c new file mode 100644 index 000000000..aacb79ffe --- /dev/null +++ b/grub-core/bus/spi/rk3288_spi.c @@ -0,0 +1,103 @@ +/* + * GRUB -- GRand Unified Bootloader + * + * Copyright (C) 2012 Google Inc. + * Copyright (C) 2016 Free Software Foundation, Inc. + * + * This is based on depthcharge code. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +static grub_err_t +spi_send (const struct grub_fdtbus_dev *dev, const void *data, grub_size_t sz) +{ + const grub_uint8_t *ptr = data, *end = ptr + sz; + volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0); + spi[2] = 0; + spi[1] = sz - 1; + spi[0] = ((1 << 18) | spi[0]) & ~(1 << 19); + spi[2] = 1; + while (ptr < end) + { + while (spi[9] & 2); + spi[256] = *ptr++; + } + while (spi[9] & 1); + return GRUB_ERR_NONE; +} + +static grub_err_t +spi_receive (const struct grub_fdtbus_dev *dev, void *data, grub_size_t sz) +{ + grub_uint8_t *ptr = data, *end = ptr + sz; + volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0); + spi[2] = 0; + spi[1] = sz - 1; + spi[0] = ((1 << 19) | spi[0]) & ~(1 << 18); + spi[2] = 1; + while (ptr < end) + { + while (spi[9] & 8); + *ptr++ = spi[512]; + } + while (spi[9] & 1); + return GRUB_ERR_NONE; +} + +static grub_err_t +spi_start (const struct grub_fdtbus_dev *dev) +{ + volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0); + spi[3] = 1; + return GRUB_ERR_NONE; +} + +static void +spi_stop (const struct grub_fdtbus_dev *dev) +{ + volatile grub_uint32_t *spi = grub_fdtbus_map_reg (dev, 0, 0); + spi[3] = 0; +} + +static grub_err_t +spi_attach(const struct grub_fdtbus_dev *dev) +{ + if (!grub_fdtbus_is_mapping_valid (grub_fdtbus_map_reg (dev, 0, 0))) + return GRUB_ERR_IO; + + return GRUB_ERR_NONE; +} + +static struct grub_fdtbus_driver spi = +{ + .compatible = "rockchip,rk3288-spi", + .attach = spi_attach, + .send = spi_send, + .receive = spi_receive, + .start = spi_start, + .stop = spi_stop, +}; + +void +grub_rk3288_spi_init (void) +{ + grub_fdtbus_register (&spi); +} diff --git a/grub-core/bus/usb/ehci-fdt.c b/grub-core/bus/usb/ehci-fdt.c new file mode 100644 index 000000000..29b50bdd5 --- /dev/null +++ b/grub-core/bus/usb/ehci-fdt.c @@ -0,0 +1,45 @@ +/* ehci.c - EHCI Support. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +static grub_err_t +ehci_attach(const struct grub_fdtbus_dev *dev) +{ + grub_dprintf ("ehci", "Found generic-ehci\n"); + + grub_ehci_init_device (grub_fdtbus_map_reg (dev, 0, 0)); + return 0; +} + +struct grub_fdtbus_driver ehci = +{ + .compatible = "generic-ehci", + .attach = ehci_attach +}; + +void +grub_ehci_pci_scan (void) +{ + grub_fdtbus_register (&ehci); +} diff --git a/grub-core/bus/usb/ehci-pci.c b/grub-core/bus/usb/ehci-pci.c new file mode 100644 index 000000000..aa04988fd --- /dev/null +++ b/grub-core/bus/usb/ehci-pci.c @@ -0,0 +1,208 @@ +/* ehci.c - EHCI Support. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#define GRUB_EHCI_PCI_SBRN_REG 0x60 +#define GRUB_EHCI_ADDR_MEM_MASK (~0xff) + +/* USBLEGSUP bits and related OS OWNED byte offset */ +enum +{ + GRUB_EHCI_BIOS_OWNED = (1 << 16), + GRUB_EHCI_OS_OWNED = (1 << 24) +}; + +/* PCI iteration function... */ +static int +grub_ehci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + volatile grub_uint32_t *regs; + grub_uint32_t base, base_h; + grub_uint32_t eecp_offset; + grub_uint32_t usblegsup = 0; + grub_uint64_t maxtime; + grub_uint32_t interf; + grub_uint32_t subclass; + grub_uint32_t class; + grub_uint8_t release; + grub_uint32_t class_code; + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n"); + + if (pciid == GRUB_CS5536_PCIID) + { + grub_uint64_t basereg; + + basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE); + if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE)) + { + /* Shouldn't happen. */ + grub_dprintf ("ehci", "No EHCI address is assigned\n"); + return 0; + } + base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK); + basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER; + basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED; + basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS; + basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE; + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg); + } + else + { + grub_pci_address_t addr; + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class_code = grub_pci_read (addr) >> 8; + interf = class_code & 0xFF; + subclass = (class_code >> 8) & 0xFF; + class = class_code >> 16; + + /* If this is not an EHCI controller, just return. */ + if (class != 0x0c || subclass != 0x03 || interf != 0x20) + return 0; + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n"); + + /* Check Serial Bus Release Number */ + addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG); + release = grub_pci_read_byte (addr); + if (release != 0x20) + { + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n", + release); + return 0; + } + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n"); + + /* Determine EHCI EHCC registers base address. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + base = grub_pci_read (addr); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); + base_h = grub_pci_read (addr); + /* Stop if registers are mapped above 4G - GRUB does not currently + * work with registers mapped above 4G */ + if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32) + && (base_h != 0)) + { + grub_dprintf ("ehci", + "EHCI grub_ehci_pci_iter: registers above 4G are not supported\n"); + return 0; + } + base &= GRUB_PCI_ADDR_MEM_MASK; + if (!base) + { + grub_dprintf ("ehci", + "EHCI: EHCI is not mapped\n"); + return 0; + } + + /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word(addr, + GRUB_PCI_COMMAND_MEM_ENABLED + | GRUB_PCI_COMMAND_BUS_MASTER + | grub_pci_read_word(addr)); + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n"); + } + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n", + (base & GRUB_EHCI_ADDR_MEM_MASK)); + + regs = grub_pci_device_map_range (dev, + (base & GRUB_EHCI_ADDR_MEM_MASK), + 0x100); + + /* Is there EECP ? */ + eecp_offset = (grub_le_to_cpu32 (regs[2]) >> 8) & 0xff; + + /* Determine and change ownership. */ + /* EECP offset valid in HCCPARAMS */ + /* Ownership can be changed via EECP only */ + if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40) + { + grub_pci_address_t pciaddr_eecp; + pciaddr_eecp = grub_pci_make_address (dev, eecp_offset); + + usblegsup = grub_pci_read (pciaddr_eecp); + if (usblegsup & GRUB_EHCI_BIOS_OWNED) + { + grub_boot_time ("Taking ownership of EHCI controller"); + grub_dprintf ("ehci", + "EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n"); + /* Ownership change - set OS_OWNED bit */ + grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED); + /* Ensure PCI register is written */ + grub_pci_read (pciaddr_eecp); + + /* Wait for finish of ownership change, EHCI specification + * doesn't say how long it can take... */ + maxtime = grub_get_time_ms () + 1000; + while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED) + && (grub_get_time_ms () < maxtime)); + if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED) + { + grub_dprintf ("ehci", + "EHCI grub_ehci_pci_iter: EHCI change ownership timeout"); + /* Change ownership in "hard way" - reset BIOS ownership */ + grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED); + /* Ensure PCI register is written */ + grub_pci_read (pciaddr_eecp); + } + } + else if (usblegsup & GRUB_EHCI_OS_OWNED) + /* XXX: What to do in this case - nothing ? Can it happen ? */ + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n"); + else + { + grub_dprintf ("ehci", + "EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n"); + /* XXX: What to do in this case ? Can it happen ? + * Is code below correct ? */ + /* Ownership change - set OS_OWNED bit */ + grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED); + /* Ensure PCI register is written */ + grub_pci_read (pciaddr_eecp); + } + + /* Disable SMI, just to be sure. */ + pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4); + grub_pci_write (pciaddr_eecp, 0); + /* Ensure PCI register is written */ + grub_pci_read (pciaddr_eecp); + } + + grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n"); + + grub_ehci_init_device (regs); + return 0; +} + +void +grub_ehci_pci_scan (void) +{ + grub_pci_iterate (grub_ehci_pci_iter, NULL); +} diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c index b7005192b..2db07c7c0 100644 --- a/grub-core/bus/usb/ehci.c +++ b/grub-core/bus/usb/ehci.c @@ -22,12 +22,11 @@ #include #include #include -#include -#include -#include #include #include -#include +#include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -37,8 +36,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); * - is not supporting interrupt transfers */ -#define GRUB_EHCI_PCI_SBRN_REG 0x60 - /* Capability registers offsets */ enum { @@ -52,7 +49,6 @@ enum #define GRUB_EHCI_EECP_MASK (0xff << 8) #define GRUB_EHCI_EECP_SHIFT 8 -#define GRUB_EHCI_ADDR_MEM_MASK (~0xff) #define GRUB_EHCI_POINTER_MASK (~0x1f) /* Capability register SPARAMS bits */ @@ -83,13 +79,6 @@ enum #define GRUB_EHCI_QH_EMPTY 1 -/* USBLEGSUP bits and related OS OWNED byte offset */ -enum -{ - GRUB_EHCI_BIOS_OWNED = (1 << 16), - GRUB_EHCI_OS_OWNED = (1 << 24) -}; - /* Operational registers offsets */ enum { @@ -229,7 +218,7 @@ enum #define GRUB_EHCI_TERMINATE (1<<0) -#define GRUB_EHCI_TOGGLE (1<<31) +#define GRUB_EHCI_TOGGLE ((grub_uint32_t) 1<<31) enum { @@ -336,6 +325,21 @@ struct grub_ehci static struct grub_ehci *ehci; +static void +sync_all_caches (struct grub_ehci *e) +{ + if (!e) + return; + if (e->td_virt) + grub_arch_sync_dma_caches (e->td_virt, sizeof (struct grub_ehci_td) * + GRUB_EHCI_N_TD); + if (e->qh_virt) + grub_arch_sync_dma_caches (e->qh_virt, sizeof (struct grub_ehci_qh) * + GRUB_EHCI_N_QH); + if (e->framelist_virt) + grub_arch_sync_dma_caches (e->framelist_virt, 4096); +} + /* EHCC registers access functions */ static inline grub_uint32_t grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr) @@ -436,9 +440,12 @@ grub_ehci_reset (struct grub_ehci *e) { grub_uint64_t maxtime; + sync_all_caches (e); + + grub_dprintf ("ehci", "reset\n"); + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, - GRUB_EHCI_CMD_HC_RESET - | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + GRUB_EHCI_CMD_HC_RESET); /* Ensure command is written */ grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND); /* XXX: How long time could take reset of HC ? */ @@ -454,102 +461,24 @@ grub_ehci_reset (struct grub_ehci *e) } /* PCI iteration function... */ -static int NESTED_FUNC_ATTR -grub_ehci_pci_iter (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__ ((unused))) +void +grub_ehci_init_device (volatile void *regs) { - grub_uint8_t release; - grub_uint32_t class_code; - grub_uint32_t interf; - grub_uint32_t subclass; - grub_uint32_t class; - grub_uint32_t base, base_h; struct grub_ehci *e; - grub_uint32_t eecp_offset; grub_uint32_t fp; int i; - grub_uint32_t usblegsup = 0; - grub_uint64_t maxtime; grub_uint32_t n_ports; grub_uint8_t caplen; - grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n"); - - if (pciid == GRUB_CS5536_PCIID) - { - grub_uint64_t basereg; - - basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE); - if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE)) - { - /* Shouldn't happen. */ - grub_dprintf ("ehci", "No EHCI address is assigned\n"); - return 0; - } - base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK); - basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER; - basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED; - basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS; - basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE; - grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg); - } - else - { - grub_pci_address_t addr; - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class_code = grub_pci_read (addr) >> 8; - interf = class_code & 0xFF; - subclass = (class_code >> 8) & 0xFF; - class = class_code >> 16; - - /* If this is not an EHCI controller, just return. */ - if (class != 0x0c || subclass != 0x03 || interf != 0x20) - return 0; - - grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n"); - - /* Check Serial Bus Release Number */ - addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG); - release = grub_pci_read_byte (addr); - if (release != 0x20) - { - grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n", - release); - return 0; - } - grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n"); - - /* Determine EHCI EHCC registers base address. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - base = grub_pci_read (addr); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); - base_h = grub_pci_read (addr); - /* Stop if registers are mapped above 4G - GRUB does not currently - * work with registers mapped above 4G */ - if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32) - && (base_h != 0)) - { - grub_dprintf ("ehci", - "EHCI grub_ehci_pci_iter: registers above 4G are not supported\n"); - return 0; - } - - grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n"); - } - /* Allocate memory for the controller and fill basic values. */ e = grub_zalloc (sizeof (*e)); if (!e) - return 1; + return; e->framelist_chunk = NULL; e->td_chunk = NULL; e->qh_chunk = NULL; - e->iobase_ehcc = grub_pci_device_map_range (dev, - (base & GRUB_EHCI_ADDR_MEM_MASK), - 0x100); + e->iobase_ehcc = regs; - grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n", - (base & GRUB_EHCI_ADDR_MEM_MASK)); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CAPLEN: %02x\n", grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN)); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: VERSION: %04x\n", @@ -565,18 +494,18 @@ grub_ehci_pci_iter (grub_pci_device_t dev, if (caplen & (sizeof (grub_uint32_t) - 1)) { grub_dprintf ("ehci", "Unaligned caplen\n"); - return 0; + return; } e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc + (caplen / sizeof (grub_uint32_t))); -#else - e->iobase = (volatile grub_uint32_t *) +#else + e->iobase = (volatile grub_uint32_t *) ((grub_uint8_t *) e->iobase_ehcc + caplen); #endif grub_dprintf ("ehci", - "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n", - (base & GRUB_EHCI_ADDR_MEM_MASK) + caplen); + "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08llxx\n", + (unsigned long long) (grub_addr_t) e->iobase_ehcc + caplen); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n", grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n", @@ -592,10 +521,6 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n", grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG)); - /* Is there EECP ? */ - eecp_offset = (grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS) - & GRUB_EHCI_EECP_MASK) >> GRUB_EHCI_EECP_SHIFT; - /* Check format of data structures requested by EHCI */ /* XXX: In fact it is not used at any place, it is prepared for future * This implementation uses 32-bits pointers only */ @@ -655,23 +580,23 @@ grub_ehci_pci_iter (grub_pci_device_t dev, for (i = 0; i < (GRUB_EHCI_N_TD - 1); i++) { e->td_virt[i].link_td = e->td_phys + (i + 1) * sizeof (struct grub_ehci_td); - e->td_virt[i].next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); - e->td_virt[i].alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + e->td_virt[i].next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + e->td_virt[i].alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); } e->td_virt[GRUB_EHCI_N_TD - 1].next_td = - grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); e->td_virt[GRUB_EHCI_N_TD - 1].alt_next_td = - grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); e->tdfree_virt = e->td_virt; /* Set Terminate in first QH, which is used in framelist */ - e->qh_virt[0].qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); - e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + e->qh_virt[0].qh_hptr = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH); + e->qh_virt[0].td_overlay.next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); e->qh_virt[0].td_overlay.alt_next_td = - grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); /* Also set Halted bit in token */ - e->qh_virt[0].td_overlay.token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED); + e->qh_virt[0].td_overlay.token = grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED); /* Set the H bit in first QH used for AL */ - e->qh_virt[1].ep_char = grub_cpu_to_le32 (GRUB_EHCI_H); + e->qh_virt[1].ep_char = grub_cpu_to_le32_compile_time (GRUB_EHCI_H); /* Set Terminate into TD in rest of QHs and set horizontal link * pointer to itself - these QHs will be used for asynchronous * schedule and they should have valid value in horiz. link */ @@ -682,12 +607,12 @@ grub_ehci_pci_iter (grub_pci_device_t dev, e->qh_chunk) & GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH); e->qh_virt[i].td_overlay.next_td = - grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); e->qh_virt[i].td_overlay.alt_next_td = - grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); /* Also set Halted bit in token */ e->qh_virt[i].td_overlay.token = - grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED); + grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED); } /* Note: QH 0 and QH 1 are reserved and must not be used anywhere. @@ -699,67 +624,6 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH/TD init. OK\n"); - /* Determine and change ownership. */ - /* EECP offset valid in HCCPARAMS */ - /* Ownership can be changed via EECP only */ - if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40) - { - grub_pci_address_t pciaddr_eecp; - pciaddr_eecp = grub_pci_make_address (dev, eecp_offset); - - usblegsup = grub_pci_read (pciaddr_eecp); - if (usblegsup & GRUB_EHCI_BIOS_OWNED) - { - grub_dprintf ("ehci", - "EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n"); - /* Ownership change - set OS_OWNED bit */ - grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED); - /* Ensure PCI register is written */ - grub_pci_read (pciaddr_eecp); - - /* Wait for finish of ownership change, EHCI specification - * doesn't say how long it can take... */ - maxtime = grub_get_time_ms () + 1000; - while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED) - && (grub_get_time_ms () < maxtime)); - if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED) - { - grub_dprintf ("ehci", - "EHCI grub_ehci_pci_iter: EHCI change ownership timeout"); - /* Change ownership in "hard way" - reset BIOS ownership */ - grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED); - /* Ensure PCI register is written */ - grub_pci_read (pciaddr_eecp); - /* Disable SMI. */ - pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4); - grub_pci_write (pciaddr_eecp, 0); - /* Ensure PCI register is written */ - grub_pci_read (pciaddr_eecp); - } - } - else if (usblegsup & GRUB_EHCI_OS_OWNED) - /* XXX: What to do in this case - nothing ? Can it happen ? */ - grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n"); - else - { - grub_dprintf ("ehci", - "EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n"); - /* XXX: What to do in this case ? Can it happen ? - * Is code below correct ? */ - /* Ownership change - set OS_OWNED bit */ - grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED); - /* Ensure PCI register is written */ - grub_pci_read (pciaddr_eecp); - /* Disable SMI, just to be sure. */ - pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4); - grub_pci_write (pciaddr_eecp, 0); - /* Ensure PCI register is written */ - grub_pci_read (pciaddr_eecp); - } - } - - grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n"); - /* Now we can setup EHCI (maybe...) */ /* Check if EHCI is halted and halt it if not */ @@ -791,7 +655,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, /* Set ownership of root hub ports to EHCI */ grub_ehci_oper_write32 (e, GRUB_EHCI_CONFIG_FLAG, GRUB_EHCI_CF_EHCI_OWNER); - /* Enable asynchronous list */ + /* Enable both lists */ grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, GRUB_EHCI_CMD_AS_ENABL | GRUB_EHCI_CMD_PS_ENABL @@ -827,11 +691,13 @@ grub_ehci_pci_iter (grub_pci_device_t dev, e->next = ehci; ehci = e; + sync_all_caches (e); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n"); grub_dprintf ("ehci", - "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n", - (base & GRUB_EHCI_ADDR_MEM_MASK)); + "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08llx\n", + (unsigned long long) (grub_addr_t) regs); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n", grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n", @@ -847,7 +713,7 @@ grub_ehci_pci_iter (grub_pci_device_t dev, grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n", grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG)); - return 0; + return; fail: if (e) @@ -861,11 +727,11 @@ fail: } grub_free (e); - return 0; + return; } static int -grub_ehci_iterate (int (*hook) (grub_usb_controller_t dev)) +grub_ehci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) { struct grub_ehci *e; struct grub_usb_controller dev; @@ -873,7 +739,7 @@ grub_ehci_iterate (int (*hook) (grub_usb_controller_t dev)) for (e = ehci; e; e = e->next) { dev.data = e; - if (hook (&dev)) + if (hook (&dev, hook_data)) return 1; } @@ -935,9 +801,9 @@ grub_ehci_setup_qh (grub_ehci_qh_t qh, grub_usb_transfer_t transfer) * SplitCompletionMask - AFAIK it is ignored in asynchronous list, * InterruptScheduleMask - AFAIK it should be zero in async. list */ ep_cap |= GRUB_EHCI_MULT_THREE; - ep_cap |= (transfer->dev->port << GRUB_EHCI_DEVPORT_OFF) + ep_cap |= (transfer->dev->split_hubport << GRUB_EHCI_DEVPORT_OFF) & GRUB_EHCI_DEVPORT_MASK; - ep_cap |= (transfer->dev->hubaddr << GRUB_EHCI_HUBADDR_OFF) + ep_cap |= (transfer->dev->split_hubaddr << GRUB_EHCI_HUBADDR_OFF) & GRUB_EHCI_HUBADDR_MASK; if (transfer->dev->speed == GRUB_USB_SPEED_LOW && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL) @@ -969,28 +835,70 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer) int i; grub_ehci_qh_t qh = e->qh_virt; grub_ehci_qh_t head; + grub_uint32_t qh_phys; + grub_uint32_t qh_terminate = + GRUB_EHCI_TERMINATE | GRUB_EHCI_HPTR_TYPE_QH; + grub_ehci_qh_t qh_iter; /* Prepare part of EP Characteristic to find existing QH */ target = ((transfer->endpoint << GRUB_EHCI_EP_NUM_OFF) | transfer->devaddr) & GRUB_EHCI_TARGET_MASK; target = grub_cpu_to_le32 (target); - mask = grub_cpu_to_le32 (GRUB_EHCI_TARGET_MASK); + mask = grub_cpu_to_le32_compile_time (GRUB_EHCI_TARGET_MASK); - /* First try to find existing QH with proper target */ - for (i = 2; i < GRUB_EHCI_N_QH; i++) /* We ignore zero and first QH */ + /* low speed interrupt transfers are linked to the periodic */ + /* schedule, everything else to the asynchronous schedule */ + if (transfer->dev->speed == GRUB_USB_SPEED_LOW + && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL) + head = &qh[0]; + else + head = &qh[1]; + + /* First try to find existing QH with proper target in proper list */ + qh_phys = grub_le_to_cpu32( head->qh_hptr ); + if (qh_phys != qh_terminate) + qh_iter = grub_dma_phys2virt ( qh_phys & GRUB_EHCI_QHTDPTR_MASK, + e->qh_chunk ); + else + qh_iter = NULL; + + for ( + i = 0; + (qh_phys != qh_terminate) && (qh_iter != NULL) && + (qh_iter != head) && (i < GRUB_EHCI_N_QH); + i++ ) + { + if (target == (qh_iter->ep_char & mask)) + { + /* Found proper existing (and linked) QH, do setup of QH */ + grub_dprintf ("ehci", "find_qh: found, QH=%p\n", qh_iter); + grub_ehci_setup_qh (qh_iter, transfer); + sync_all_caches (e); + return qh_iter; + } + + qh_phys = grub_le_to_cpu32( qh_iter->qh_hptr ); + if (qh_phys != qh_terminate) + qh_iter = grub_dma_phys2virt ( qh_phys & GRUB_EHCI_QHTDPTR_MASK, + e->qh_chunk ); + else + qh_iter = NULL; + } + + /* variable "i" should be never equal to GRUB_EHCI_N_QH here */ + if (i >= GRUB_EHCI_N_QH) + { /* Something very bad happened in QH list(s) ! */ + grub_dprintf ("ehci", "find_qh: Mismatch in QH list! head=%p\n", + head); + } + + /* QH with target_addr does not exist, we have to find and add it */ + for (i = 2; i < GRUB_EHCI_N_QH; i++) /* We ignore zero and first QH */ { if (!qh[i].ep_char) - break; /* Found first not-allocated QH, finish */ - if (target == (qh[i].ep_char & mask)) - { - /* Found proper existing (and linked) QH, do setup of QH */ - grub_dprintf ("ehci", "find_qh: found, i=%d, QH=%p\n", - i, &qh[i]); - grub_ehci_setup_qh (&qh[i], transfer); - return &qh[i]; - } + break; /* Found first not-allocated QH, finish */ } - /* QH with target_addr does not exist, we have to add it */ + /* Have we any free QH in array ? */ if (i >= GRUB_EHCI_N_QH) /* No. */ { @@ -1005,14 +913,6 @@ grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer) /* We should preset new QH and link it into AL */ grub_ehci_setup_qh (&qh[i], transfer); - /* low speed interrupt transfers are linked to the periodic - * scheudle, everything else to the asynchronous schedule */ - if (transfer->dev->speed == GRUB_USB_SPEED_LOW - && transfer->type != GRUB_USB_TRANSACTION_TYPE_CONTROL) - head = &qh[0]; - else - head = &qh[1]; - /* Linking - this new (last) QH will copy the QH from the head QH */ qh[i].qh_hptr = head->qh_hptr; /* Linking - the head QH will point to this new QH */ @@ -1075,7 +975,7 @@ grub_ehci_free_tds (struct grub_ehci *e, grub_ehci_td_t td, token = grub_le_to_cpu32 (td->token); to_transfer = (token & GRUB_EHCI_TOTAL_MASK) >> GRUB_EHCI_TOTAL_OFF; - /* Check state of TD - if it did not transfered + /* Check state of TD - if it did not transfer * whole data then set last_trans - it should be last executed TD * in case when something went wrong. */ if (transfer && (td->size != to_transfer)) @@ -1154,7 +1054,7 @@ grub_ehci_transaction (struct grub_ehci *e, grub_memset ((void *) td, 0, sizeof (struct grub_ehci_td)); /* Don't point to any TD yet, just terminate. */ - td->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + td->next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); /* Set alternate pointer. When short packet occurs, alternate TD * will not be really fetched because it is not active. But don't * forget, EHCI will try to fetch alternate TD every scan of AL @@ -1243,25 +1143,27 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev, grub_ehci_td_t td_prev = NULL; int i; struct grub_ehci_transfer_controller_data *cdata; + grub_uint32_t status; + + sync_all_caches (e); /* Check if EHCI is running and AL is enabled */ - if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) - & GRUB_EHCI_ST_HC_HALTED) != 0) + status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS); + if ((status & GRUB_EHCI_ST_HC_HALTED) != 0) /* XXX: Fix it: Currently we don't do anything to restart EHCI */ - return GRUB_USB_ERR_INTERNAL; - if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) + { + grub_dprintf ("ehci", "setup_transfer: halted, status = 0x%x\n", + status); + return GRUB_USB_ERR_INTERNAL; + } + status = grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS); + if ((status & (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0) /* XXX: Fix it: Currently we don't do anything to restart EHCI */ - return GRUB_USB_ERR_INTERNAL; - - /* Check if transfer is not high speed and connected to root hub. - * It should not happened but... */ - if ((transfer->dev->speed != GRUB_USB_SPEED_HIGH) - && !transfer->dev->hubaddr) { - grub_error (GRUB_USB_ERR_BADDEVICE, - "FULL/LOW speed device on EHCI port!?!"); - return GRUB_USB_ERR_BADDEVICE; + grub_dprintf ("ehci", "setup_transfer: no AS/PS, status = 0x%x\n", + status); + return GRUB_USB_ERR_INTERNAL; } /* Allocate memory for controller transfer data. */ @@ -1274,6 +1176,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev, cdata->qh_virt = grub_ehci_find_qh (e, transfer); if (!cdata->qh_virt) { + grub_dprintf ("ehci", "setup_transfer: no QH\n"); grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } @@ -1283,15 +1186,16 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev, cdata->td_alt_virt = grub_ehci_alloc_td (e); if (!cdata->td_alt_virt) { + grub_dprintf ("ehci", "setup_transfer: no TDs\n"); grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } /* Fill whole alternate TD by zeros (= inactive) and set * Terminate bits and Halt bit */ grub_memset ((void *) cdata->td_alt_virt, 0, sizeof (struct grub_ehci_td)); - cdata->td_alt_virt->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); - cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); - cdata->td_alt_virt->token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED); + cdata->td_alt_virt->next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); + cdata->td_alt_virt->token = grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED); /* Allocate appropriate number of TDs and set */ for (i = 0; i < transfer->transcnt; i++) @@ -1309,6 +1213,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev, grub_ehci_free_tds (e, cdata->td_first_virt, NULL, &actual); grub_free (cdata); + grub_dprintf ("ehci", "setup_transfer: no TD\n"); return GRUB_USB_ERR_INTERNAL; } @@ -1328,7 +1233,7 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev, cdata->td_last_virt = td; cdata->td_last_phys = grub_dma_virt2phys (td, e->td_chunk); /* Last TD should not have set alternate TD */ - cdata->td_last_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + cdata->td_last_virt->alt_next_td = grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); grub_dprintf ("ehci", "setup_transfer: cdata=%p, qh=%p\n", cdata,cdata->qh_virt); @@ -1341,14 +1246,16 @@ grub_ehci_setup_transfer (grub_usb_controller_t dev, /* Start transfer: */ /* Unlink possible alternate pointer in QH */ cdata->qh_virt->td_overlay.alt_next_td = - grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + grub_cpu_to_le32_compile_time (GRUB_EHCI_TERMINATE); /* Link new TDs with QH via next_td */ cdata->qh_virt->td_overlay.next_td = grub_cpu_to_le32 (grub_dma_virt2phys (cdata->td_first_virt, e->td_chunk)); /* Reset Active and Halted bits in QH to activate Advance Queue, * i.e. reset token */ - cdata->qh_virt->td_overlay.token = grub_cpu_to_le32 (0); + cdata->qh_virt->td_overlay.token = grub_cpu_to_le32_compile_time (0); + + sync_all_caches (e); /* Finito */ transfer->controller_data = cdata; @@ -1372,9 +1279,9 @@ grub_ehci_pre_finish_transfer (grub_usb_transfer_t transfer) * safely manipulate with QH TD part. */ cdata->qh_virt->td_overlay.token = (cdata->qh_virt->td_overlay.token | - grub_cpu_to_le32 + grub_cpu_to_le32_compile_time (GRUB_EHCI_STATUS_HALTED)) & - grub_cpu_to_le32 (~GRUB_EHCI_STATUS_ACTIVE); + grub_cpu_to_le32_compile_time (~GRUB_EHCI_STATUS_ACTIVE); /* Print debug data here if necessary */ @@ -1398,6 +1305,8 @@ grub_ehci_parse_notrun (grub_usb_controller_t dev, grub_ehci_free_td (e, cdata->td_alt_virt); grub_free (cdata); + sync_all_caches (e); + /* Additionally, do something with EHCI to make it running (what?) */ /* Try enable EHCI and AL */ grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, @@ -1433,6 +1342,8 @@ grub_ehci_parse_halt (grub_usb_controller_t dev, grub_ehci_free_td (e, cdata->td_alt_virt); grub_free (cdata); + sync_all_caches (e); + /* Evaluation of error code - currently we don't have GRUB USB error * codes for some EHCI states, GRUB_USB_ERR_DATA is used for them. * Order of evaluation is critical, specially bubble/stall. */ @@ -1466,6 +1377,8 @@ grub_ehci_parse_success (grub_usb_controller_t dev, grub_ehci_free_td (e, cdata->td_alt_virt); grub_free (cdata); + sync_all_caches (e); + return GRUB_USB_ERR_NONE; } @@ -1477,7 +1390,9 @@ grub_ehci_check_transfer (grub_usb_controller_t dev, struct grub_ehci *e = dev->data; struct grub_ehci_transfer_controller_data *cdata = transfer->controller_data; - grub_uint32_t token; + grub_uint32_t token, token_ftd; + + sync_all_caches (e); grub_dprintf ("ehci", "check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n", @@ -1505,13 +1420,18 @@ grub_ehci_check_transfer (grub_usb_controller_t dev, return grub_ehci_parse_notrun (dev, transfer, actual); token = grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token); + /* If the transfer consist from only one TD, we should check */ + /* if the TD was really executed and deactivated - to prevent */ + /* false detection of transfer finish. */ + token_ftd = grub_le_to_cpu32 (cdata->td_first_virt->token); /* Detect QH halted */ if ((token & GRUB_EHCI_STATUS_HALTED) != 0) return grub_ehci_parse_halt (dev, transfer, actual); /* Detect QH not active - QH is not active and no next TD */ - if ((token & GRUB_EHCI_STATUS_ACTIVE) == 0) + if (token && ((token & GRUB_EHCI_STATUS_ACTIVE) == 0) + && ((token_ftd & GRUB_EHCI_STATUS_ACTIVE) == 0)) { /* It could be finish at all or short packet condition */ if ((grub_le_to_cpu32 (cdata->qh_virt->td_overlay.next_td) @@ -1541,32 +1461,40 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev, grub_uint64_t maxtime; grub_uint32_t qh_phys; + sync_all_caches (e); + + grub_uint32_t interrupt = + cdata->qh_virt->ep_cap & GRUB_EHCI_SMASK_MASK; + /* QH can be active and should be de-activated and halted */ grub_dprintf ("ehci", "cancel_transfer: begin\n"); - /* First check if EHCI is running and AL is enabled and if not, - * there is no problem... */ - if (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) - & GRUB_EHCI_ST_HC_HALTED) != 0) || - ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) - & (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0)) + /* First check if EHCI is running - if not, there is no problem */ + /* to cancel any transfer. Or, if transfer is asynchronous, check */ + /* if AL is enabled - if not, transfer can be canceled also. */ + if (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) & + GRUB_EHCI_ST_HC_HALTED) != 0) || + (!interrupt && ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) & + (GRUB_EHCI_ST_AS_STATUS | GRUB_EHCI_ST_PS_STATUS)) == 0))) { grub_ehci_pre_finish_transfer (transfer); grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual); grub_ehci_free_td (e, cdata->td_alt_virt); grub_free (cdata); + sync_all_caches (e); grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n"); return GRUB_USB_ERR_NONE; } - /* EHCI and AL are running. What to do? - * Try to Halt QH via de-scheduling QH. */ + /* EHCI and (AL or SL) are running. What to do? */ + /* Try to Halt QH via de-scheduling QH. */ /* Find index of previous QH */ qh_phys = grub_dma_virt2phys(cdata->qh_virt, e->qh_chunk); for (i = 0; i < GRUB_EHCI_N_QH; i++) { - if ((e->qh_virt[i].qh_hptr & GRUB_EHCI_QHTDPTR_MASK) == qh_phys) + if ((grub_le_to_cpu32(e->qh_virt[i].qh_hptr) + & GRUB_EHCI_QHTDPTR_MASK) == qh_phys) break; } if (i == GRUB_EHCI_N_QH) @@ -1577,6 +1505,8 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev, /* Unlink QH from AL */ e->qh_virt[i].qh_hptr = cdata->qh_virt->qh_hptr; + sync_all_caches (e); + /* If this is an interrupt transfer, we just wait for the periodic * schedule to advance a few times and then assume that the EHCI * controller has read the updated QH. */ @@ -1620,29 +1550,19 @@ grub_ehci_cancel_transfer (grub_usb_controller_t dev, grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual); grub_ehci_free_td (e, cdata->td_alt_virt); - /* FIXME Putting the QH back on the list should work, but for some - * strange reason doing that will affect other QHs on the periodic - * list. So free the QH instead of putting it back on the list - * which does seem to work, but I would like to know why. */ - -#if 0 - /* Finaly we should return QH back to the AL... */ - e->qh_virt[i].qh_hptr = - grub_cpu_to_le32 (grub_dma_virt2phys - (cdata->qh_virt, e->qh_chunk)); -#else - /* Free the QH */ + /* "Free" the QH - link it to itself */ cdata->qh_virt->ep_char = 0; cdata->qh_virt->qh_hptr = grub_cpu_to_le32 ((grub_dma_virt2phys (cdata->qh_virt, e->qh_chunk) & GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH); -#endif grub_free (cdata); grub_dprintf ("ehci", "cancel_transfer: end\n"); + sync_all_caches (e); + return GRUB_USB_ERR_NONE; } @@ -1658,7 +1578,7 @@ grub_ehci_hubports (grub_usb_controller_t dev) return portinfo; } -static grub_err_t +static grub_usb_err_t grub_ehci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) { @@ -1680,18 +1600,20 @@ grub_ehci_portstatus (grub_usb_controller_t dev, endtime = grub_get_time_ms () + 1000; while (grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_ENABLED) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "portstatus: EHCI Timed out - disable"); + return GRUB_USB_ERR_TIMEOUT; if (!enable) /* We don't need reset port */ { grub_dprintf ("ehci", "portstatus: Disabled.\n"); grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n", grub_ehci_port_read (e, port)); - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } grub_dprintf ("ehci", "portstatus: enable\n"); + grub_boot_time ("Resetting port %d", port); + /* Now we will do reset - if HIGH speed device connected, it will * result in Enabled state, otherwise port remains disabled. */ /* Set RESET bit for 50ms */ @@ -1703,8 +1625,8 @@ grub_ehci_portstatus (grub_usb_controller_t dev, endtime = grub_get_time_ms () + 1000; while (grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_RESET) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, - "portstatus: EHCI Timed out - reset port"); + return GRUB_USB_ERR_TIMEOUT; + grub_boot_time ("Port %d reset", port); /* Remember "we did the reset" - needed by detect_dev */ e->reset |= (1 << port); /* Test if port enabled, i.e. HIGH speed device connected */ @@ -1731,7 +1653,7 @@ grub_ehci_portstatus (grub_usb_controller_t dev, grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n", grub_ehci_port_read (e, port)); - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } static grub_usb_speed_t @@ -1742,11 +1664,6 @@ grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed) status = grub_ehci_port_read (e, port); - grub_dprintf ("ehci", "detect_dev: EHCI STATUS: %08x\n", - grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)); - grub_dprintf ("ehci", "detect_dev: iobase=%p, port=%d, status=0x%02x\n", - e->iobase, port, status); - /* Connect Status Change bit - it detects change of connection */ if (status & GRUB_EHCI_PORT_CONNECT_CH) { @@ -1807,12 +1724,6 @@ grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed) } } -static void -grub_ehci_inithw (void) -{ - grub_pci_iterate (grub_ehci_pci_iter); -} - static grub_err_t grub_ehci_restore_hw (void) { @@ -1866,7 +1777,7 @@ grub_ehci_restore_hw (void) } } - return GRUB_USB_ERR_NONE; + return GRUB_ERR_NONE; } static grub_err_t @@ -1877,16 +1788,19 @@ grub_ehci_fini_hw (int noreturn __attribute__ ((unused))) /* We should disable all EHCI HW to prevent any DMA access etc. */ for (e = ehci; e; e = e->next) { + /* Disable both lists */ + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, + ~(GRUB_EHCI_CMD_AS_ENABL | GRUB_EHCI_CMD_PS_ENABL) + & grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + /* Check if EHCI is halted and halt it if not */ - if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE) - grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI halt timeout"); + grub_ehci_halt (e); /* Reset EHCI */ - if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE) - grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI reset timeout"); + grub_ehci_reset (e); } - return GRUB_USB_ERR_NONE; + return GRUB_ERR_NONE; } static struct grub_usb_controller_dev usb_controller = { @@ -1897,15 +1811,23 @@ static struct grub_usb_controller_dev usb_controller = { .cancel_transfer = grub_ehci_cancel_transfer, .hubports = grub_ehci_hubports, .portstatus = grub_ehci_portstatus, - .detect_dev = grub_ehci_detect_dev + .detect_dev = grub_ehci_detect_dev, + /* estimated max. count of TDs for one bulk transfer */ + .max_bulk_tds = GRUB_EHCI_N_TD * 3 / 4 }; GRUB_MOD_INIT (ehci) { COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_td) == 64); COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_qh) == 96); - grub_ehci_inithw (); + + grub_stop_disk_firmware (); + + grub_boot_time ("Initing EHCI hardware"); + grub_ehci_pci_scan (); + grub_boot_time ("Registering EHCI driver"); grub_usb_controller_dev_register (&usb_controller); + grub_boot_time ("EHCI driver registered"); grub_loader_register_preboot_hook (grub_ehci_fini_hw, grub_ehci_restore_hw, GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } diff --git a/grub-core/bus/usb/emu/usb.c b/grub-core/bus/usb/emu/usb.c deleted file mode 100644 index 38c5f01f1..000000000 --- a/grub-core/bus/usb/emu/usb.c +++ /dev/null @@ -1,203 +0,0 @@ -/* usb.c -- libusb USB support for GRUB. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB 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 GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include - -GRUB_MOD_LICENSE ("GPLv3+"); - - -static struct grub_usb_controller_dev usb_controller = -{ - .name = "libusb" -}; - -static struct grub_usb_device *grub_usb_devs[128]; - -struct usb_bus *busses; - -static grub_err_t -grub_libusb_devices (void) - -{ - struct usb_bus *bus; - int last = 0; - - busses = usb_get_busses(); - - for (bus = busses; bus; bus = bus->next) - { - struct usb_device *usbdev; - struct grub_usb_device *dev; - - for (usbdev = bus->devices; usbdev; usbdev = usbdev->next) - { - struct usb_device_descriptor *desc = &usbdev->descriptor; - grub_err_t err; - - if (! desc->bcdUSB) - continue; - - dev = grub_malloc (sizeof (*dev)); - if (! dev) - return grub_errno; - - dev->data = usbdev; - - /* Fill in all descriptors. */ - err = grub_usb_device_initialize (dev); - if (err) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - - /* Register the device. */ - grub_usb_devs[last++] = dev; - } - } - - return GRUB_USB_ERR_NONE; -} - -void -grub_usb_poll_devices (void) -{ - /* TODO: recheck grub_usb_devs */ -} - - -int -grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) -{ - int i; - - for (i = 0; i < 128; i++) - { - if (grub_usb_devs[i]) - { - if (hook (grub_usb_devs[i])) - return 1; - } - } - - return 0; -} - -grub_usb_err_t -grub_usb_root_hub (grub_usb_controller_t controller __attribute__((unused))) -{ - return GRUB_USB_ERR_NONE; -} - -grub_usb_err_t -grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t reqtype, - grub_uint8_t request, grub_uint16_t value, - grub_uint16_t idx, grub_size_t size, char *data) -{ - usb_dev_handle *devh; - struct usb_device *d = dev->data; - - devh = usb_open (d); - if (usb_control_msg (devh, reqtype, request, - value, idx, data, size, 20) < 0) - { - usb_close (devh); - return GRUB_USB_ERR_STALL; - } - - usb_close (devh); - - return GRUB_USB_ERR_NONE; -} - -grub_usb_err_t -grub_usb_bulk_read (grub_usb_device_t dev, - int endpoint, grub_size_t size, char *data) -{ - usb_dev_handle *devh; - struct usb_device *d = dev->data; - - devh = usb_open (d); - if (usb_claim_interface (devh, 0) < 1) - { - usb_close (devh); - return GRUB_USB_ERR_STALL; - } - - if (usb_bulk_read (devh, endpoint, data, size, 20) < 1) - { - usb_close (devh); - return GRUB_USB_ERR_STALL; - } - - usb_release_interface (devh, 0); - usb_close (devh); - - return GRUB_USB_ERR_NONE; -} - -grub_usb_err_t -grub_usb_bulk_write (grub_usb_device_t dev, - int endpoint, grub_size_t size, char *data) -{ - usb_dev_handle *devh; - struct usb_device *d = dev->data; - - devh = usb_open (d); - if (usb_claim_interface (devh, 0) < 0) - goto fail; - - if (usb_bulk_write (devh, endpoint, data, size, 20) < 0) - goto fail; - - if (usb_release_interface (devh, 0) < 0) - goto fail; - - usb_close (devh); - - return GRUB_USB_ERR_NONE; - - fail: - usb_close (devh); - return GRUB_USB_ERR_STALL; -} - -GRUB_MOD_INIT (libusb) -{ - usb_init(); - usb_find_busses(); - usb_find_devices(); - - if (grub_libusb_devices ()) - return; - - grub_usb_controller_dev_register (&usb_controller); - - return; -} - -GRUB_MOD_FINI (libusb) -{ - return; -} diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index 23cf63187..5363a61f6 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -46,7 +47,7 @@ struct grub_ohci_hcca grub_uint32_t donehead; grub_uint8_t reserved[116]; -} __attribute__((packed)); +} GRUB_PACKED; /* OHCI General Transfer Descriptor */ struct grub_ohci_td @@ -63,7 +64,7 @@ struct grub_ohci_td * physical address in CPU endian */ grub_uint32_t tr_index; /* index of TD in transfer */ grub_uint8_t pad[8 - sizeof (volatile struct grub_ohci_td *)]; /* padding to 32 bytes */ -} __attribute__((packed)); +} GRUB_PACKED; /* OHCI Endpoint Descriptor. */ struct grub_ohci_ed @@ -72,7 +73,7 @@ struct grub_ohci_ed grub_uint32_t td_tail; grub_uint32_t td_head; grub_uint32_t next_ed; -} __attribute__((packed)); +} GRUB_PACKED; typedef volatile struct grub_ohci_td *grub_ohci_td_t; typedef volatile struct grub_ohci_ed *grub_ohci_ed_t; @@ -195,7 +196,7 @@ grub_ohci_td_virt2phys (struct grub_ohci *o, grub_ohci_td_t x) return (grub_uint8_t *)x - (grub_uint8_t *)o->td + o->td_addr; } - + static grub_uint32_t grub_ohci_readreg32 (struct grub_ohci *o, grub_ohci_reg_t reg) { @@ -213,9 +214,9 @@ grub_ohci_writereg32 (struct grub_ohci *o, /* Iterate over all PCI devices. Determine if a device is an OHCI controller. If this is the case, initialize it. */ -static int NESTED_FUNC_ATTR -grub_ohci_pci_iter (grub_pci_device_t dev, - grub_pci_id_t pciid) +static int +grub_ohci_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_uint32_t interf; grub_uint32_t base; @@ -223,7 +224,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, struct grub_ohci *o; grub_uint32_t revision; int j; - + /* Determine IO base address. */ grub_dprintf ("ohci", "pciid = %x\n", pciid); @@ -252,7 +253,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); class_code = grub_pci_read (addr) >> 8; - + interf = class_code & 0xFF; subclass = (class_code >> 8) & 0xFF; class = class_code >> 16; @@ -264,11 +265,20 @@ grub_ohci_pci_iter (grub_pci_device_t dev, addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); base = grub_pci_read (addr); -#if 0 - /* Stop if there is no IO space base address defined. */ - if (! (base & 1)) - return 0; -#endif + base &= GRUB_PCI_ADDR_MEM_MASK; + if (!base) + { + grub_dprintf ("ehci", + "EHCI: EHCI is not mapper\n"); + return 0; + } + + /* Set bus master - needed for coreboot, VMware, broken BIOSes etc. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word(addr, + GRUB_PCI_COMMAND_MEM_ENABLED + | GRUB_PCI_COMMAND_BUS_MASTER + | grub_pci_read_word(addr)); grub_dprintf ("ohci", "class=0x%02x 0x%02x interface 0x%02x\n", class, subclass, interf); @@ -304,8 +314,8 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_memset ((void *) o->ed_ctrl, 0, sizeof (struct grub_ohci_ed) * GRUB_OHCI_CTRL_EDS); for (j=0; j < GRUB_OHCI_CTRL_EDS; j++) - o->ed_ctrl[j].target = grub_cpu_to_le32 (1 << 14); /* skip */ - + o->ed_ctrl[j].target = grub_cpu_to_le32_compile_time (1 << 14); /* skip */ + grub_dprintf ("ohci", "EDs-C: chunk=%p, virt=%p, phys=0x%02x\n", o->ed_ctrl_chunk, o->ed_ctrl, o->ed_ctrl_addr); @@ -319,7 +329,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, /* Preset EDs */ grub_memset ((void*)o->ed_bulk, 0, sizeof(struct grub_ohci_ed) * GRUB_OHCI_BULK_EDS); for (j=0; j < GRUB_OHCI_BULK_EDS; j++) - o->ed_bulk[j].target = grub_cpu_to_le32 (1 << 14); /* skip */ + o->ed_bulk[j].target = grub_cpu_to_le32_compile_time (1 << 14); /* skip */ grub_dprintf ("ohci", "EDs-B: chunk=%p, virt=%p, phys=0x%02x\n", o->ed_bulk_chunk, o->ed_bulk, o->ed_bulk_addr); @@ -375,7 +385,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_dprintf("ohci", "Ownership changing timeout, change forced !\n"); } } - else if (((control & 0x100) == 0) && + else if (((control & 0x100) == 0) && ((control & 0xc0) != 0)) /* Not owned by SMM nor reset */ { grub_dprintf("ohci", "OHCI is owned by BIOS\n"); @@ -386,7 +396,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, { grub_dprintf("ohci", "OHCI is not owned by SMM nor BIOS\n"); /* We can setup OHCI. */ - } + } } /* Suspend the OHCI by issuing a reset. */ @@ -472,13 +482,13 @@ grub_ohci_pci_iter (grub_pci_device_t dev, static void grub_ohci_inithw (void) { - grub_pci_iterate (grub_ohci_pci_iter); + grub_pci_iterate (grub_ohci_pci_iter, NULL); } static int -grub_ohci_iterate (int (*hook) (grub_usb_controller_t dev)) +grub_ohci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) { struct grub_ohci *o; struct grub_usb_controller dev; @@ -486,7 +496,7 @@ grub_ohci_iterate (int (*hook) (grub_usb_controller_t dev)) for (o = ohci; o; o = o->next) { dev.data = o; - if (hook (&dev)) + if (hook (&dev, hook_data)) return 1; } @@ -503,7 +513,7 @@ grub_ohci_find_ed (struct grub_ohci *o, int bulk, grub_uint32_t target) /* Use proper values and structures. */ if (bulk) - { + { count = GRUB_OHCI_BULK_EDS; ed = o->ed_bulk; ed_next = grub_ohci_ed_phys2virt(o, bulk, @@ -566,7 +576,7 @@ grub_ohci_alloc_td (struct grub_ohci *o) static void grub_ohci_free_td (struct grub_ohci *o, grub_ohci_td_t td) { - grub_memset ( (void*)td, 0, sizeof(struct grub_ohci_td) ); + grub_memset ( (void*)td, 0, sizeof(struct grub_ohci_td) ); td->link_td = o->td_free; /* Cahin new free TD & rest */ o->td_free = td; /* Change address of first free TD */ } @@ -576,7 +586,7 @@ grub_ohci_free_tds (struct grub_ohci *o, grub_ohci_td_t td) { if (!td) return; - + /* Unchain first TD from previous TD if it is chained */ if (td->prev_td_phys) { @@ -586,12 +596,12 @@ grub_ohci_free_tds (struct grub_ohci *o, grub_ohci_td_t td) if (td == (grub_ohci_td_t) td_prev_virt->link_td) td_prev_virt->link_td = 0; } - + /* Free all TDs from td (chained by link_td) */ while (td) { grub_ohci_td_t tdprev; - + /* Unlink the queue. */ tdprev = td; td = (grub_ohci_td_t) td->link_td; @@ -648,7 +658,7 @@ grub_ohci_transaction (grub_ohci_td_t td, td->buffer = grub_cpu_to_le32 (buffer); td->buffer_end = grub_cpu_to_le32 (buffer_end); } - else + else { td->buffer = 0; td->buffer_end = 0; @@ -718,7 +728,7 @@ grub_ohci_setup_transfer (grub_usb_controller_t dev, grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } - + /* Take pointer to first TD from ED */ td_head_phys = grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf; td_tail_phys = grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf; @@ -733,14 +743,17 @@ grub_ohci_setup_transfer (grub_usb_controller_t dev, grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } - + /* Now we should handle first TD. If ED is newly allocated, * we must allocate the first TD. */ if (!td_head_phys) { cdata->td_head_virt = grub_ohci_alloc_td (o); if (!cdata->td_head_virt) - return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */ + { + grub_free (cdata); + return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */ + } /* We can set td_head only when ED is not active, i.e. * when it is newly allocated. */ cdata->ed_virt->td_head @@ -749,7 +762,7 @@ grub_ohci_setup_transfer (grub_usb_controller_t dev, } else cdata->td_head_virt = grub_ohci_td_phys2virt ( o, td_head_phys ); - + /* Set TDs */ cdata->td_last_phys = td_head_phys; /* initial value to make compiler happy... */ for (i = 0, cdata->td_current_virt = cdata->td_head_virt; @@ -762,10 +775,10 @@ grub_ohci_setup_transfer (grub_usb_controller_t dev, /* Set index of TD in transfer */ cdata->td_current_virt->tr_index = (grub_uint32_t) i; - + /* Remember last used (processed) TD phys. addr. */ cdata->td_last_phys = grub_ohci_td_virt2phys (o, cdata->td_current_virt); - + /* Allocate next TD */ td_next_virt = grub_ohci_alloc_td (o); if (!td_next_virt) /* No free TD, cancel transfer and free TDs except head TD */ @@ -794,7 +807,7 @@ grub_ohci_setup_transfer (grub_usb_controller_t dev, grub_dprintf ("ohci", "Tail TD (not processed) = %p\n", cdata->td_current_virt); - + /* Setup the Endpoint Descriptor for transfer. */ /* First set necessary fields in TARGET but keep (or set) skip bit */ /* Note: It could be simpler if speed, format and max. packet @@ -910,7 +923,7 @@ finish_transfer (grub_usb_controller_t dev, struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; /* Set empty ED - set HEAD = TAIL = last (not processed) TD */ - cdata->ed_virt->td_head = grub_cpu_to_le32 (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf); + cdata->ed_virt->td_head = grub_cpu_to_le32 (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf); /* At this point always should be: * ED has skip bit set and halted or empty or after next SOF, @@ -922,7 +935,7 @@ finish_transfer (grub_usb_controller_t dev, { grub_ohci_td_t td_prev_virt = grub_ohci_td_phys2virt (o, cdata->td_current_virt->prev_td_phys); - + if (cdata->td_current_virt == (grub_ohci_td_t) td_prev_virt->link_td) td_prev_virt->link_td = 0; @@ -965,7 +978,7 @@ parse_halt (grub_usb_controller_t dev, } else transfer->last_trans = -1; - + /* Evaluation of error code */ grub_dprintf ("ohci", "OHCI tderr_phys=0x%02x, errcode=0x%02x\n", cdata->tderr_phys, errcode); @@ -1076,7 +1089,7 @@ parse_success (grub_usb_controller_t dev, /* Prepare pointer to last processed TD */ tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys); - + /* Set index of last processed TD */ if (tderr_virt) transfer->last_trans = tderr_virt->tr_index; @@ -1194,7 +1207,7 @@ grub_ohci_cancel_transfer (grub_usb_controller_t dev, cdata->tderr_phys = grub_ohci_td_phys2virt (o, grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf)->prev_td_phys; - + tderr_virt = grub_ohci_td_phys2virt (o,cdata-> tderr_phys); grub_dprintf ("ohci", "Cancel: tderr_phys=0x%x, tderr_virt=%p\n", @@ -1210,7 +1223,7 @@ grub_ohci_cancel_transfer (grub_usb_controller_t dev, return GRUB_USB_ERR_NONE; } -static grub_err_t +static grub_usb_err_t grub_ohci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) { @@ -1230,13 +1243,13 @@ grub_ohci_portstatus (grub_usb_controller_t dev, while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) & (1 << 1))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "OHCI Timed out - disable"); + return GRUB_USB_ERR_TIMEOUT; grub_dprintf ("ohci", "end of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } - + /* OHCI does one reset signal 10ms long but USB spec. * requests 50ms for root hub (no need to be continuous). * So, we do reset 5 times... */ @@ -1251,7 +1264,7 @@ grub_ohci_portstatus (grub_usb_controller_t dev, while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) & GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE)) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "OHCI Timed out - reset"); + return GRUB_USB_ERR_TIMEOUT; /* End the reset signaling - reset the reset status change */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, @@ -1263,13 +1276,13 @@ grub_ohci_portstatus (grub_usb_controller_t dev, grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, GRUB_OHCI_SET_PORT_ENABLE); grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port); - + /* Wait for signal enabled */ endtime = grub_get_time_ms () + 1000; while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) & (1 << 1))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "OHCI Timed out - enable"); + return GRUB_USB_ERR_TIMEOUT; /* Reset bit Connect Status Change */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, @@ -1277,11 +1290,11 @@ grub_ohci_portstatus (grub_usb_controller_t dev, /* "Reset recovery time" (USB spec.) */ grub_millisleep (10); - + grub_dprintf ("ohci", "end of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); - - return GRUB_ERR_NONE; + + return GRUB_USB_ERR_NONE; } static grub_usb_speed_t @@ -1339,10 +1352,10 @@ grub_ohci_fini_hw (int noreturn __attribute__ ((unused))) /* Set skip in all EDs */ if (o->ed_bulk) for (i=0; i < GRUB_OHCI_BULK_EDS; i++) - o->ed_bulk[i].target |= grub_cpu_to_le32 (1 << 14); /* skip */ + o->ed_bulk[i].target |= grub_cpu_to_le32_compile_time (1 << 14); /* skip */ if (o->ed_ctrl) for (i=0; i < GRUB_OHCI_CTRL_EDS; i++) - o->ed_ctrl[i].target |= grub_cpu_to_le32 (1 << 14); /* skip */ + o->ed_ctrl[i].target |= grub_cpu_to_le32_compile_time (1 << 14); /* skip */ /* We should wait for next SOF to be sure that all EDs are * unaccessed by OHCI. But OHCI can be non-functional, so @@ -1426,7 +1439,9 @@ static struct grub_usb_controller_dev usb_controller = .cancel_transfer = grub_ohci_cancel_transfer, .hubports = grub_ohci_hubports, .portstatus = grub_ohci_portstatus, - .detect_dev = grub_ohci_detect_dev + .detect_dev = grub_ohci_detect_dev, + /* estimated max. count of TDs for one bulk transfer */ + .max_bulk_tds = GRUB_OHCI_TDS * 3 / 4 }; static struct grub_preboot *fini_hnd; @@ -1435,6 +1450,9 @@ GRUB_MOD_INIT(ohci) { COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_td) == 32); COMPILE_TIME_ASSERT (sizeof (struct grub_ohci_ed) == 16); + + grub_stop_disk_firmware (); + grub_ohci_inithw (); grub_usb_controller_dev_register (&usb_controller); fini_hnd = grub_loader_register_preboot_hook (grub_ohci_fini_hw, diff --git a/grub-core/bus/usb/serial/common.c b/grub-core/bus/usb/serial/common.c index 55d1884cc..e9c995a0a 100644 --- a/grub-core/bus/usb/serial/common.c +++ b/grub-core/bus/usb/serial/common.c @@ -42,7 +42,8 @@ static int usbnum = 0; int grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, - struct grub_serial_driver *driver) + struct grub_serial_driver *driver, int in_endp, + int out_endp) { struct grub_serial_port *port; int j; @@ -51,7 +52,7 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, interf = usbdev->config[configno].interf[interfno].descif; - port = grub_malloc (sizeof (*port)); + port = grub_zalloc (sizeof (*port)); if (!port) { grub_print_error (); @@ -73,12 +74,16 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, struct grub_usb_desc_endp *endp; endp = &usbdev->config[0].interf[interfno].descendp[j]; - if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2) + if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2 + && (in_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING + || in_endp == endp->endp_addr)) { /* Bulk IN endpoint. */ port->in_endp = endp; } - else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2) + else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2 + && (out_endp == GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING + || out_endp == endp->endp_addr)) { /* Bulk OUT endpoint. */ port->out_endp = endp; @@ -88,7 +93,7 @@ grub_usbserial_attach (grub_usb_device_t usbdev, int configno, int interfno, /* Configure device */ if (port->out_endp && port->in_endp) err = grub_usb_set_configuration (usbdev, configno + 1); - + if (!port->out_endp || !port->in_endp || err) { grub_free (port->name); @@ -119,7 +124,7 @@ grub_usbserial_fetch (struct grub_serial_port *port, grub_size_t header_size) if (port->bufstart < port->bufend) return port->buf[port->bufstart++]; - err = grub_usb_bulk_read_extended (port->usbdev, port->in_endp->endp_addr, + err = grub_usb_bulk_read_extended (port->usbdev, port->in_endp, sizeof (port->buf), port->buf, 10, &actual); if (err != GRUB_USB_ERR_NONE) diff --git a/grub-core/bus/usb/serial/ftdi.c b/grub-core/bus/usb/serial/ftdi.c index 15ea8fb89..3c1388ed2 100644 --- a/grub-core/bus/usb/serial/ftdi.c +++ b/grub-core/bus/usb/serial/ftdi.c @@ -91,11 +91,13 @@ real_config (struct grub_serial_port *port) grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, GRUB_FTDI_MODEM_CTRL, - GRUB_FTDI_MODEM_CTRL_DTRRTS, 0, 0, 0); + port->config.rtscts ? GRUB_FTDI_MODEM_CTRL_DTRRTS : 0, + 0, 0, 0); grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, GRUB_FTDI_FLOW_CTRL, - GRUB_FTDI_FLOW_CTRL_DTRRTS, 0, 0, 0); + port->config.rtscts ? GRUB_FTDI_FLOW_CTRL_DTRRTS : 0, + 0, 0, 0); divisor = get_divisor (port->config.speed); grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, @@ -128,7 +130,7 @@ ftdi_hw_put (struct grub_serial_port *port, const int c) real_config (port); - grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc); + grub_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc); } static grub_err_t @@ -172,7 +174,7 @@ static struct grub_serial_driver grub_ftdi_driver = .fini = grub_usbserial_fini }; -static const struct +static const struct { grub_uint16_t vendor, product; } products[] = @@ -193,7 +195,9 @@ grub_ftdi_attach (grub_usb_device_t usbdev, int configno, int interfno) return 0; return grub_usbserial_attach (usbdev, configno, interfno, - &grub_ftdi_driver); + &grub_ftdi_driver, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING); } static struct grub_usb_attach_desc attach_hook = diff --git a/grub-core/bus/usb/serial/pl2303.c b/grub-core/bus/usb/serial/pl2303.c index 5433763e5..8576c4611 100644 --- a/grub-core/bus/usb/serial/pl2303.c +++ b/grub-core/bus/usb/serial/pl2303.c @@ -55,7 +55,7 @@ struct grub_pl2303_config grub_uint8_t stop_bits; grub_uint8_t parity; grub_uint8_t word_len; -} __attribute__ ((packed)); +} GRUB_PACKED; static void real_config (struct grub_serial_port *port) @@ -125,7 +125,7 @@ real_config (struct grub_serial_port *port) 0x22, 3, 0, 0, 0); grub_usb_control_msg (port->usbdev, GRUB_USB_REQTYPE_VENDOR_OUT, - 1, 0, 0x61, 0, 0); + 1, 0, port->config.rtscts ? 0x61 : 0, 0, 0); port->configured = 1; } @@ -146,7 +146,7 @@ pl2303_hw_put (struct grub_serial_port *port, const int c) real_config (port); - grub_usb_bulk_write (port->usbdev, port->out_endp->endp_addr, 1, &cc); + grub_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc); } static grub_err_t @@ -187,7 +187,7 @@ static struct grub_serial_driver grub_pl2303_driver = .fini = grub_usbserial_fini }; -static const struct +static const struct { grub_uint16_t vendor, product; } products[] = @@ -208,7 +208,9 @@ grub_pl2303_attach (grub_usb_device_t usbdev, int configno, int interfno) return 0; return grub_usbserial_attach (usbdev, configno, interfno, - &grub_pl2303_driver); + &grub_pl2303_driver, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING, + GRUB_USB_SERIAL_ENDPOINT_LAST_MATCHING); } static struct grub_usb_attach_desc attach_hook = diff --git a/grub-core/bus/usb/serial/usbdebug_late.c b/grub-core/bus/usb/serial/usbdebug_late.c new file mode 100644 index 000000000..e88ba130e --- /dev/null +++ b/grub-core/bus/usb/serial/usbdebug_late.c @@ -0,0 +1,93 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2004,2005,2007,2008,2009,2010,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + + +/* Fetch a key. */ +static int +usbdebug_late_hw_fetch (struct grub_serial_port *port) +{ + return grub_usbserial_fetch (port, 0); +} + +/* Put a character. */ +static void +usbdebug_late_hw_put (struct grub_serial_port *port, const int c) +{ + char cc = c; + + grub_usb_bulk_write (port->usbdev, port->out_endp, 1, &cc); +} + +static grub_err_t +usbdebug_late_hw_configure (struct grub_serial_port *port __attribute__ ((unused)), + struct grub_serial_config *config __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} + +static struct grub_serial_driver grub_usbdebug_late_driver = + { + .configure = usbdebug_late_hw_configure, + .fetch = usbdebug_late_hw_fetch, + .put = usbdebug_late_hw_put, + .fini = grub_usbserial_fini + }; + +static int +grub_usbdebug_late_attach (grub_usb_device_t usbdev, int configno, int interfno) +{ + grub_usb_err_t err; + struct grub_usb_desc_debug debugdesc; + + err = grub_usb_get_descriptor (usbdev, GRUB_USB_DESCRIPTOR_DEBUG, configno, + sizeof (debugdesc), (char *) &debugdesc); + if (err) + return 0; + + return grub_usbserial_attach (usbdev, configno, interfno, + &grub_usbdebug_late_driver, + debugdesc.in_endp, debugdesc.out_endp); +} + +static struct grub_usb_attach_desc attach_hook = +{ + .class = 0xff, + .hook = grub_usbdebug_late_attach +}; + +GRUB_MOD_INIT(usbserial_usbdebug_late) +{ + grub_usb_register_attach_hook_class (&attach_hook); +} + +GRUB_MOD_FINI(usbserial_usbdebug_late) +{ + grub_serial_unregister_driver (&grub_usbdebug_late_driver); + grub_usb_unregister_attach_hook_class (&attach_hook); +} diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c index 8f60850de..0fdea4c1e 100644 --- a/grub-core/bus/usb/uhci.c +++ b/grub-core/bus/usb/uhci.c @@ -26,6 +26,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -44,12 +45,22 @@ typedef enum GRUB_UHCI_REG_USBLEGSUP = 0xc0 } grub_uhci_reg_t; +enum + { + GRUB_UHCI_DETECT_CHANGED = (1 << 1), + GRUB_UHCI_DETECT_HAVE_DEVICE = 1, + GRUB_UHCI_DETECT_LOW_SPEED = (1 << 8) + }; + /* R/WC legacy support bits */ -#define GRUB_UHCI_LEGSUP_END_A20GATE (1 << 15) -#define GRUB_UHCI_TRAP_BY_64H_WSTAT (1 << 11) -#define GRUB_UHCI_TRAP_BY_64H_RSTAT (1 << 10) -#define GRUB_UHCI_TRAP_BY_60H_WSTAT (1 << 9) -#define GRUB_UHCI_TRAP_BY_60H_RSTAT (1 << 8) +enum + { + GRUB_UHCI_LEGSUP_END_A20GATE = (1 << 15), + GRUB_UHCI_TRAP_BY_64H_WSTAT = (1 << 11), + GRUB_UHCI_TRAP_BY_64H_RSTAT = (1 << 10), + GRUB_UHCI_TRAP_BY_60H_WSTAT = (1 << 9), + GRUB_UHCI_TRAP_BY_60H_RSTAT = (1 << 8) + }; /* Reset all legacy support - clear all R/WC bits and all R/W bits */ #define GRUB_UHCI_RESET_LEGSUP_SMI ( GRUB_UHCI_LEGSUP_END_A20GATE \ @@ -94,7 +105,7 @@ struct grub_uhci_qh /* Queue heads are aligned on 16 bytes, pad so a queue head is 16 bytes so we can store many in a 4K page. */ grub_uint8_t pad[8]; -} __attribute__ ((packed)); +} GRUB_PACKED; /* UHCI Transfer Descriptor. */ struct grub_uhci_td @@ -118,14 +129,14 @@ struct grub_uhci_td /* 3 additional 32 bits words reserved for the Host Controller Driver. */ grub_uint32_t data[3]; -} __attribute__ ((packed)); +} GRUB_PACKED; typedef volatile struct grub_uhci_td *grub_uhci_td_t; typedef volatile struct grub_uhci_qh *grub_uhci_qh_t; struct grub_uhci { - int iobase; + grub_port_t iobase; volatile grub_uint32_t *framelist_virt; grub_uint32_t framelist_phys; struct grub_pci_dma_chunk *framelist_chunk; @@ -178,16 +189,12 @@ grub_uhci_writereg32 (struct grub_uhci *u, grub_outl (val, u->iobase + reg); } -static grub_err_t -grub_uhci_portstatus (grub_usb_controller_t dev, - unsigned int port, unsigned int enable); - - /* Iterate over all PCI devices. Determine if a device is an UHCI controller. If this is the case, initialize it. */ -static int NESTED_FUNC_ATTR +static int grub_uhci_pci_iter (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__((unused))) + grub_pci_id_t pciid __attribute__((unused)), + void *data __attribute__ ((unused))) { grub_uint32_t class_code; grub_uint32_t class; @@ -210,30 +217,37 @@ grub_uhci_pci_iter (grub_pci_device_t dev, if (class != 0x0c || subclass != 0x03 || interf != 0x00) return 0; - /* Set bus master - needed for coreboot or broken BIOSes */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write_word(addr, - GRUB_PCI_COMMAND_BUS_MASTER | grub_pci_read_word(addr)); - /* Determine IO base address. */ addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4); base = grub_pci_read (addr); /* Stop if there is no IO space base address defined. */ - if (! (base & 1)) + if ((base & GRUB_PCI_ADDR_SPACE_MASK) != GRUB_PCI_ADDR_SPACE_IO) return 0; + if ((base & GRUB_UHCI_IOMASK) == 0) + return 0; + + /* Set bus master - needed for coreboot or broken BIOSes */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word(addr, GRUB_PCI_COMMAND_IO_ENABLED + | GRUB_PCI_COMMAND_BUS_MASTER + | GRUB_PCI_COMMAND_MEM_ENABLED + | grub_pci_read_word (addr)); + + grub_dprintf ("uhci", "base = %x\n", base); + /* Allocate memory for the controller and register it. */ u = grub_zalloc (sizeof (*u)); if (! u) return 1; - u->iobase = base & GRUB_UHCI_IOMASK; + u->iobase = (base & GRUB_UHCI_IOMASK) + GRUB_MACHINE_PCI_IO_BASE; /* Reset PIRQ and SMI */ - addr = grub_pci_make_address (dev, GRUB_UHCI_REG_USBLEGSUP); + addr = grub_pci_make_address (dev, GRUB_UHCI_REG_USBLEGSUP); grub_pci_write_word(addr, GRUB_UHCI_RESET_LEGSUP_SMI); /* Reset the HC */ - grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, GRUB_UHCI_CMD_HCRESET); + grub_uhci_writereg16(u, GRUB_UHCI_REG_USBCMD, GRUB_UHCI_CMD_HCRESET); grub_millisleep(5); /* Disable interrupts and commands (just to be safe) */ grub_uhci_writereg16(u, GRUB_UHCI_REG_USBINTR, 0); @@ -351,7 +365,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev, static void grub_uhci_inithw (void) { - grub_pci_iterate (grub_uhci_pci_iter); + grub_pci_iterate (grub_uhci_pci_iter, NULL); } static grub_uhci_td_t @@ -385,21 +399,25 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td, u->qh_busy[qh - u->qh_virt] = 0; *actual = 0; - + /* Free the TDs in this queue and set last_trans. */ for (i=0; td; i++) { grub_uhci_td_t tdprev; + grub_dprintf ("uhci", "Freeing %p\n", td); /* Check state of TD and possibly set last_trans */ if (transfer && (td->linkptr & 1)) transfer->last_trans = i; *actual += (td->ctrl_status + 1) & 0x7ff; - + /* Unlink the queue. */ tdprev = td; - td = grub_dma_phys2virt (td->linkptr2, u->td_chunk); + if (!td->linkptr2) + td = 0; + else + td = grub_dma_phys2virt (td->linkptr2, u->td_chunk); /* Free the TD. */ grub_free_td (u, tdprev); @@ -519,7 +537,7 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev, } grub_dprintf ("uhci", "transfer, iobase:%08x\n", u->iobase); - + for (i = 0; i < transfer->transcnt; i++) { grub_usb_transaction_t tr = &transfer->transactions[i]; @@ -582,10 +600,17 @@ grub_uhci_check_transfer (grub_usb_controller_t dev, *actual = 0; - errtd = grub_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk); - - grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n", - errtd->ctrl_status, errtd->buffer & (~15), errtd); + if (cdata->qh->elinkptr & ~0x0f) + errtd = grub_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk); + else + errtd = 0; + + if (errtd) + { + grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p, %x\n", + errtd->ctrl_status, errtd->buffer & (~15), errtd, + cdata->qh->elinkptr); + } /* Check if the transaction completed. */ if (cdata->qh->elinkptr & 1) @@ -600,36 +625,34 @@ grub_uhci_check_transfer (grub_usb_controller_t dev, return GRUB_USB_ERR_NONE; } - grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status); - - if (!(errtd->ctrl_status & (1 << 23))) + if (errtd && !(errtd->ctrl_status & (1 << 23))) { grub_usb_err_t err = GRUB_USB_ERR_NONE; /* Check if the endpoint is stalled. */ if (errtd->ctrl_status & (1 << 22)) err = GRUB_USB_ERR_STALL; - + /* Check if an error related to the data buffer occurred. */ else if (errtd->ctrl_status & (1 << 21)) err = GRUB_USB_ERR_DATA; - + /* Check if a babble error occurred. */ else if (errtd->ctrl_status & (1 << 20)) err = GRUB_USB_ERR_BABBLE; - + /* Check if a NAK occurred. */ else if (errtd->ctrl_status & (1 << 19)) err = GRUB_USB_ERR_NAK; - + /* Check if a timeout occurred. */ else if (errtd->ctrl_status & (1 << 18)) err = GRUB_USB_ERR_TIMEOUT; - + /* Check if a bitstuff error occurred. */ else if (errtd->ctrl_status & (1 << 17)) err = GRUB_USB_ERR_BITSTUFF; - + if (err) { grub_dprintf ("uhci", "transaction failed\n"); @@ -671,7 +694,7 @@ grub_uhci_cancel_transfer (grub_usb_controller_t dev, } static int -grub_uhci_iterate (int (*hook) (grub_usb_controller_t dev)) +grub_uhci_iterate (grub_usb_controller_iterate_hook_t hook, void *hook_data) { struct grub_uhci *u; struct grub_usb_controller dev; @@ -679,14 +702,14 @@ grub_uhci_iterate (int (*hook) (grub_usb_controller_t dev)) for (u = uhci; u; u = u->next) { dev.data = u; - if (hook (&dev)) + if (hook (&dev, hook_data)) return 1; } return 0; } -static grub_err_t +static grub_usb_err_t grub_uhci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) { @@ -696,7 +719,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, grub_uint64_t endtime; grub_dprintf ("uhci", "portstatus, iobase:%08x\n", u->iobase); - + grub_dprintf ("uhci", "enable=%d port=%d\n", enable, port); if (port == 0) @@ -704,8 +727,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, else if (port == 1) reg = GRUB_UHCI_REG_PORTSC2; else - return grub_error (GRUB_ERR_OUT_OF_RANGE, - "UHCI Root Hub port does not exist"); + return GRUB_USB_ERR_INTERNAL; status = grub_uhci_readreg16 (u, reg); grub_dprintf ("uhci", "detect=0x%02x\n", status); @@ -718,13 +740,13 @@ grub_uhci_portstatus (grub_usb_controller_t dev, endtime = grub_get_time_ms () + 1000; while ((grub_uhci_readreg16 (u, reg) & (1 << 2))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "UHCI Timed out - disable"); + return GRUB_USB_ERR_TIMEOUT; status = grub_uhci_readreg16 (u, reg); grub_dprintf ("uhci", ">3detect=0x%02x\n", status); - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } - + /* Reset the port. */ status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; grub_uhci_writereg16 (u, reg, status | (1 << 9)); @@ -753,7 +775,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, endtime = grub_get_time_ms () + 1000; while (! ((status = grub_uhci_readreg16 (u, reg)) & (1 << 2))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "UHCI Timed out - enable"); + return GRUB_USB_ERR_TIMEOUT; /* Reset recovery time */ grub_millisleep (10); @@ -763,7 +785,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, grub_dprintf ("uhci", ">3detect=0x%02x\n", status); - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } static grub_usb_speed_t @@ -774,7 +796,7 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) unsigned int status; grub_dprintf ("uhci", "detect_dev, iobase:%08x\n", u->iobase); - + if (port == 0) reg = GRUB_UHCI_REG_PORTSC1; else if (port == 1) @@ -787,7 +809,7 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) grub_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port); /* Connect Status Change bit - it detects change of connection */ - if (status & (1 << 1)) + if (status & GRUB_UHCI_DETECT_CHANGED) { *changed = 1; /* Reset bit Connect Status Change */ @@ -796,10 +818,10 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) } else *changed = 0; - - if (! (status & 1)) + + if (! (status & GRUB_UHCI_DETECT_HAVE_DEVICE)) return GRUB_USB_SPEED_NONE; - else if (status & (1 << 8)) + else if (status & GRUB_UHCI_DETECT_LOW_SPEED) return GRUB_USB_SPEED_LOW; else return GRUB_USB_SPEED_FULL; @@ -822,11 +844,15 @@ static struct grub_usb_controller_dev usb_controller = .cancel_transfer = grub_uhci_cancel_transfer, .hubports = grub_uhci_hubports, .portstatus = grub_uhci_portstatus, - .detect_dev = grub_uhci_detect_dev + .detect_dev = grub_uhci_detect_dev, + /* estimated max. count of TDs for one bulk transfer */ + .max_bulk_tds = N_TD * 3 / 4 }; GRUB_MOD_INIT(uhci) { + grub_stop_disk_firmware (); + grub_uhci_inithw (); grub_usb_controller_dev_register (&usb_controller); grub_dprintf ("uhci", "registered\n"); diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c index fb04e6572..7bd49d201 100644 --- a/grub-core/bus/usb/usb.c +++ b/grub-core/bus/usb/usb.c @@ -26,67 +26,44 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_usb_controller_dev_t grub_usb_list; static struct grub_usb_attach_desc *attach_hooks; -void -grub_usb_controller_dev_register (grub_usb_controller_dev_t usb) -{ - auto int iterate_hook (grub_usb_controller_t dev); - - /* Iterate over all controllers found by the driver. */ - int iterate_hook (grub_usb_controller_t dev) - { - dev->dev = usb; - - /* Enable the ports of the USB Root Hub. */ - grub_usb_root_hub (dev); - - return 0; - } - - usb->next = grub_usb_list; - grub_usb_list = usb; - - if (usb->iterate) - usb->iterate (iterate_hook); -} - -void -grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb) -{ - grub_usb_controller_dev_t *p, q; - - for (p = &grub_usb_list, q = *p; q; p = &(q->next), q = q->next) - if (q == usb) - { - *p = q->next; - break; - } -} - #if 0 -int -grub_usb_controller_iterate (int (*hook) (grub_usb_controller_t dev)) +/* Context for grub_usb_controller_iterate. */ +struct grub_usb_controller_iterate_ctx { + grub_usb_controller_iterate_hook_t hook; + void *hook_data; grub_usb_controller_dev_t p; +}; - auto int iterate_hook (grub_usb_controller_t dev); +/* Helper for grub_usb_controller_iterate. */ +static int +grub_usb_controller_iterate_iter (grub_usb_controller_t dev, void *data) +{ + struct grub_usb_controller_iterate_ctx *ctx = data; - int iterate_hook (grub_usb_controller_t dev) - { - dev->dev = p; - if (hook (dev)) - return 1; - return 0; - } + dev->dev = ctx->p; + if (ctx->hook (dev, ctx->hook_data)) + return 1; + return 0; +} + +int +grub_usb_controller_iterate (grub_usb_controller_iterate_hook_t hook, + void *hook_data) +{ + struct grub_usb_controller_iterate_ctx ctx = { + .hook = hook, + .hook_data = hook_data + }; /* Iterate over all controller drivers. */ - for (p = grub_usb_list; p; p = p->next) + for (ctx.p = grub_usb_list; ctx.p; ctx.p = ctx.p->next) { /* Iterate over the busses of the controllers. XXX: Actually, a hub driver should do this. */ - if (p->iterate (iterate_hook)) + if (ctx.p->iterate (grub_usb_controller_iterate_iter, &ctx)) return 1; } @@ -98,6 +75,9 @@ grub_usb_controller_iterate (int (*hook) (grub_usb_controller_t dev)) grub_usb_err_t grub_usb_clear_halt (grub_usb_device_t dev, int endpoint) { + if (endpoint >= GRUB_USB_MAX_TOGGLE) + return GRUB_USB_ERR_BADDEVICE; + dev->toggle[endpoint] = 0; return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT | GRUB_USB_REQTYPE_STANDARD @@ -132,31 +112,6 @@ grub_usb_get_descriptor (grub_usb_device_t dev, 0, size, data); } -struct grub_usb_desc_endp * -grub_usb_get_endpdescriptor (grub_usb_device_t usbdev, int addr) -{ - int i; - - for (i = 0; i < usbdev->config[0].descconf->numif; i++) - { - struct grub_usb_desc_if *interf; - int j; - - interf = usbdev->config[0].interf[i].descif; - - for (j = 0; j < interf->endpointcnt; j++) - { - struct grub_usb_desc_endp *endp; - endp = &usbdev->config[0].interf[i].descendp[j]; - - if (endp->endp_addr == addr) - return endp; - } - } - - return NULL; -} - grub_usb_err_t grub_usb_device_initialize (grub_usb_device_t dev) { @@ -182,20 +137,21 @@ grub_usb_device_initialize (grub_usb_device_t dev) return err; descdev = &dev->descdev; - for (i = 0; i < 8; i++) + for (i = 0; i < GRUB_USB_MAX_CONF; i++) dev->config[i].descconf = NULL; - if (descdev->configcnt == 0) + if (descdev->configcnt == 0 || descdev->configcnt > GRUB_USB_MAX_CONF) { err = GRUB_USB_ERR_BADDEVICE; goto fail; - } + } for (i = 0; i < descdev->configcnt; i++) { int pos; int currif; char *data; + struct grub_usb_desc *desc; /* First just read the first 4 bytes of the configuration descriptor, after that it is known how many bytes really have @@ -219,21 +175,44 @@ grub_usb_device_initialize (grub_usb_device_t dev) /* Skip the configuration descriptor. */ pos = dev->config[i].descconf->length; + if (dev->config[i].descconf->numif > GRUB_USB_MAX_IF) + { + err = GRUB_USB_ERR_BADDEVICE; + goto fail; + } + /* Read all interfaces. */ for (currif = 0; currif < dev->config[i].descconf->numif; currif++) { - while (pos < config.totallen - && ((struct grub_usb_desc *)&data[pos])->type - != GRUB_USB_DESCRIPTOR_INTERFACE) - pos += ((struct grub_usb_desc *)&data[pos])->length; + while (pos < config.totallen) + { + desc = (struct grub_usb_desc *)&data[pos]; + if (desc->type == GRUB_USB_DESCRIPTOR_INTERFACE) + break; + if (!desc->length) + { + err = GRUB_USB_ERR_BADDEVICE; + goto fail; + } + pos += desc->length; + } + dev->config[i].interf[currif].descif = (struct grub_usb_desc_if *) &data[pos]; pos += dev->config[i].interf[currif].descif->length; - while (pos < config.totallen - && ((struct grub_usb_desc *)&data[pos])->type - != GRUB_USB_DESCRIPTOR_ENDPOINT) - pos += ((struct grub_usb_desc *)&data[pos])->length; + while (pos < config.totallen) + { + desc = (struct grub_usb_desc *)&data[pos]; + if (desc->type == GRUB_USB_DESCRIPTOR_ENDPOINT) + break; + if (!desc->length) + { + err = GRUB_USB_ERR_BADDEVICE; + goto fail; + } + pos += desc->length; + } /* Point to the first endpoint. */ dev->config[i].interf[currif].descendp @@ -247,7 +226,7 @@ grub_usb_device_initialize (grub_usb_device_t dev) fail: - for (i = 0; i < 8; i++) + for (i = 0; i < GRUB_USB_MAX_CONF; i++) grub_free (dev->config[i].descconf); return err; @@ -256,7 +235,7 @@ grub_usb_device_initialize (grub_usb_device_t dev) void grub_usb_device_attach (grub_usb_device_t dev) { int i; - + /* XXX: Just check configuration 0 for now. */ for (i = 0; i < dev->config[0].descconf->numif; i++) { @@ -272,8 +251,13 @@ void grub_usb_device_attach (grub_usb_device_t dev) continue; for (desc = attach_hooks; desc; desc = desc->next) - if (interf->class == desc->class && desc->hook (dev, 0, i)) - dev->config[0].interf[i].attached = 1; + if (interf->class == desc->class) + { + grub_boot_time ("Probing USB device driver class %x", desc->class); + if (desc->hook (dev, 0, i)) + dev->config[0].interf[i].attached = 1; + grub_boot_time ("Probed USB device driver class %x", desc->class); + } if (dev->config[0].interf[i].attached) continue; @@ -282,65 +266,72 @@ void grub_usb_device_attach (grub_usb_device_t dev) { case GRUB_USB_CLASS_MASS_STORAGE: grub_dl_load ("usbms"); + grub_print_error (); break; case GRUB_USB_CLASS_HID: grub_dl_load ("usb_keyboard"); + grub_print_error (); break; case 0xff: /* FIXME: don't load useless modules. */ grub_dl_load ("usbserial_ftdi"); + grub_print_error (); grub_dl_load ("usbserial_pl2303"); + grub_print_error (); + grub_dl_load ("usbserial_usbdebug"); + grub_print_error (); break; } } } +/* Helper for grub_usb_register_attach_hook_class. */ +static int +grub_usb_register_attach_hook_class_iter (grub_usb_device_t usbdev, void *data) +{ + struct grub_usb_attach_desc *desc = data; + struct grub_usb_desc_device *descdev = &usbdev->descdev; + int i; + + if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0 + || descdev->configcnt == 0) + return 0; + + /* XXX: Just check configuration 0 for now. */ + for (i = 0; i < usbdev->config[0].descconf->numif; i++) + { + struct grub_usb_desc_if *interf; + + interf = usbdev->config[0].interf[i].descif; + + grub_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n", + i, interf->class, interf->subclass, interf->protocol); + + if (usbdev->config[0].interf[i].attached) + continue; + + if (interf->class != desc->class) + continue; + if (desc->hook (usbdev, 0, i)) + usbdev->config[0].interf[i].attached = 1; + } + + return 0; +} + void grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc) { - auto int usb_iterate (grub_usb_device_t dev); - - int usb_iterate (grub_usb_device_t usbdev) - { - struct grub_usb_desc_device *descdev = &usbdev->descdev; - int i; - - if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0 - || descdev->configcnt == 0) - return 0; - - /* XXX: Just check configuration 0 for now. */ - for (i = 0; i < usbdev->config[0].descconf->numif; i++) - { - struct grub_usb_desc_if *interf; - - interf = usbdev->config[0].interf[i].descif; - - grub_dprintf ("usb", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n", - i, interf->class, interf->subclass, interf->protocol); - - if (usbdev->config[0].interf[i].attached) - continue; - - if (interf->class != desc->class) - continue; - if (desc->hook (usbdev, 0, i)) - usbdev->config[0].interf[i].attached = 1; - } - - return 0; - } - desc->next = attach_hooks; attach_hooks = desc; - grub_usb_iterate (usb_iterate); + grub_usb_iterate (grub_usb_register_attach_hook_class_iter, desc); } void grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc) { - grub_list_remove (GRUB_AS_LIST (desc)); + grub_list_remove (GRUB_AS_LIST (desc)); } diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c index 5fc5eba39..f5608e330 100644 --- a/grub-core/bus/usb/usbhub.c +++ b/grub-core/bus/usb/usbhub.c @@ -29,6 +29,7 @@ static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES]; static int rescan = 0; +static int npending = 0; struct grub_usb_hub { @@ -36,30 +37,34 @@ struct grub_usb_hub grub_usb_controller_t controller; int nports; struct grub_usb_device **devices; + struct grub_usb_hub_port *ports; grub_usb_device_t dev; }; static struct grub_usb_hub *hubs; +static grub_usb_controller_dev_t grub_usb_list; /* Add a device that currently has device number 0 and resides on CONTROLLER, the Hub reported that the device speed is SPEED. */ static grub_usb_device_t grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed, - int port, int hubaddr) + int split_hubport, int split_hubaddr) { grub_usb_device_t dev; int i; grub_usb_err_t err; + grub_boot_time ("Attaching USB device"); + dev = grub_zalloc (sizeof (struct grub_usb_device)); if (! dev) return NULL; dev->controller = *controller; dev->speed = speed; - dev->port = port; - dev->hubaddr = hubaddr; + dev->split_hubport = split_hubport; + dev->split_hubaddr = split_hubaddr; err = grub_usb_device_initialize (dev); if (err) @@ -77,7 +82,7 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, if (i == GRUB_USBHUB_MAX_DEVICES) { grub_error (GRUB_ERR_IO, "can't assign address to USB device"); - for (i = 0; i < 8; i++) + for (i = 0; i < GRUB_USB_MAX_CONF; i++) grub_free (dev->config[i].descconf); grub_free (dev); return NULL; @@ -91,7 +96,7 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, i, 0, 0, NULL); if (err) { - for (i = 0; i < 8; i++) + for (i = 0; i < GRUB_USB_MAX_CONF; i++) grub_free (dev->config[i].descconf); grub_free (dev); return NULL; @@ -103,14 +108,18 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_dprintf ("usb", "Added new usb device: %p, addr=%d\n", dev, i); - grub_dprintf ("usb", "speed=%d, port=%d, hubaddr=%d\n", - speed, port, hubaddr); + grub_dprintf ("usb", "speed=%d, split_hubport=%d, split_hubaddr=%d\n", + speed, split_hubport, split_hubaddr); /* Wait "recovery interval", spec. says 2ms */ grub_millisleep (2); - + + grub_boot_time ("Probing USB device driver"); + grub_usb_device_attach (dev); - + + grub_boot_time ("Attached USB device"); + return dev; } @@ -121,7 +130,7 @@ grub_usb_add_hub (grub_usb_device_t dev) struct grub_usb_usb_hubdesc hubdesc; grub_usb_err_t err; int i; - + err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN | GRUB_USB_REQTYPE_CLASS | GRUB_USB_REQTYPE_TARGET_DEV), @@ -139,10 +148,15 @@ grub_usb_add_hub (grub_usb_device_t dev) grub_dprintf ("usb", "Hub set configuration\n"); grub_usb_set_configuration (dev, 1); - dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0])); - if (!dev->children) - return GRUB_USB_ERR_INTERNAL; dev->nports = hubdesc.portcnt; + dev->children = grub_calloc (hubdesc.portcnt, sizeof (dev->children[0])); + dev->ports = grub_calloc (dev->nports, sizeof (dev->ports[0])); + if (!dev->children || !dev->ports) + { + grub_free (dev->children); + grub_free (dev->ports); + return GRUB_USB_ERR_INTERNAL; + } /* Power on all Hub ports. */ for (i = 1; i <= hubdesc.portcnt; i++) @@ -173,7 +187,7 @@ grub_usb_add_hub (grub_usb_device_t dev) if (len > sizeof (dev->statuschange)) len = sizeof (dev->statuschange); dev->hub_transfer - = grub_usb_bulk_read_background (dev, endp->endp_addr, len, + = grub_usb_bulk_read_background (dev, endp, len, (char *) &dev->statuschange); break; } @@ -181,7 +195,7 @@ grub_usb_add_hub (grub_usb_device_t dev) rescan = 1; - return GRUB_ERR_NONE; + return GRUB_USB_ERR_NONE; } static void @@ -189,48 +203,30 @@ attach_root_port (struct grub_usb_hub *hub, int portno, grub_usb_speed_t speed) { grub_usb_device_t dev; - grub_err_t err; - int total, i; - grub_usb_speed_t current_speed = GRUB_USB_SPEED_NONE; - int changed=0; + grub_usb_err_t err; -#if 0 -/* Specification does not say about disabling of port when device - * connected. If disabling is really necessary for some devices, - * delete this #if 0 and related #endif */ - /* Disable the port. XXX: Why? */ - err = hub->controller->dev->portstatus (hub->controller, portno, 0); - if (err) - return; -#endif - /* Wait for completion of insertion and stable power (USB spec.) - * Should be at least 100ms, some devices requires more... - * There is also another thing - some devices have worse contacts - * and connected signal is unstable for some time - we should handle - * it - but prevent deadlock in case when device is too faulty... */ - for (total = i = 0; (i < 250) && (total < 2000); i++, total++) - { - grub_millisleep (1); - current_speed = hub->controller->dev->detect_dev - (hub->controller, portno, &changed); - if (current_speed == GRUB_USB_SPEED_NONE) - i = 0; - } - grub_dprintf ("usb", "total=%d\n", total); - if (total >= 2000) - return; + grub_boot_time ("After detect_dev"); /* Enable the port. */ err = hub->controller->dev->portstatus (hub->controller, portno, 1); if (err) return; hub->controller->dev->pending_reset = grub_get_time_ms () + 5000; + npending++; grub_millisleep (10); + grub_boot_time ("Port enabled"); + /* Enable the port and create a device. */ - dev = grub_usb_hub_add_dev (hub->controller, speed, portno, 0); + /* High speed device needs not transaction translation + and full/low speed device cannot be connected to EHCI root hub + and full/low speed device connected to OHCI/UHCI needs not + transaction translation - e.g. hubport and hubaddr should be + always none (zero) for any device connected to any root hub. */ + dev = grub_usb_hub_add_dev (hub->controller, speed, 0, 0); hub->controller->dev->pending_reset = 0; + npending--; if (! dev) return; @@ -239,14 +235,20 @@ attach_root_port (struct grub_usb_hub *hub, int portno, /* If the device is a Hub, scan it for more devices. */ if (dev->descdev.class == 0x09) grub_usb_add_hub (dev); + + grub_boot_time ("Attached root port"); } -grub_usb_err_t -grub_usb_root_hub (grub_usb_controller_t controller) +/* Iterate over all controllers found by the driver. */ +static int +grub_usb_controller_dev_register_iter (grub_usb_controller_t controller, void *data) { - int i; + grub_usb_controller_dev_t usb = data; struct grub_usb_hub *hub; - int changed=0; + + controller->dev = usb; + + grub_boot_time ("Registering USB root hub"); hub = grub_malloc (sizeof (*hub)); if (!hub) @@ -266,28 +268,123 @@ grub_usb_root_hub (grub_usb_controller_t controller) /* Query the number of ports the root Hub has. */ hub->nports = controller->dev->hubports (controller); - hub->devices = grub_zalloc (sizeof (hub->devices[0]) * hub->nports); - if (!hub->devices) + hub->devices = grub_calloc (hub->nports, sizeof (hub->devices[0])); + hub->ports = grub_calloc (hub->nports, sizeof (hub->ports[0])); + if (!hub->devices || !hub->ports) { + grub_free (hub->devices); + grub_free (hub->ports); grub_free (hub->controller); grub_free (hub); - return GRUB_USB_ERR_INTERNAL; + grub_print_error (); + return 0; } - for (i = 0; i < hub->nports; i++) + return 0; +} + +void +grub_usb_controller_dev_unregister (grub_usb_controller_dev_t usb) +{ + grub_usb_controller_dev_t *p, q; + + for (p = &grub_usb_list, q = *p; q; p = &(q->next), q = q->next) + if (q == usb) + { + *p = q->next; + break; + } +} + +void +grub_usb_controller_dev_register (grub_usb_controller_dev_t usb) +{ + int portno; + int continue_waiting = 0; + struct grub_usb_hub *hub; + + usb->next = grub_usb_list; + grub_usb_list = usb; + + if (usb->iterate) + usb->iterate (grub_usb_controller_dev_register_iter, usb); + + grub_boot_time ("waiting for stable power on USB root\n"); + + while (1) { - grub_usb_speed_t speed; - if (!controller->dev->pending_reset) - { - speed = controller->dev->detect_dev (hub->controller, i, - &changed); + for (hub = hubs; hub; hub = hub->next) + if (hub->controller->dev == usb) + { + /* Wait for completion of insertion and stable power (USB spec.) + * Should be at least 100ms, some devices requires more... + * There is also another thing - some devices have worse contacts + * and connected signal is unstable for some time - we should handle + * it - but prevent deadlock in case when device is too faulty... */ + for (portno = 0; portno < hub->nports; portno++) + { + grub_usb_speed_t speed; + int changed = 0; - if (speed != GRUB_USB_SPEED_NONE) - attach_root_port (hub, i, speed); - } + speed = hub->controller->dev->detect_dev (hub->controller, portno, + &changed); + + if (hub->ports[portno].state == PORT_STATE_NORMAL + && speed != GRUB_USB_SPEED_NONE) + { + hub->ports[portno].soft_limit_time = grub_get_time_ms () + 250; + hub->ports[portno].hard_limit_time = hub->ports[portno].soft_limit_time + 1750; + hub->ports[portno].state = PORT_STATE_WAITING_FOR_STABLE_POWER; + grub_boot_time ("Scheduling stable power wait for port %p:%d", + usb, portno); + continue_waiting++; + continue; + } + + if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER + && speed == GRUB_USB_SPEED_NONE) + { + hub->ports[portno].soft_limit_time = grub_get_time_ms () + 250; + continue; + } + if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER + && grub_get_time_ms () > hub->ports[portno].soft_limit_time) + { + hub->ports[portno].state = PORT_STATE_STABLE_POWER; + grub_boot_time ("Got stable power wait for port %p:%d", + usb, portno); + continue_waiting--; + continue; + } + if (hub->ports[portno].state == PORT_STATE_WAITING_FOR_STABLE_POWER + && grub_get_time_ms () > hub->ports[portno].hard_limit_time) + { + hub->ports[portno].state = PORT_STATE_FAILED_DEVICE; + continue_waiting--; + continue; + } + } + } + if (!continue_waiting) + break; + grub_millisleep (1); } - return GRUB_USB_ERR_NONE; + grub_boot_time ("After the stable power wait on USB root"); + + for (hub = hubs; hub; hub = hub->next) + if (hub->controller->dev == usb) + for (portno = 0; portno < hub->nports; portno++) + if (hub->ports[portno].state == PORT_STATE_STABLE_POWER) + { + grub_usb_speed_t speed; + int changed = 0; + hub->ports[portno].state = PORT_STATE_NORMAL; + speed = hub->controller->dev->detect_dev (hub->controller, portno, &changed); + attach_root_port (hub, portno, speed); + } + + grub_boot_time ("USB root hub registered"); } static void detach_device (grub_usb_device_t dev); @@ -319,14 +416,78 @@ detach_device (grub_usb_device_t dev) grub_usb_devs[dev->addr] = 0; } +static int +wait_power_nonroot_hub (grub_usb_device_t dev) +{ + grub_usb_err_t err; + int continue_waiting = 0; + unsigned i; + + for (i = 1; i <= dev->nports; i++) + if (dev->ports[i - 1].state == PORT_STATE_WAITING_FOR_STABLE_POWER) + { + grub_uint64_t tm; + grub_uint32_t current_status = 0; + + /* Get the port status. */ + err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_GET_STATUS, + 0, i, + sizeof (current_status), + (char *) ¤t_status); + if (err) + { + dev->ports[i - 1].state = PORT_STATE_FAILED_DEVICE; + continue; + } + tm = grub_get_time_ms (); + if (!(current_status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)) + dev->ports[i - 1].soft_limit_time = tm + 250; + if (tm >= dev->ports[i - 1].soft_limit_time) + { + if (dev->controller.dev->pending_reset) + continue; + /* Now do reset of port. */ + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_SET_FEATURE, + GRUB_USB_HUB_FEATURE_PORT_RESET, + i, 0, 0); + dev->ports[i - 1].state = PORT_STATE_NORMAL; + grub_boot_time ("Resetting port %p:%d", dev, i - 1); + + rescan = 1; + /* We cannot reset more than one device at the same time ! + * Resetting more devices together results in very bad + * situation: more than one device has default address 0 + * at the same time !!! + * Additionaly, we cannot perform another reset + * anywhere on the same OHCI controller until + * we will finish addressing of reseted device ! */ + dev->controller.dev->pending_reset = grub_get_time_ms () + 5000; + npending++; + continue; + } + if (tm >= dev->ports[i - 1].hard_limit_time) + { + dev->ports[i - 1].state = PORT_STATE_FAILED_DEVICE; + continue; + } + continue_waiting = 1; + } + return continue_waiting && dev->controller.dev->pending_reset == 0; +} + static void poll_nonroot_hub (grub_usb_device_t dev) { grub_usb_err_t err; unsigned i; - grub_uint8_t changed; + grub_uint32_t changed; grub_size_t actual, len; - int j, total; if (!dev->hub_transfer) return; @@ -342,7 +503,7 @@ poll_nonroot_hub (grub_usb_device_t dev) if (len > sizeof (dev->statuschange)) len = sizeof (dev->statuschange); dev->hub_transfer - = grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, len, + = grub_usb_bulk_read_background (dev, dev->hub_endpoint, len, (char *) &dev->statuschange); if (err || actual == 0 || changed == 0) @@ -352,9 +513,9 @@ poll_nonroot_hub (grub_usb_device_t dev) for (i = 1; i <= dev->nports; i++) { grub_uint32_t status; - grub_uint32_t current_status = 0; - if (!(changed & (1 << i))) + if (!(changed & (1 << i)) + || dev->ports[i - 1].state == PORT_STATE_WAITING_FOR_STABLE_POWER) continue; /* Get the port status. */ @@ -403,56 +564,23 @@ poll_nonroot_hub (grub_usb_device_t dev) detach_device (dev->children[i - 1]); dev->children[i - 1] = NULL; - + /* Connected and status of connection changed ? */ if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) { + grub_boot_time ("Before the stable power wait portno=%d", i); /* A device is actually connected to this port. */ - /* Wait for completion of insertion and stable power (USB spec.) - * Should be at least 100ms, some devices requires more... - * There is also another thing - some devices have worse contacts - * and connected signal is unstable for some time - we should handle - * it - but prevent deadlock in case when device is too faulty... */ - for (total = j = 0; (j < 250) && (total < 2000); j++, total++) - { - grub_millisleep (1); - /* Get the port status. */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_GET_STATUS, - 0, i, - sizeof (current_status), - (char *) ¤t_status); - if (err) - { - total = 2000; - break; - } - if (!(current_status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)) - j = 0; - } - grub_dprintf ("usb", "(non-root) total=%d\n", total); - if (total >= 2000) - continue; - - /* Now do reset of port. */ - grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_SET_FEATURE, - GRUB_USB_HUB_FEATURE_PORT_RESET, - i, 0, 0); - rescan = 1; - /* We cannot reset more than one device at the same time ! - * Resetting more devices together results in very bad - * situation: more than one device has default address 0 - * at the same time !!! - * Additionaly, we cannot perform another reset - * anywhere on the same OHCI controller until - * we will finish addressing of reseted device ! */ - dev->controller.dev->pending_reset = grub_get_time_ms () + 5000; - return; + /* Wait for completion of insertion and stable power (USB spec.) + * Should be at least 100ms, some devices requires more... + * There is also another thing - some devices have worse contacts + * and connected signal is unstable for some time - we should handle + * it - but prevent deadlock in case when device is too faulty... */ + dev->ports[i - 1].soft_limit_time = grub_get_time_ms () + 250; + dev->ports[i - 1].hard_limit_time = dev->ports[i - 1].soft_limit_time + 1750; + dev->ports[i - 1].state = PORT_STATE_WAITING_FOR_STABLE_POWER; + grub_boot_time ("Scheduling stable power wait for port %p:%d", + dev, i - 1); + continue; } } @@ -464,10 +592,14 @@ poll_nonroot_hub (grub_usb_device_t dev) GRUB_USB_REQ_CLEAR_FEATURE, GRUB_USB_HUB_FEATURE_C_PORT_RESET, i, 0, 0); + grub_boot_time ("Port %d reset", i); + if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) { grub_usb_speed_t speed; grub_usb_device_t next_dev; + int split_hubport = 0; + int split_hubaddr = 0; /* Determine the device speed. */ if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED) @@ -483,9 +615,42 @@ poll_nonroot_hub (grub_usb_device_t dev) /* Wait a recovery time after reset, spec. says 10ms */ grub_millisleep (10); + /* Find correct values for SPLIT hubport and hubaddr */ + if (speed == GRUB_USB_SPEED_HIGH) + { + /* HIGH speed device needs not transaction translation */ + split_hubport = 0; + split_hubaddr = 0; + } + else + /* FULL/LOW device needs hub port and hub address + for transaction translation (if connected to EHCI) */ + if (dev->speed == GRUB_USB_SPEED_HIGH) + { + /* This port is the first FULL/LOW speed port + in the chain from root hub. Attached device + should use its port number and hub address */ + split_hubport = i; + split_hubaddr = dev->addr; + } + else + { + /* This port is NOT the first FULL/LOW speed port + in the chain from root hub. Attached device + should use values inherited from some parent + HIGH speed hub - if any. */ + split_hubport = dev->split_hubport; + split_hubaddr = dev->split_hubaddr; + } + /* Add the device and assign a device address to it. */ - next_dev = grub_usb_hub_add_dev (&dev->controller, speed, i, dev->addr); - dev->controller.dev->pending_reset = 0; + next_dev = grub_usb_hub_add_dev (&dev->controller, speed, + split_hubport, split_hubaddr); + if (dev->controller.dev->pending_reset) + { + dev->controller.dev->pending_reset = 0; + npending--; + } if (! next_dev) continue; @@ -500,7 +665,7 @@ poll_nonroot_hub (grub_usb_device_t dev) } void -grub_usb_poll_devices (void) +grub_usb_poll_devices (int wait_for_completion) { struct grub_usb_hub *hub; int i; @@ -514,7 +679,7 @@ grub_usb_poll_devices (void) grub_usb_speed_t speed = GRUB_USB_SPEED_NONE; int changed = 0; - if (!hub->controller->dev->pending_reset) + if (hub->controller->dev->pending_reset) { /* Check for possible timeout */ if (grub_get_time_ms () > hub->controller->dev->pending_reset) @@ -522,10 +687,13 @@ grub_usb_poll_devices (void) /* Something went wrong, reset device was not * addressed properly, timeout happened */ hub->controller->dev->pending_reset = 0; - speed = hub->controller->dev->detect_dev (hub->controller, - i, &changed); + npending--; } } + if (!hub->controller->dev->pending_reset) + speed = hub->controller->dev->detect_dev (hub->controller, + i, &changed); + if (changed) { detach_device (hub->devices[i]); @@ -539,24 +707,39 @@ grub_usb_poll_devices (void) while (1) { rescan = 0; - + /* We should check changes of non-root hubs too. */ for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) { grub_usb_device_t dev = grub_usb_devs[i]; - + if (dev && dev->descdev.class == 0x09) poll_nonroot_hub (dev); } - if (!rescan) - break; - grub_millisleep (50); - } + while (1) + { + int continue_waiting = 0; + for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) + { + grub_usb_device_t dev = grub_usb_devs[i]; + + if (dev && dev->descdev.class == 0x09) + continue_waiting = continue_waiting || wait_power_nonroot_hub (dev); + } + if (!continue_waiting) + break; + grub_millisleep (1); + } + + if (!(rescan || (npending && wait_for_completion))) + break; + grub_millisleep (25); + } } int -grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) +grub_usb_iterate (grub_usb_iterate_hook_t hook, void *hook_data) { int i; @@ -564,7 +747,7 @@ grub_usb_iterate (int (*hook) (grub_usb_device_t dev)) { if (grub_usb_devs[i]) { - if (hook (grub_usb_devs[i])) + if (hook (grub_usb_devs[i], hook_data)) return 1; } } diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c index 167fae5a2..c5680b33a 100644 --- a/grub-core/bus/usb/usbtrans.c +++ b/grub-core/bus/usb/usbtrans.c @@ -18,15 +18,29 @@ */ #include -#include +#include #include #include #include #include #include +#include + + +static inline unsigned int +grub_usb_bulk_maxpacket (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint) +{ + /* Use the maximum packet size given in the endpoint descriptor. */ + if (dev->initialized && endpoint && (unsigned int) endpoint->maxpacket) + return endpoint->maxpacket; + + return 64; +} + static grub_usb_err_t -grub_usb_execute_and_wait_transfer (grub_usb_device_t dev, +grub_usb_execute_and_wait_transfer (grub_usb_device_t dev, grub_usb_transfer_t transfer, int timeout, grub_size_t *actual) { @@ -88,6 +102,8 @@ grub_usb_control_msg (grub_usb_device_t dev, data_addr = grub_dma_get_phys (data_chunk); grub_memcpy ((char *) data, data_in, size); + grub_arch_sync_dma_caches (data, size); + grub_dprintf ("usb", "control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%lu\n", reqtype, request, value, index, (unsigned long)size); @@ -148,6 +164,8 @@ grub_usb_control_msg (grub_usb_device_t dev, setupdata->value = value; setupdata->index = index; setupdata->length = size; + grub_arch_sync_dma_caches (setupdata, sizeof (*setupdata)); + transfer->transactions[0].size = sizeof (*setupdata); transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP; transfer->transactions[0].data = setupdata_addr; @@ -187,19 +205,22 @@ grub_usb_control_msg (grub_usb_device_t dev, grub_dprintf ("usb", "control: err=%d\n", err); grub_free (transfer->transactions); - + grub_free (transfer); - grub_dma_free (data_chunk); grub_dma_free (setupdata_chunk); + grub_arch_sync_dma_caches (data, size0); grub_memcpy (data_in, (char *) data, size0); + grub_dma_free (data_chunk); + return err; } static grub_usb_transfer_t grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, - int endpoint, grub_size_t size0, char *data_in, + struct grub_usb_desc_endp *endpoint, + grub_size_t size0, char *data_in, grub_transfer_type_t type) { int i; @@ -210,7 +231,7 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, grub_uint32_t data_addr; struct grub_pci_dma_chunk *data_chunk; grub_size_t size = size0; - int toggle = dev->toggle[endpoint]; + int toggle = dev->toggle[endpoint->endp_addr]; grub_dprintf ("usb", "bulk: size=0x%02lx type=%d\n", (unsigned long) size, type); @@ -222,21 +243,10 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, data = grub_dma_get_virt (data_chunk); data_addr = grub_dma_get_phys (data_chunk); if (type == GRUB_USB_TRANSFER_TYPE_OUT) - grub_memcpy ((char *) data, data_in, size); - - /* Use the maximum packet size given in the endpoint descriptor. */ - if (dev->initialized) { - struct grub_usb_desc_endp *endpdesc; - endpdesc = grub_usb_get_endpdescriptor (dev, endpoint); - - if (endpdesc) - max = endpdesc->maxpacket; - else - max = 64; + grub_memcpy ((char *) data, data_in, size); + grub_arch_sync_dma_caches (data, size); } - else - max = 64; /* Create a transfer. */ transfer = grub_malloc (sizeof (struct grub_usb_transfer)); @@ -246,10 +256,12 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, return NULL; } + max = grub_usb_bulk_maxpacket (dev, endpoint); + datablocks = ((size + max - 1) / max); transfer->transcnt = datablocks; transfer->size = size - 1; - transfer->endpoint = endpoint; + transfer->endpoint = endpoint->endp_addr; transfer->devaddr = dev->addr; transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK; transfer->dir = type; @@ -304,18 +316,23 @@ grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer) dev->toggle[transfer->endpoint] = toggle; if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN) - grub_memcpy (transfer->data, (void *) - grub_dma_get_virt (transfer->data_chunk), - transfer->size + 1); + { + grub_arch_sync_dma_caches (grub_dma_get_virt (transfer->data_chunk), + transfer->size + 1); + grub_memcpy (transfer->data, (void *) + grub_dma_get_virt (transfer->data_chunk), + transfer->size + 1); + } grub_free (transfer->transactions); - grub_free (transfer); grub_dma_free (transfer->data_chunk); + grub_free (transfer); } static grub_usb_err_t grub_usb_bulk_readwrite (grub_usb_device_t dev, - int endpoint, grub_size_t size0, char *data_in, + struct grub_usb_desc_endp *endpoint, + grub_size_t size0, char *data_in, grub_transfer_type_t type, int timeout, grub_size_t *actual) { @@ -333,31 +350,61 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, return err; } -grub_usb_err_t -grub_usb_bulk_write (grub_usb_device_t dev, - int endpoint, grub_size_t size, char *data) +static grub_usb_err_t +grub_usb_bulk_readwrite_packetize (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint, + grub_transfer_type_t type, + grub_size_t size, char *data) { - grub_size_t actual; - grub_usb_err_t err; + grub_size_t actual, transferred; + grub_usb_err_t err = GRUB_USB_ERR_NONE; + grub_size_t current_size, position; + grub_size_t max_bulk_transfer_len = MAX_USB_TRANSFER_LEN; + grub_size_t max; - err = grub_usb_bulk_readwrite (dev, endpoint, size, data, - GRUB_USB_TRANSFER_TYPE_OUT, 1000, &actual); - if (!err && actual != size) + if (dev->controller.dev->max_bulk_tds) + { + max = grub_usb_bulk_maxpacket (dev, endpoint); + + /* Calculate max. possible length of bulk transfer */ + max_bulk_transfer_len = dev->controller.dev->max_bulk_tds * max; + } + + for (position = 0, transferred = 0; + position < size; position += max_bulk_transfer_len) + { + current_size = size - position; + if (current_size >= max_bulk_transfer_len) + current_size = max_bulk_transfer_len; + err = grub_usb_bulk_readwrite (dev, endpoint, current_size, + &data[position], type, 1000, &actual); + transferred += actual; + if (err || (current_size != actual)) break; + } + + if (!err && transferred != size) err = GRUB_USB_ERR_DATA; return err; } grub_usb_err_t -grub_usb_bulk_read (grub_usb_device_t dev, - int endpoint, grub_size_t size, char *data) +grub_usb_bulk_write (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint, + grub_size_t size, char *data) { - grub_size_t actual; - grub_usb_err_t err; - err = grub_usb_bulk_readwrite (dev, endpoint, size, data, - GRUB_USB_TRANSFER_TYPE_IN, 1000, &actual); - if (!err && actual != size) - err = GRUB_USB_ERR_DATA; - return err; + return grub_usb_bulk_readwrite_packetize (dev, endpoint, + GRUB_USB_TRANSFER_TYPE_OUT, + size, data); +} + +grub_usb_err_t +grub_usb_bulk_read (grub_usb_device_t dev, + struct grub_usb_desc_endp *endpoint, + grub_size_t size, char *data) +{ + return grub_usb_bulk_readwrite_packetize (dev, endpoint, + GRUB_USB_TRANSFER_TYPE_IN, + size, data); } grub_usb_err_t @@ -378,7 +425,8 @@ grub_usb_check_transfer (grub_usb_transfer_t transfer, grub_size_t *actual) grub_usb_transfer_t grub_usb_bulk_read_background (grub_usb_device_t dev, - int endpoint, grub_size_t size, void *data) + struct grub_usb_desc_endp *endpoint, + grub_size_t size, void *data) { grub_usb_err_t err; grub_usb_transfer_t transfer; @@ -405,7 +453,8 @@ grub_usb_cancel_transfer (grub_usb_transfer_t transfer) grub_usb_err_t grub_usb_bulk_read_extended (grub_usb_device_t dev, - int endpoint, grub_size_t size, char *data, + struct grub_usb_desc_endp *endpoint, + grub_size_t size, char *data, int timeout, grub_size_t *actual) { return grub_usb_bulk_readwrite (dev, endpoint, size, data, diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index c6be5e1f5..f72a19c03 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -27,6 +27,7 @@ #include #include #include +#include #ifdef GRUB_MACHINE_EFI #include @@ -37,6 +38,20 @@ GRUB_MOD_LICENSE ("GPLv3+"); +enum + { + OPTION_EXCLUDE = 0, + OPTION_LOAD_ONLY, + OPTION_V1, + OPTION_V2, + OPTION_OEMID, + OPTION_OEMTABLE, + OPTION_OEMTABLEREV, + OPTION_OEMTABLECREATOR, + OPTION_OEMTABLECREATORREV, + OPTION_NO_EBDA + }; + static const struct grub_arg_option options[] = { {"exclude", 'x', 0, N_("Don't load host tables specified by comma-separated list."), @@ -61,18 +76,6 @@ static const struct grub_arg_option options[] = { {0, 0, 0, 0, 0, 0} }; -/* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */ -grub_uint8_t -grub_byte_checksum (void *base, grub_size_t size) -{ - grub_uint8_t *ptr; - grub_uint8_t ret = 0; - for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size; - ptr++) - ret += *ptr; - return ret; -} - /* rev1 is 1 if ACPIv1 is to be generated, 0 otherwise. rev2 contains the revision of ACPIv2+ to generate or 0 if none. */ static int rev1, rev2; @@ -131,6 +134,8 @@ grub_acpi_get_rsdpv1 (void) return grub_machine_acpi_get_rsdpv1 (); } +#if defined (__i386__) || defined (__x86_64__) + static inline int iszero (grub_uint8_t *reg, int size) { @@ -141,50 +146,61 @@ iszero (grub_uint8_t *reg, int size) return 1; } -#if defined (__i386__) || defined (__x86_64__) +/* Context for grub_acpi_create_ebda. */ +struct grub_acpi_create_ebda_ctx { + int ebda_len; + grub_uint64_t highestlow; +}; + +/* Helper for grub_acpi_create_ebda. */ +static int +find_hook (grub_uint64_t start, grub_uint64_t size, grub_memory_type_t type, + void *data) +{ + struct grub_acpi_create_ebda_ctx *ctx = data; + grub_uint64_t end = start + size; + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + if (end > 0x100000) + end = 0x100000; + if (end > start + ctx->ebda_len + && ctx->highestlow < ((end - ctx->ebda_len) & (~0xf)) ) + ctx->highestlow = (end - ctx->ebda_len) & (~0xf); + return 0; +} + grub_err_t grub_acpi_create_ebda (void) { - int ebda_kb_len; - int ebda_len; + struct grub_acpi_create_ebda_ctx ctx = { + .highestlow = 0 + }; + int ebda_kb_len = 0; int mmapregion = 0; grub_uint8_t *ebda, *v1inebda = 0, *v2inebda = 0; - grub_uint64_t highestlow = 0; grub_uint8_t *targetebda, *target; struct grub_acpi_rsdp_v10 *v1; struct grub_acpi_rsdp_v20 *v2; - auto int NESTED_FUNC_ATTR find_hook (grub_uint64_t, grub_uint64_t, - grub_uint32_t); - int NESTED_FUNC_ATTR find_hook (grub_uint64_t start, grub_uint64_t size, - grub_memory_type_t type) - { - grub_uint64_t end = start + size; - if (type != GRUB_MEMORY_AVAILABLE) - return 0; - if (end > 0x100000) - end = 0x100000; - if (end > start + ebda_len - && highestlow < ((end - ebda_len) & (~0xf)) ) - highestlow = (end - ebda_len) & (~0xf); - return 0; - } - ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4); - ebda_kb_len = *(grub_uint16_t *) ebda; - if (! ebda || ebda_kb_len > 16) + ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *) grub_absolute_pointer (0x40e))) << 4); + grub_dprintf ("acpi", "EBDA @%p\n", ebda); + if (ebda) + ebda_kb_len = *(grub_uint16_t *) ebda; + grub_dprintf ("acpi", "EBDA length 0x%x\n", ebda_kb_len); + if (ebda_kb_len > 16) ebda_kb_len = 0; - ebda_len = (ebda_kb_len + 1) << 10; + ctx.ebda_len = (ebda_kb_len + 1) << 10; /* FIXME: use low-memory mm allocation once it's available. */ - grub_mmap_iterate (find_hook); - targetebda = (grub_uint8_t *) (grub_addr_t) highestlow; + grub_mmap_iterate (find_hook, &ctx); + targetebda = (grub_uint8_t *) (grub_addr_t) ctx.highestlow; grub_dprintf ("acpi", "creating ebda @%llx\n", - (unsigned long long) highestlow); - if (! highestlow) + (unsigned long long) ctx.highestlow); + if (! ctx.highestlow) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't find space for the new EBDA"); - mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ebda_len, + mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ctx.ebda_len, GRUB_MEMORY_RESERVED); if (! mmapregion) return grub_errno; @@ -207,7 +223,7 @@ grub_acpi_create_ebda (void) { grub_dprintf ("acpi", "Scanning EBDA for old rsdpv2\n"); for (; target < targetebda + 0x400 - v2->length; target += 0x10) - if (grub_memcmp (target, "RSD PTR ", 8) == 0 + if (grub_memcmp (target, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (target, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) target)->revision != 0 @@ -217,7 +233,7 @@ grub_acpi_create_ebda (void) grub_dprintf ("acpi", "Copying rsdpv2 to %p\n", target); v2inebda = target; target += v2->length; - target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1); + target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16); v2 = 0; break; } @@ -228,7 +244,7 @@ grub_acpi_create_ebda (void) grub_dprintf ("acpi", "Scanning EBDA for old rsdpv1\n"); for (; target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10); target += 0x10) - if (grub_memcmp (target, "RSD PTR ", 8) == 0 + if (grub_memcmp (target, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (target, sizeof (struct grub_acpi_rsdp_v10)) == 0) { @@ -236,7 +252,7 @@ grub_acpi_create_ebda (void) grub_dprintf ("acpi", "Copying rsdpv1 to %p\n", target); v1inebda = target; target += sizeof (struct grub_acpi_rsdp_v10); - target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1); + target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16); v1 = 0; break; } @@ -255,7 +271,7 @@ grub_acpi_create_ebda (void) grub_memcpy (target, v2, v2->length); v2inebda = target; target += v2->length; - target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1); + target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16); v2 = 0; break; } @@ -272,7 +288,7 @@ grub_acpi_create_ebda (void) grub_memcpy (target, v1, sizeof (struct grub_acpi_rsdp_v10)); v1inebda = target; target += sizeof (struct grub_acpi_rsdp_v10); - target = (grub_uint8_t *) ((((long) target - 1) | 0xf) + 1); + target = (grub_uint8_t *) ALIGN_UP((grub_addr_t) target, 16); v1 = 0; break; } @@ -289,14 +305,14 @@ grub_acpi_create_ebda (void) for (target = targetebda; target < targetebda + 0x400 - sizeof (struct grub_acpi_rsdp_v10); target += 0x10) - if (grub_memcmp (target, "RSD PTR ", 8) == 0 + if (grub_memcmp (target, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (target, sizeof (struct grub_acpi_rsdp_v10)) == 0 && target != v1inebda && target != v2inebda) *target = 0; grub_dprintf ("acpi", "Switching EBDA\n"); - (*((grub_uint16_t *) 0x40e)) = ((long)targetebda) >> 4; + (*((grub_uint16_t *) grub_absolute_pointer (0x40e))) = ((grub_addr_t) targetebda) >> 4; grub_dprintf ("acpi", "EBDA switched\n"); return GRUB_ERR_NONE; @@ -355,13 +371,13 @@ setup_common_tables (void) numoftables++; rsdt_addr = rsdt = (struct grub_acpi_table_header *) playground_ptr; - playground_ptr += sizeof (struct grub_acpi_table_header) + 4 * numoftables; + playground_ptr += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint32_t) * numoftables; rsdt_entry = (grub_uint32_t *) (rsdt + 1); /* Fill RSDT header. */ grub_memcpy (&(rsdt->signature), "RSDT", 4); - rsdt->length = sizeof (struct grub_acpi_table_header) + 4 * numoftables; + rsdt->length = sizeof (struct grub_acpi_table_header) + sizeof (grub_uint32_t) * numoftables; rsdt->revision = 1; grub_memcpy (&(rsdt->oemid), root_oemid, sizeof (rsdt->oemid)); grub_memcpy (&(rsdt->oemtable), root_oemtable, sizeof (rsdt->oemtable)); @@ -384,7 +400,7 @@ setv1table (void) /* Create RSDP. */ rsdpv1_new = (struct grub_acpi_rsdp_v10 *) playground_ptr; playground_ptr += sizeof (struct grub_acpi_rsdp_v10); - grub_memcpy (&(rsdpv1_new->signature), "RSD PTR ", + grub_memcpy (&(rsdpv1_new->signature), GRUB_RSDP_SIGNATURE, sizeof (rsdpv1_new->signature)); grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid)); rsdpv1_new->revision = 0; @@ -409,13 +425,13 @@ setv2table (void) /* Create XSDT. */ xsdt = (struct grub_acpi_table_header *) playground_ptr; - playground_ptr += sizeof (struct grub_acpi_table_header) + 8 * numoftables; + playground_ptr += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint64_t) * numoftables; xsdt_entry = (grub_uint64_t *)(xsdt + 1); for (cur = acpi_tables; cur; cur = cur->next) *(xsdt_entry++) = (grub_addr_t) cur->addr; grub_memcpy (&(xsdt->signature), "XSDT", 4); - xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables; + xsdt->length = sizeof (struct grub_acpi_table_header) + sizeof (grub_uint64_t) * numoftables; xsdt->revision = 1; grub_memcpy (&(xsdt->oemid), root_oemid, sizeof (xsdt->oemid)); grub_memcpy (&(xsdt->oemtable), root_oemtable, sizeof (xsdt->oemtable)); @@ -428,7 +444,7 @@ setv2table (void) /* Create RSDPv2. */ rsdpv2_new = (struct grub_acpi_rsdp_v20 *) playground_ptr; playground_ptr += sizeof (struct grub_acpi_rsdp_v20); - grub_memcpy (&(rsdpv2_new->rsdpv1.signature), "RSD PTR ", + grub_memcpy (&(rsdpv2_new->rsdpv1.signature), GRUB_RSDP_SIGNATURE, sizeof (rsdpv2_new->rsdpv1.signature)); grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid, sizeof (rsdpv2_new->rsdpv1.oemid)); @@ -484,23 +500,25 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) if (! rsdp) rsdp = grub_machine_acpi_get_rsdpv1 (); + grub_dprintf ("acpi", "RSDP @%p\n", rsdp); + if (rsdp) { - grub_uint32_t *entry_ptr; + grub_uint8_t *entry_ptr; char *exclude = 0; char *load_only = 0; char *ptr; - /* RSDT consists of header and an array of 32-bit pointers. */ - struct grub_acpi_table_header *rsdt; + grub_size_t tbl_addr_size; + struct grub_acpi_table_header *table_head; - exclude = state[0].set ? grub_strdup (state[0].arg) : 0; + exclude = state[OPTION_EXCLUDE].set ? grub_strdup (state[OPTION_EXCLUDE].arg) : 0; if (exclude) { for (ptr = exclude; *ptr; ptr++) *ptr = grub_tolower (*ptr); } - load_only = state[1].set ? grub_strdup (state[1].arg) : 0; + load_only = state[OPTION_LOAD_ONLY].set ? grub_strdup (state[OPTION_LOAD_ONLY].arg) : 0; if (load_only) { for (ptr = load_only; *ptr; ptr++) @@ -510,17 +528,32 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) /* Set revision variables to replicate the same version as host. */ rev1 = ! rsdp->revision; rev2 = rsdp->revision; - rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr; + if (rev2 && ((struct grub_acpi_table_header *) (grub_addr_t) ((struct grub_acpi_rsdp_v20 *) rsdp)->xsdt_addr) != NULL) + { + /* XSDT consists of header and an array of 64-bit pointers. */ + table_head = (struct grub_acpi_table_header *) (grub_addr_t) ((struct grub_acpi_rsdp_v20 *) rsdp)->xsdt_addr; + tbl_addr_size = sizeof (((struct grub_acpi_rsdp_v20 *) rsdp)->xsdt_addr); + } + else + { + /* RSDT consists of header and an array of 32-bit pointers. */ + table_head = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr; + tbl_addr_size = sizeof (rsdp->rsdt_addr); + } + /* Load host tables. */ - for (entry_ptr = (grub_uint32_t *) (rsdt + 1); - entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt) - + rsdt->length); - entry_ptr++) + for (entry_ptr = (grub_uint8_t *) (table_head + 1); + entry_ptr < (grub_uint8_t *) (((grub_uint8_t *) table_head) + table_head->length); + entry_ptr += tbl_addr_size) { char signature[5]; struct efiemu_acpi_table *table; - struct grub_acpi_table_header *curtable - = (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr; + struct grub_acpi_table_header *curtable; + if (tbl_addr_size == sizeof (rsdp->rsdt_addr)) + curtable = (struct grub_acpi_table_header *) (grub_addr_t) *((grub_uint32_t *) entry_ptr); + else + curtable = (struct grub_acpi_table_header *) (grub_addr_t) *((grub_uint64_t *) entry_ptr); + signature[4] = 0; for (i = 0; i < 4;i++) signature[i] = grub_tolower (curtable->signature[i]); @@ -590,6 +623,9 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) if (! table->addr) { free_tables (); + grub_free (exclude); + grub_free (load_only); + grub_free (table); return grub_errno; } table->next = acpi_tables; @@ -601,26 +637,26 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) } /* Does user specify versions to generate? */ - if (state[2].set || state[3].set) + if (state[OPTION_V1].set || state[OPTION_V2].set) { - rev1 = state[2].set; - if (state[3].set) + rev1 = state[OPTION_V1].set; + if (state[OPTION_V2].set) rev2 = rev2 ? : 2; else rev2 = 0; } /* Does user override root header information? */ - if (state[4].set) - grub_strncpy (root_oemid, state[4].arg, sizeof (root_oemid)); - if (state[5].set) - grub_strncpy (root_oemtable, state[5].arg, sizeof (root_oemtable)); - if (state[6].set) - root_oemrev = grub_strtoul (state[6].arg, 0, 0); - if (state[7].set) - grub_strncpy (root_creator_id, state[7].arg, sizeof (root_creator_id)); - if (state[8].set) - root_creator_rev = grub_strtoul (state[8].arg, 0, 0); + if (state[OPTION_OEMID].set) + grub_strncpy (root_oemid, state[OPTION_OEMID].arg, sizeof (root_oemid)); + if (state[OPTION_OEMTABLE].set) + grub_strncpy (root_oemtable, state[OPTION_OEMTABLE].arg, sizeof (root_oemtable)); + if (state[OPTION_OEMTABLEREV].set) + root_oemrev = grub_strtoul (state[OPTION_OEMTABLEREV].arg, 0, 0); + if (state[OPTION_OEMTABLECREATOR].set) + grub_strncpy (root_creator_id, state[OPTION_OEMTABLECREATOR].arg, sizeof (root_creator_id)); + if (state[OPTION_OEMTABLECREATORREV].set) + root_creator_rev = grub_strtoul (state[OPTION_OEMTABLECREATORREV].arg, 0, 0); /* Load user tables */ for (i = 0; i < argc; i++) @@ -629,7 +665,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) grub_size_t size; char *buf; - file = grub_file_open (args[i]); + file = grub_file_open (args[i], GRUB_FILE_TYPE_ACPI_TABLE); if (! file) { free_tables (); @@ -698,11 +734,11 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) /* DSDT. */ playground_size += dsdt_size; /* RSDT. */ - playground_size += sizeof (struct grub_acpi_table_header) + 4 * numoftables; + playground_size += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint32_t) * numoftables; /* RSDPv1. */ playground_size += sizeof (struct grub_acpi_rsdp_v10); /* XSDT. */ - playground_size += sizeof (struct grub_acpi_table_header) + 8 * numoftables; + playground_size += sizeof (struct grub_acpi_table_header) + sizeof (grub_uint64_t) * numoftables; /* RSDPv2. */ playground_size += sizeof (struct grub_acpi_rsdp_v20); @@ -736,7 +772,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) acpi_tables = 0; #if defined (__i386__) || defined (__x86_64__) - if (! state[9].set) + if (! state[OPTION_NO_EBDA].set) { grub_err_t err; err = grub_acpi_create_ebda (); @@ -752,13 +788,13 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) #ifdef GRUB_MACHINE_EFI { - struct grub_efi_guid acpi = GRUB_EFI_ACPI_TABLE_GUID; - struct grub_efi_guid acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID; + static grub_guid_t acpi = GRUB_EFI_ACPI_TABLE_GUID; + static grub_guid_t acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID; - grub_efi_system_table->boot_services->install_configuration_table - (&acpi20, grub_acpi_get_rsdpv2 ()); - grub_efi_system_table->boot_services->install_configuration_table - (&acpi, grub_acpi_get_rsdpv1 ()); + grub_efi_system_table->boot_services->install_configuration_table (&acpi20, + grub_acpi_get_rsdpv2 ()); + grub_efi_system_table->boot_services->install_configuration_table (&acpi, + grub_acpi_get_rsdpv1 ()); } #endif @@ -769,13 +805,13 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(acpi) { - cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, 0, - N_("[-1|-2] [--exclude=TABLE1,TABLE2|" - "--load-only=TABLE1,TABLE2] FILE1" - " [FILE2] [...]"), - N_("Load host ACPI tables and tables " - "specified by arguments."), - options); + cmd = grub_register_extcmd_lockdown ("acpi", grub_cmd_acpi, 0, + N_("[-1|-2] [--exclude=TABLE1,TABLE2|" + "--load-only=TABLE1,TABLE2] FILE1" + " [FILE2] [...]"), + N_("Load host ACPI tables and tables " + "specified by arguments."), + options); } GRUB_MOD_FINI(acpi) diff --git a/grub-core/commands/acpihalt.c b/grub-core/commands/acpihalt.c index 3db224d4d..9a5e22155 100644 --- a/grub-core/commands/acpihalt.c +++ b/grub-core/commands/acpihalt.c @@ -22,9 +22,12 @@ #include #include #include +#include #define grub_dprintf(cond, args...) printf ( args ) #define grub_printf printf +#define grub_util_fopen fopen +#define grub_memcmp memcmp typedef uint64_t grub_uint64_t; typedef uint32_t grub_uint32_t; typedef uint16_t grub_uint16_t; @@ -41,6 +44,7 @@ typedef uint8_t grub_uint8_t; #endif #ifndef GRUB_DSDT_TEST +#include #include #include #include @@ -74,7 +78,7 @@ static inline grub_uint32_t skip_name_string (const grub_uint8_t *ptr, const grub_uint8_t *end) { const grub_uint8_t *ptr0 = ptr; - + while (ptr < end && (*ptr == '^' || *ptr == '\\')) ptr++; switch (*ptr) @@ -133,6 +137,49 @@ skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end) } } +static inline grub_uint32_t +skip_term (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + grub_uint32_t add; + const grub_uint8_t *ptr0 = ptr; + + switch(*ptr) + { + case GRUB_ACPI_OPCODE_ADD: + case GRUB_ACPI_OPCODE_AND: + case GRUB_ACPI_OPCODE_CONCAT: + case GRUB_ACPI_OPCODE_CONCATRES: + case GRUB_ACPI_OPCODE_DIVIDE: + case GRUB_ACPI_OPCODE_INDEX: + case GRUB_ACPI_OPCODE_LSHIFT: + case GRUB_ACPI_OPCODE_MOD: + case GRUB_ACPI_OPCODE_MULTIPLY: + case GRUB_ACPI_OPCODE_NAND: + case GRUB_ACPI_OPCODE_NOR: + case GRUB_ACPI_OPCODE_OR: + case GRUB_ACPI_OPCODE_RSHIFT: + case GRUB_ACPI_OPCODE_SUBTRACT: + case GRUB_ACPI_OPCODE_TOSTRING: + case GRUB_ACPI_OPCODE_XOR: + /* + * Parameters for these opcodes: TermArg, TermArg Target, see ACPI + * spec r5.0, page 828f. + */ + ptr++; + ptr += add = skip_term (ptr, end); + if (!add) + return 0; + ptr += add = skip_term (ptr, end); + if (!add) + return 0; + ptr += skip_name_string (ptr, end); + break; + default: + return skip_data_ref_object (ptr, end); + } + return ptr - ptr0; +} + static inline grub_uint32_t skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end) { @@ -146,19 +193,28 @@ skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end) ptr += skip_name_string (ptr, end); ptr++; break; + case GRUB_ACPI_EXTOPCODE_EVENT_OP: + ptr++; + ptr += skip_name_string (ptr, end); + break; case GRUB_ACPI_EXTOPCODE_OPERATION_REGION: ptr++; ptr += skip_name_string (ptr, end); ptr++; - ptr += add = skip_data_ref_object (ptr, end); + ptr += add = skip_term (ptr, end); if (!add) return 0; - ptr += add = skip_data_ref_object (ptr, end); + ptr += add = skip_term (ptr, end); if (!add) return 0; break; case GRUB_ACPI_EXTOPCODE_FIELD_OP: + case GRUB_ACPI_EXTOPCODE_DEVICE_OP: + case GRUB_ACPI_EXTOPCODE_PROCESSOR_OP: + case GRUB_ACPI_EXTOPCODE_POWER_RES_OP: + case GRUB_ACPI_EXTOPCODE_THERMAL_ZONE_OP: case GRUB_ACPI_EXTOPCODE_INDEX_FIELD_OP: + case GRUB_ACPI_EXTOPCODE_BANK_FIELD_OP: ptr++; ptr += decode_length (ptr, 0); break; @@ -169,13 +225,15 @@ skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end) return ptr - ptr0; } + static int -get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) +get_sleep_type (grub_uint8_t *table, grub_uint8_t *ptr, grub_uint8_t *end, + grub_uint8_t *scope, int scope_len) { - grub_uint8_t *ptr, *prev = table; - int sleep_type = -1; - - ptr = table + sizeof (struct grub_acpi_table_header); + grub_uint8_t *prev = table; + + if (!ptr) + ptr = table + sizeof (struct grub_acpi_table_header); while (ptr < end && prev < ptr) { int add; @@ -190,6 +248,7 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) if (!add) return -1; break; + case GRUB_ACPI_OPCODE_CREATE_DWORD_FIELD: case GRUB_ACPI_OPCODE_CREATE_WORD_FIELD: case GRUB_ACPI_OPCODE_CREATE_BYTE_FIELD: { @@ -202,7 +261,8 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) } case GRUB_ACPI_OPCODE_NAME: ptr++; - if (memcmp (ptr, "_S5_", 4) == 0 || memcmp (ptr, "\\_S5_", 4) == 0) + if ((!scope || grub_memcmp (scope, "\\", scope_len) == 0) && + (grub_memcmp (ptr, "_S5_", 4) == 0 || grub_memcmp (ptr, "\\_S5_", 4) == 0)) { int ll; grub_uint8_t *ptr2 = ptr; @@ -220,14 +280,11 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) switch (*ptr2) { case GRUB_ACPI_OPCODE_ZERO: - sleep_type = 0; - break; + return 0; case GRUB_ACPI_OPCODE_ONE: - sleep_type = 1; - break; + return 1; case GRUB_ACPI_OPCODE_BYTE_CONST: - sleep_type = ptr2[1]; - break; + return ptr2[1]; default: grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2); return -1; @@ -240,7 +297,37 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) if (!add) return -1; break; + case GRUB_ACPI_OPCODE_ALIAS: + ptr++; + /* We need to skip two name strings */ + ptr += add = skip_name_string (ptr, end); + if (!add) + return -1; + ptr += add = skip_name_string (ptr, end); + if (!add) + return -1; + break; + case GRUB_ACPI_OPCODE_SCOPE: + { + int scope_sleep_type; + int ll; + grub_uint8_t *name; + int name_len; + + ptr++; + add = decode_length (ptr, &ll); + name = ptr + ll; + name_len = skip_name_string (name, ptr + add); + if (!name_len) + return -1; + scope_sleep_type = get_sleep_type (table, name + name_len, + ptr + add, name, name_len); + if (scope_sleep_type != -2) + return scope_sleep_type; + ptr += add; + break; + } case GRUB_ACPI_OPCODE_IF: case GRUB_ACPI_OPCODE_METHOD: { @@ -250,12 +337,11 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) } default: grub_printf ("Unknown opcode 0x%x\n", *ptr); - return -1; + return -1; } } - grub_dprintf ("acpi", "TYP = %d\n", sleep_type); - return sleep_type; + return -2; } #ifdef GRUB_DSDT_TEST @@ -267,7 +353,7 @@ main (int argc, char **argv) unsigned char *buf; if (argc < 2) printf ("Usage: %s FILE\n", argv[0]); - f = fopen (argv[1], "rb"); + f = grub_util_fopen (argv[1], "rb"); if (!f) { printf ("Couldn't open file\n"); @@ -279,19 +365,19 @@ main (int argc, char **argv) buf = malloc (len); if (!buf) { - printf ("Couldn't malloc buffer\n"); + printf (_("error: %s.\n"), _("out of memory")); fclose (f); return 2; } if (fread (buf, 1, len, f) != len) { - printf ("Read failed\n"); + printf (_("cannot read `%s': %s"), argv[1], strerror (errno)); free (buf); fclose (f); return 2; } - printf ("Sleep type = %d\n", get_sleep_type (buf, buf + len)); + printf ("Sleep type = %d\n", get_sleep_type (buf, NULL, buf + len, NULL, 0)); free (buf); fclose (f); return 0; @@ -304,8 +390,10 @@ grub_acpi_halt (void) { struct grub_acpi_rsdp_v20 *rsdp2; struct grub_acpi_rsdp_v10 *rsdp1; - struct grub_acpi_table_header *rsdt; - grub_uint32_t *entry_ptr; + struct grub_acpi_table_header *rsdt; + grub_uint32_t *entry_ptr; + grub_uint32_t port = 0; + int sleep_type = -1; rsdp2 = grub_acpi_get_rsdpv2 (); if (rsdp2) @@ -324,35 +412,40 @@ grub_acpi_halt (void) { if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "FACP", 4) == 0) { - grub_uint32_t port; struct grub_acpi_fadt *fadt = ((struct grub_acpi_fadt *) (grub_addr_t) *entry_ptr); struct grub_acpi_table_header *dsdt = (struct grub_acpi_table_header *) (grub_addr_t) fadt->dsdt_addr; - int sleep_type = -1; + grub_uint8_t *buf = (grub_uint8_t *) dsdt; port = fadt->pm1a; grub_dprintf ("acpi", "PM1a port=%x\n", port); if (grub_memcmp (dsdt->signature, "DSDT", - sizeof (dsdt->signature)) != 0) - break; + sizeof (dsdt->signature)) == 0 + && sleep_type < 0) + sleep_type = get_sleep_type (buf, NULL, buf + dsdt->length, + NULL, 0); + } + else if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "SSDT", 4) == 0 + && sleep_type < 0) + { + struct grub_acpi_table_header *ssdt + = (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr; + grub_uint8_t *buf = (grub_uint8_t *) ssdt; - sleep_type = get_sleep_type ((grub_uint8_t *) dsdt, - (grub_uint8_t *) dsdt + dsdt->length); + grub_dprintf ("acpi", "SSDT = %p\n", ssdt); - if (sleep_type < 0 || sleep_type >= 8) - break; - - grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n", - sleep_type, port); - - grub_outw (GRUB_ACPI_SLP_EN - | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET), port & 0xffff); + sleep_type = get_sleep_type (buf, NULL, buf + ssdt->length, NULL, 0); } } + grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n", sleep_type, port); + if (port && sleep_type >= 0 && sleep_type < 8) + grub_outw (GRUB_ACPI_SLP_EN | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET), + port & 0xffff); + grub_millisleep (1500); /* TRANSLATORS: It's computer shutdown using ACPI, not disabling ACPI. */ diff --git a/grub-core/commands/arc/lsdev.c b/grub-core/commands/arc/lsdev.c index 5d4b0cd09..27ed0a248 100644 --- a/grub-core/commands/arc/lsdev.c +++ b/grub-core/commands/arc/lsdev.c @@ -24,18 +24,22 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Helper for grub_cmd_lsdev. */ +static int +grub_cmd_lsdev_iter (const char *name, + const struct grub_arc_component *comp __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + grub_printf ("%s\n", name); + return 0; +} + static grub_err_t grub_cmd_lsdev (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - auto int hook (const char *name, const struct grub_arc_component *comp); - int hook (const char *name, const struct grub_arc_component *comp __attribute__ ((unused))) - { - grub_printf ("%s\n", name); - return 0; - } - grub_arc_iterate_devs (hook, 0); + grub_arc_iterate_devs (grub_cmd_lsdev_iter, 0, 0); return 0; } diff --git a/grub-core/commands/bli.c b/grub-core/commands/bli.c new file mode 100644 index 000000000..298c5f70a --- /dev/null +++ b/grub-core/commands/bli.c @@ -0,0 +1,138 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2023 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + * + * Implementation of the Boot Loader Interface. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define MODNAME "bli" + +static const grub_guid_t bli_vendor_guid = GRUB_EFI_VENDOR_BOOT_LOADER_INTERFACE_GUID; + +static grub_err_t +get_part_uuid (const char *device_name, char **part_uuid) +{ + grub_device_t device; + grub_err_t status = GRUB_ERR_NONE; + grub_disk_t disk = NULL; + struct grub_gpt_partentry entry; + + device = grub_device_open (device_name); + if (device == NULL) + return grub_error (grub_errno, N_("cannot open device: %s"), device_name); + + if (device->disk == NULL) + { + grub_dprintf ("bli", "%s is not a disk device, partuuid skipped\n", device_name); + *part_uuid = NULL; + grub_device_close (device); + return GRUB_ERR_NONE; + } + + if (device->disk->partition == NULL) + { + grub_dprintf ("bli", "%s has no partition, partuuid skipped\n", device_name); + *part_uuid = NULL; + grub_device_close (device); + return GRUB_ERR_NONE; + } + + disk = grub_disk_open (device->disk->name); + if (disk == NULL) + { + status = grub_error (grub_errno, N_("cannot open disk: %s"), device_name); + grub_device_close (device); + return status; + } + + if (grub_strcmp (device->disk->partition->partmap->name, "gpt") != 0) + { + status = grub_error (GRUB_ERR_BAD_PART_TABLE, + N_("this is not a GPT partition table: %s"), device_name); + goto fail; + } + + if (grub_disk_read (disk, device->disk->partition->offset, + device->disk->partition->index, sizeof (entry), &entry) != GRUB_ERR_NONE) + { + status = grub_error (grub_errno, N_("read error: %s"), device_name); + goto fail; + } + + *part_uuid = grub_xasprintf ("%pG", &entry.guid); + if (*part_uuid == NULL) + status = grub_errno; + + fail: + grub_disk_close (disk); + grub_device_close (device); + + return status; +} + +static grub_err_t +set_loader_device_part_uuid (void) +{ + grub_efi_loaded_image_t *image; + char *device_name; + grub_err_t status = GRUB_ERR_NONE; + char *part_uuid = NULL; + + image = grub_efi_get_loaded_image (grub_efi_image_handle); + if (image == NULL) + return grub_error (GRUB_ERR_BAD_DEVICE, N_("unable to find boot device")); + + device_name = grub_efidisk_get_device_name (image->device_handle); + if (device_name == NULL) + return grub_error (GRUB_ERR_BAD_DEVICE, N_("unable to find boot device")); + + status = get_part_uuid (device_name, &part_uuid); + + if (status == GRUB_ERR_NONE && part_uuid) + status = grub_efi_set_variable_to_string ("LoaderDevicePartUUID", &bli_vendor_guid, part_uuid, + GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | + GRUB_EFI_VARIABLE_RUNTIME_ACCESS); + else + grub_error (status, N_("unable to determine partition UUID of boot device")); + + grub_free (part_uuid); + grub_free (device_name); + return status; +} + +GRUB_MOD_INIT (bli) +{ + grub_efi_set_variable_to_string ("LoaderInfo", &bli_vendor_guid, PACKAGE_STRING, + GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS | + GRUB_EFI_VARIABLE_RUNTIME_ACCESS); + set_loader_device_part_uuid (); + /* No error here is critical, other than being logged */ + grub_print_error (); +} diff --git a/grub-core/commands/blocklist.c b/grub-core/commands/blocklist.c index 164a6fea3..48fd85a33 100644 --- a/grub-core/commands/blocklist.c +++ b/grub-core/commands/blocklist.c @@ -28,64 +28,103 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Context for grub_cmd_blocklist. */ +struct blocklist_ctx +{ + unsigned long start_sector; + unsigned num_sectors; + int num_entries; + grub_disk_addr_t part_start; +}; + +/* Helper for grub_cmd_blocklist. */ +static void +print_blocklist (grub_disk_addr_t sector, unsigned num, + unsigned offset, unsigned length, struct blocklist_ctx *ctx) +{ + if (ctx->num_entries++) + grub_printf (","); + + grub_printf ("%llu", (unsigned long long) (sector - ctx->part_start)); + if (num > 0) + grub_printf ("+%u", num); + if (offset != 0 || length != 0) + grub_printf ("[%u-%u]", offset, offset + length); +} + +/* Helper for grub_cmd_blocklist. */ +static grub_err_t +read_blocklist (grub_disk_addr_t sector, unsigned offset, unsigned length, + char *buf __attribute__ ((unused)), void *data) +{ + struct blocklist_ctx *ctx = data; + + if (ctx->num_sectors > 0) + { + if (ctx->start_sector + ctx->num_sectors == sector + && offset == 0 && length >= GRUB_DISK_SECTOR_SIZE) + { + ctx->num_sectors += length >> GRUB_DISK_SECTOR_BITS; + sector += length >> GRUB_DISK_SECTOR_BITS; + length &= (GRUB_DISK_SECTOR_SIZE - 1); + } + + if (!length) + return GRUB_ERR_NONE; + print_blocklist (ctx->start_sector, ctx->num_sectors, 0, 0, ctx); + ctx->num_sectors = 0; + } + + if (offset) + { + unsigned l = length + offset; + l &= (GRUB_DISK_SECTOR_SIZE - 1); + l -= offset; + print_blocklist (sector, 0, offset, l, ctx); + length -= l; + sector++; + offset = 0; + } + + if (!length) + return GRUB_ERR_NONE; + + if (length & (GRUB_DISK_SECTOR_SIZE - 1)) + { + if (length >> GRUB_DISK_SECTOR_BITS) + { + print_blocklist (sector, length >> GRUB_DISK_SECTOR_BITS, 0, 0, ctx); + sector += length >> GRUB_DISK_SECTOR_BITS; + } + print_blocklist (sector, 0, 0, length & (GRUB_DISK_SECTOR_SIZE - 1), ctx); + } + else + { + ctx->start_sector = sector; + ctx->num_sectors = length >> GRUB_DISK_SECTOR_BITS; + } + + return GRUB_ERR_NONE; +} + static grub_err_t grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { grub_file_t file; char buf[GRUB_DISK_SECTOR_SIZE]; - unsigned long start_sector = 0; - unsigned num_sectors = 0; - int num_entries = 0; - grub_disk_addr_t part_start = 0; - auto void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset, - unsigned length); - auto void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num, - unsigned offset, unsigned length); - - void NESTED_FUNC_ATTR read_blocklist (grub_disk_addr_t sector, unsigned offset, - unsigned length) - { - if (num_sectors > 0) - { - if (start_sector + num_sectors == sector - && offset == 0 && length == GRUB_DISK_SECTOR_SIZE) - { - num_sectors++; - return; - } - - print_blocklist (start_sector, num_sectors, 0, 0); - num_sectors = 0; - } - - if (offset == 0 && length == GRUB_DISK_SECTOR_SIZE) - { - start_sector = sector; - num_sectors++; - } - else - print_blocklist (sector, 0, offset, length); - } - - void NESTED_FUNC_ATTR print_blocklist (grub_disk_addr_t sector, unsigned num, - unsigned offset, unsigned length) - { - if (num_entries++) - grub_printf (","); - - grub_printf ("%llu", (unsigned long long) (sector - part_start)); - if (num > 0) - grub_printf ("+%u", num); - if (offset != 0 || length != 0) - grub_printf ("[%u-%u]", offset, offset + length); - } + struct blocklist_ctx ctx = { + .start_sector = 0, + .num_sectors = 0, + .num_entries = 0, + .part_start = 0 + }; if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); - grub_file_filter_disable_compression (); - file = grub_file_open (args[0]); + file = grub_file_open (args[0], GRUB_FILE_TYPE_PRINT_BLOCKLIST + | GRUB_FILE_TYPE_NO_DECOMPRESS); if (! file) return grub_errno; @@ -93,15 +132,16 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_DEVICE, "this command is available only for disk devices"); - part_start = grub_partition_get_start (file->device->disk->partition); + ctx.part_start = grub_partition_get_start (file->device->disk->partition); file->read_hook = read_blocklist; + file->read_hook_data = &ctx; while (grub_file_read (file, buf, sizeof (buf)) > 0) ; - if (num_sectors > 0) - print_blocklist (start_sector, num_sectors, 0, 0); + if (ctx.num_sectors > 0) + print_blocklist (ctx.start_sector, ctx.num_sectors, 0, 0, &ctx); grub_file_close (file); diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c index 91ec87d80..61514788e 100644 --- a/grub-core/commands/boot.c +++ b/grub-core/commands/boot.c @@ -27,10 +27,20 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_err_t (*grub_loader_boot_func) (void); -static grub_err_t (*grub_loader_unload_func) (void); +static grub_err_t (*grub_loader_boot_func) (void *context); +static grub_err_t (*grub_loader_unload_func) (void *context); +static void *grub_loader_context; static int grub_loader_flags; +struct grub_simple_loader_hooks +{ + grub_err_t (*boot) (void); + grub_err_t (*unload) (void); +}; + +/* Don't heap allocate this to avoid making grub_loader_set() fallible. */ +static struct grub_simple_loader_hooks simple_loader_hooks; + struct grub_preboot { grub_err_t (*preboot_func) (int); @@ -44,6 +54,29 @@ static int grub_loader_loaded; static struct grub_preboot *preboots_head = 0, *preboots_tail = 0; +static grub_err_t +grub_simple_boot_hook (void *context) +{ + struct grub_simple_loader_hooks *hooks; + + hooks = (struct grub_simple_loader_hooks *) context; + return hooks->boot (); +} + +static grub_err_t +grub_simple_unload_hook (void *context) +{ + struct grub_simple_loader_hooks *hooks; + grub_err_t ret; + + hooks = (struct grub_simple_loader_hooks *) context; + + ret = hooks->unload (); + grub_memset (hooks, 0, sizeof (*hooks)); + + return ret; +} + int grub_loader_is_loaded (void) { @@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd) } void -grub_loader_set (grub_err_t (*boot) (void), - grub_err_t (*unload) (void), - int flags) +grub_loader_set_ex (grub_err_t (*boot) (void *context), + grub_err_t (*unload) (void *context), + void *context, + int flags) { if (grub_loader_loaded && grub_loader_unload_func) - grub_loader_unload_func (); + grub_loader_unload_func (grub_loader_context); grub_loader_boot_func = boot; grub_loader_unload_func = unload; + grub_loader_context = context; grub_loader_flags = flags; grub_loader_loaded = 1; } +void +grub_loader_set (grub_err_t (*boot) (void), + grub_err_t (*unload) (void), + int flags) +{ + grub_loader_set_ex (grub_simple_boot_hook, + grub_simple_unload_hook, + &simple_loader_hooks, + flags); + + simple_loader_hooks.boot = boot; + simple_loader_hooks.unload = unload; +} + void grub_loader_unset(void) { if (grub_loader_loaded && grub_loader_unload_func) - grub_loader_unload_func (); + grub_loader_unload_func (grub_loader_context); grub_loader_boot_func = 0; grub_loader_unload_func = 0; + grub_loader_context = 0; grub_loader_loaded = 0; } @@ -146,8 +196,7 @@ grub_loader_boot (void) return grub_error (GRUB_ERR_NO_KERNEL, N_("you need to load the kernel first")); - if (grub_loader_flags & GRUB_LOADER_FLAG_NORETURN) - grub_machine_fini (); + grub_machine_fini (grub_loader_flags); for (cur = preboots_head; cur; cur = cur->next) { @@ -159,7 +208,7 @@ grub_loader_boot (void) return err; } } - err = (grub_loader_boot_func) (); + err = (grub_loader_boot_func) (grub_loader_context); for (cur = preboots_tail; cur; cur = cur->prev) if (! err) @@ -183,22 +232,14 @@ grub_cmd_boot (struct grub_command *cmd __attribute__ ((unused)), static grub_command_t cmd_boot; -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) -void grub_boot_init (void) -#else GRUB_MOD_INIT(boot) -#endif { cmd_boot = grub_register_command ("boot", grub_cmd_boot, 0, N_("Boot an operating system.")); } -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) -void grub_boot_fini (void) -#else GRUB_MOD_FINI(boot) -#endif { grub_unregister_command (cmd_boot); } diff --git a/grub-core/commands/boottime.c b/grub-core/commands/boottime.c new file mode 100644 index 000000000..424412851 --- /dev/null +++ b/grub-core/commands/boottime.c @@ -0,0 +1,65 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + + +static grub_err_t +grub_cmd_boottime (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + struct grub_boot_time *cur; + grub_uint64_t last_time = 0, start_time = 0; + if (!grub_boot_time_head) + { + grub_puts_ (N_("No boot time statistics is available\n")); + return 0; + } + start_time = last_time = grub_boot_time_head->tp; + for (cur = grub_boot_time_head; cur; cur = cur->next) + { + grub_uint32_t tmabs = cur->tp - start_time; + grub_uint32_t tmrel = cur->tp - last_time; + last_time = cur->tp; + + grub_printf ("%3d.%03ds %2d.%03ds %s:%d %s\n", + tmabs / 1000, tmabs % 1000, tmrel / 1000, tmrel % 1000, cur->file, cur->line, + cur->msg); + } + return 0; +} + +static grub_command_t cmd_boottime; + +GRUB_MOD_INIT(boottime) +{ + cmd_boottime = + grub_register_command ("boottime", grub_cmd_boottime, + 0, N_("Show boot time statistics.")); +} + +GRUB_MOD_FINI(boottime) +{ + grub_unregister_command (cmd_boottime); +} diff --git a/grub-core/commands/cacheinfo.c b/grub-core/commands/cacheinfo.c index ead6ff82c..e8ee05b85 100644 --- a/grub-core/commands/cacheinfo.c +++ b/grub-core/commands/cacheinfo.c @@ -23,6 +23,8 @@ #include #include +GRUB_MOD_LICENSE ("GPLv3+"); + static grub_err_t grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), @@ -40,7 +42,7 @@ grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)), hits, misses); } else - grub_printf ("%s\n", _("No disk cache statistics available\n")); + grub_printf ("%s\n", _("No disk cache statistics available\n")); return 0; } diff --git a/grub-core/commands/cat.c b/grub-core/commands/cat.c index cd2d76099..2b67c1c7f 100644 --- a/grub-core/commands/cat.c +++ b/grub-core/commands/cat.c @@ -24,6 +24,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -39,9 +40,15 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) struct grub_arg_list *state = ctxt->state; int dos = 0; grub_file_t file; - char buf[GRUB_DISK_SECTOR_SIZE]; + unsigned char buf[GRUB_DISK_SECTOR_SIZE]; grub_ssize_t size; int key = GRUB_TERM_NO_KEY; + grub_uint32_t code = 0; + int count = 0; + unsigned char utbuf[GRUB_MAX_UTF8_PER_CODEPOINT + 1]; + int utcount = 0; + int is_0d = 0; + int j; if (state[0].set) dos = 1; @@ -49,7 +56,7 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); - file = grub_file_open (args[0]); + file = grub_file_open (args[0], GRUB_FILE_TYPE_CAT); if (! file) return grub_errno; @@ -60,21 +67,65 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) for (i = 0; i < size; i++) { - unsigned char c = buf[i]; + utbuf[utcount++] = buf[i]; - if ((grub_isprint (c) || grub_isspace (c)) && c != '\r') - grub_printf ("%c", c); - else if (dos && c == '\r' && i + 1 < size && buf[i + 1] == '\n') - { - grub_printf ("\n"); - i++; - } - else + if (is_0d && buf[i] != '\n') { grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); - grub_printf ("<%x>", (int) c); + grub_printf ("<%x>", (int) '\r'); grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); } + + is_0d = 0; + + if (!grub_utf8_process (buf[i], &code, &count)) + { + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + for (j = 0; j < utcount - 1; j++) + grub_printf ("<%x>", (unsigned int) utbuf[j]); + code = 0; + count = 0; + if (utcount == 1 || !grub_utf8_process (buf[i], &code, &count)) + { + grub_printf ("<%x>", (unsigned int) buf[i]); + code = 0; + count = 0; + utcount = 0; + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + continue; + } + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + utcount = 1; + } + if (count) + continue; + + if ((code >= 0xa1 || grub_isprint (code) + || grub_isspace (code)) && code != '\r') + { + grub_printf ("%C", code); + count = 0; + code = 0; + utcount = 0; + continue; + } + + if (dos && code == '\r') + { + is_0d = 1; + count = 0; + code = 0; + utcount = 0; + continue; + } + + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + for (j = 0; j < utcount; j++) + grub_printf ("<%x>", (unsigned int) utbuf[j]); + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + count = 0; + code = 0; + utcount = 0; } do @@ -82,6 +133,21 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) while (key != GRUB_TERM_ESC && key != GRUB_TERM_NO_KEY); } + if (is_0d) + { + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + grub_printf ("<%x>", (unsigned int) '\r'); + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + } + + if (utcount) + { + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + for (j = 0; j < utcount; j++) + grub_printf ("<%x>", (unsigned int) utbuf[j]); + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + } + grub_xputs ("\n"); grub_refresh (); grub_file_close (file); diff --git a/grub-core/commands/cmp.c b/grub-core/commands/cmp.c index cc23ee67e..46185fbbc 100644 --- a/grub-core/commands/cmp.c +++ b/grub-core/commands/cmp.c @@ -22,14 +22,21 @@ #include #include #include +#include #include GRUB_MOD_LICENSE ("GPLv3+"); #define BUFFER_SIZE 512 +static const struct grub_arg_option options[] = + { + {0, 'v', 0, N_("Enable verbose output"), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + static grub_err_t -grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), +grub_cmd_cmp (grub_extcmd_context_t ctxt, int argc, char **args) { grub_ssize_t rd1, rd2; @@ -38,19 +45,20 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), grub_file_t file2 = 0; char *buf1 = 0; char *buf2 = 0; + grub_err_t err = GRUB_ERR_TEST_FAILURE; if (argc != 2) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); - grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0], - args[1]); + if (ctxt->state[0].set) + grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0], args[1]); - file1 = grub_file_open (args[0]); - file2 = grub_file_open (args[1]); + file1 = grub_file_open (args[0], GRUB_FILE_TYPE_CMP); + file2 = grub_file_open (args[1], GRUB_FILE_TYPE_CMP); if (! file1 || ! file2) goto cleanup; - if (grub_file_size (file1) != grub_file_size (file2)) + if (ctxt->state[0].set && (grub_file_size (file1) != grub_file_size (file2))) grub_printf_ (N_("Files differ in size: %llu [%s], %llu [%s]\n"), (unsigned long long) grub_file_size (file1), args[0], (unsigned long long) grub_file_size (file2), args[1]); @@ -78,9 +86,10 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), { if (buf1[i] != buf2[i]) { - grub_printf_ (N_("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n"), - (unsigned long long) (i + pos), buf1[i], - args[0], buf2[i], args[1]); + if (ctxt->state[0].set) + grub_printf_ (N_("Files differ at the offset %llu: 0x%x [%s], 0x%x [%s]\n"), + (unsigned long long) (i + pos), buf1[i], + args[0], buf2[i], args[1]); goto cleanup; } } @@ -90,7 +99,9 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), while (rd2); /* TRANSLATORS: it's always exactly 2 files. */ - grub_printf_ (N_("The files are identical.\n")); + if (ctxt->state[0].set) + grub_printf_ (N_("The files are identical.\n")); + err = GRUB_ERR_NONE; } cleanup: @@ -102,18 +113,19 @@ cleanup: if (file2) grub_file_close (file2); - return grub_errno; + return err; } -static grub_command_t cmd; +static grub_extcmd_t cmd; GRUB_MOD_INIT(cmp) { - cmd = grub_register_command ("cmp", grub_cmd_cmp, - N_("FILE1 FILE2"), N_("Compare two files.")); + cmd = grub_register_extcmd ("cmp", grub_cmd_cmp, 0, + N_("FILE1 FILE2"), N_("Compare two files."), + options); } GRUB_MOD_FINI(cmp) { - grub_unregister_command (cmd); + grub_unregister_extcmd (cmd); } diff --git a/grub-core/commands/configfile.c b/grub-core/commands/configfile.c index 99c0a2479..f2d2abb5f 100644 --- a/grub-core/commands/configfile.c +++ b/grub-core/commands/configfile.c @@ -78,7 +78,7 @@ GRUB_MOD_INIT(configfile) cmd_extractor_configfile = grub_register_command ("extract_entries_configfile", grub_cmd_source, N_("FILE"), - N_("Load another config file without changing context but take only menu entries.") + N_("Load another config file but take only menu entries.") ); cmd_dot = diff --git a/grub-core/commands/date.c b/grub-core/commands/date.c index 8e1f41f14..5cb4fafd4 100644 --- a/grub-core/commands/date.c +++ b/grub-core/commands/date.c @@ -59,7 +59,8 @@ grub_cmd_date (grub_command_t cmd __attribute__ ((unused)), for (; argc; argc--, args++) { - char *p, c; + const char *p; + char c; int m1, ofs, n, cur_mask; p = args[0]; diff --git a/grub-core/commands/echo.c b/grub-core/commands/echo.c index 81ba50d68..f95877285 100644 --- a/grub-core/commands/echo.c +++ b/grub-core/commands/echo.c @@ -119,7 +119,7 @@ grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args) if (newline) grub_printf ("\n"); - grub_refresh (); + grub_refresh (); return 0; } diff --git a/grub-core/commands/efi/acpi.c b/grub-core/commands/efi/acpi.c deleted file mode 100644 index 93a560d9c..000000000 --- a/grub-core/commands/efi/acpi.c +++ /dev/null @@ -1,59 +0,0 @@ -/* acpi.c - get acpi tables. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB 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 GRUB. If not, see . - */ - -#include -#include -#include -#include - -struct grub_acpi_rsdp_v10 * -grub_machine_acpi_get_rsdpv1 (void) -{ - unsigned i; - static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID; - - for (i = 0; i < grub_efi_system_table->num_table_entries; i++) - { - grub_efi_guid_t *guid = - &grub_efi_system_table->configuration_table[i].vendor_guid; - - if (! grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_guid_t))) - return (struct grub_acpi_rsdp_v10 *) - grub_efi_system_table->configuration_table[i].vendor_table; - } - return 0; -} - -struct grub_acpi_rsdp_v20 * -grub_machine_acpi_get_rsdpv2 (void) -{ - unsigned i; - static grub_efi_guid_t acpi20_guid = GRUB_EFI_ACPI_20_TABLE_GUID; - - for (i = 0; i < grub_efi_system_table->num_table_entries; i++) - { - grub_efi_guid_t *guid = - &grub_efi_system_table->configuration_table[i].vendor_guid; - - if (! grub_memcmp (guid, &acpi20_guid, sizeof (grub_efi_guid_t))) - return (struct grub_acpi_rsdp_v20 *) - grub_efi_system_table->configuration_table[i].vendor_table; - } - return 0; -} diff --git a/grub-core/commands/efi/efifwsetup.c b/grub-core/commands/efi/efifwsetup.c new file mode 100644 index 000000000..704f9d352 --- /dev/null +++ b/grub-core/commands/efi/efifwsetup.c @@ -0,0 +1,102 @@ +/* fwsetup.c - Reboot into firmware setup menu. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_efi_boolean_t efifwsetup_is_supported (void); + +static grub_err_t +grub_cmd_fwsetup (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_efi_uint64_t *old_os_indications; + grub_efi_uint64_t os_indications = GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI; + grub_err_t status; + grub_size_t oi_size; + static grub_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; + + if (argc >= 1 && grub_strcmp(args[0], "--is-supported") == 0) + return !efifwsetup_is_supported (); + + if (!efifwsetup_is_supported ()) + return grub_error (GRUB_ERR_INVALID_COMMAND, + N_("reboot to firmware setup is not supported by the current firmware")); + + grub_efi_get_variable ("OsIndications", &global, &oi_size, + (void **) &old_os_indications); + + if (old_os_indications != NULL && oi_size == sizeof (os_indications)) + os_indications |= *old_os_indications; + + grub_free (old_os_indications); + + status = grub_efi_set_variable ("OsIndications", &global, &os_indications, + sizeof (os_indications)); + if (status != GRUB_ERR_NONE) + return status; + + grub_reboot (); + + return GRUB_ERR_BUG; +} + +static grub_command_t cmd = NULL; + +static grub_efi_boolean_t +efifwsetup_is_supported (void) +{ + grub_efi_uint64_t *os_indications_supported = NULL; + grub_size_t oi_size = 0; + static grub_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID; + grub_efi_boolean_t ret = 0; + + grub_efi_get_variable ("OsIndicationsSupported", &global, &oi_size, + (void **) &os_indications_supported); + + if (!os_indications_supported) + goto done; + + if (*os_indications_supported & GRUB_EFI_OS_INDICATIONS_BOOT_TO_FW_UI) + ret = 1; + + done: + grub_free (os_indications_supported); + return ret; +} + +GRUB_MOD_INIT (efifwsetup) +{ + cmd = grub_register_command ("fwsetup", grub_cmd_fwsetup, NULL, + N_("Reboot into firmware setup menu.")); +} + +GRUB_MOD_FINI (efifwsetup) +{ + if (cmd) + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/efi/efitextmode.c b/grub-core/commands/efi/efitextmode.c new file mode 100644 index 000000000..198bc694d --- /dev/null +++ b/grub-core/commands/efi/efitextmode.c @@ -0,0 +1,153 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + * + * Set/Get UEFI text output mode resolution. + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_efi_set_mode (grub_efi_simple_text_output_interface_t *o, + grub_efi_int32_t mode) +{ + grub_efi_status_t status; + + if (mode != o->mode->mode) + { + status = o->set_mode (o, mode); + if (status == GRUB_EFI_SUCCESS) + ; + else if (status == GRUB_EFI_DEVICE_ERROR) + return grub_error (GRUB_ERR_BAD_DEVICE, + N_("device error: could not set requested mode")); + else if (status == GRUB_EFI_UNSUPPORTED) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("invalid mode: number not valid")); + else + return grub_error (GRUB_ERR_BAD_FIRMWARE, + N_("unexpected EFI error number: `%u'"), + (unsigned) status); + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_efitextmode (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_efi_simple_text_output_interface_t *o = grub_efi_system_table->con_out; + unsigned long mode; + const char *p = NULL; + grub_err_t err; + grub_efi_uintn_t columns, rows; + grub_efi_int32_t i; + + if (o == NULL) + return grub_error (GRUB_ERR_BAD_DEVICE, N_("no UEFI output console interface")); + + if (o->mode == NULL) + return grub_error (GRUB_ERR_BUG, N_("no mode struct for UEFI output console")); + + if (argc > 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("at most two arguments expected")); + + if (argc == 0) + { + grub_printf_ (N_("Available modes for console output device.\n")); + + for (i = 0; i < o->mode->max_mode; i++) + if (GRUB_EFI_SUCCESS == o->query_mode (o, i, &columns, &rows)) + grub_printf_ (N_(" [%" PRIuGRUB_EFI_UINT32_T "] Col %5" + PRIuGRUB_EFI_UINTN_T " Row %5" PRIuGRUB_EFI_UINTN_T + " %c\n"), + i, columns, rows, (i == o->mode->mode) ? '*' : ' '); + } + else if (argc == 1) + { + if (grub_strcmp (args[0], "min") == 0) + mode = 0; + else if (grub_strcmp (args[0], "max") == 0) + mode = o->mode->max_mode - 1; + else + { + mode = grub_strtoul (args[0], &p, 0); + + if (*args[0] == '\0' || *p != '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("non-numeric or invalid mode `%s'"), args[0]); + } + + if (mode < (unsigned long) o->mode->max_mode) + { + err = grub_efi_set_mode (o, (grub_efi_int32_t) mode); + if (err != GRUB_ERR_NONE) + return err; + } + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("invalid mode: `%lu' is greater than maximum mode `%lu'"), + mode, (unsigned long) o->mode->max_mode); + } + else if (argc == 2) + { + grub_efi_uintn_t u_columns, u_rows; + + u_columns = (grub_efi_uintn_t) grub_strtoul (args[0], &p, 0); + + if (*args[0] == '\0' || *p != '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("non-numeric or invalid columns number `%s'"), args[0]); + + u_rows = (grub_efi_uintn_t) grub_strtoul (args[1], &p, 0); + + if (*args[1] == '\0' || *p != '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("non-numeric or invalid rows number `%s'"), args[1]); + + for (i = 0; i < o->mode->max_mode; i++) + if (GRUB_EFI_SUCCESS == o->query_mode (o, i, &columns, &rows)) + if (u_columns == columns && u_rows == rows) + return grub_efi_set_mode (o, (grub_efi_int32_t) i); + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("no mode found with requested columns and rows")); + } + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; +GRUB_MOD_INIT (efitextmode) +{ + cmd = grub_register_command ("efitextmode", grub_cmd_efitextmode, + N_("[min | max | | ]"), + N_("Get or set EFI text mode.")); +} + +GRUB_MOD_FINI (efitextmode) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/efi/fixvideo.c b/grub-core/commands/efi/fixvideo.c index 3ed40b386..d9d54a2e8 100644 --- a/grub-core/commands/efi/fixvideo.c +++ b/grub-core/commands/efi/fixvideo.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -40,8 +41,9 @@ static struct grub_video_patch {0, 0, 0, 0, 0} }; -static int NESTED_FUNC_ATTR -scan_card (grub_pci_device_t dev, grub_pci_id_t pciid) +static int +scan_card (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_pci_address_t addr; @@ -93,7 +95,7 @@ grub_cmd_fixvideo (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) { - grub_pci_iterate (scan_card); + grub_pci_iterate (scan_card, NULL); return 0; } diff --git a/grub-core/commands/efi/loadbios.c b/grub-core/commands/efi/loadbios.c index 214adc3d2..8e042095a 100644 --- a/grub-core/commands/efi/loadbios.c +++ b/grub-core/commands/efi/loadbios.c @@ -27,9 +27,9 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_efi_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID; -static grub_efi_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID; -static grub_efi_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID; +static grub_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID; +static grub_guid_t acpi2_guid = GRUB_EFI_ACPI_20_TABLE_GUID; +static grub_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID; #define EBDA_SEG_ADDR 0x40e #define LOW_MEM_ADDR 0x413 @@ -46,7 +46,7 @@ enable_rom_area (void) grub_uint32_t *rom_ptr; grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0}; - rom_ptr = (grub_uint32_t *) VBIOS_ADDR; + rom_ptr = grub_absolute_pointer (VBIOS_ADDR); if (*rom_ptr != BLANK_MEM) { grub_puts_ (N_("ROM image is present.")); @@ -92,47 +92,29 @@ lock_rom_area (void) static void fake_bios_data (int use_rom) { - unsigned i; void *acpi, *smbios; grub_uint16_t *ebda_seg_ptr, *low_mem_ptr; - ebda_seg_ptr = (grub_uint16_t *) EBDA_SEG_ADDR; - low_mem_ptr = (grub_uint16_t *) LOW_MEM_ADDR; + ebda_seg_ptr = grub_absolute_pointer (EBDA_SEG_ADDR); + low_mem_ptr = grub_absolute_pointer (LOW_MEM_ADDR); if ((*ebda_seg_ptr) || (*low_mem_ptr)) return; - acpi = 0; - smbios = 0; - for (i = 0; i < grub_efi_system_table->num_table_entries; i++) - { - grub_efi_guid_t *guid = - &grub_efi_system_table->configuration_table[i].vendor_guid; + acpi = grub_efi_find_configuration_table (&acpi2_guid); + grub_dprintf ("efi", "ACPI2: %p\n", acpi); + if (!acpi) { + acpi = grub_efi_find_configuration_table (&acpi_guid); + grub_dprintf ("efi", "ACPI: %p\n", acpi); + } - if (! grub_memcmp (guid, &acpi2_guid, sizeof (grub_efi_guid_t))) - { - acpi = grub_efi_system_table->configuration_table[i].vendor_table; - grub_dprintf ("efi", "ACPI2: %p\n", acpi); - } - else if (! grub_memcmp (guid, &acpi_guid, sizeof (grub_efi_guid_t))) - { - void *t; - - t = grub_efi_system_table->configuration_table[i].vendor_table; - if (! acpi) - acpi = t; - grub_dprintf ("efi", "ACPI: %p\n", t); - } - else if (! grub_memcmp (guid, &smbios_guid, sizeof (grub_efi_guid_t))) - { - smbios = grub_efi_system_table->configuration_table[i].vendor_table; - grub_dprintf ("efi", "SMBIOS: %p\n", smbios); - } - } + smbios = grub_efi_find_configuration_table (&smbios_guid); + grub_dprintf ("efi", "SMBIOS: %p\n", smbios); *ebda_seg_ptr = FAKE_EBDA_SEG; *low_mem_ptr = (FAKE_EBDA_SEG >> 6); - *((grub_uint16_t *) (FAKE_EBDA_SEG << 4)) = 640 - *low_mem_ptr; + /* *((grub_uint16_t *) (FAKE_EBDA_SEG << 4)) = 640 - *low_mem_ptr; */ + *((grub_uint16_t *) (grub_absolute_pointer (FAKE_EBDA_SEG << 4))) = 640 - *low_mem_ptr; if (acpi) grub_memcpy ((char *) ((FAKE_EBDA_SEG << 4) + 16), acpi, 1024 - 16); @@ -169,7 +151,7 @@ grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)), if (argc > 1) { - file = grub_file_open (argv[1]); + file = grub_file_open (argv[1], GRUB_FILE_TYPE_VBE_DUMP); if (! file) return grub_errno; @@ -183,7 +165,7 @@ grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)), return grub_errno; } - file = grub_file_open (argv[0]); + file = grub_file_open (argv[0], GRUB_FILE_TYPE_VBE_DUMP); if (! file) return grub_errno; @@ -205,14 +187,14 @@ static grub_command_t cmd_fakebios, cmd_loadbios; GRUB_MOD_INIT(loadbios) { - cmd_fakebios = grub_register_command ("fakebios", grub_cmd_fakebios, - 0, N_("Create BIOS-like structures for" - " backward compatibility with" - " existing OS.")); + cmd_fakebios = grub_register_command_lockdown ("fakebios", grub_cmd_fakebios, + 0, N_("Create BIOS-like structures for" + " backward compatibility with" + " existing OS.")); - cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios, - N_("BIOS_DUMP [INT10_DUMP]"), - N_("Load BIOS dump.")); + cmd_loadbios = grub_register_command_lockdown ("loadbios", grub_cmd_loadbios, + N_("BIOS_DUMP [INT10_DUMP]"), + N_("Load BIOS dump.")); } GRUB_MOD_FINI(loadbios) diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c new file mode 100644 index 000000000..7b8316d41 --- /dev/null +++ b/grub-core/commands/efi/lsefi.c @@ -0,0 +1,146 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static struct known_protocol +{ + grub_guid_t guid; + const char *name; +} known_protocols[] = + { + { GRUB_EFI_DISK_IO_GUID, "disk" }, + { GRUB_EFI_BLOCK_IO_GUID, "block" }, + { GRUB_EFI_SERIAL_IO_GUID, "serial" }, + { GRUB_EFI_SIMPLE_NETWORK_GUID, "network" }, + { GRUB_EFI_PXE_GUID, "pxe" }, + { GRUB_EFI_DEVICE_PATH_GUID, "device path" }, + { GRUB_EFI_PCI_IO_GUID, "PCI" }, + { GRUB_EFI_PCI_ROOT_IO_GUID, "PCI root" }, + { GRUB_EFI_EDID_ACTIVE_GUID, "active EDID" }, + { GRUB_EFI_EDID_DISCOVERED_GUID, "discovered EDID" }, + { GRUB_EFI_EDID_OVERRIDE_GUID, "override EDID" }, + { GRUB_EFI_GOP_GUID, "GOP" }, + { GRUB_EFI_UGA_DRAW_GUID, "UGA draw" }, + { GRUB_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID, "simple text output" }, + { GRUB_EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID, "simple text input" }, + { GRUB_EFI_SIMPLE_POINTER_PROTOCOL_GUID, "simple pointer" }, + { GRUB_EFI_CONSOLE_CONTROL_GUID, "console control" }, + { GRUB_EFI_ABSOLUTE_POINTER_PROTOCOL_GUID, "absolute pointer" }, + { GRUB_EFI_DRIVER_BINDING_PROTOCOL_GUID, "EFI driver binding" }, + { GRUB_EFI_LOAD_FILE_PROTOCOL_GUID, "load file" }, + { GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID, "load file2" }, + { GRUB_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, "simple FS" }, + { GRUB_EFI_TAPE_IO_PROTOCOL_GUID, "tape I/O" }, + { GRUB_EFI_UNICODE_COLLATION_PROTOCOL_GUID, "unicode collation" }, + { GRUB_EFI_SCSI_IO_PROTOCOL_GUID, "SCSI I/O" }, + { GRUB_EFI_USB2_HC_PROTOCOL_GUID, "USB host" }, + { GRUB_EFI_DEBUG_SUPPORT_PROTOCOL_GUID, "debug support" }, + { GRUB_EFI_DEBUGPORT_PROTOCOL_GUID, "debug port" }, + { GRUB_EFI_DECOMPRESS_PROTOCOL_GUID, "decompress" }, + { GRUB_EFI_LOADED_IMAGE_PROTOCOL_GUID, "loaded image" }, + { GRUB_EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID, "device path to text" }, + { GRUB_EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID, "device path utilities" }, + { GRUB_EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID, "device path from text" }, + { GRUB_EFI_HII_CONFIG_ROUTING_PROTOCOL_GUID, "HII config routing" }, + { GRUB_EFI_HII_DATABASE_PROTOCOL_GUID, "HII database" }, + { GRUB_EFI_HII_STRING_PROTOCOL_GUID, "HII string" }, + { GRUB_EFI_HII_IMAGE_PROTOCOL_GUID, "HII image" }, + { GRUB_EFI_HII_FONT_PROTOCOL_GUID, "HII font" }, + { GRUB_EFI_COMPONENT_NAME2_PROTOCOL_GUID, "component name 2" }, + { GRUB_EFI_HII_CONFIGURATION_ACCESS_PROTOCOL_GUID, + "HII configuration access" }, + { GRUB_EFI_USB_IO_PROTOCOL_GUID, "USB I/O" }, + }; + +static grub_err_t +grub_cmd_lsefi (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_efi_handle_t *handles; + grub_efi_uintn_t num_handles; + unsigned i, j, k; + + handles = grub_efi_locate_handle (GRUB_EFI_ALL_HANDLES, + NULL, NULL, &num_handles); + + for (i = 0; i < num_handles; i++) + { + grub_efi_handle_t handle = handles[i]; + grub_efi_status_t status; + grub_efi_uintn_t num_protocols; + grub_packed_guid_t **protocols; + grub_efi_device_path_t *dp; + + grub_printf ("Handle %p\n", handle); + + dp = grub_efi_get_device_path (handle); + if (dp) + { + grub_printf (" "); + grub_efi_print_device_path (dp); + } + + status = grub_efi_system_table->boot_services->protocols_per_handle (handle, + &protocols, + &num_protocols); + if (status != GRUB_EFI_SUCCESS) { + grub_printf ("Unable to retrieve protocols\n"); + continue; + } + for (j = 0; j < num_protocols; j++) + { + for (k = 0; k < ARRAY_SIZE (known_protocols); k++) + if (grub_memcmp (protocols[j], &known_protocols[k].guid, + sizeof (known_protocols[k].guid)) == 0) + break; + if (k < ARRAY_SIZE (known_protocols)) + grub_printf (" %s\n", known_protocols[k].name); + else + grub_printf (" %pG\n", protocols[j]); + } + + } + + return 0; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lsefi) +{ + cmd = grub_register_command ("lsefi", grub_cmd_lsefi, + NULL, "Display EFI handles."); +} + +GRUB_MOD_FINI(lsefi) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/efi/lsefimmap.c b/grub-core/commands/efi/lsefimmap.c index 215b45bff..d0885d72f 100644 --- a/grub-core/commands/efi/lsefimmap.c +++ b/grub-core/commands/efi/lsefimmap.c @@ -51,7 +51,7 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)), grub_printf ("Type Physical start - end #Pages " - " Size Attributes\n"); + " Size Attributes\n"); memory_map_end = ADD_MEMORY_DESCRIPTOR (memory_map, map_size); for (desc = memory_map; desc < memory_map_end; @@ -59,9 +59,9 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)), { grub_efi_uint64_t size; grub_efi_uint64_t attr; - static const char types_str[][9] = + static const char types_str[][9] = { - "reserved", + "reserved", "ldr-code", "ldr-data", "BS-code ", @@ -74,34 +74,43 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)), "ACPI-nvs", "MMIO ", "IO-ports", - "PAL-code" + "PAL-code", + "persist ", }; if (desc->type < ARRAY_SIZE (types_str)) grub_printf ("%s ", types_str[desc->type]); else grub_printf ("Unk %02x ", desc->type); - + grub_printf (" %016" PRIxGRUB_UINT64_T "-%016" PRIxGRUB_UINT64_T " %08" PRIxGRUB_UINT64_T, desc->physical_start, desc->physical_start + (desc->num_pages << 12) - 1, desc->num_pages); - size = desc->num_pages; - size <<= (12 - 10); - if (size < 1024) - grub_printf (" %4" PRIuGRUB_UINT64_T "KB", size); + size = desc->num_pages << 12; /* 4 KiB page size */ + /* + * Since size is a multiple of 4 KiB, no need to handle units + * of just Bytes (which would use a mask of 0x3ff). + * + * 14 characters would support the largest possible number of 4 KiB + * pages that are not a multiple of larger units (e.g., MiB): + * 17592186044415 (0xffffff_fffff000), but that uses a lot of + * whitespace for a rare case. 6 characters usually suffices; + * columns will be off if not, but this is preferable to rounding. + */ + if (size & 0xfffff) + grub_printf (" %6" PRIuGRUB_UINT64_T "KiB", size >> 10); + else if (size & 0x3fffffff) + grub_printf (" %6" PRIuGRUB_UINT64_T "MiB", size >> 20); + else if (size & 0xffffffffff) + grub_printf (" %6" PRIuGRUB_UINT64_T "GiB", size >> 30); + else if (size & 0x3ffffffffffff) + grub_printf (" %6" PRIuGRUB_UINT64_T "TiB", size >> 40); + else if (size & 0xfffffffffffffff) + grub_printf (" %6" PRIuGRUB_UINT64_T "PiB", size >> 50); else - { - size /= 1024; - if (size < 1024) - grub_printf (" %4" PRIuGRUB_UINT64_T "MB", size); - else - { - size /= 1024; - grub_printf (" %4" PRIuGRUB_UINT64_T "GB", size); - } - } + grub_printf (" %6" PRIuGRUB_UINT64_T "EiB", size >> 60); attr = desc->attribute; if (attr & GRUB_EFI_MEMORY_RUNTIME) @@ -122,6 +131,12 @@ grub_cmd_lsefimmap (grub_command_t cmd __attribute__ ((unused)), grub_printf (" RP"); if (attr & GRUB_EFI_MEMORY_XP) grub_printf (" XP"); + if (attr & GRUB_EFI_MEMORY_NV) + grub_printf (" NV"); + if (attr & GRUB_EFI_MEMORY_MORE_RELIABLE) + grub_printf (" MR"); + if (attr & GRUB_EFI_MEMORY_RO) + grub_printf (" RO"); grub_printf ("\n"); } diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c index b2359253a..ffb24fc3b 100644 --- a/grub-core/commands/efi/lsefisystab.c +++ b/grub-core/commands/efi/lsefisystab.c @@ -29,7 +29,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); struct guid_mapping { - grub_efi_guid_t guid; + grub_guid_t guid; const char *name; }; @@ -37,10 +37,25 @@ static const struct guid_mapping guid_mappings[] = { { GRUB_EFI_ACPI_20_TABLE_GUID, "ACPI-2.0"}, { GRUB_EFI_ACPI_TABLE_GUID, "ACPI-1.0"}, + { GRUB_EFI_CONFORMANCE_PROFILES_TABLE_GUID, "CONFORMANCE PROFILES"}, + { GRUB_EFI_CRC32_GUIDED_SECTION_EXTRACTION_GUID, + "CRC32 GUIDED SECTION EXTRACTION"}, + { GRUB_EFI_DEBUG_IMAGE_INFO_TABLE_GUID, "DEBUG IMAGE INFO"}, + { GRUB_EFI_DEVICE_TREE_GUID, "DEVICE TREE"}, + { GRUB_EFI_DXE_SERVICES_TABLE_GUID, "DXE SERVICES"}, + { GRUB_EFI_HCDP_TABLE_GUID, "HCDP"}, + { GRUB_EFI_HOB_LIST_GUID, "HOB LIST"}, + { GRUB_EFI_IMAGE_SECURITY_DATABASE_GUID, "IMAGE EXECUTION INFORMATION"}, + { GRUB_EFI_LZMA_CUSTOM_DECOMPRESS_GUID, "LZMA CUSTOM DECOMPRESS"}, + { GRUB_EFI_MEMORY_TYPE_INFORMATION_GUID, "MEMORY TYPE INFO"}, + { GRUB_EFI_MPS_TABLE_GUID, "MPS"}, + { GRUB_EFI_RT_PROPERTIES_TABLE_GUID, "RT PROPERTIES"}, { GRUB_EFI_SAL_TABLE_GUID, "SAL"}, { GRUB_EFI_SMBIOS_TABLE_GUID, "SMBIOS"}, - { GRUB_EFI_MPS_TABLE_GUID, "MPS"}, - { GRUB_EFI_HCDP_TABLE_GUID, "HCDP"} + { GRUB_EFI_SMBIOS3_TABLE_GUID, "SMBIOS3"}, + { GRUB_EFI_SYSTEM_RESOURCE_TABLE_GUID, "SYSTEM RESOURCE TABLE"}, + { GRUB_EFI_TIANO_CUSTOM_DECOMPRESS_GUID, "TIANO CUSTOM DECOMPRESS"}, + { GRUB_EFI_TSC_FREQUENCY_GUID, "TSC FREQUENCY"}, }; static grub_err_t @@ -49,18 +64,26 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), char **args __attribute__ ((unused))) { const grub_efi_system_table_t *st = grub_efi_system_table; + const grub_efi_uint32_t major_rev = st->hdr.revision >> 16; + const grub_efi_uint32_t minor_rev_upper = (st->hdr.revision & 0xffff) / 10; + const grub_efi_uint32_t minor_rev_lower = (st->hdr.revision & 0xffff) % 10; grub_efi_configuration_table_t *t; unsigned int i; - grub_printf ("Signature: %016" PRIxGRUB_UINT64_T " revision: %08x\n", - st->hdr.signature, st->hdr.revision); + grub_printf ("Address: %p\n", st); + grub_printf ("Signature: %016" PRIxGRUB_UINT64_T " revision: %u.%u", + st->hdr.signature, major_rev, minor_rev_upper); + if (minor_rev_lower) + grub_printf (".%u", minor_rev_lower); + grub_printf ("\n"); { char *vendor; grub_uint16_t *vendor_utf16; grub_printf ("Vendor: "); - + for (vendor_utf16 = st->firmware_vendor; *vendor_utf16; vendor_utf16++); - vendor = grub_malloc (4 * (vendor_utf16 - st->firmware_vendor) + 1); + /* Allocate extra 3 bytes to simplify math. */ + vendor = grub_calloc (4, vendor_utf16 - st->firmware_vendor + 1); if (!vendor) return grub_errno; *grub_utf16_to_utf8 ((grub_uint8_t *) vendor, st->firmware_vendor, @@ -71,7 +94,7 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), grub_printf (", Version=%x\n", st->firmware_revision); - grub_printf ("%ld tables:\n", st->num_table_entries); + grub_printf ("%lld tables:\n", (long long) st->num_table_entries); t = st->configuration_table; for (i = 0; i < st->num_table_entries; i++) { @@ -79,15 +102,11 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), grub_printf ("%p ", t->vendor_table); - grub_printf ("%08x-%04x-%04x-", - t->vendor_guid.data1, t->vendor_guid.data2, - t->vendor_guid.data3); - for (j = 0; j < 8; j++) - grub_printf ("%02x", t->vendor_guid.data4[j]); - + grub_printf ("%pG", &t->vendor_guid); + for (j = 0; j < ARRAY_SIZE (guid_mappings); j++) if (grub_memcmp (&guid_mappings[j].guid, &t->vendor_guid, - sizeof (grub_efi_guid_t)) == 0) + sizeof (grub_guid_t)) == 0) grub_printf (" %s", guid_mappings[j].name); grub_printf ("\n"); @@ -100,7 +119,7 @@ static grub_command_t cmd; GRUB_MOD_INIT(lsefisystab) { - cmd = grub_register_command ("lsefisystab", grub_cmd_lsefisystab, + cmd = grub_register_command ("lsefisystab", grub_cmd_lsefisystab, "", "Display EFI system tables."); } diff --git a/grub-core/commands/efi/lssal.c b/grub-core/commands/efi/lssal.c index fa8005b88..7248bdc29 100644 --- a/grub-core/commands/efi/lssal.c +++ b/grub-core/commands/efi/lssal.c @@ -32,7 +32,7 @@ disp_sal (void *table) { struct grub_efi_sal_system_table *t = table; void *desc; - grub_uint32_t len, l; + grub_uint32_t len, l, i; grub_printf ("SAL rev: %02x, signature: %x, len:%x\n", t->sal_rev, t->signature, t->total_table_len); @@ -44,7 +44,9 @@ disp_sal (void *table) desc = t->entries; len = t->total_table_len - sizeof (struct grub_efi_sal_system_table); - while (len > 0) + if (t->total_table_len <= sizeof (struct grub_efi_sal_system_table)) + return; + for (i = 0; i < t->entry_count; i++) { switch (*(grub_uint8_t *) desc) { @@ -123,6 +125,8 @@ disp_sal (void *table) return; } desc = (grub_uint8_t *)desc + l; + if (len <= l) + return; len -= l; } } @@ -132,22 +136,16 @@ grub_cmd_lssal (struct grub_command *cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - const grub_efi_system_table_t *st = grub_efi_system_table; - grub_efi_configuration_table_t *t = st->configuration_table; - unsigned int i; - grub_efi_guid_t guid = GRUB_EFI_SAL_TABLE_GUID; + static grub_guid_t guid = GRUB_EFI_SAL_TABLE_GUID; + void *table = grub_efi_find_configuration_table (&guid); - for (i = 0; i < st->num_table_entries; i++) + if (table == NULL) { - if (grub_memcmp (&guid, &t->vendor_guid, - sizeof (grub_efi_guid_t)) == 0) - { - disp_sal (t->vendor_table); - return GRUB_ERR_NONE; - } - t++; + grub_printf ("SAL not found\n"); + return GRUB_ERR_NONE; } - grub_printf ("SAL not found\n"); + + disp_sal (table); return GRUB_ERR_NONE; } diff --git a/grub-core/commands/efi/smbios.c b/grub-core/commands/efi/smbios.c new file mode 100644 index 000000000..717e5fc1d --- /dev/null +++ b/grub-core/commands/efi/smbios.c @@ -0,0 +1,37 @@ +/* smbios.c - get smbios tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2019 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +struct grub_smbios_eps * +grub_machine_smbios_get_eps (void) +{ + static grub_guid_t smbios_guid = GRUB_EFI_SMBIOS_TABLE_GUID; + + return (struct grub_smbios_eps *) grub_efi_find_configuration_table (&smbios_guid); +} + +struct grub_smbios_eps3 * +grub_machine_smbios_get_eps3 (void) +{ + static grub_guid_t smbios3_guid = GRUB_EFI_SMBIOS3_TABLE_GUID; + + return (struct grub_smbios_eps3 *) grub_efi_find_configuration_table (&smbios3_guid); +} diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c new file mode 100644 index 000000000..cbac69866 --- /dev/null +++ b/grub-core/commands/efi/tpm.c @@ -0,0 +1,334 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + * + * EFI TPM support code. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef TCG_PCR_EVENT grub_tpm_event_t; + +static grub_guid_t tpm_guid = EFI_TPM_GUID; +static grub_guid_t tpm2_guid = EFI_TPM2_GUID; +static grub_guid_t cc_measurement_guid = GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID; + +static grub_efi_handle_t *grub_tpm_handle; +static grub_uint8_t grub_tpm_version; + +static grub_int8_t tpm1_present = -1; +static grub_int8_t tpm2_present = -1; + +static grub_efi_boolean_t +grub_tpm1_present (grub_efi_tpm_protocol_t *tpm) +{ + grub_efi_status_t status; + TCG_EFI_BOOT_SERVICE_CAPABILITY caps; + grub_uint32_t flags; + grub_efi_physical_address_t eventlog, lastevent; + + if (tpm1_present != -1) + return (grub_efi_boolean_t) tpm1_present; + + caps.Size = (grub_uint8_t) sizeof (caps); + + status = tpm->status_check (tpm, &caps, &flags, &eventlog, &lastevent); + + if (status != GRUB_EFI_SUCCESS || caps.TPMDeactivatedFlag + || !caps.TPMPresentFlag) + tpm1_present = 0; + else + tpm1_present = 1; + + grub_dprintf ("tpm", "tpm1%s present\n", tpm1_present ? "" : " NOT"); + + return (grub_efi_boolean_t) tpm1_present; +} + +static grub_efi_boolean_t +grub_tpm2_present (grub_efi_tpm2_protocol_t *tpm) +{ + grub_efi_status_t status; + EFI_TCG2_BOOT_SERVICE_CAPABILITY caps; + + caps.Size = (grub_uint8_t) sizeof (caps); + + if (tpm2_present != -1) + return (grub_efi_boolean_t) tpm2_present; + + status = tpm->get_capability (tpm, &caps); + + if (status != GRUB_EFI_SUCCESS || !caps.TPMPresentFlag) + tpm2_present = 0; + else + tpm2_present = 1; + + grub_dprintf ("tpm", "tpm2%s present\n", tpm2_present ? "" : " NOT"); + + return (grub_efi_boolean_t) tpm2_present; +} + +static grub_efi_boolean_t +grub_tpm_handle_find (grub_efi_handle_t *tpm_handle, + grub_efi_uint8_t *protocol_version) +{ + grub_efi_handle_t *handles; + grub_efi_uintn_t num_handles; + + if (grub_tpm_handle != NULL) + { + *tpm_handle = grub_tpm_handle; + *protocol_version = grub_tpm_version; + return 1; + } + + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &tpm_guid, NULL, + &num_handles); + if (handles && num_handles > 0) + { + grub_tpm_handle = handles[0]; + *tpm_handle = handles[0]; + grub_tpm_version = 1; + *protocol_version = 1; + grub_dprintf ("tpm", "TPM handle Found, version: 1\n"); + return 1; + } + + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &tpm2_guid, NULL, + &num_handles); + if (handles && num_handles > 0) + { + grub_tpm_handle = handles[0]; + *tpm_handle = handles[0]; + grub_tpm_version = 2; + *protocol_version = 2; + grub_dprintf ("tpm", "TPM handle Found, version: 2\n"); + return 1; + } + + return 0; +} + +static grub_err_t +grub_efi_log_event_status (grub_efi_status_t status) +{ + switch (status) + { + case GRUB_EFI_SUCCESS: + return GRUB_ERR_NONE; + case GRUB_EFI_DEVICE_ERROR: + return grub_error (GRUB_ERR_IO, N_("command failed")); + case GRUB_EFI_INVALID_PARAMETER: + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid parameter")); + case GRUB_EFI_BUFFER_TOO_SMALL: + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("output buffer too small")); + case GRUB_EFI_NOT_FOUND: + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable")); + default: + return grub_error (grub_is_tpm_fail_fatal () ? GRUB_ERR_UNKNOWN_DEVICE : GRUB_ERR_NONE, N_("unknown TPM error")); + } +} + +static grub_err_t +grub_tpm1_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, + grub_size_t size, grub_uint8_t pcr, + const char *description) +{ + grub_tpm_event_t *event; + grub_efi_status_t status; + grub_efi_tpm_protocol_t *tpm; + grub_efi_physical_address_t lastevent; + grub_uint32_t algorithm; + grub_uint32_t eventnum = 0; + + tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!grub_tpm1_present (tpm)) + return 0; + + event = grub_zalloc (sizeof (*event) + grub_strlen (description) + 1); + if (!event) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + N_("cannot allocate TPM event buffer")); + + event->PCRIndex = pcr; + event->EventType = EV_IPL; + event->EventSize = grub_strlen (description) + 1; + grub_strcpy ((char *) event->Event, description); + + algorithm = TCG_ALG_SHA; + status = tpm->log_extend_event (tpm, (grub_addr_t) buf, (grub_uint64_t) size, + algorithm, event, &eventnum, &lastevent); + grub_free (event); + + return grub_efi_log_event_status (status); +} + +static grub_err_t +grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, + grub_size_t size, grub_uint8_t pcr, + const char *description) +{ + EFI_TCG2_EVENT *event; + grub_efi_status_t status; + grub_efi_tpm2_protocol_t *tpm; + + tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!grub_tpm2_present (tpm)) + return 0; + + event = + grub_zalloc (sizeof (EFI_TCG2_EVENT) + grub_strlen (description) + 1); + if (!event) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + N_("cannot allocate TPM event buffer")); + + event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER); + event->Header.HeaderVersion = 1; + event->Header.PCRIndex = pcr; + event->Header.EventType = EV_IPL; + event->Size = + sizeof (*event) - sizeof (event->Event) + grub_strlen (description) + 1; + grub_strcpy ((char *) event->Event, description); + + status = tpm->hash_log_extend_event (tpm, 0, (grub_addr_t) buf, + (grub_uint64_t) size, event); + grub_free (event); + + return grub_efi_log_event_status (status); +} + +static void +grub_cc_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *description) +{ + grub_efi_cc_event_t *event; + grub_efi_status_t status; + grub_efi_cc_protocol_t *cc; + grub_efi_cc_mr_index_t mr; + + cc = grub_efi_locate_protocol (&cc_measurement_guid, NULL); + if (cc == NULL) + return; + + status = cc->map_pcr_to_mr_index (cc, pcr, &mr); + if (status != GRUB_EFI_SUCCESS) + { + grub_efi_log_event_status (status); + return; + } + + event = grub_zalloc (sizeof (grub_efi_cc_event_t) + + grub_strlen (description) + 1); + if (event == NULL) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate CC event buffer")); + return; + } + + event->Header.HeaderSize = sizeof (grub_efi_cc_event_header_t); + event->Header.HeaderVersion = GRUB_EFI_CC_EVENT_HEADER_VERSION; + event->Header.MrIndex = mr; + event->Header.EventType = EV_IPL; + event->Size = sizeof (*event) + grub_strlen (description) + 1; + grub_strcpy ((char *) event->Event, description); + + status = cc->hash_log_extend_event (cc, 0, + (grub_efi_physical_address_t)(grub_addr_t) buf, + (grub_efi_uint64_t) size, event); + grub_free (event); + + if (status != GRUB_EFI_SUCCESS) + grub_efi_log_event_status (status); +} + +grub_err_t +grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *description) +{ + grub_efi_handle_t tpm_handle; + grub_efi_uint8_t protocol_version; + + grub_cc_log_event(buf, size, pcr, description); + + if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) + return 0; + + grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n", + pcr, size, description); + + if (protocol_version == 1) + return grub_tpm1_log_event (tpm_handle, buf, size, pcr, description); + else + return grub_tpm2_log_event (tpm_handle, buf, size, pcr, description); +} + +int +grub_tpm_present (void) +{ + grub_efi_handle_t tpm_handle; + grub_efi_uint8_t protocol_version; + grub_efi_cc_protocol_t *cc; + + /* + * When confidential computing measurement protocol is enabled + * we assume the TPM is present. + */ + cc = grub_efi_locate_protocol (&cc_measurement_guid, NULL); + if (cc != NULL) + return 1; + + if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) + return 0; + + if (protocol_version == 1) + { + grub_efi_tpm_protocol_t *tpm; + + tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!tpm) + { + grub_dprintf ("tpm", "Cannot open TPM protocol\n"); + return 0; + } + return grub_tpm1_present (tpm); + } + else + { + grub_efi_tpm2_protocol_t *tpm; + + tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!tpm) + { + grub_dprintf ("tpm", "Cannot open TPM protocol\n"); + return 0; + } + return grub_tpm2_present (tpm); + } +} diff --git a/grub-core/commands/eval.c b/grub-core/commands/eval.c new file mode 100644 index 000000000..f826a4f22 --- /dev/null +++ b/grub-core/commands/eval.c @@ -0,0 +1,71 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_cmd_eval (grub_command_t cmd __attribute__((__unused__)), + int argc, char *argv[]) +{ + int i; + grub_size_t size = argc; /* +1 for final zero */ + char *str, *p; + grub_err_t ret; + + if (argc == 0) + return GRUB_ERR_NONE; + + for (i = 0; i < argc; i++) + size += grub_strlen (argv[i]); + + str = p = grub_malloc (size); + if (!str) + return grub_errno; + + for (i = 0; i < argc; i++) + { + p = grub_stpcpy (p, argv[i]); + *p++ = ' '; + } + *--p = '\0'; + + ret = grub_script_execute_sourcecode (str); + grub_free (str); + return ret; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(eval) +{ + cmd = grub_register_command ("eval", grub_cmd_eval, N_("STRING ..."), + N_("Evaluate arguments as GRUB commands")); +} + +GRUB_MOD_FINI(eval) +{ + grub_unregister_command (cmd); +} + diff --git a/grub-core/commands/extcmd.c b/grub-core/commands/extcmd.c index 69574e2b0..c236be13a 100644 --- a/grub-core/commands/extcmd.c +++ b/grub-core/commands/extcmd.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -48,6 +49,9 @@ grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args, } state = grub_arg_list_alloc (ext, argc, args); + if (state == NULL) + return grub_errno; + if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc)) { context.state = state; @@ -110,6 +114,28 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func, summary, description, parser, 1); } +static grub_err_t +grub_extcmd_lockdown (grub_extcmd_context_t ctxt __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **argv __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_ACCESS_DENIED, + N_("%s: the command is not allowed when lockdown is enforced"), + ctxt->extcmd->cmd->name); +} + +grub_extcmd_t +grub_register_extcmd_lockdown (const char *name, grub_extcmd_func_t func, + grub_command_flags_t flags, const char *summary, + const char *description, + const struct grub_arg_option *parser) +{ + if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED) + func = grub_extcmd_lockdown; + + return grub_register_extcmd (name, func, flags, summary, description, parser); +} + void grub_unregister_extcmd (grub_extcmd_t ext) { diff --git a/grub-core/commands/file.c b/grub-core/commands/file.c new file mode 100644 index 000000000..19602d757 --- /dev/null +++ b/grub-core/commands/file.c @@ -0,0 +1,707 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static const struct grub_arg_option options[] = { + {"is-i386-xen-pae-domu", 0, 0, + N_("Check if FILE can be booted as i386 PAE Xen unprivileged guest kernel"), + 0, 0}, + {"is-x86_64-xen-domu", 0, 0, + N_("Check if FILE can be booted as x86_64 Xen unprivileged guest kernel"), 0, 0}, + {"is-x86-xen-dom0", 0, 0, + N_("Check if FILE can be used as Xen x86 privileged guest kernel"), 0, 0}, + {"is-x86-multiboot", 0, 0, + N_("Check if FILE can be used as x86 multiboot kernel"), 0, 0}, + {"is-x86-multiboot2", 0, 0, + N_("Check if FILE can be used as x86 multiboot2 kernel"), 0, 0}, + {"is-arm-linux", 0, 0, + N_("Check if FILE is ARM Linux"), 0, 0}, + {"is-arm64-linux", 0, 0, + N_("Check if FILE is ARM64 Linux"), 0, 0}, + {"is-ia64-linux", 0, 0, + N_("Check if FILE is IA64 Linux"), 0, 0}, + {"is-mips-linux", 0, 0, + N_("Check if FILE is MIPS Linux"), 0, 0}, + {"is-mipsel-linux", 0, 0, + N_("Check if FILE is MIPSEL Linux"), 0, 0}, + {"is-sparc64-linux", 0, 0, + N_("Check if FILE is SPARC64 Linux"), 0, 0}, + {"is-powerpc-linux", 0, 0, + N_("Check if FILE is POWERPC Linux"), 0, 0}, + {"is-x86-linux", 0, 0, + N_("Check if FILE is x86 Linux"), 0, 0}, + {"is-x86-linux32", 0, 0, + N_("Check if FILE is x86 Linux supporting 32-bit protocol"), 0, 0}, + {"is-x86-kfreebsd", 0, 0, + N_("Check if FILE is x86 kFreeBSD"), 0, 0}, + {"is-i386-kfreebsd", 0, 0, + N_("Check if FILE is i386 kFreeBSD"), 0, 0}, + {"is-x86_64-kfreebsd", 0, 0, + N_("Check if FILE is x86_64 kFreeBSD"), 0, 0}, + + {"is-x86-knetbsd", 0, 0, + N_("Check if FILE is x86 kNetBSD"), 0, 0}, + {"is-i386-knetbsd", 0, 0, + N_("Check if FILE is i386 kNetBSD"), 0, 0}, + {"is-x86_64-knetbsd", 0, 0, + N_("Check if FILE is x86_64 kNetBSD"), 0, 0}, + + {"is-i386-efi", 0, 0, + N_("Check if FILE is i386 EFI file"), 0, 0}, + {"is-x86_64-efi", 0, 0, + N_("Check if FILE is x86_64 EFI file"), 0, 0}, + {"is-ia64-efi", 0, 0, + N_("Check if FILE is IA64 EFI file"), 0, 0}, + {"is-arm64-efi", 0, 0, + N_("Check if FILE is ARM64 EFI file"), 0, 0}, + {"is-arm-efi", 0, 0, + N_("Check if FILE is ARM EFI file"), 0, 0}, + {"is-riscv32-efi", 0, 0, + N_("Check if FILE is RISC-V 32bit EFI file"), 0, 0}, + {"is-riscv64-efi", 0, 0, + N_("Check if FILE is RISC-V 64bit EFI file"), 0, 0}, + {"is-hibernated-hiberfil", 0, 0, + N_("Check if FILE is hiberfil.sys in hibernated state"), 0, 0}, + {"is-x86_64-xnu", 0, 0, + N_("Check if FILE is x86_64 XNU (Mac OS X kernel)"), 0, 0}, + {"is-i386-xnu", 0, 0, + N_("Check if FILE is i386 XNU (Mac OS X kernel)"), 0, 0}, + {"is-xnu-hibr", 0, 0, + N_("Check if FILE is XNU (Mac OS X kernel) hibernated image"), 0, 0}, + {"is-x86-bios-bootsector", 0, 0, + N_("Check if FILE is BIOS bootsector"), 0, 0}, + {0, 0, 0, 0, 0, 0} +}; + +enum +{ + IS_PAE_DOMU, + IS_64_DOMU, + IS_DOM0, + IS_MULTIBOOT, + IS_MULTIBOOT2, + IS_ARM_LINUX, + IS_ARM64_LINUX, + IS_IA64_LINUX, + IS_MIPS_LINUX, + IS_MIPSEL_LINUX, + IS_SPARC64_LINUX, + IS_POWERPC_LINUX, + IS_X86_LINUX, + IS_X86_LINUX32, + IS_X86_KFREEBSD, + IS_X86_KFREEBSD32, + IS_X86_KFREEBSD64, + IS_X86_KNETBSD, + IS_X86_KNETBSD32, + IS_X86_KNETBSD64, + IS_32_EFI, + IS_64_EFI, + IS_IA_EFI, + IS_ARM64_EFI, + IS_ARM_EFI, + IS_RISCV32_EFI, + IS_RISCV64_EFI, + IS_HIBERNATED, + IS_XNU64, + IS_XNU32, + IS_XNU_HIBR, + IS_BIOS_BOOTSECTOR, + OPT_TYPE_MIN = IS_PAE_DOMU, + OPT_TYPE_MAX = IS_BIOS_BOOTSECTOR +}; + + +static grub_err_t +grub_cmd_file (grub_extcmd_context_t ctxt, int argc, char **args) +{ + grub_file_t file = 0; + grub_elf_t elf = 0; + grub_err_t err; + int type = -1, i; + int ret = 0; + grub_macho_t macho = 0; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + for (i = OPT_TYPE_MIN; i <= OPT_TYPE_MAX; i++) + if (ctxt->state[i].set) + { + if (type == -1) + { + type = i; + continue; + } + return grub_error (GRUB_ERR_BAD_ARGUMENT, "multiple types specified"); + } + if (type == -1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no type specified"); + + file = grub_file_open (args[0], GRUB_FILE_TYPE_XNU_KERNEL); + if (!file) + return grub_errno; + switch (type) + { + case IS_BIOS_BOOTSECTOR: + { + grub_uint16_t sig; + if (grub_file_size (file) != 512) + break; + if (grub_file_seek (file, 510) == (grub_size_t) -1) + break; + if (grub_file_read (file, &sig, 2) != 2) + break; + if (sig != grub_cpu_to_le16_compile_time (0xaa55)) + break; + ret = 1; + break; + } + case IS_IA64_LINUX: + { + Elf64_Ehdr ehdr; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_ident[EI_CLASS] != ELFCLASS64 + || ehdr.e_ident[EI_DATA] != ELFDATA2LSB + || ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_IA_64)) + break; + + ret = 1; + + break; + } + + case IS_SPARC64_LINUX: + { + Elf64_Ehdr ehdr; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_ident[EI_CLASS] != ELFCLASS64 + || ehdr.e_ident[EI_DATA] != ELFDATA2MSB) + break; + + if (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_SPARCV9) + || ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC)) + break; + + ret = 1; + + break; + } + + case IS_POWERPC_LINUX: + { + Elf32_Ehdr ehdr; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB + || (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_PPC) + && ehdr.e_machine != + grub_cpu_to_le16_compile_time (EM_PPC64))) + break; + + if (ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC) + && ehdr.e_type != grub_cpu_to_be16_compile_time (ET_DYN)) + break; + + ret = 1; + + break; + } + + case IS_MIPS_LINUX: + { + Elf32_Ehdr ehdr; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_ident[EI_DATA] != ELFDATA2MSB + || ehdr.e_machine != grub_cpu_to_be16_compile_time (EM_MIPS) + || ehdr.e_type != grub_cpu_to_be16_compile_time (ET_EXEC)) + break; + + ret = 1; + + break; + } + + case IS_X86_KNETBSD: + case IS_X86_KNETBSD32: + case IS_X86_KNETBSD64: + { + int is32, is64; + + elf = grub_elf_file (file, file->name); + + if (elf == NULL) + break; + if (elf->ehdr.ehdr32.e_type != grub_cpu_to_le16_compile_time (ET_EXEC) + || elf->ehdr.ehdr32.e_ident[EI_DATA] != ELFDATA2LSB) + break; + + is32 = grub_elf_is_elf32 (elf); + is64 = grub_elf_is_elf64 (elf); + if (!is32 && !is64) + break; + if (!is32 && type == IS_X86_KNETBSD32) + break; + if (!is64 && type == IS_X86_KNETBSD64) + break; + if (is64) + ret = grub_file_check_netbsd64 (elf); + if (is32) + ret = grub_file_check_netbsd32 (elf); + break; + } + + case IS_X86_KFREEBSD: + case IS_X86_KFREEBSD32: + case IS_X86_KFREEBSD64: + { + Elf32_Ehdr ehdr; + int is32, is64; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_type != grub_cpu_to_le16_compile_time (ET_EXEC) + || ehdr.e_ident[EI_DATA] != ELFDATA2LSB) + break; + + if (ehdr.e_ident[EI_OSABI] != ELFOSABI_FREEBSD) + break; + + is32 = (ehdr.e_machine == grub_cpu_to_le16_compile_time (EM_386) + && ehdr.e_ident[EI_CLASS] == ELFCLASS32); + is64 = (ehdr.e_machine == grub_cpu_to_le16_compile_time (EM_X86_64) + && ehdr.e_ident[EI_CLASS] == ELFCLASS64); + if (!is32 && !is64) + break; + if (!is32 && (type == IS_X86_KFREEBSD32 || type == IS_X86_KNETBSD32)) + break; + if (!is64 && (type == IS_X86_KFREEBSD64 || type == IS_X86_KNETBSD64)) + break; + ret = 1; + + break; + } + + + case IS_MIPSEL_LINUX: + { + Elf32_Ehdr ehdr; + + if (grub_file_read (file, &ehdr, sizeof (ehdr)) != sizeof (ehdr)) + break; + + if (ehdr.e_ident[EI_MAG0] != ELFMAG0 + || ehdr.e_ident[EI_MAG1] != ELFMAG1 + || ehdr.e_ident[EI_MAG2] != ELFMAG2 + || ehdr.e_ident[EI_MAG3] != ELFMAG3 + || ehdr.e_ident[EI_VERSION] != EV_CURRENT + || ehdr.e_version != EV_CURRENT) + break; + + if (ehdr.e_machine != grub_cpu_to_le16_compile_time (EM_MIPS) + || ehdr.e_type != grub_cpu_to_le16_compile_time (ET_EXEC)) + break; + + ret = 1; + + break; + } + case IS_ARM_LINUX: + { + struct linux_arch_kernel_header lh; + + if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) + break; + /* Short forward branch in A32 state (for Raspberry pi kernels). */ + if (lh.code0 == grub_cpu_to_le32_compile_time (0xea000006)) + { + ret = 1; + break; + } + + if (lh.magic == + grub_cpu_to_le32_compile_time (GRUB_LINUX_ARM_MAGIC_SIGNATURE)) + { + ret = 1; + break; + } + break; + } + case IS_ARM64_LINUX: + { + struct linux_arch_kernel_header lh; + + if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) + break; + + /* + * The PE/COFF header can be anywhere in the file. Load it from the correct + * offset if it is not where it is expected. + */ + if ((grub_uint8_t *) &lh + lh.hdr_offset != (grub_uint8_t *) &lh.pe_image_header) + { + if (grub_file_seek (file, lh.hdr_offset) == (grub_off_t) -1 + || grub_file_read (file, &lh.pe_image_header, sizeof (struct grub_pe_image_header)) + != sizeof (struct grub_pe_image_header)) + return grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read COFF image header"); + } + + if (lh.pe_image_header.coff_header.machine == grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_ARM64)) + { + ret = 1; + break; + } + break; + } + case IS_PAE_DOMU ... IS_DOM0: + { + struct grub_xen_file_info xen_inf; + elf = grub_xen_file (file); + if (!elf) + break; + err = grub_xen_get_info (elf, &xen_inf); + if (err) + break; + /* Unfortuntely no way to check if kernel supports dom0. */ + if (type == IS_DOM0) + ret = 1; + if (type == IS_PAE_DOMU) + ret = (xen_inf.arch == GRUB_XEN_FILE_I386_PAE + || xen_inf.arch == GRUB_XEN_FILE_I386_PAE_BIMODE); + if (type == IS_64_DOMU) + ret = (xen_inf.arch == GRUB_XEN_FILE_X86_64); + break; + } + case IS_MULTIBOOT: + case IS_MULTIBOOT2: + { + grub_uint32_t *buffer; + grub_ssize_t len; + grub_size_t search_size; + grub_uint32_t *header; + grub_uint32_t magic; + grub_size_t step; + + if (type == IS_MULTIBOOT2) + { + search_size = 32768; + magic = grub_cpu_to_le32_compile_time (0xe85250d6); + step = 2; + } + else + { + search_size = 8192; + magic = grub_cpu_to_le32_compile_time (0x1BADB002); + step = 1; + } + + buffer = grub_malloc (search_size); + if (!buffer) + break; + + len = grub_file_read (file, buffer, search_size); + if (len < 32) + { + grub_free (buffer); + break; + } + + /* Look for the multiboot header in the buffer. The header should + be at least 12 bytes and aligned on a 4-byte boundary. */ + for (header = buffer; + ((char *) header <= + (char *) buffer + len - (type == IS_MULTIBOOT2 ? 16 : 12)); + header += step) + { + if (header[0] == magic + && !(grub_le_to_cpu32 (header[0]) + + grub_le_to_cpu32 (header[1]) + + grub_le_to_cpu32 (header[2]) + + (type == IS_MULTIBOOT2 + ? grub_le_to_cpu32 (header[3]) : 0))) + { + ret = 1; + break; + } + } + + grub_free (buffer); + break; + } + case IS_X86_LINUX32: + case IS_X86_LINUX: + { + struct linux_i386_kernel_header lh; + if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) + break; + if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55)) + break; + + if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS) + break; + + /* FIXME: some really old kernels (< 1.3.73) will fail this. */ + if (lh.header != + grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE) + || grub_le_to_cpu16 (lh.version) < 0x0200) + break; + + if (type == IS_X86_LINUX) + { + ret = 1; + break; + } + + /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and + still not support 32-bit boot. */ + if (lh.header != + grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE) + || grub_le_to_cpu16 (lh.version) < 0x0203) + break; + + if (!(lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL)) + break; + ret = 1; + break; + } + case IS_HIBERNATED: + { + grub_uint8_t hibr_file_magic[4]; + if (grub_file_read (file, &hibr_file_magic, sizeof (hibr_file_magic)) + != sizeof (hibr_file_magic)) + break; + if (grub_memcmp ("hibr", hibr_file_magic, sizeof (hibr_file_magic)) == + 0 + || grub_memcmp ("HIBR", hibr_file_magic, + sizeof (hibr_file_magic)) == 0) + ret = 1; + break; + } + case IS_XNU64: + case IS_XNU32: + { + macho = grub_macho_open (args[0], GRUB_FILE_TYPE_XNU_KERNEL, + (type == IS_XNU64)); + if (!macho) + break; + /* FIXME: more checks? */ + ret = 1; + break; + } + case IS_XNU_HIBR: + { + struct grub_xnu_hibernate_header hibhead; + if (grub_file_read (file, &hibhead, sizeof (hibhead)) + != sizeof (hibhead)) + break; + if (hibhead.magic != + grub_cpu_to_le32_compile_time (GRUB_XNU_HIBERNATE_MAGIC)) + break; + ret = 1; + break; + } + case IS_32_EFI: + case IS_64_EFI: + case IS_IA_EFI: + case IS_ARM64_EFI: + case IS_ARM_EFI: + case IS_RISCV32_EFI: + case IS_RISCV64_EFI: + { + char signature[4]; + grub_uint32_t pe_offset; + struct grub_pe32_coff_header coff_head; + + if (grub_file_read (file, signature, 2) != 2) + break; + if (signature[0] != 'M' || signature[1] != 'Z') + break; + if ((grub_ssize_t) grub_file_seek (file, 0x3c) == -1) + break; + if (grub_file_read (file, &pe_offset, 4) != 4) + break; + if ((grub_ssize_t) grub_file_seek (file, grub_le_to_cpu32 (pe_offset)) + == -1) + break; + if (grub_file_read (file, signature, 4) != 4) + break; + if (signature[0] != 'P' || signature[1] != 'E' + || signature[2] != '\0' || signature[3] != '\0') + break; + + if (grub_file_read (file, &coff_head, sizeof (coff_head)) + != sizeof (coff_head)) + break; + if (type == IS_32_EFI + && coff_head.machine != + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_I386)) + break; + if (type == IS_64_EFI + && coff_head.machine != + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_X86_64)) + break; + if (type == IS_IA_EFI + && coff_head.machine != + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_IA64)) + break; + if (type == IS_ARM64_EFI + && coff_head.machine != + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_ARM64)) + break; + if (type == IS_ARM_EFI + && coff_head.machine != + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_ARMTHUMB_MIXED)) + break; + if ((type == IS_RISCV32_EFI || type == IS_RISCV64_EFI) + && coff_head.machine != + grub_cpu_to_le16_compile_time (GRUB_PE32_MACHINE_RISCV64)) + /* TODO: Determine bitness dynamically */ + break; + if (type == IS_IA_EFI || type == IS_64_EFI || type == IS_ARM64_EFI || + type == IS_RISCV32_EFI || type == IS_RISCV64_EFI) + { + struct grub_pe64_optional_header o64; + if (grub_file_read (file, &o64, sizeof (o64)) != sizeof (o64)) + break; + if (o64.magic != + grub_cpu_to_le16_compile_time (GRUB_PE32_PE64_MAGIC)) + break; + if (o64.subsystem != + grub_cpu_to_le16_compile_time + (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION)) + break; + ret = 1; + break; + } + if (type == IS_32_EFI || type == IS_ARM_EFI) + { + struct grub_pe32_optional_header o32; + if (grub_file_read (file, &o32, sizeof (o32)) != sizeof (o32)) + break; + if (o32.magic != + grub_cpu_to_le16_compile_time (GRUB_PE32_PE32_MAGIC)) + break; + if (o32.subsystem != + grub_cpu_to_le16_compile_time + (GRUB_PE32_SUBSYSTEM_EFI_APPLICATION)) + break; + ret = 1; + break; + } + break; + } + } + + if (elf) + grub_elf_close (elf); + else if (macho) + grub_macho_close (macho); + else if (file) + grub_file_close (file); + + if (!ret && (grub_errno == GRUB_ERR_BAD_OS || grub_errno == GRUB_ERR_NONE)) + /* TRANSLATORS: it's a standalone boolean value, + opposite of "true". */ + grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); + return grub_errno; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(file) +{ + cmd = grub_register_extcmd ("file", grub_cmd_file, 0, + N_("OPTIONS FILE"), + N_("Check if FILE is of specified type."), + options); +} + +GRUB_MOD_FINI(file) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/commands/file32.c b/grub-core/commands/file32.c new file mode 100644 index 000000000..0861c458d --- /dev/null +++ b/grub-core/commands/file32.c @@ -0,0 +1,5 @@ +#define GRUB_TARGET_WORDSIZE 32 +#define XX 32 +#define ehdrXX ehdr32 +#define grub_file_check_netbsdXX grub_file_check_netbsd32 +#include "fileXX.c" diff --git a/grub-core/commands/file64.c b/grub-core/commands/file64.c new file mode 100644 index 000000000..90890d481 --- /dev/null +++ b/grub-core/commands/file64.c @@ -0,0 +1,5 @@ +#define GRUB_TARGET_WORDSIZE 64 +#define XX 64 +#define ehdrXX ehdr64 +#define grub_file_check_netbsdXX grub_file_check_netbsd64 +#include "fileXX.c" diff --git a/grub-core/commands/fileXX.c b/grub-core/commands/fileXX.c new file mode 100644 index 000000000..c17d26ce6 --- /dev/null +++ b/grub-core/commands/fileXX.c @@ -0,0 +1,74 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wcast-align" + +int +grub_file_check_netbsdXX (grub_elf_t elf) +{ + Elf_Shdr *s, *s0; + + grub_size_t shnum = elf->ehdr.ehdrXX.e_shnum; + grub_size_t shentsize = elf->ehdr.ehdrXX.e_shentsize; + grub_size_t shsize = shnum * shentsize; + grub_off_t stroff; + + if (!shnum || !shentsize) + return 0; + + s0 = grub_malloc (shsize); + if (!s0) + return 0; + + if (grub_file_seek (elf->file, elf->ehdr.ehdrXX.e_shoff) == (grub_off_t) -1) + goto fail; + + if (grub_file_read (elf->file, s0, shsize) != (grub_ssize_t) shsize) + goto fail; + + s = (Elf_Shdr *) ((char *) s0 + elf->ehdr.ehdrXX.e_shstrndx * shentsize); + stroff = s->sh_offset; + + for (s = s0; s < (Elf_Shdr *) ((char *) s0 + shnum * shentsize); + s = (Elf_Shdr *) ((char *) s + shentsize)) + { + char name[sizeof(".note.netbsd.ident")]; + grub_memset (name, 0, sizeof (name)); + if (grub_file_seek (elf->file, stroff + s->sh_name) == (grub_off_t) -1) + goto fail; + + if (grub_file_read (elf->file, name, sizeof (name)) != (grub_ssize_t) sizeof (name)) + { + if (grub_errno) + goto fail; + continue; + } + if (grub_memcmp (name, ".note.netbsd.ident", + sizeof(".note.netbsd.ident")) != 0) + continue; + grub_free (s0); + return 1; + } + fail: + grub_free (s0); + return 0; +} diff --git a/grub-core/commands/gptsync.c b/grub-core/commands/gptsync.c index 1a203dc59..444e24874 100644 --- a/grub-core/commands/gptsync.c +++ b/grub-core/commands/gptsync.c @@ -37,11 +37,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); Is it a problem? */ static void -lba_to_chs (int lba, grub_uint8_t *cl, grub_uint8_t *ch, +lba_to_chs (grub_uint32_t lba, grub_uint8_t *cl, grub_uint8_t *ch, grub_uint8_t *dh) { - int cylinder, head, sector; - int sectors = 63, heads = 255, cylinders = 1024; + grub_uint32_t cylinder, head, sector; + grub_uint32_t sectors = 63, heads = 255, cylinders = 1024; sector = lba % sectors + 1; head = (lba / sectors) % heads; @@ -101,7 +101,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)), } /* Check if it is valid. */ - if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) + if (mbr.signature != grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE)) { grub_device_close (dev); return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); @@ -216,7 +216,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)), first_sector--; mbr.entries[0].flag = 0; mbr.entries[0].type = GRUB_PC_PARTITION_TYPE_GPT_DISK; - mbr.entries[0].start = grub_cpu_to_le32 (1); + mbr.entries[0].start = grub_cpu_to_le32_compile_time (1); lba_to_chs (1, &(mbr.entries[0].start_sector), &(mbr.entries[0].start_cylinder), @@ -227,7 +227,7 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)), &(mbr.entries[0].end_head)); mbr.entries[0].length = grub_cpu_to_le32 (first_sector); - mbr.signature = grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE); + mbr.signature = grub_cpu_to_le16_compile_time (GRUB_PC_PARTITION_SIGNATURE); if (grub_disk_write (dev->disk, 0, 0, sizeof (mbr), &mbr)) { @@ -235,6 +235,8 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)), return grub_errno; } + grub_device_close (dev); + grub_printf_ (N_("New MBR is written to `%s'\n"), args[0]); return GRUB_ERR_NONE; diff --git a/grub-core/commands/halt.c b/grub-core/commands/halt.c index f8596ecdc..8f2e88040 100644 --- a/grub-core/commands/halt.c +++ b/grub-core/commands/halt.c @@ -37,7 +37,7 @@ static grub_command_t cmd; GRUB_MOD_INIT(halt) { cmd = grub_register_command ("halt", grub_cmd_halt, - 0, N_("Halts the computer. This command does" + 0, N_("Halts the computer. This command does" " not work on all firmware implementations.")); } diff --git a/grub-core/commands/hashsum.c b/grub-core/commands/hashsum.c index ba33ea294..d56b5b0bb 100644 --- a/grub-core/commands/hashsum.c +++ b/grub-core/commands/hashsum.c @@ -39,7 +39,7 @@ static const struct grub_arg_option options[] = { {0, 0, 0, 0, 0, 0} }; -static struct { const char *name; const char *hashname; } aliases[] = +static struct { const char *name; const char *hashname; } aliases[] = { {"sha256sum", "sha256"}, {"sha512sum", "sha512"}, @@ -63,17 +63,23 @@ hextoval (char c) static grub_err_t hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result) { - grub_uint8_t context[hash->contextsize]; - grub_uint8_t readbuf[4096]; + void *context; + grub_uint8_t *readbuf; +#define BUF_SIZE 4096 + readbuf = grub_malloc (BUF_SIZE); + if (!readbuf) + return grub_errno; + context = grub_zalloc (hash->contextsize); + if (!readbuf || !context) + goto fail; - grub_memset (context, 0, sizeof (context)); hash->init (context); while (1) { grub_ssize_t r; - r = grub_file_read (file, readbuf, sizeof (readbuf)); + r = grub_file_read (file, readbuf, BUF_SIZE); if (r < 0) - return grub_errno; + goto fail; if (r == 0) break; hash->write (context, readbuf, r); @@ -81,7 +87,15 @@ hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result) hash->final (context); grub_memcpy (result, hash->read (context), hash->mdlen); + grub_free (readbuf); + grub_free (context); + return GRUB_ERR_NONE; + + fail: + grub_free (readbuf); + grub_free (context); + return grub_errno; } static grub_err_t @@ -90,16 +104,19 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, { grub_file_t hashlist, file; char *buf = NULL; - grub_uint8_t expected[hash->mdlen]; - grub_uint8_t actual[hash->mdlen]; + grub_uint8_t expected[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t actual[GRUB_CRYPTO_MAX_MDLEN]; grub_err_t err; unsigned i; unsigned unread = 0, mismatch = 0; - hashlist = grub_file_open (hashfilename); + if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return grub_error (GRUB_ERR_BUG, "mdlen is too long"); + + hashlist = grub_file_open (hashfilename, GRUB_FILE_TYPE_HASHLIST); if (!hashlist) return grub_errno; - + while (grub_free (buf), (buf = grub_file_getline (hashlist))) { const char *p = buf; @@ -111,30 +128,37 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, high = hextoval (*p++); low = hextoval (*p++); if (high < 0 || low < 0) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list"); + { + grub_free (buf); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list"); + } expected[i] = (high << 4) | low; } if ((p[0] != ' ' && p[0] != '\t') || (p[1] != ' ' && p[1] != '\t')) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list"); + { + grub_free (buf); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid hash list"); + } p += 2; if (prefix) { char *filename; - + filename = grub_xasprintf ("%s/%s", prefix, p); if (!filename) - return grub_errno; - if (!uncompress) - grub_file_filter_disable_compression (); - file = grub_file_open (filename); + { + grub_free (buf); + return grub_errno; + } + file = grub_file_open (filename, GRUB_FILE_TYPE_TO_HASH + | (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS + : GRUB_FILE_TYPE_NONE)); grub_free (filename); } else - { - if (!uncompress) - grub_file_filter_disable_compression (); - file = grub_file_open (p); - } + file = grub_file_open (p, GRUB_FILE_TYPE_TO_HASH + | (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS + : GRUB_FILE_TYPE_NONE)); if (!file) { grub_file_close (hashlist); @@ -168,7 +192,7 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, "hash of '%s' mismatches", p); } mismatch++; - continue; + continue; } grub_printf_ (N_("%s: OK\n"), p); } @@ -205,6 +229,9 @@ grub_cmd_hashsum (struct grub_extcmd_context *ctxt, if (!hash) return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown hash"); + if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return grub_error (GRUB_ERR_BUG, "mdlen is too long"); + if (state[2].set) prefix = state[2].arg; @@ -218,13 +245,13 @@ grub_cmd_hashsum (struct grub_extcmd_context *ctxt, for (i = 0; i < (unsigned) argc; i++) { - GRUB_PROPERLY_ALIGNED_ARRAY (result, hash->mdlen); + GRUB_PROPERLY_ALIGNED_ARRAY (result, GRUB_CRYPTO_MAX_MDLEN); grub_file_t file; grub_err_t err; unsigned j; - if (!uncompress) - grub_file_filter_disable_compression (); - file = grub_file_open (args[i]); + file = grub_file_open (args[i], GRUB_FILE_TYPE_TO_HASH + | (!uncompress ? GRUB_FILE_TYPE_NO_DECOMPRESS + : GRUB_FILE_TYPE_NONE)); if (!file) { if (!keep) diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c index 3fb08912d..96f2336f3 100644 --- a/grub-core/commands/hdparm.c +++ b/grub-core/commands/hdparm.c @@ -328,10 +328,12 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) ata = ((struct grub_scsi *) disk->data)->data; break; } + /* FALLTHROUGH */ default: + grub_disk_close (disk); return grub_error (GRUB_ERR_IO, "not an ATA device"); } - + /* Change settings. */ if (aam >= 0) @@ -434,9 +436,9 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(hdparm) { - cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm, 0, - N_("[OPTIONS] DISK"), - N_("Get/set ATA disk parameters."), options); + cmd = grub_register_extcmd_lockdown ("hdparm", grub_cmd_hdparm, 0, + N_("[OPTIONS] DISK"), + N_("Get/set ATA disk parameters."), options); } GRUB_MOD_FINI(hdparm) diff --git a/grub-core/commands/help.c b/grub-core/commands/help.c index d64c28915..113d0d0ca 100644 --- a/grub-core/commands/help.c +++ b/grub-core/commands/help.c @@ -64,11 +64,11 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, stringwidth = 0; - while (unicode_last_screen_position < unicode_last_position && + while (unicode_last_screen_position < unicode_last_position && stringwidth < ((grub_term_width (term) / 2) - 2)) { struct grub_unicode_glyph glyph; - unicode_last_screen_position + unicode_last_screen_position += grub_unicode_aglomerate_comb (unicode_last_screen_position, unicode_last_position - unicode_last_screen_position, @@ -88,7 +88,7 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, if (cnt % 2) grub_printf ("\n"); cnt++; - + grub_free (command_help); grub_free (unicode_command_help); } @@ -99,12 +99,13 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, else { int i; - grub_command_t cmd_iter, cmd; + grub_command_t cmd_iter, cmd, cmd_next; for (i = 0; i < argc; i++) { currarg = args[i]; - FOR_COMMANDS(cmd_iter) + + FOR_COMMANDS_SAFE (cmd_iter, cmd_next) { if (!(cmd_iter->prio & GRUB_COMMAND_FLAG_ACTIVE)) continue; @@ -134,6 +135,8 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, } } + grub_printf ("\n\nTo enable less(1)-like paging, \"set pager=1\".\n"); + return 0; } diff --git a/grub-core/commands/hexdump.c b/grub-core/commands/hexdump.c index 4c884b3a1..d6f61d98a 100644 --- a/grub-core/commands/hexdump.c +++ b/grub-core/commands/hexdump.c @@ -24,6 +24,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -51,7 +52,11 @@ grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args) length = (state[1].set) ? grub_strtoul (state[1].arg, 0, 0) : 256; if (!grub_strcmp (args[0], "(mem)")) - hexdump (skip, (char *) (grub_addr_t) skip, length); + { + if (grub_is_lockdown() == GRUB_LOCKDOWN_ENABLED) + return grub_error (GRUB_ERR_ACCESS_DENIED, N_("memory reading is disabled in lockdown mode")); + hexdump (skip, (char *) (grub_addr_t) skip, length); + } else if ((args[0][0] == '(') && (args[0][namelen - 1] == ')')) { grub_disk_t disk; @@ -90,7 +95,7 @@ grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args) { grub_file_t file; - file = grub_file_open (args[0]); + file = grub_file_open (args[0], GRUB_FILE_TYPE_HEXCAT); if (! file) return 0; diff --git a/grub-core/commands/i386/cmosdump.c b/grub-core/commands/i386/cmosdump.c new file mode 100644 index 000000000..626485ccb --- /dev/null +++ b/grub-core/commands/i386/cmosdump.c @@ -0,0 +1,64 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_cmd_cmosdump (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) +{ + int i; + + for (i = 0; i < 256; i++) + { + grub_err_t err; + grub_uint8_t value; + if ((i & 0xf) == 0) + grub_printf ("%02x: ", i); + + err = grub_cmos_read (i, &value); + if (err) + return err; + + grub_printf ("%02x ", value); + if ((i & 0xf) == 0xf) + grub_printf ("\n"); + } + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + + +GRUB_MOD_INIT(cmosdump) +{ + cmd = grub_register_command ("cmosdump", grub_cmd_cmosdump, + 0, + N_("Show raw dump of the CMOS contents.")); +} + +GRUB_MOD_FINI(cmosdump) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/i386/cmostest.c b/grub-core/commands/i386/cmostest.c index d2a184026..1f0c5341d 100644 --- a/grub-core/commands/i386/cmostest.c +++ b/grub-core/commands/i386/cmostest.c @@ -27,7 +27,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); static grub_err_t parse_args (int argc, char *argv[], int *byte, int *bit) { - char *rest; + const char *rest; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "address required"); @@ -45,7 +45,7 @@ static grub_err_t grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), int argc, char *argv[]) { - int byte, bit; + int byte = 0, bit = 0; grub_err_t err; grub_uint8_t value; @@ -67,7 +67,7 @@ static grub_err_t grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)), int argc, char *argv[]) { - int byte, bit; + int byte = 0, bit = 0; grub_err_t err; grub_uint8_t value; @@ -81,21 +81,44 @@ grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)), return grub_cmos_write (byte, value & (~(1 << bit))); } -static grub_command_t cmd, cmd_clean; +static grub_err_t +grub_cmd_cmosset (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + int byte = 0, bit = 0; + grub_err_t err; + grub_uint8_t value; + + err = parse_args (argc, argv, &byte, &bit); + if (err) + return err; + err = grub_cmos_read (byte, &value); + if (err) + return err; + + return grub_cmos_write (byte, value | (1 << bit)); +} + +static grub_command_t cmd, cmd_clean, cmd_set; GRUB_MOD_INIT(cmostest) { - cmd = grub_register_command ("cmostest", grub_cmd_cmostest, + cmd = grub_register_command_lockdown ("cmostest", grub_cmd_cmostest, N_("BYTE:BIT"), N_("Test bit at BYTE:BIT in CMOS.")); - cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean, + cmd_clean = grub_register_command_lockdown ("cmosclean", grub_cmd_cmosclean, N_("BYTE:BIT"), - N_("Clean bit at BYTE:BIT in CMOS.")); + N_("Clear bit at BYTE:BIT in CMOS.")); + cmd_set = grub_register_command_lockdown ("cmosset", grub_cmd_cmosset, + N_("BYTE:BIT"), + /* TRANSLATORS: A bit may be either set (1) or clear (0). */ + N_("Set bit at BYTE:BIT in CMOS.")); } GRUB_MOD_FINI(cmostest) { grub_unregister_command (cmd); grub_unregister_command (cmd_clean); + grub_unregister_command (cmd_set); } diff --git a/grub-core/commands/i386/coreboot/cb_timestamps.c b/grub-core/commands/i386/coreboot/cb_timestamps.c new file mode 100644 index 000000000..c44abb3fa --- /dev/null +++ b/grub-core/commands/i386/coreboot/cb_timestamps.c @@ -0,0 +1,126 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_uint32_t +tsc2ms (grub_uint64_t tsc) +{ + grub_uint64_t ah = tsc >> 32; + grub_uint64_t al = tsc & 0xffffffff; + + return ((al * grub_tsc_rate) >> 32) + ah * grub_tsc_rate; +} + +static const char *descs[] = { + [1] = "romstage", + [2] = "before RAM init", + [3] = "after RAM init", + [4] = "end of romstage", + [5] = "start of verified boot", + [6] = "end of verified boot", + [8] = "start of RAM copy", + [9] = "end of RAM copy", + [10] = "start of ramstage", + [11] = "start of bootblock", + [12] = "end of bootblock", + [13] = "starting to load romstage", + [14] = "finished loading romstage", + [15] = "starting LZMA decompress (ignore for x86)", + [16] = "finished LZMA decompress (ignore for x86)", + [30] = "device enumerate", + [40] = "device configure", + [50] = "device enable", + [60] = "device initialize", + [70] = "device done", + [75] = "CBMEM POST", + [80] = "writing tables", + [90] = "loading payload", + [98] = "wake jump", + [99] = "selfboot jump", +}; + +static int +iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, + void *data) +{ + int *available = data; + grub_uint64_t last_tsc = 0; + struct grub_linuxbios_timestamp_table *ts_table; + unsigned i; + + if (table_item->tag != GRUB_LINUXBIOS_MEMBER_TIMESTAMPS) + return 0; + + *available = 1; + ts_table = (struct grub_linuxbios_timestamp_table *) (grub_addr_t) + *(grub_uint64_t *) (table_item + 1); + + for (i = 0; i < ts_table->used; i++) + { + grub_uint32_t tmabs = tsc2ms (ts_table->entries[i].tsc); + grub_uint32_t tmrel = tsc2ms (ts_table->entries[i].tsc - last_tsc); + last_tsc = ts_table->entries[i].tsc; + + grub_printf ("%3d.%03ds %2d.%03ds %02d %s\n", + tmabs / 1000, tmabs % 1000, tmrel / 1000, tmrel % 1000, + ts_table->entries[i].id, + (ts_table->entries[i].id < ARRAY_SIZE (descs) + && descs[ts_table->entries[i].id]) + ? descs[ts_table->entries[i].id] : ""); + } + return 1; +} + + +static grub_err_t +grub_cmd_coreboot_boottime (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + int available = 0; + + grub_linuxbios_table_iterate (iterate_linuxbios_table, &available); + if (!available) + { + grub_puts_ (N_("No boot time statistics is available\n")); + return 0; + } + return 0; +} + +static grub_command_t cmd_boottime; + +GRUB_MOD_INIT(cbtime) +{ + cmd_boottime = + grub_register_command ("coreboot_boottime", grub_cmd_coreboot_boottime, + 0, N_("Show coreboot boot time statistics.")); +} + +GRUB_MOD_FINI(cbtime) +{ + grub_unregister_command (cmd_boottime); +} diff --git a/grub-core/commands/i386/coreboot/cbls.c b/grub-core/commands/i386/coreboot/cbls.c new file mode 100644 index 000000000..50b7b8750 --- /dev/null +++ b/grub-core/commands/i386/coreboot/cbls.c @@ -0,0 +1,143 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static const char *console_descs[] = { + "8250 UART", + "VGA", + "BTEXT", + "log buffer console", + "SROM", + "EHCI debug", + "memory-mapped 8250 UART" +}; + +static const char *descs[] = { + [GRUB_LINUXBIOS_MEMBER_MEMORY] = "memory map (`lsmmap' to list)", + [GRUB_LINUXBIOS_MEMBER_MAINBOARD] = "mainboard", + [4] = "version", + [5] = "extra version", + [6] = "build", + [7] = "compile time", + [8] = "compile by", + [9] = "compile host", + [0xa] = "compile domain", + [0xb] = "compiler", + [0xc] = "linker", + [0xd] = "assembler", + [0xf] = "serial", + [GRUB_LINUXBIOS_MEMBER_CONSOLE] = "console", + [GRUB_LINUXBIOS_MEMBER_FRAMEBUFFER] = "framebuffer", + [0x13] = "GPIO", + [0x15] = "VDAT", + [GRUB_LINUXBIOS_MEMBER_TIMESTAMPS] = "timestamps (`coreboot_boottime' to list)", + [GRUB_LINUXBIOS_MEMBER_CBMEMC] = "CBMEM console (`cbmemc' to list)", + [0x18] = "MRC cache", + [0x19] = "VBNV", + [0xc8] = "CMOS option table", + [0xc9] = "CMOS option", + [0xca] = "CMOS option enum", + [0xcb] = "CMOS option defaults", + [0xcc] = "CMOS checksum", +}; + +static int +iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, + void *data __attribute__ ((unused))) +{ + if (table_item->tag < ARRAY_SIZE (descs) && descs[table_item->tag]) + grub_printf ("tag=%02x size=%02x %s", + table_item->tag, table_item->size, descs[table_item->tag]); + else + grub_printf ("tag=%02x size=%02x", + table_item->tag, table_item->size); + + switch (table_item->tag) + { + case GRUB_LINUXBIOS_MEMBER_FRAMEBUFFER: + { + struct grub_linuxbios_table_framebuffer *fb; + fb = (struct grub_linuxbios_table_framebuffer *) (table_item + 1); + + grub_printf (": %dx%dx%d pitch=%d lfb=0x%llx %d/%d/%d/%d %d/%d/%d/%d", + fb->width, fb->height, + fb->bpp, fb->pitch, + (unsigned long long) fb->lfb, + fb->red_mask_size, fb->green_mask_size, + fb->blue_mask_size, fb->reserved_mask_size, + fb->red_field_pos, fb->green_field_pos, + fb->blue_field_pos, fb->reserved_field_pos); + break; + } + case GRUB_LINUXBIOS_MEMBER_MAINBOARD: + { + struct grub_linuxbios_mainboard *mb; + mb = (struct grub_linuxbios_mainboard *) (table_item + 1); + grub_printf (": vendor=`%s' part_number=`%s'", + mb->strings + mb->vendor, + mb->strings + mb->part_number); + break; + } + case 0x04 ... 0x0d: + grub_printf (": `%s'", (char *) (table_item + 1)); + break; + case GRUB_LINUXBIOS_MEMBER_CONSOLE: + { + grub_uint16_t *val = (grub_uint16_t *) (table_item + 1); + grub_printf (": id=%d", *val); + if (*val < ARRAY_SIZE (console_descs) + && console_descs[*val]) + grub_printf (" %s", console_descs[*val]); + } + } + grub_printf ("\n"); + + return 0; +} + + +static grub_err_t +grub_cmd_lscoreboot (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + grub_linuxbios_table_iterate (iterate_linuxbios_table, 0); + return 0; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(cbls) +{ + cmd = + grub_register_command ("lscoreboot", grub_cmd_lscoreboot, + 0, N_("List coreboot tables.")); +} + +GRUB_MOD_FINI(cbls) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/i386/cpuid.c b/grub-core/commands/i386/cpuid.c index 3b895cb93..42b984154 100644 --- a/grub-core/commands/i386/cpuid.c +++ b/grub-core/commands/i386/cpuid.c @@ -29,29 +29,43 @@ GRUB_MOD_LICENSE ("GPLv3+"); -#define cpuid(num,a,b,c,d) \ - asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ - : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ - : "0" (num)) - static const struct grub_arg_option options[] = { /* TRANSLATORS: "(default)" at the end means that this option is used if no argument is specified. */ {"long-mode", 'l', 0, N_("Check if CPU supports 64-bit (long) mode (default)."), 0, 0}, + {"pae", 'p', 0, N_("Check if CPU supports Physical Address Extension."), 0, 0}, {0, 0, 0, 0, 0, 0} }; -#define bit_LM (1 << 29) +enum + { + MODE_LM = 0, + MODE_PAE = 1 + }; -unsigned char grub_cpuid_has_longmode = 0; +enum + { + bit_PAE = (1 << 6), + }; +enum + { + bit_LM = (1 << 29) + }; + +unsigned char grub_cpuid_has_longmode = 0, grub_cpuid_has_pae = 0; static grub_err_t -grub_cmd_cpuid (grub_extcmd_context_t ctxt __attribute__ ((unused)), +grub_cmd_cpuid (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - return grub_cpuid_has_longmode ? GRUB_ERR_NONE + int val = 0; + if (ctxt->state[MODE_PAE].set) + val = grub_cpuid_has_pae; + else + val = grub_cpuid_has_longmode; + return val ? GRUB_ERR_NONE /* TRANSLATORS: it's a standalone boolean value, opposite of "true". */ : grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); @@ -64,6 +78,7 @@ GRUB_MOD_INIT(cpuid) #ifdef __x86_64__ /* grub-emu */ grub_cpuid_has_longmode = 1; + grub_cpuid_has_pae = 1; #else unsigned int eax, ebx, ecx, edx; unsigned int max_level; @@ -78,18 +93,24 @@ GRUB_MOD_INIT(cpuid) goto done; /* Check the highest input value for eax. */ - cpuid (0, eax, ebx, ecx, edx); + grub_cpuid (0, eax, ebx, ecx, edx); /* We only look at the first four characters. */ max_level = eax; if (max_level == 0) goto done; - cpuid (0x80000000, eax, ebx, ecx, edx); + if (max_level >= 1) + { + grub_cpuid (1, eax, ebx, ecx, edx); + grub_cpuid_has_pae = !!(edx & bit_PAE); + } + + grub_cpuid (0x80000000, eax, ebx, ecx, edx); ext_level = eax; if (ext_level < 0x80000000) goto done; - cpuid (0x80000001, eax, ebx, ecx, edx); + grub_cpuid (0x80000001, eax, ebx, ecx, edx); grub_cpuid_has_longmode = !!(edx & bit_LM); done: #endif diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c index 7fbf8de87..a7ee4c9bd 100644 --- a/grub-core/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -31,9 +31,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); -/* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ -static grub_uint32_t *const int13slot = (grub_uint32_t *) (4 * 0x13); - /* Remember to update enum opt_idxs accordingly. */ static const struct grub_arg_option options[] = { /* TRANSLATORS: In this file "mapping" refers to a change GRUB makes so if @@ -74,7 +71,7 @@ typedef struct drivemap_node grub_uint8_t redirto; } drivemap_node_t; -typedef struct __attribute__ ((packed)) int13map_node +typedef struct GRUB_PACKED int13map_node { grub_uint8_t disknum; grub_uint8_t mapto; @@ -185,7 +182,7 @@ list_mappings (void) return GRUB_ERR_NONE; } - /* TRANSLATORS: This is the header of mapping list. + /* TRANSLATORS: This is the header of mapping list. On the left is how OS will see the disks and on the right current GRUB vision. */ grub_puts_ (N_("OS disk #num ------> GRUB/BIOS device")); @@ -280,6 +277,8 @@ install_int13_handler (int noret __attribute__ ((unused))) grub_uint8_t *handler_base = 0; /* Address of the map within the deployed bundle. */ int13map_node_t *handler_map; + /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ + grub_uint32_t *int13slot = (grub_uint32_t *) grub_absolute_pointer (4 * 0x13); int i; int entries = 0; @@ -354,6 +353,9 @@ install_int13_handler (int noret __attribute__ ((unused))) static grub_err_t uninstall_int13_handler (void) { + /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ + grub_uint32_t *int13slot = (grub_uint32_t *) grub_absolute_pointer (4 * 0x13); + if (! grub_drivemap_oldhandler) return GRUB_ERR_NONE; diff --git a/grub-core/commands/i386/pc/halt.c b/grub-core/commands/i386/pc/halt.c index 1e7c2c9b3..e87e8dccd 100644 --- a/grub-core/commands/i386/pc/halt.c +++ b/grub-core/commands/i386/pc/halt.c @@ -59,7 +59,7 @@ grub_halt (int no_apm) regs.ebx = 0; regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x15, ®s); - + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) stop (); diff --git a/grub-core/commands/i386/pc/lsapm.c b/grub-core/commands/i386/pc/lsapm.c index c82476df1..8f49880da 100644 --- a/grub-core/commands/i386/pc/lsapm.c +++ b/grub-core/commands/i386/pc/lsapm.c @@ -34,7 +34,7 @@ grub_apm_get_info (struct grub_apm_info *info) regs.ebx = 0; regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x15, ®s); - + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) return 0; info->version = regs.eax & 0xffff; diff --git a/grub-core/commands/i386/pc/play.c b/grub-core/commands/i386/pc/play.c index 10a018181..7ff8cd633 100644 --- a/grub-core/commands/i386/pc/play.c +++ b/grub-core/commands/i386/pc/play.c @@ -28,80 +28,12 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); #define BASE_TEMPO (60 * 1000) -/* The speaker port. */ -#define SPEAKER 0x61 - -/* If 0, follow state of SPEAKER_DATA bit, otherwise enable output - from timer 2. */ -#define SPEAKER_TMR2 0x01 - -/* If SPEAKER_TMR2 is not set, this provides direct input into the - speaker. Otherwise, this enables or disables the output from the - timer. */ -#define SPEAKER_DATA 0x02 - -/* The PIT channel value ports. You can write to and read from them. - Do not mess with timer 0 or 1. */ -#define PIT_COUNTER_0 0x40 -#define PIT_COUNTER_1 0x41 -#define PIT_COUNTER_2 0x42 - -/* The frequency of the PIT clock. */ -#define PIT_FREQUENCY 0x1234dd - -/* The PIT control port. You can only write to it. Do not mess with - timer 0 or 1. */ -#define PIT_CTRL 0x43 -#define PIT_CTRL_SELECT_MASK 0xc0 -#define PIT_CTRL_SELECT_0 0x00 -#define PIT_CTRL_SELECT_1 0x40 -#define PIT_CTRL_SELECT_2 0x80 - -/* Read and load control. */ -#define PIT_CTRL_READLOAD_MASK 0x30 -#define PIT_CTRL_COUNTER_LATCH 0x00 /* Hold timer value until read. */ -#define PIT_CTRL_READLOAD_LSB 0x10 /* Read/load the LSB. */ -#define PIT_CTRL_READLOAD_MSB 0x20 /* Read/load the MSB. */ -#define PIT_CTRL_READLOAD_WORD 0x30 /* Read/load the LSB then the MSB. */ - -/* Mode control. */ -#define PIT_CTRL_MODE_MASK 0x0e - -/* Interrupt on terminal count. Setting the mode sets output to low. - When counter is set and terminated, output is set to high. */ -#define PIT_CTRL_INTR_ON_TERM 0x00 - -/* Programmable one-shot. When loading counter, output is set to - high. When counter terminated, output is set to low. Can be - triggered again from that point on by setting the gate pin to - high. */ -#define PIT_CTRL_PROGR_ONE_SHOT 0x02 - -/* Rate generator. Output is low for one period of the counter, and - high for the other. */ -#define PIT_CTRL_RATE_GEN 0x04 - -/* Square wave generator. Output is low for one half of the period, - and high for the other half. */ -#define PIT_CTRL_SQUAREWAVE_GEN 0x06 - -/* Software triggered strobe. Setting the mode sets output to high. - When counter is set and terminated, output is set to low. */ -#define PIT_CTRL_SOFTSTROBE 0x08 - -/* Hardware triggered strobe. Like software triggered strobe, but - only starts the counter when the gate pin is set to high. */ -#define PIT_CTRL_HARDSTROBE 0x0a - -/* Count mode. */ -#define PIT_CTRL_COUNT_MASK 0x01 -#define PIT_CTRL_COUNT_BINARY 0x00 /* 16-bit binary counter. */ -#define PIT_CTRL_COUNT_BCD 0x01 /* 4-decade BCD counter. */ #define T_REST ((grub_uint16_t) 0) #define T_FINE ((grub_uint16_t) -1) @@ -112,39 +44,6 @@ struct note grub_uint16_t duration; }; -static void -beep_off (void) -{ - unsigned char status; - - status = grub_inb (SPEAKER); - grub_outb (status & ~(SPEAKER_TMR2 | SPEAKER_DATA), SPEAKER); -} - -static void -beep_on (grub_uint16_t pitch) -{ - unsigned char status; - unsigned int counter; - - if (pitch < 20) - pitch = 20; - else if (pitch > 20000) - pitch = 20000; - - counter = PIT_FREQUENCY / pitch; - - /* Program timer 2. */ - grub_outb (PIT_CTRL_SELECT_2 | PIT_CTRL_READLOAD_WORD - | PIT_CTRL_SQUAREWAVE_GEN | PIT_CTRL_COUNT_BINARY, PIT_CTRL); - grub_outb (counter & 0xff, PIT_COUNTER_2); /* LSB */ - grub_outb ((counter >> 8) & 0xff, PIT_COUNTER_2); /* MSB */ - - /* Start speaker. */ - status = grub_inb (SPEAKER); - grub_outb (status | SPEAKER_TMR2 | SPEAKER_DATA, SPEAKER); -} - /* Returns whether playing should continue. */ static int play (unsigned tempo, struct note *note) @@ -160,11 +59,11 @@ play (unsigned tempo, struct note *note) switch (note->pitch) { case T_REST: - beep_off (); + grub_speaker_beep_off (); break; default: - beep_on (note->pitch); + grub_speaker_beep_on (note->pitch); break; } @@ -181,7 +80,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), { if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BAD_ARGUMENT, /* TRANSLATORS: It's musical notes, not the notes you take. Play command expects arguments which can be either a filename or tempo+notes. @@ -194,7 +93,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), grub_uint32_t tempo; grub_file_t file; - file = grub_file_open (args[0]); + file = grub_file_open (args[0], GRUB_FILE_TYPE_AUDIO); if (! file) return grub_errno; @@ -208,6 +107,14 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), return grub_errno; } + if (!tempo) + { + grub_file_close (file); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid tempo in %s"), + args[0]); + return grub_errno; + } + tempo = grub_le_to_cpu32 (tempo); grub_dprintf ("play","tempo = %d\n", tempo); @@ -225,13 +132,20 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), } else { - char *end; + const char *end; unsigned tempo; struct note note; int i; tempo = grub_strtoul (args[0], &end, 0); + if (!tempo) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid tempo in %s"), + args[0]); + return grub_errno; + } + if (*end) /* Was not a number either, assume it was supposed to be a file name. */ return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), args[0]); @@ -263,7 +177,7 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), } } - beep_off (); + grub_speaker_beep_off (); return 0; } diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c index 17f648d78..282bb5d42 100644 --- a/grub-core/commands/i386/pc/sendkey.c +++ b/grub-core/commands/i386/pc/sendkey.c @@ -55,12 +55,12 @@ static const struct grub_arg_option options[] = {"no-led", 0, 0, N_("don't update LED state"), 0, 0}, {0, 0, 0, 0, 0, 0} }; -static int simple_flag_offsets[] +static int simple_flag_offsets[] = {5, 6, 4, 7, 11, 1, 0, 10, 13, 14, 12, 15, 9, 3, 8, 2}; static grub_uint32_t andmask = 0xffffffff, ormask = 0; -struct +struct keysym { const char *unshifted_name; /* the name in unshifted state */ @@ -171,13 +171,13 @@ static struct keysym keysym_table[] = {"right", 0, 0xe0, 0, 0x4d} }; -/* Set a simple flag in flags variable +/* Set a simple flag in flags variable OUTOFFSET - offset of flag in FLAGS, OP - action id */ static void grub_sendkey_set_simple_flag (int outoffset, int op) -{ +{ if (op == 2) { andmask |= (1 << outoffset); @@ -199,7 +199,7 @@ grub_sendkey_parse_op (struct grub_arg_list state) if (! state.set) return 2; - if (grub_strcmp (state.arg, "off") == 0 || grub_strcmp (state.arg, "0") == 0 + if (grub_strcmp (state.arg, "off") == 0 || grub_strcmp (state.arg, "0") == 0 || grub_strcmp (state.arg, "unpress") == 0) return 0; @@ -216,12 +216,12 @@ static grub_err_t grub_sendkey_postboot (void) { /* For convention: pointer to flags. */ - grub_uint32_t *flags = (grub_uint32_t *) 0x417; + grub_uint32_t *flags = grub_absolute_pointer (0x417); *flags = oldflags; - *((char *) 0x41a) = 0x1e; - *((char *) 0x41c) = 0x1e; + *((volatile char *) grub_absolute_pointer (0x41a)) = 0x1e; + *((volatile char *) grub_absolute_pointer (0x41c)) = 0x1e; return GRUB_ERR_NONE; } @@ -231,13 +231,13 @@ static grub_err_t grub_sendkey_preboot (int noret __attribute__ ((unused))) { /* For convention: pointer to flags. */ - grub_uint32_t *flags = (grub_uint32_t *) 0x417; + grub_uint32_t *flags = grub_absolute_pointer (0x417); oldflags = *flags; - + /* Set the sendkey. */ - *((char *) 0x41a) = 0x1e; - *((char *) 0x41c) = keylen + 0x1e; + *((volatile char *) grub_absolute_pointer (0x41a)) = 0x1e; + *((volatile char *) grub_absolute_pointer (0x41c)) = keylen + 0x1e; grub_memcpy ((char *) 0x41e, sendkey, 0x20); /* Transform "any ctrl" to "right ctrl" flag. */ @@ -247,7 +247,7 @@ grub_sendkey_preboot (int noret __attribute__ ((unused))) /* Transform "any alt" to "right alt" flag. */ if (*flags & (1 << 9)) *flags &= ~(1 << 3); - + *flags = (*flags & andmask) | ormask; /* Transform "right ctrl" to "any ctrl" flag. */ @@ -286,48 +286,49 @@ grub_sendkey_preboot (int noret __attribute__ ((unused))) return GRUB_ERR_NONE; } +/* Helper for grub_cmd_sendkey. */ +static int +find_key_code (char *key) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(keysym_table); i++) + { + if (keysym_table[i].unshifted_name + && grub_strcmp (key, keysym_table[i].unshifted_name) == 0) + return keysym_table[i].keycode; + else if (keysym_table[i].shifted_name + && grub_strcmp (key, keysym_table[i].shifted_name) == 0) + return keysym_table[i].keycode; + } + + return 0; +} + +/* Helper for grub_cmd_sendkey. */ +static int +find_ascii_code (char *key) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE(keysym_table); i++) + { + if (keysym_table[i].unshifted_name + && grub_strcmp (key, keysym_table[i].unshifted_name) == 0) + return keysym_table[i].unshifted_ascii; + else if (keysym_table[i].shifted_name + && grub_strcmp (key, keysym_table[i].shifted_name) == 0) + return keysym_table[i].shifted_ascii; + } + + return 0; +} + static grub_err_t grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; - auto int find_key_code (char *key); - auto int find_ascii_code (char *key); - - int find_key_code (char *key) - { - unsigned i; - - for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) - { - if (keysym_table[i].unshifted_name - && grub_strcmp (key, keysym_table[i].unshifted_name) == 0) - return keysym_table[i].keycode; - else if (keysym_table[i].shifted_name - && grub_strcmp (key, keysym_table[i].shifted_name) == 0) - return keysym_table[i].keycode; - } - - return 0; - } - - int find_ascii_code (char *key) - { - unsigned i; - - for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) - { - if (keysym_table[i].unshifted_name - && grub_strcmp (key, keysym_table[i].unshifted_name) == 0) - return keysym_table[i].unshifted_ascii; - else if (keysym_table[i].shifted_name - && grub_strcmp (key, keysym_table[i].shifted_name) == 0) - return keysym_table[i].shifted_ascii; - } - - return 0; - } - andmask = 0xffffffff; ormask = 0; @@ -339,7 +340,7 @@ grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args) for (i = 0; i < argc && keylen < 0x20; i++) { int key_code; - + key_code = find_key_code (args[i]); if (key_code) { @@ -351,15 +352,13 @@ grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args) { unsigned i; - for (i = 0; i < sizeof (simple_flag_offsets) - / sizeof (simple_flag_offsets[0]); i++) - grub_sendkey_set_simple_flag (simple_flag_offsets[i], + for (i = 0; i < ARRAY_SIZE(simple_flag_offsets); i++) + grub_sendkey_set_simple_flag (simple_flag_offsets[i], grub_sendkey_parse_op(state[i])); } /* Set noled. */ - noled = (state[sizeof (simple_flag_offsets) - / sizeof (simple_flag_offsets[0])].set); + noled = (state[ARRAY_SIZE(simple_flag_offsets)].set); return GRUB_ERR_NONE; } @@ -375,8 +374,8 @@ GRUB_MOD_INIT (sendkey) keypresses. */ N_("Emulate a keystroke sequence"), options); - preboot_hook - = grub_loader_register_preboot_hook (grub_sendkey_preboot, + preboot_hook + = grub_loader_register_preboot_hook (grub_sendkey_preboot, grub_sendkey_postboot, GRUB_LOADER_PREBOOT_HOOK_PRIO_CONSOLE); } diff --git a/grub-core/commands/i386/pc/smbios.c b/grub-core/commands/i386/pc/smbios.c new file mode 100644 index 000000000..069d66367 --- /dev/null +++ b/grub-core/commands/i386/pc/smbios.c @@ -0,0 +1,52 @@ +/* smbios.c - get smbios tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2019 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include + +struct grub_smbios_eps * +grub_machine_smbios_get_eps (void) +{ + grub_uint8_t *ptr; + + grub_dprintf ("smbios", "Looking for SMBIOS EPS. Scanning BIOS\n"); + + for (ptr = (grub_uint8_t *) 0xf0000; ptr < (grub_uint8_t *) 0x100000; ptr += 16) + if (grub_memcmp (ptr, "_SM_", 4) == 0 + && grub_byte_checksum (ptr, sizeof (struct grub_smbios_eps)) == 0) + return (struct grub_smbios_eps *) ptr; + + return 0; +} + +struct grub_smbios_eps3 * +grub_machine_smbios_get_eps3 (void) +{ + grub_uint8_t *ptr; + + grub_dprintf ("smbios", "Looking for SMBIOS3 EPS. Scanning BIOS\n"); + + for (ptr = (grub_uint8_t *) 0xf0000; ptr < (grub_uint8_t *) 0x100000; ptr += 16) + if (grub_memcmp (ptr, "_SM3_", 5) == 0 + && grub_byte_checksum (ptr, sizeof (struct grub_smbios_eps3)) == 0) + return (struct grub_smbios_eps3 *) ptr; + + return 0; +} diff --git a/grub-core/commands/i386/rdmsr.c b/grub-core/commands/i386/rdmsr.c new file mode 100644 index 000000000..2e42f6197 --- /dev/null +++ b/grub-core/commands/i386/rdmsr.c @@ -0,0 +1,91 @@ +/* rdmsr.c - Read CPU model-specific registers. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2019 Free Software Foundation, Inc. + * Based on gcc/gcc/config/i386/driver-i386.c + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE("GPLv3+"); + +static grub_extcmd_t cmd_read; + +static const struct grub_arg_option options[] = +{ + {0, 'v', 0, N_("Save read value into variable VARNAME."), + N_("VARNAME"), ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} +}; + +static grub_err_t +grub_cmd_msr_read (grub_extcmd_context_t ctxt, int argc, char **argv) +{ + grub_err_t err; + grub_uint32_t addr; + grub_uint64_t value; + const char *ptr; + char buf[sizeof("1122334455667788")]; + + err = grub_cpu_is_msr_supported (); + + if (err != GRUB_ERR_NONE) + return grub_error (err, N_("RDMSR is unsupported")); + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + grub_errno = GRUB_ERR_NONE; + ptr = argv[0]; + addr = grub_strtoul (ptr, &ptr, 0); + + if (grub_errno != GRUB_ERR_NONE) + return grub_errno; + if (*ptr != '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument")); + + value = grub_rdmsr (addr); + + if (ctxt->state[0].set) + { + grub_snprintf (buf, sizeof(buf), "%llx", (unsigned long long) value); + grub_env_set (ctxt->state[0].arg, buf); + } + else + grub_printf ("0x%llx\n", (unsigned long long) value); + + return GRUB_ERR_NONE; +} + +GRUB_MOD_INIT(rdmsr) +{ + cmd_read = grub_register_extcmd ("rdmsr", grub_cmd_msr_read, 0, N_("ADDR"), + N_("Read a CPU model specific register."), + options); +} + +GRUB_MOD_FINI(rdmsr) +{ + grub_unregister_extcmd (cmd_read); +} diff --git a/grub-core/commands/i386/wrmsr.c b/grub-core/commands/i386/wrmsr.c new file mode 100644 index 000000000..7fbedaed9 --- /dev/null +++ b/grub-core/commands/i386/wrmsr.c @@ -0,0 +1,83 @@ +/* wrmsr.c - Write CPU model-specific registers. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2019 Free Software Foundation, Inc. + * Based on gcc/gcc/config/i386/driver-i386.c + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE("GPLv3+"); + +static grub_command_t cmd_write; + +static grub_err_t +grub_cmd_msr_write (grub_command_t cmd __attribute__ ((unused)), int argc, char **argv) +{ + grub_err_t err; + grub_uint32_t addr; + grub_uint64_t value; + const char *ptr; + + err = grub_cpu_is_msr_supported (); + + if (err != GRUB_ERR_NONE) + return grub_error (err, N_("WRMSR is unsupported")); + + if (argc != 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); + + grub_errno = GRUB_ERR_NONE; + ptr = argv[0]; + addr = grub_strtoul (ptr, &ptr, 0); + + if (grub_errno != GRUB_ERR_NONE) + return grub_errno; + if (*ptr != '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument")); + + ptr = argv[1]; + value = grub_strtoull (ptr, &ptr, 0); + + if (grub_errno != GRUB_ERR_NONE) + return grub_errno; + if (*ptr != '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid argument")); + + grub_wrmsr (addr, value); + + return GRUB_ERR_NONE; +} + +GRUB_MOD_INIT(wrmsr) +{ + cmd_write = grub_register_command_lockdown ("wrmsr", grub_cmd_msr_write, N_("ADDR VALUE"), + N_("Write a value to a CPU model specific register.")); +} + +GRUB_MOD_FINI(wrmsr) +{ + grub_unregister_command (cmd_write); +} diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c new file mode 100644 index 000000000..4958b04a9 --- /dev/null +++ b/grub-core/commands/ieee1275/ibmvtpm.c @@ -0,0 +1,117 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Free Software Foundation, Inc. + * Copyright (C) 2022 IBM Corporation + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + * + * IBM vTPM support code. + */ + +#include +#include +#include +#include +#include +#include +#include + +static int +ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex, + grub_uint32_t eventtype, + const char *description, + grub_size_t description_size, + void *buf, grub_size_t size) +{ + struct tpm_2hash_ext_log + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t size; + grub_ieee1275_cell_t buf; + grub_ieee1275_cell_t description_size; + grub_ieee1275_cell_t description; + grub_ieee1275_cell_t eventtype; + grub_ieee1275_cell_t pcrindex; + grub_ieee1275_cell_t catch_result; + grub_ieee1275_cell_t rc; + }; + struct tpm_2hash_ext_log args; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 2); + args.method = (grub_ieee1275_cell_t) "2hash-ext-log"; + args.ihandle = grub_ieee1275_tpm_ihandle; + args.pcrindex = pcrindex; + args.eventtype = eventtype; + args.description = (grub_ieee1275_cell_t) description; + args.description_size = description_size; + args.buf = (grub_ieee1275_cell_t) buf; + args.size = (grub_ieee1275_cell_t) size; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return -1; + + /* + * catch_result is set if firmware does not support 2hash-ext-log + * rc is GRUB_IEEE1275_CELL_FALSE (0) on failure + */ + if ((args.catch_result) || args.rc == GRUB_IEEE1275_CELL_FALSE) + return -1; + + return 0; +} + +static grub_err_t +tpm2_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *description) +{ + static int error_displayed = 0; + int rc; + + rc = ibmvtpm_2hash_ext_log (pcr, EV_IPL, + description, grub_strlen(description) + 1, + buf, size); + if (rc && !error_displayed) + { + error_displayed++; + return grub_error (GRUB_ERR_BAD_DEVICE, + "2HASH-EXT-LOG failed: Firmware is likely too old.\n"); + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *description) +{ + grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n", + pcr, size, description); + + if (grub_ieee1275_tpm_ihandle != GRUB_IEEE1275_IHANDLE_INVALID) + return tpm2_log_event (buf, size, pcr, description); + + return GRUB_ERR_NONE; +} + +int +grub_tpm_present (void) +{ + /* + * Call tpm_init() "late" rather than from GRUB_MOD_INIT() so that device nodes + * can be found. + */ + return grub_ieee1275_tpm_init() == GRUB_ERR_NONE; +} diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c index a0c164e54..584baec8f 100644 --- a/grub-core/commands/iorw.c +++ b/grub-core/commands/iorw.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -131,17 +132,17 @@ GRUB_MOD_INIT(memrw) N_("PORT"), N_("Read 32-bit value from PORT."), options); cmd_write_byte = - grub_register_command ("outb", grub_cmd_write, - N_("PORT VALUE [MASK]"), - N_("Write 8-bit VALUE to PORT.")); + grub_register_command_lockdown ("outb", grub_cmd_write, + N_("PORT VALUE [MASK]"), + N_("Write 8-bit VALUE to PORT.")); cmd_write_word = - grub_register_command ("outw", grub_cmd_write, - N_("PORT VALUE [MASK]"), - N_("Write 16-bit VALUE to PORT.")); + grub_register_command_lockdown ("outw", grub_cmd_write, + N_("PORT VALUE [MASK]"), + N_("Write 16-bit VALUE to PORT.")); cmd_write_dword = - grub_register_command ("outl", grub_cmd_write, - N_("ADDR VALUE [MASK]"), - N_("Write 32-bit VALUE to PORT.")); + grub_register_command_lockdown ("outl", grub_cmd_write, + N_("ADDR VALUE [MASK]"), + N_("Write 32-bit VALUE to PORT.")); } GRUB_MOD_FINI(memrw) diff --git a/grub-core/commands/keylayouts.c b/grub-core/commands/keylayouts.c index 6b5141c29..aa3ba34f2 100644 --- a/grub-core/commands/keylayouts.c +++ b/grub-core/commands/keylayouts.c @@ -35,19 +35,19 @@ static struct grub_keyboard_layout layout_us = { /* Keyboard errors. Handled by driver. */ /* 0x00 */ 0, 0, 0, 0, - /* 0x04 */ 'a', 'b', 'c', 'd', + /* 0x04 */ 'a', 'b', 'c', 'd', /* 0x08 */ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', /* 0x10 */ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', /* 0x18 */ 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', /* 0x20 */ '3', '4', '5', '6', '7', '8', '9', '0', - /* 0x28 */ '\n', '\e', '\b', '\t', ' ', '-', '=', '[', + /* 0x28 */ '\n', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[', /* According to usage table 0x31 should be mapped to '/' but testing with real keyboard shows that 0x32 is remapped to '/'. - Map 0x31 to 0. + Map 0x31 to 0. */ /* 0x30 */ ']', 0, '\\', ';', '\'', '`', ',', '.', /* 0x39 is CapsLock. Handled by driver. */ - /* 0x38 */ '/', 0, GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2, + /* 0x38 */ '/', 0, GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2, /* 0x3c */ GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, /* 0x3e */ GRUB_TERM_KEY_F5, GRUB_TERM_KEY_F6, /* 0x40 */ GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, @@ -56,16 +56,16 @@ static struct grub_keyboard_layout layout_us = { /* PrtScr and ScrollLock. Not handled yet. */ /* 0x46 */ 0, 0, /* 0x48 is Pause. Not handled yet. */ - /* 0x48 */ 0, GRUB_TERM_KEY_INSERT, + /* 0x48 */ 0, GRUB_TERM_KEY_INSERT, /* 0x4a */ GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_PPAGE, /* 0x4c */ GRUB_TERM_KEY_DC, GRUB_TERM_KEY_END, /* 0x4e */ GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_RIGHT, /* 0x50 */ GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_DOWN, /* 0x53 is NumLock. Handled by driver. */ /* 0x52 */ GRUB_TERM_KEY_UP, 0, - /* 0x54 */ '/', '*', + /* 0x54 */ '/', '*', /* 0x56 */ '-', '+', - /* 0x58 */ '\n', GRUB_TERM_KEY_END, + /* 0x58 */ '\n', GRUB_TERM_KEY_END, /* 0x5a */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_NPAGE, /* 0x5c */ GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_CENTER, /* 0x5e */ GRUB_TERM_KEY_RIGHT, GRUB_TERM_KEY_HOME, @@ -77,37 +77,37 @@ static struct grub_keyboard_layout layout_us = { /* Keyboard errors. Handled by driver. */ /* 0x00 */ 0, 0, 0, 0, - /* 0x04 */ 'A', 'B', 'C', 'D', + /* 0x04 */ 'A', 'B', 'C', 'D', /* 0x08 */ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', /* 0x10 */ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 0x18 */ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', /* 0x20 */ '#', '$', '%', '^', '&', '*', '(', ')', - /* 0x28 */ '\n' | GRUB_TERM_SHIFT, '\e' | GRUB_TERM_SHIFT, - /* 0x2a */ '\b' | GRUB_TERM_SHIFT, '\t' | GRUB_TERM_SHIFT, + /* 0x28 */ '\n' | GRUB_TERM_SHIFT, GRUB_TERM_ESC | GRUB_TERM_SHIFT, + /* 0x2a */ GRUB_TERM_BACKSPACE | GRUB_TERM_SHIFT, GRUB_TERM_TAB | GRUB_TERM_SHIFT, /* 0x2c */ ' ' | GRUB_TERM_SHIFT, '_', '+', '{', /* According to usage table 0x31 should be mapped to '/' but testing with real keyboard shows that 0x32 is remapped to '/'. - Map 0x31 to 0. + Map 0x31 to 0. */ /* 0x30 */ '}', 0, '|', ':', '"', '~', '<', '>', /* 0x39 is CapsLock. Handled by driver. */ /* 0x38 */ '?', 0, /* 0x3a */ GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT, - /* 0x3b */ GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT, - /* 0x3c */ GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT, - /* 0x3d */ GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT, - /* 0x3e */ GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT, - /* 0x3f */ GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT, - /* 0x40 */ GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT, - /* 0x41 */ GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT, - /* 0x42 */ GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT, - /* 0x43 */ GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT, - /* 0x44 */ GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT, - /* 0x45 */ GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT, + /* 0x3b */ GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT, + /* 0x3c */ GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT, + /* 0x3d */ GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT, + /* 0x3e */ GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT, + /* 0x3f */ GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT, + /* 0x40 */ GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT, + /* 0x41 */ GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT, + /* 0x42 */ GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT, + /* 0x43 */ GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT, + /* 0x44 */ GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT, + /* 0x45 */ GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT, /* PrtScr and ScrollLock. Not handled yet. */ /* 0x46 */ 0, 0, /* 0x48 is Pause. Not handled yet. */ - /* 0x48 */ 0, GRUB_TERM_KEY_INSERT | GRUB_TERM_SHIFT, + /* 0x48 */ 0, GRUB_TERM_KEY_INSERT | GRUB_TERM_SHIFT, /* 0x4a */ GRUB_TERM_KEY_HOME | GRUB_TERM_SHIFT, /* 0x4b */ GRUB_TERM_KEY_PPAGE | GRUB_TERM_SHIFT, /* 0x4c */ GRUB_TERM_KEY_DC | GRUB_TERM_SHIFT, @@ -118,7 +118,7 @@ static struct grub_keyboard_layout layout_us = { /* 0x51 */ GRUB_TERM_KEY_DOWN | GRUB_TERM_SHIFT, /* 0x53 is NumLock. Handled by driver. */ /* 0x52 */ GRUB_TERM_KEY_UP | GRUB_TERM_SHIFT, 0, - /* 0x54 */ '/', '*', + /* 0x54 */ '/', '*', /* 0x56 */ '-', '+', /* 0x58 */ '\n' | GRUB_TERM_SHIFT, '1', '2', '3', '4', '5','6', '7', /* 0x60 */ '8', '9', '0', '.', '|' @@ -132,6 +132,9 @@ map_key_core (int code, int status, int *alt_gr_consumed) { *alt_gr_consumed = 0; + if (code >= GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) + return 0; + if (status & GRUB_TERM_STATUS_RALT) { if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) @@ -145,7 +148,7 @@ map_key_core (int code, int status, int *alt_gr_consumed) else if (grub_current_layout->keyboard_map_l3[code]) { *alt_gr_consumed = 1; - return grub_current_layout->keyboard_map_l3[code]; + return grub_current_layout->keyboard_map_l3[code]; } } if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) @@ -169,10 +172,12 @@ grub_term_map_key (grub_keyboard_key_t code, int status) } key = map_key_core (code, status, &alt_gr_consumed); - - if (key == 0 || key == GRUB_TERM_SHIFT) + + if (key == 0 || key == GRUB_TERM_SHIFT) { grub_printf ("Unknown key 0x%x detected\n", code); - + return GRUB_TERM_NO_KEY; + } + if (status & GRUB_TERM_STATUS_CAPS) { if ((key >= 'a') && (key <= 'z')) @@ -180,8 +185,8 @@ grub_term_map_key (grub_keyboard_key_t code, int status) else if ((key >= 'A') && (key <= 'Z')) key += 'a' - 'A'; } - - if ((status & GRUB_TERM_STATUS_LALT) || + + if ((status & GRUB_TERM_STATUS_LALT) || ((status & GRUB_TERM_STATUS_RALT) && !alt_gr_consumed)) key |= GRUB_TERM_ALT; if (status & (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL)) @@ -207,7 +212,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), { const char *prefix = grub_env_get ("prefix"); if (!prefix) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("variable `%s' isn't set"), "prefix"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("variable `%s' isn't set"), "prefix"); filename = grub_xasprintf ("%s/layouts/%s.gkb", prefix, argv[0]); if (!filename) return grub_errno; @@ -215,7 +220,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), else filename = argv[0]; - file = grub_file_open (filename); + file = grub_file_open (filename, GRUB_FILE_TYPE_KEYBOARD_LAYOUT); if (! file) goto fail; @@ -242,7 +247,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), goto fail; } - if (grub_le_to_cpu32 (version) != GRUB_KEYBOARD_LAYOUTS_VERSION) + if (version != grub_cpu_to_le32_compile_time (GRUB_KEYBOARD_LAYOUTS_VERSION)) { grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid version"); goto fail; @@ -290,21 +295,13 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), static grub_command_t cmd; -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) -void grub_keylayouts_init (void) -#else GRUB_MOD_INIT(keylayouts) -#endif { cmd = grub_register_command ("keymap", grub_cmd_keymap, 0, N_("Load a keyboard layout.")); } -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) -void grub_keylayouts_fini (void) -#else GRUB_MOD_FINI(keylayouts) -#endif { grub_unregister_command (cmd); } diff --git a/grub-core/commands/keystatus.c b/grub-core/commands/keystatus.c index 0925c6a0f..ff3f58781 100644 --- a/grub-core/commands/keystatus.c +++ b/grub-core/commands/keystatus.c @@ -35,24 +35,6 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -static int -grub_getkeystatus (void) -{ - int status = 0; - grub_term_input_t term; - - if (grub_term_poll_usb) - grub_term_poll_usb (); - - FOR_ACTIVE_TERM_INPUTS(term) - { - if (term->getkeystatus) - status |= term->getkeystatus (term); - } - - return status; -} - static grub_err_t grub_cmd_keystatus (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index 5293accab..3bf9fe2e4 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -32,9 +32,19 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); +/* Helper for legacy_file. */ +static grub_err_t +legacy_file_getline (char **line, int cont __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + *line = 0; + return GRUB_ERR_NONE; +} + static grub_err_t legacy_file (const char *filename) { @@ -43,27 +53,25 @@ legacy_file (const char *filename) grub_menu_t menu; char *suffix = grub_strdup (""); - auto grub_err_t getline (char **line, int cont); - grub_err_t getline (char **line, - int cont __attribute__ ((unused))) - { - *line = 0; - return GRUB_ERR_NONE; - } - if (!suffix) return grub_errno; - file = grub_file_open (filename); + file = grub_file_open (filename, GRUB_FILE_TYPE_CONFIG); if (! file) - return grub_errno; + { + grub_free (suffix); + return grub_errno; + } menu = grub_env_get_menu (); if (! menu) { menu = grub_zalloc (sizeof (*menu)); if (! menu) - return grub_errno; + { + grub_free (suffix); + return grub_errno; + } grub_env_set_menu (menu); } @@ -76,6 +84,7 @@ legacy_file (const char *filename) if (!buf && grub_errno) { grub_file_close (file); + grub_free (suffix); return grub_errno; } @@ -96,13 +105,22 @@ legacy_file (const char *filename) if (newsuffix) { char *t; - + grub_size_t sz; + + if (grub_add (grub_strlen (suffix), grub_strlen (newsuffix), &sz) || + grub_add (sz, 1, &sz)) + { + grub_errno = GRUB_ERR_OUT_OF_RANGE; + goto fail_0; + } + t = suffix; - suffix = grub_realloc (suffix, grub_strlen (suffix) - + grub_strlen (newsuffix) + 1); + suffix = grub_realloc (suffix, sz); if (!suffix) { grub_free (t); + + fail_0: grub_free (entrysrc); grub_free (parsed); grub_free (newsuffix); @@ -134,7 +152,7 @@ legacy_file (const char *filename) if (parsed && !entryname) { - grub_normal_parse_line (parsed, getline); + grub_normal_parse_line (parsed, legacy_file_getline, NULL); grub_print_error (); grub_free (parsed); parsed = NULL; @@ -146,13 +164,22 @@ legacy_file (const char *filename) else { char *t; + grub_size_t sz; + + if (grub_add (grub_strlen (entrysrc), grub_strlen (parsed), &sz) || + grub_add (sz, 1, &sz)) + { + grub_errno = GRUB_ERR_OUT_OF_RANGE; + goto fail_1; + } t = entrysrc; - entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc) - + grub_strlen (parsed) + 1); + entrysrc = grub_realloc (entrysrc, sz); if (!entrysrc) { grub_free (t); + + fail_1: grub_free (parsed); grub_free (suffix); return grub_errno; @@ -171,7 +198,8 @@ legacy_file (const char *filename) const char **args = grub_malloc (sizeof (args[0])); if (!args) { - grub_file_close (file); + grub_free (suffix); + grub_free (entrysrc); return grub_errno; } args[0] = entryname; @@ -180,7 +208,7 @@ legacy_file (const char *filename) grub_free (args); } - grub_normal_parse_line (suffix, getline); + grub_normal_parse_line (suffix, legacy_file_getline, NULL); grub_print_error (); grub_free (suffix); grub_free (entrysrc); @@ -228,8 +256,8 @@ grub_cmd_legacy_source (struct grub_command *cmd, } static enum - { - GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD + { + GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD } kernel_type; static grub_err_t @@ -243,7 +271,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), struct grub_command *cmd; char **cutargs; int cutargc; - + grub_err_t err = GRUB_ERR_NONE; + for (i = 0; i < 2; i++) { /* FIXME: really support this. */ @@ -303,7 +332,9 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), if (argc < 2) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); - cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1)); + cutargs = grub_calloc (argc - 1, sizeof (cutargs[0])); + if (!cutargs) + return grub_errno; cutargc = argc - 1; grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2)); cutargs[0] = args[0]; @@ -313,13 +344,17 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), /* First try Linux. */ if (kernel_type == GUESS_IT || kernel_type == LINUX) { +#ifdef GRUB_MACHINE_PCBIOS cmd = grub_command_find ("linux16"); +#else + cmd = grub_command_find ("linux"); +#endif if (cmd) { if (!(cmd->func) (cmd, cutargc, cutargs)) { kernel_type = LINUX; - return GRUB_ERR_NONE; + goto out; } } grub_errno = GRUB_ERR_NONE; @@ -334,7 +369,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), if (!(cmd->func) (cmd, argc, args)) { kernel_type = MULTIBOOT; - return GRUB_ERR_NONE; + goto out; } } grub_errno = GRUB_ERR_NONE; @@ -357,7 +392,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), dev = grub_device_open (0); if (dev && dev->disk && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID - && dev->disk->dev->id >= 0x80 && dev->disk->dev->id <= 0x90) + && dev->disk->id >= 0x80 && dev->disk->id <= 0x90) { struct grub_partition *part = dev->disk->partition; bsd_device = dev->disk->id - 0x80 - hdbias; @@ -371,8 +406,10 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), if (part && grub_strcmp (part->partmap->name, "msdos") == 0) bsd_slice = part->number; } + if (dev) + grub_device_close (dev); } - + /* k*BSD didn't really work well with grub-legacy. */ if (kernel_type == GUESS_IT || kernel_type == KFREEBSD) { @@ -397,7 +434,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), if (!(cmd->func) (cmd, cutargc, cutargs)) { kernel_type = KFREEBSD; - return GRUB_ERR_NONE; + goto out; } } grub_errno = GRUB_ERR_NONE; @@ -406,6 +443,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), char **bsdargs; int bsdargc; char bsddevname[sizeof ("wdXXXXXXXXXXXXY")]; + int found = 0; + if (bsd_device == -1) { bsdargs = cutargs; @@ -415,7 +454,12 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), { char rbuf[3] = "-r"; bsdargc = cutargc + 2; - bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc); + bsdargs = grub_calloc (bsdargc, sizeof (bsdargs[0])); + if (!bsdargs) + { + err = grub_errno; + goto out; + } grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); bsdargs[argc] = rbuf; bsdargs[argc + 1] = bsddevname; @@ -431,7 +475,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), if (!(cmd->func) (cmd, bsdargc, bsdargs)) { kernel_type = KNETBSD; - return GRUB_ERR_NONE; + found = 1; + goto free_bsdargs; } } grub_errno = GRUB_ERR_NONE; @@ -444,20 +489,28 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), if (!(cmd->func) (cmd, bsdargc, bsdargs)) { kernel_type = KOPENBSD; - return GRUB_ERR_NONE; + found = 1; + goto free_bsdargs; } } grub_errno = GRUB_ERR_NONE; } + +free_bsdargs: if (bsdargs != cutargs) grub_free (bsdargs); + if (found) + goto out; } } } while (0); - return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s", - args[0]); + err = grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s", + args[0]); +out: + grub_free (cutargs); + return err; } static grub_err_t @@ -468,12 +521,21 @@ grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), if (kernel_type == LINUX) { +#ifdef GRUB_MACHINE_PCBIOS cmd = grub_command_find ("initrd16"); +#else + cmd = grub_command_find ("initrd"); +#endif if (!cmd) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), - "initrd16"); +#ifdef GRUB_MACHINE_PCBIOS + "initrd16" +#else + "initrd" +#endif + ); - return cmd->func (cmd, argc, args); + return cmd->func (cmd, argc ? 1 : 0, args); } if (kernel_type == MULTIBOOT) { @@ -509,16 +571,18 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused char **newargs; grub_err_t err; char nounzipbuf[10] = "--nounzip"; - newargs = grub_malloc ((argc + 1) * sizeof (newargs[0])); - if (!newargs) - return grub_errno; - grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0])); - newargs[0] = nounzipbuf; + cmd = grub_command_find ("module"); if (!cmd) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), "module"); + newargs = grub_calloc (argc + 1, sizeof (newargs[0])); + if (!newargs) + return grub_errno; + grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0])); + newargs[0] = nounzipbuf; + err = cmd->func (cmd, argc + 1, newargs); grub_free (newargs); return err; @@ -545,8 +609,6 @@ struct legacy_md5_password grub_uint8_t hash[MD5_HASHLEN]; }; -#pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" - static int check_password_md5_real (const char *entered, struct legacy_md5_password *pw) @@ -554,8 +616,13 @@ check_password_md5_real (const char *entered, grub_size_t enteredlen = grub_strlen (entered); unsigned char alt_result[MD5_HASHLEN]; unsigned char *digest; - grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; + grub_uint8_t *ctx; grub_size_t i; + int ret; + + ctx = grub_zalloc (GRUB_MD_MD5->contextsize); + if (!ctx) + return 0; GRUB_MD_MD5->init (ctx); GRUB_MD_MD5->write (ctx, entered, enteredlen); @@ -563,8 +630,8 @@ check_password_md5_real (const char *entered, GRUB_MD_MD5->write (ctx, entered, enteredlen); digest = GRUB_MD_MD5->read (ctx); GRUB_MD_MD5->final (ctx); - memcpy (alt_result, digest, MD5_HASHLEN); - + grub_memcpy (alt_result, digest, MD5_HASHLEN); + GRUB_MD_MD5->init (ctx); GRUB_MD_MD5->write (ctx, entered, enteredlen); GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */ @@ -579,14 +646,14 @@ check_password_md5_real (const char *entered, for (i = 0; i < 1000; i++) { - memcpy (alt_result, digest, 16); + grub_memcpy (alt_result, digest, 16); GRUB_MD_MD5->init (ctx); if ((i & 1) != 0) GRUB_MD_MD5->write (ctx, entered, enteredlen); else GRUB_MD_MD5->write (ctx, alt_result, 16); - + if (i % 3 != 0) GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); @@ -601,7 +668,9 @@ check_password_md5_real (const char *entered, GRUB_MD_MD5->final (ctx); } - return (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); + ret = (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); + grub_free (ctx); + return ret; } static grub_err_t @@ -724,18 +793,12 @@ grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), NULL); } -static grub_err_t -grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)), - int argc, char **args) +int +grub_legacy_check_md5_password (int argc, char **args, + char *entered) { struct legacy_md5_password *pw = NULL; - char entered[GRUB_AUTH_MAX_PASSLEN]; - - if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); - grub_puts_ (N_("Enter password: ")); - if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) - return GRUB_ACCESS_DENIED; + int ret; if (args[0][0] != '-' || args[0][1] != '-') { @@ -744,17 +807,33 @@ grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unuse grub_memset (correct, 0, sizeof (correct)); grub_strncpy (correct, args[0], sizeof (correct)); - if (grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) != 0) - return GRUB_ACCESS_DENIED; - return GRUB_ERR_NONE; + return grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) == 0; } pw = parse_legacy_md5 (argc, args); if (!pw) + return 0; + + ret = check_password_md5_real (entered, pw); + grub_free (pw); + return ret; +} + +static grub_err_t +grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + char entered[GRUB_AUTH_MAX_PASSLEN]; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + grub_puts_ (N_("Enter password: ")); + if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) return GRUB_ACCESS_DENIED; - if (!check_password_md5_real (entered, pw)) + if (!grub_legacy_check_md5_password (argc, args, + entered)) return GRUB_ACCESS_DENIED; return GRUB_ERR_NONE; diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c index 18ebb7eab..166445849 100644 --- a/grub-core/commands/loadenv.c +++ b/grub-core/commands/loadenv.c @@ -35,45 +35,48 @@ static const struct grub_arg_option options[] = /* TRANSLATORS: This option is used to override default filename for loading and storing environment. */ {"file", 'f', 0, N_("Specify filename."), 0, ARG_TYPE_PATHNAME}, + {"skip-sig", 's', 0, + N_("Skip signature-checking of the environment file."), 0, ARG_TYPE_NONE}, {0, 0, 0, 0, 0, 0} }; +/* Opens 'filename' with compression filters disabled. Optionally disables the + PUBKEY filter (that insists upon properly signed files) as well. PUBKEY + filter is restored before the function returns. */ static grub_file_t -open_envblk_file (char *filename) +open_envblk_file (char *filename, + enum grub_file_type type) { grub_file_t file; + char *buf = 0; if (! filename) { const char *prefix; + int len; prefix = grub_env_get ("prefix"); - if (prefix) - { - int len; - - len = grub_strlen (prefix); - filename = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG)); - if (! filename) - return 0; - - grub_strcpy (filename, prefix); - filename[len] = '/'; - grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG); - grub_file_filter_disable_compression (); - file = grub_file_open (filename); - grub_free (filename); - return file; - } - else + if (! prefix) { grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); return 0; } + + len = grub_strlen (prefix); + buf = grub_malloc (len + 1 + sizeof (GRUB_ENVBLK_DEFCFG)); + if (! buf) + return 0; + filename = buf; + + grub_strcpy (filename, prefix); + filename[len] = '/'; + grub_strcpy (filename + len + 1, GRUB_ENVBLK_DEFCFG); } - grub_file_filter_disable_compression (); - return grub_file_open (filename); + file = grub_file_open (filename, type); + + grub_free (buf); + return file; } static grub_envblk_t @@ -114,23 +117,59 @@ read_envblk_file (grub_file_t file) return envblk; } +struct grub_env_whitelist +{ + grub_size_t len; + char **list; +}; +typedef struct grub_env_whitelist grub_env_whitelist_t; + +static int +test_whitelist_membership (const char* name, + const grub_env_whitelist_t* whitelist) +{ + grub_size_t i; + + for (i = 0; i < whitelist->len; i++) + if (grub_strcmp (name, whitelist->list[i]) == 0) + return 1; /* found it */ + + return 0; /* not found */ +} + +/* Helper for grub_cmd_load_env. */ +static int +set_var (const char *name, const char *value, void *whitelist) +{ + if (! whitelist) + { + grub_env_set (name, value); + return 0; + } + + if (test_whitelist_membership (name, + (const grub_env_whitelist_t *) whitelist)) + grub_env_set (name, value); + + return 0; +} + static grub_err_t -grub_cmd_load_env (grub_extcmd_context_t ctxt, - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) +grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; + grub_env_whitelist_t whitelist; - auto int set_var (const char *name, const char *value); - int set_var (const char *name, const char *value) - { - grub_env_set (name, value); - return 0; - } + whitelist.len = argc; + whitelist.list = args; - file = open_envblk_file ((state[0].set) ? state[0].arg : 0); + /* state[0] is the -f flag; state[1] is the --skip-sig flag */ + file = open_envblk_file ((state[0].set) ? state[0].arg : 0, + GRUB_FILE_TYPE_LOADENV + | (state[1].set + ? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE)); if (! file) return grub_errno; @@ -138,7 +177,8 @@ grub_cmd_load_env (grub_extcmd_context_t ctxt, if (! envblk) goto fail; - grub_envblk_iterate (envblk, set_var); + /* argc > 0 indicates caller provided a whitelist of variables to read. */ + grub_envblk_iterate (envblk, argc > 0 ? &whitelist : 0, set_var); grub_envblk_close (envblk); fail: @@ -146,6 +186,15 @@ grub_cmd_load_env (grub_extcmd_context_t ctxt, return grub_errno; } +/* Print all variables in current context. */ +static int +print_var (const char *name, const char *value, + void *hook_data __attribute__ ((unused))) +{ + grub_printf ("%s=%s\n", name, value); + return 0; +} + static grub_err_t grub_cmd_list_env (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), @@ -155,15 +204,10 @@ grub_cmd_list_env (grub_extcmd_context_t ctxt, grub_file_t file; grub_envblk_t envblk; - /* Print all variables in current context. */ - auto int print_var (const char *name, const char *value); - int print_var (const char *name, const char *value) - { - grub_printf ("%s=%s\n", name, value); - return 0; - } - - file = open_envblk_file ((state[0].set) ? state[0].arg : 0); + file = open_envblk_file ((state[0].set) ? state[0].arg : 0, + GRUB_FILE_TYPE_LOADENV + | (state[1].set + ? GRUB_FILE_TYPE_SKIP_SIGNATURE : GRUB_FILE_TYPE_NONE)); if (! file) return grub_errno; @@ -171,7 +215,7 @@ grub_cmd_list_env (grub_extcmd_context_t ctxt, if (! envblk) goto fail; - grub_envblk_iterate (envblk, print_var); + grub_envblk_iterate (envblk, NULL, print_var); grub_envblk_close (envblk); fail: @@ -216,10 +260,19 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, for (p = blocklists; p; p = p->next) { struct blocklist *q; + /* Check if any pair of blocks overlap. */ for (q = p->next; q; q = q->next) { - /* Check if any pair of blocks overlap. */ - if (p->sector == q->sector) + grub_disk_addr_t s1, s2; + grub_disk_addr_t e1, e2; + + s1 = p->sector; + e1 = s1 + ((p->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); + + s2 = q->sector; + e2 = s2 + ((q->length + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); + + if (s1 < e2 && s2 < e1) { /* This might be actually valid, but it is unbelievable that any filesystem makes such a silly allocation. */ @@ -243,9 +296,18 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, part_start = grub_partition_get_start (disk->partition); buf = grub_envblk_buffer (envblk); + char *blockbuf = NULL; + grub_size_t blockbuf_len = 0; for (p = blocklists, index = 0; p; index += p->length, p = p->next) { - char blockbuf[GRUB_DISK_SECTOR_SIZE]; + if (p->length > blockbuf_len) + { + grub_free (blockbuf); + blockbuf_len = 2 * p->length; + blockbuf = grub_malloc (blockbuf_len); + if (!blockbuf) + return grub_errno; + } if (grub_disk_read (disk, p->sector - part_start, p->offset, p->length, blockbuf)) @@ -283,49 +345,56 @@ write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, return 1; } +/* Context for grub_cmd_save_env. */ +struct grub_cmd_save_env_ctx +{ + struct blocklist *head, *tail; +}; + +/* Store blocklists in a linked list. */ +static grub_err_t +save_env_read_hook (grub_disk_addr_t sector, unsigned offset, unsigned length, + char *buf __attribute__ ((unused)), void *data) +{ + struct grub_cmd_save_env_ctx *ctx = data; + struct blocklist *block; + + block = grub_malloc (sizeof (*block)); + if (! block) + return GRUB_ERR_NONE; + + block->sector = sector; + block->offset = offset; + block->length = length; + + /* Slightly complicated, because the list should be FIFO. */ + block->next = 0; + if (ctx->tail) + ctx->tail->next = block; + ctx->tail = block; + if (! ctx->head) + ctx->head = block; + + return GRUB_ERR_NONE; +} + static grub_err_t grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; - struct blocklist *head = 0; - struct blocklist *tail = 0; - - /* Store blocklists in a linked list. */ - auto void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector, - unsigned offset, - unsigned length); - void NESTED_FUNC_ATTR read_hook (grub_disk_addr_t sector, - unsigned offset, unsigned length) - { - struct blocklist *block; - - if (offset + length > GRUB_DISK_SECTOR_SIZE) - /* Seemingly a bug. */ - return; - - block = grub_malloc (sizeof (*block)); - if (! block) - return; - - block->sector = sector; - block->offset = offset; - block->length = length; - - /* Slightly complicated, because the list should be FIFO. */ - block->next = 0; - if (tail) - tail->next = block; - tail = block; - if (! head) - head = block; - } + struct grub_cmd_save_env_ctx ctx = { + .head = 0, + .tail = 0 + }; if (! argc) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no variable is specified"); - file = open_envblk_file ((state[0].set) ? state[0].arg : 0); + file = open_envblk_file ((state[0].set) ? state[0].arg : 0, + GRUB_FILE_TYPE_SAVEENV + | GRUB_FILE_TYPE_SKIP_SIGNATURE); if (! file) return grub_errno; @@ -335,13 +404,14 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args) return grub_error (GRUB_ERR_BAD_DEVICE, "disk device required"); } - file->read_hook = read_hook; + file->read_hook = save_env_read_hook; + file->read_hook_data = &ctx; envblk = read_envblk_file (file); file->read_hook = 0; if (! envblk) goto fail; - if (check_blocklists (envblk, head, file)) + if (check_blocklists (envblk, ctx.head, file)) goto fail; while (argc) @@ -357,17 +427,19 @@ grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args) goto fail; } } + else + grub_envblk_delete (envblk, args[0]); argc--; args++; } - write_blocklists (envblk, head, file); + write_blocklists (envblk, ctx.head, file); fail: if (envblk) grub_envblk_close (envblk); - free_blocklists (head); + free_blocklists (ctx.head); grub_file_close (file); return grub_errno; } @@ -377,7 +449,8 @@ static grub_extcmd_t cmd_load, cmd_list, cmd_save; GRUB_MOD_INIT(loadenv) { cmd_load = - grub_register_extcmd ("load_env", grub_cmd_load_env, 0, N_("[-f FILE]"), + grub_register_extcmd ("load_env", grub_cmd_load_env, 0, + N_("[-f FILE] [-s|--skip-sig] [variable_name_to_whitelist] [...]"), N_("Load variables from environment block file."), options); cmd_list = diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 913bb6546..c3bcb089a 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -43,23 +43,24 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'}; +/* Helper for grub_ls_list_devices. */ +static int +grub_ls_print_devices (const char *name, void *data) +{ + int *longlist = data; + + if (*longlist) + grub_normal_print_device_info (name); + else + grub_printf ("(%s) ", name); + + return 0; +} static grub_err_t grub_ls_list_devices (int longlist) { - auto int grub_ls_print_devices (const char *name); - int grub_ls_print_devices (const char *name) - { - if (longlist) - grub_normal_print_device_info (name); - else - grub_printf ("(%s) ", name); - - return 0; - } - - grub_device_iterate (grub_ls_print_devices); + grub_device_iterate (grub_ls_print_devices, &longlist); grub_xputs ("\n"); #if 0 @@ -69,7 +70,7 @@ grub_ls_list_devices (int longlist) FOR_NET_APP_LEVEL (proto) { if (first) - grub_puts_ (N_ ("Network protocols:")); + grub_puts_ (N_("Network protocols:")); first = 0; grub_printf ("%s ", proto->name); } @@ -82,115 +83,116 @@ grub_ls_list_devices (int longlist) return 0; } +/* Context for grub_ls_list_files. */ +struct grub_ls_list_files_ctx +{ + char *dirname; + char *filename; + int all; + int human; + int longlist; + int print_dirhdr; +}; + +/* Helper for grub_ls_list_files. */ +static int +print_file (const char *filename, const struct grub_dirhook_info *info, + void *data) +{ + char *pathname = NULL; + struct grub_ls_list_files_ctx *ctx = data; + + if ((! ctx->all) && (filename[0] == '.')) + return 0; + + if ((ctx->filename != NULL) && (grub_strcmp (filename, ctx->filename) != 0)) + return 0; + + if (ctx->print_dirhdr) + { + grub_printf ("%s:\n", ctx->dirname); + ctx->print_dirhdr = 0; + } + + if (! ctx->longlist) + { + if (ctx->filename != NULL) + grub_xputs (ctx->dirname); + grub_printf ("%s%s ", filename, info->dir ? "/" : ""); + return 0; + } + + if (! info->dir) + { + grub_file_t file; + + if (ctx->dirname[grub_strlen (ctx->dirname) - 1] == '/') + pathname = grub_xasprintf ("%s%s", ctx->dirname, filename); + else + pathname = grub_xasprintf ("%s/%s", ctx->dirname, filename); + + if (!pathname) + return 1; + + /* XXX: For ext2fs symlinks are detected as files while they + should be reported as directories. */ + file = grub_file_open (pathname, GRUB_FILE_TYPE_GET_SIZE + | GRUB_FILE_TYPE_NO_DECOMPRESS); + if (file) + { + if (! ctx->human) + grub_printf ("%-12llu", (unsigned long long) file->size); + else + grub_printf ("%-12s", grub_get_human_size (file->size, + GRUB_HUMAN_SIZE_SHORT)); + grub_file_close (file); + } + else + grub_xputs ("????????????"); + + grub_errno = GRUB_ERR_NONE; + } + else + grub_printf ("%-12s", _("DIR")); + + if (info->mtimeset) + { + struct grub_datetime datetime; + grub_unixtime2datetime (info->mtime, &datetime); + if (ctx->human) + grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ", + datetime.year, datetime.month, datetime.day, + datetime.hour, datetime.minute, + datetime.second, + grub_get_weekday_name (&datetime)); + else + grub_printf (" %04d%02d%02d%02d%02d%02d ", + datetime.year, datetime.month, + datetime.day, datetime.hour, + datetime.minute, datetime.second); + } + /* + * Only print the full path when listing a file path given as an argument + * to ls, i.e. when ctx->filename != NULL. File listings that are printed + * due to showing the contents of a directory do not need a full path because + * the full path to the directory will have already been printed. + */ + grub_printf ("%s%s\n", (ctx->filename != NULL) ? pathname : filename, + info->dir ? "/" : ""); + + grub_free (pathname); + + return 0; +} + static grub_err_t -grub_ls_list_files (char *dirname, int longlist, int all, int human) +grub_ls_list_files (char *dirname, int longlist, int all, int human, int dirhdr) { char *device_name; grub_fs_t fs; const char *path; grub_device_t dev; - auto int print_files (const char *filename, - const struct grub_dirhook_info *info); - auto int print_files_long (const char *filename, - const struct grub_dirhook_info *info); - - int print_files (const char *filename, const struct grub_dirhook_info *info) - { - if (all || filename[0] != '.') - grub_printf ("%s%s ", filename, info->dir ? "/" : ""); - - return 0; - } - - int print_files_long (const char *filename, - const struct grub_dirhook_info *info) - { - if ((! all) && (filename[0] == '.')) - return 0; - - if (! info->dir) - { - grub_file_t file; - char *pathname; - - if (dirname[grub_strlen (dirname) - 1] == '/') - pathname = grub_xasprintf ("%s%s", dirname, filename); - else - pathname = grub_xasprintf ("%s/%s", dirname, filename); - - if (!pathname) - return 1; - - /* XXX: For ext2fs symlinks are detected as files while they - should be reported as directories. */ - grub_file_filter_disable_compression (); - file = grub_file_open (pathname); - if (! file) - { - grub_errno = 0; - grub_free (pathname); - return 0; - } - - if (! human) - grub_printf ("%-12llu", (unsigned long long) file->size); - else - { - grub_uint64_t fsize = file->size * 100ULL; - grub_uint64_t fsz = file->size; - int units = 0; - char buf[20]; - - while (fsz / 1024) - { - fsize = (fsize + 512) / 1024; - fsz /= 1024; - units++; - } - - if (units) - { - grub_uint64_t whole, fraction; - - whole = grub_divmod64 (fsize, 100, &fraction); - grub_snprintf (buf, sizeof (buf), - "%" PRIuGRUB_UINT64_T - ".%02" PRIuGRUB_UINT64_T "%c", whole, fraction, - grub_human_sizes[units]); - grub_printf ("%-12s", buf); - } - else - grub_printf ("%-12llu", (unsigned long long) file->size); - - } - grub_file_close (file); - grub_free (pathname); - } - else - grub_printf ("%-12s", _("DIR")); - - if (info->mtimeset) - { - struct grub_datetime datetime; - grub_unixtime2datetime (info->mtime, &datetime); - if (human) - grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ", - datetime.year, datetime.month, datetime.day, - datetime.hour, datetime.minute, - datetime.second, - grub_get_weekday_name (&datetime)); - else - grub_printf (" %04d%02d%02d%02d%02d%02d ", - datetime.year, datetime.month, - datetime.day, datetime.hour, - datetime.minute, datetime.second); - } - grub_printf ("%s%s\n", filename, info->dir ? "/" : ""); - - return 0; - } - device_name = grub_file_get_device_name (dirname); dev = grub_device_open (device_name); if (! dev) @@ -209,49 +211,58 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) goto fail; } - if (! *path) + if (! *path && device_name) { if (grub_errno == GRUB_ERR_UNKNOWN_FS) grub_errno = GRUB_ERR_NONE; +#ifdef GRUB_MACHINE_IEEE1275 + /* + * Close device to prevent a double open in grub_normal_print_device_info(). + * Otherwise it may lead to hangs on some IEEE 1275 platforms. + */ + grub_device_close (dev); + dev = NULL; +#endif + grub_normal_print_device_info (device_name); } else if (fs) { - if (longlist) - (fs->dir) (dev, path, print_files_long); - else - (fs->dir) (dev, path, print_files); + struct grub_ls_list_files_ctx ctx = { + .dirname = dirname, + .filename = NULL, + .all = all, + .human = human, + .longlist = longlist, + .print_dirhdr = dirhdr + }; + + (fs->fs_dir) (dev, path, print_file, &ctx); if (grub_errno == GRUB_ERR_BAD_FILE_TYPE && path[grub_strlen (path) - 1] != '/') { + /* + * Reset errno as it is currently set, but will cause subsequent code + * to think there is an error. + */ + grub_errno = GRUB_ERR_NONE; + /* PATH might be a regular file. */ - char *p; - grub_file_t file; - struct grub_dirhook_info info; - grub_errno = 0; + ctx.print_dirhdr = 0; + ctx.filename = grub_strrchr (dirname, '/'); + if (ctx.filename == NULL) + goto fail; + ++(ctx.filename); - grub_file_filter_disable_compression (); - file = grub_file_open (dirname); - if (! file) + ctx.dirname = grub_strndup (dirname, ctx.filename - dirname); + if (ctx.dirname == NULL) goto fail; - grub_file_close (file); + (fs->fs_dir) (dev, ctx.dirname + (path - dirname), print_file, &ctx); - p = grub_strrchr (dirname, '/') + 1; - dirname = grub_strndup (dirname, p - dirname); - if (! dirname) - goto fail; - - all = 1; - grub_memset (&info, 0, sizeof (info)); - if (longlist) - print_files_long (p, &info); - else - print_files (p, &info); - - grub_free (dirname); + grub_free (ctx.dirname); } if (grub_errno == GRUB_ERR_NONE) @@ -266,7 +277,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) grub_free (device_name); - return 0; + return GRUB_ERR_NONE; } static grub_err_t @@ -279,10 +290,10 @@ grub_cmd_ls (grub_extcmd_context_t ctxt, int argc, char **args) grub_ls_list_devices (state[0].set); else for (i = 0; i < argc; i++) - grub_ls_list_files (args[i], state[0].set, state[2].set, - state[1].set); + grub_ls_list_files (args[i], state[0].set, state[2].set, state[1].set, + argc > 1); - return 0; + return GRUB_ERR_NONE; } static grub_extcmd_t cmd; diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c index 07c3f0d55..f7a1a1b05 100644 --- a/grub-core/commands/lsacpi.c +++ b/grub-core/commands/lsacpi.c @@ -35,7 +35,7 @@ print_strn (grub_uint8_t *str, grub_size_t len) for (; *str && len; str++, len--) grub_printf ("%c", *str); for (len++; len; len--) - grub_printf (" "); + grub_printf (" "); } #define print_field(x) print_strn(x, sizeof (x)) @@ -44,7 +44,8 @@ static void disp_acpi_table (struct grub_acpi_table_header *t) { print_field (t->signature); - grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u OEM=", t->length, t->revision); + grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u chksum=0x%02x (%s) OEM=", t->length, t->revision, t->checksum, + grub_byte_checksum (t, t->length) == 0 ? "valid" : "invalid"); print_field (t->oemid); print_field (t->oemtable); grub_printf ("OEMrev=%08" PRIxGRUB_UINT32_T " ", t->oemrev); @@ -66,39 +67,87 @@ disp_madt_table (struct grub_acpi_madt *t) d = t->entries; for (;len > 0; len -= d->len, d = (void *) ((grub_uint8_t *) d + d->len)) { - grub_printf (" type=%x l=%u ", d->type, d->len); - switch (d->type) { + case GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC: + { + struct grub_acpi_madt_entry_lapic *dt = (void *) d; + grub_printf (" LAPIC ACPI_ID=%02x APIC_ID=%02x Flags=%08x\n", + dt->acpiid, dt->apicid, dt->flags); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + break; + } + + case GRUB_ACPI_MADT_ENTRY_TYPE_IOAPIC: + { + struct grub_acpi_madt_entry_ioapic *dt = (void *) d; + grub_printf (" IOAPIC ID=%02x address=%08x GSI=%08x\n", + dt->id, dt->address, dt->global_sys_interrupt); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + if (dt->pad) + grub_printf (" non-zero pad: %02x\n", dt->pad); + break; + } + case GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE: { struct grub_acpi_madt_entry_interrupt_override *dt = (void *) d; - grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x\n", + grub_printf (" Int Override bus=%x src=%x GSI=%08x Flags=%04x\n", dt->bus, dt->source, dt->global_sys_interrupt, dt->flags); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); } break; + + case GRUB_ACPI_MADT_ENTRY_TYPE_LAPIC_NMI: + { + struct grub_acpi_madt_entry_lapic_nmi *dt = (void *) d; + grub_printf (" LAPIC_NMI ACPI_ID=%02x Flags=%04x lint=%02x\n", + dt->acpiid, dt->flags, dt->lint); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + break; + } + case GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC: { struct grub_acpi_madt_entry_sapic *dt = (void *) d; - grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T + grub_printf (" IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T "\n", dt->id, dt->global_sys_interrupt_base, dt->addr); + if (dt->hdr.len != sizeof (*dt)) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + if (dt->pad) + grub_printf (" non-zero pad: %02x\n", dt->pad); + } break; case GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC: { struct grub_acpi_madt_entry_lsapic *dt = (void *) d; - grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x", + grub_printf (" LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x", dt->cpu_id, dt->id, dt->eid, dt->flags); if (dt->flags & GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED) grub_printf (" Enabled\n"); else grub_printf (" Disabled\n"); if (d->len > sizeof (struct grub_acpi_madt_entry_sapic)) - grub_printf (" UID val=%08x, Str=%s\n", dt->cpu_uid, + grub_printf (" UID val=%08x, Str=%s\n", dt->cpu_uid, dt->cpu_uid_str); + if (dt->hdr.len != sizeof (*dt) + grub_strlen ((char *) dt->cpu_uid_str) + 1) + grub_printf (" table size mismatch %d != %d\n", dt->hdr.len, + (int) sizeof (*dt)); + if (dt->pad[0] || dt->pad[1] || dt->pad[2]) + grub_printf (" non-zero pad: %02x%02x%02x\n", dt->pad[0], dt->pad[1], dt->pad[2]); } break; case GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE: @@ -107,17 +156,18 @@ disp_madt_table (struct grub_acpi_madt *t) static const char * const platint_type[] = {"Nul", "PMI", "INIT", "CPEI"}; - grub_printf ("Platform INT flags=%04x type=%02x (%s)" + grub_printf (" Platform INT flags=%04x type=%02x (%s)" " ID=%02x EID=%02x\n", dt->flags, dt->inttype, (dt->inttype < ARRAY_SIZE (platint_type)) ? platint_type[dt->inttype] : "??", dt->cpu_id, dt->cpu_eid); - grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n", + grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n", dt->sapic_vector, dt->global_sys_int, dt->src_flags); } break; default: + grub_printf (" type=%x l=%u ", d->type, d->len); grub_printf (" ??\n"); } } @@ -182,7 +232,7 @@ static void disp_acpi_rsdpv1 (struct grub_acpi_rsdp_v10 *rsdp) { print_field (rsdp->signature); - grub_printf ("chksum:%02x, OEM-ID: ", rsdp->checksum); + grub_printf ("chksum:%02x (%s), OEM-ID: ", rsdp->checksum, grub_byte_checksum (rsdp, sizeof (*rsdp)) == 0 ? "valid" : "invalid"); print_field (rsdp->oemid); grub_printf ("rev=%d\n", rsdp->revision); grub_printf ("RSDT=%08" PRIxGRUB_UINT32_T "\n", rsdp->rsdt_addr); @@ -192,8 +242,13 @@ static void disp_acpi_rsdpv2 (struct grub_acpi_rsdp_v20 *rsdp) { disp_acpi_rsdpv1 (&rsdp->rsdpv1); - grub_printf ("len=%d XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length, + grub_printf ("len=%d chksum=%02x (%s) XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length, rsdp->checksum, grub_byte_checksum (rsdp, rsdp->length) == 0 ? "valid" : "invalid", rsdp->xsdt_addr); + if (rsdp->length != sizeof (*rsdp)) + grub_printf (" length mismatch %d != %d\n", rsdp->length, + (int) sizeof (*rsdp)); + if (rsdp->reserved[0] || rsdp->reserved[1] || rsdp->reserved[2]) + grub_printf (" non-zero reserved %02x%02x%02x\n", rsdp->reserved[0], rsdp->reserved[1], rsdp->reserved[2]); } static const struct grub_arg_option options[] = { diff --git a/grub-core/commands/lsmmap.c b/grub-core/commands/lsmmap.c index bd32c338e..816ee47d1 100644 --- a/grub-core/commands/lsmmap.c +++ b/grub-core/commands/lsmmap.c @@ -21,9 +21,11 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); +#ifndef GRUB_MACHINE_EMU static const char *names[] = { [GRUB_MEMORY_AVAILABLE] = N_("available RAM"), @@ -35,30 +37,35 @@ static const char *names[] = is required to save accross hibernations. */ [GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage RAM"), [GRUB_MEMORY_BADRAM] = N_("faulty RAM (BadRAM)"), - [GRUB_MEMORY_CODE] = N_("RAM holding firmware code"), - [GRUB_MEMORY_HOLE] = N_("Address range not associated with RAM") + [GRUB_MEMORY_PERSISTENT] = N_("persistent RAM"), + [GRUB_MEMORY_PERSISTENT_LEGACY] = N_("persistent RAM (legacy)"), + [GRUB_MEMORY_COREBOOT_TABLES] = N_("RAM holding coreboot tables"), + [GRUB_MEMORY_CODE] = N_("RAM holding firmware code") }; +/* Helper for grub_cmd_lsmmap. */ +static int +lsmmap_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + void *data __attribute__ ((unused))) +{ + if (type < (int) ARRAY_SIZE (names) && type >= 0 && names[type]) + grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, %s\n"), + (long long) addr, (long long) size, _(names[type])); + else + grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n"), + (long long) addr, (long long) size, type); + return 0; +} +#endif + static grub_err_t grub_cmd_lsmmap (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_memory_type_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_memory_type_t type) - { - if (type < ARRAY_SIZE (names) && names[type]) - grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, %s\n"), - (long long) addr, (long long) size, _(names[type])); - else - grub_printf_ (N_("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n"), - (long long) addr, (long long) size, type); - return 0; - } #ifndef GRUB_MACHINE_EMU - grub_machine_mmap_iterate (hook); + grub_machine_mmap_iterate (lsmmap_hook, NULL); #endif return 0; diff --git a/grub-core/commands/lspci.c b/grub-core/commands/lspci.c index 9f836298f..b3cdab1b3 100644 --- a/grub-core/commands/lspci.c +++ b/grub-core/commands/lspci.c @@ -22,6 +22,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -126,8 +127,9 @@ static const struct grub_arg_option options[] = static int iospace; -static int NESTED_FUNC_ATTR -grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) +static int +grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_uint32_t class; const char *sclass; @@ -169,7 +171,7 @@ grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) if (space == 0) continue; - + switch (space & GRUB_PCI_ADDR_SPACE_MASK) { case GRUB_PCI_ADDR_SPACE_IO: @@ -193,13 +195,13 @@ grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) (space & GRUB_PCI_ADDR_MEM_MASK), space & GRUB_PCI_ADDR_MEM_PREFETCH ? "prefetchable" : "non-prefetchable"); - + } else grub_printf ("\t32-bit memory space %d at 0x%016llx [%s]\n", (unsigned) ((reg - GRUB_PCI_REG_ADDRESSES) / sizeof (grub_uint32_t)) - 1, - (unsigned long long) + (unsigned long long) (space & GRUB_PCI_ADDR_MEM_MASK), space & GRUB_PCI_ADDR_MEM_PREFETCH ? "prefetchable" : "non-prefetchable"); @@ -218,7 +220,7 @@ grub_cmd_lspci (grub_extcmd_context_t ctxt, char **args __attribute__ ((unused))) { iospace = ctxt->state[0].set; - grub_pci_iterate (grub_lspci_iter); + grub_pci_iterate (grub_lspci_iter, NULL); return GRUB_ERR_NONE; } diff --git a/grub-core/commands/macbless.c b/grub-core/commands/macbless.c new file mode 100644 index 000000000..3d761452a --- /dev/null +++ b/grub-core/commands/macbless.c @@ -0,0 +1,233 @@ +/* hfspbless.c - set the hfs+ boot directory. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2005,2007,2008,2009,2012,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct find_node_context +{ + grub_uint64_t inode_found; + char *dirname; + enum + { FOUND_NONE, FOUND_FILE, FOUND_DIR } found; +}; + +static int +find_inode (const char *filename, + const struct grub_dirhook_info *info, void *data) +{ + struct find_node_context *ctx = data; + if (!info->inodeset) + return 0; + + if ((grub_strcmp (ctx->dirname, filename) == 0 + || (info->case_insensitive + && grub_strcasecmp (ctx->dirname, filename) == 0))) + { + ctx->inode_found = info->inode; + ctx->found = info->dir ? FOUND_DIR : FOUND_FILE; + } + return 0; +} + +grub_err_t +grub_mac_bless_inode (grub_device_t dev, grub_uint32_t inode, int is_dir, + int intel) +{ + grub_err_t err; + union + { + struct grub_hfs_sblock hfs; + struct grub_hfsplus_volheader hfsplus; + } volheader; + grub_disk_addr_t embedded_offset; + + if (intel && is_dir) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "can't bless a directory for mactel"); + if (!intel && !is_dir) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "can't bless a file for mac PPC"); + + /* Read the bootblock. */ + err = grub_disk_read (dev->disk, GRUB_HFSPLUS_SBLOCK, 0, sizeof (volheader), + (char *) &volheader); + if (err) + return err; + + embedded_offset = 0; + if (grub_be_to_cpu16 (volheader.hfs.magic) == GRUB_HFS_MAGIC) + { + int extent_start; + int ablk_size; + int ablk_start; + + /* See if there's an embedded HFS+ filesystem. */ + if (grub_be_to_cpu16 (volheader.hfs.embed_sig) != GRUB_HFSPLUS_MAGIC) + { + if (intel) + volheader.hfs.intel_bootfile = grub_be_to_cpu32 (inode); + else + volheader.hfs.ppc_bootdir = grub_be_to_cpu32 (inode); + return GRUB_ERR_NONE; + } + + /* Calculate the offset needed to translate HFS+ sector numbers. */ + extent_start = + grub_be_to_cpu16 (volheader.hfs.embed_extent.first_block); + ablk_size = grub_be_to_cpu32 (volheader.hfs.blksz); + ablk_start = grub_be_to_cpu16 (volheader.hfs.first_block); + embedded_offset = (ablk_start + + ((grub_uint64_t) extent_start) + * (ablk_size >> GRUB_DISK_SECTOR_BITS)); + + err = + grub_disk_read (dev->disk, embedded_offset + GRUB_HFSPLUS_SBLOCK, 0, + sizeof (volheader), (char *) &volheader); + if (err) + return err; + } + + if ((grub_be_to_cpu16 (volheader.hfsplus.magic) != GRUB_HFSPLUS_MAGIC) + && (grub_be_to_cpu16 (volheader.hfsplus.magic) != GRUB_HFSPLUSX_MAGIC)) + return grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem"); + if (intel) + volheader.hfsplus.intel_bootfile = grub_be_to_cpu32 (inode); + else + volheader.hfsplus.ppc_bootdir = grub_be_to_cpu32 (inode); + + return grub_disk_write (dev->disk, embedded_offset + GRUB_HFSPLUS_SBLOCK, 0, + sizeof (volheader), (char *) &volheader); +} + +grub_err_t +grub_mac_bless_file (grub_device_t dev, const char *path_in, int intel) +{ + grub_fs_t fs; + + char *path, *tail; + struct find_node_context ctx; + + fs = grub_fs_probe (dev); + if (!fs || (grub_strcmp (fs->name, "hfsplus") != 0 + && grub_strcmp (fs->name, "hfs") != 0)) + return grub_error (GRUB_ERR_BAD_FS, "no suitable FS found"); + + path = grub_strdup (path_in); + if (!path) + return grub_errno; + + tail = path + grub_strlen (path) - 1; + + /* Remove trailing '/'. */ + while (tail != path && *tail == '/') + *(tail--) = 0; + + tail = grub_strrchr (path, '/'); + ctx.found = 0; + + if (tail) + { + *tail = 0; + ctx.dirname = tail + 1; + + (fs->fs_dir) (dev, *path == 0 ? "/" : path, find_inode, &ctx); + } + else + { + ctx.dirname = path + 1; + (fs->fs_dir) (dev, "/", find_inode, &ctx); + } + if (!ctx.found) + { + grub_free (path); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), + path_in); + } + grub_free (path); + + return grub_mac_bless_inode (dev, (grub_uint32_t) ctx.inode_found, + (ctx.found == FOUND_DIR), intel); +} + +static grub_err_t +grub_cmd_macbless (grub_command_t cmd, int argc, char **args) +{ + char *device_name; + char *path = 0; + grub_device_t dev = 0; + grub_err_t err; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + device_name = grub_file_get_device_name (args[0]); + dev = grub_device_open (device_name); + + path = grub_strchr (args[0], ')'); + if (!path) + path = args[0]; + else + path = path + 1; + + if (!path || *path == 0 || !dev) + { + if (dev) + grub_device_close (dev); + + grub_free (device_name); + + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument"); + } + + err = grub_mac_bless_file (dev, path, cmd->name[3] == 't'); + + grub_device_close (dev); + grub_free (device_name); + return err; +} + +static grub_command_t cmd, cmd_ppc; + +GRUB_MOD_INIT(macbless) +{ + cmd = grub_register_command ("mactelbless", grub_cmd_macbless, + N_("FILE"), + N_("Bless FILE of HFS or HFS+ partition for intel macs.")); + cmd_ppc = + grub_register_command ("macppcbless", grub_cmd_macbless, N_("DIR"), + N_("Bless DIR of HFS or HFS+ partition for PPC macs.")); +} + +GRUB_MOD_FINI(macbless) +{ + grub_unregister_command (cmd); + grub_unregister_command (cmd_ppc); +} diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c index 98769eadb..3542683d1 100644 --- a/grub-core/commands/memrw.c +++ b/grub-core/commands/memrw.c @@ -22,6 +22,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -121,29 +122,32 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv) GRUB_MOD_INIT(memrw) { cmd_read_byte = - grub_register_extcmd ("read_byte", grub_cmd_read, 0, - N_("ADDR"), N_("Read 8-bit value from ADDR."), - options); + grub_register_extcmd_lockdown ("read_byte", grub_cmd_read, 0, + N_("ADDR"), + N_("Read 8-bit value from ADDR."), + options); cmd_read_word = - grub_register_extcmd ("read_word", grub_cmd_read, 0, - N_("ADDR"), N_("Read 16-bit value from ADDR."), - options); + grub_register_extcmd_lockdown ("read_word", grub_cmd_read, 0, + N_("ADDR"), + N_("Read 16-bit value from ADDR."), + options); cmd_read_dword = - grub_register_extcmd ("read_dword", grub_cmd_read, 0, - N_("ADDR"), N_("Read 32-bit value from ADDR."), - options); + grub_register_extcmd_lockdown ("read_dword", grub_cmd_read, 0, + N_("ADDR"), + N_("Read 32-bit value from ADDR."), + options); cmd_write_byte = - grub_register_command ("write_byte", grub_cmd_write, - N_("ADDR VALUE [MASK]"), - N_("Write 8-bit VALUE to ADDR.")); + grub_register_command_lockdown ("write_byte", grub_cmd_write, + N_("ADDR VALUE [MASK]"), + N_("Write 8-bit VALUE to ADDR.")); cmd_write_word = - grub_register_command ("write_word", grub_cmd_write, - N_("ADDR VALUE [MASK]"), - N_("Write 16-bit VALUE to ADDR.")); + grub_register_command_lockdown ("write_word", grub_cmd_write, + N_("ADDR VALUE [MASK]"), + N_("Write 16-bit VALUE to ADDR.")); cmd_write_dword = - grub_register_command ("write_dword", grub_cmd_write, - N_("ADDR VALUE [MASK]"), - N_("Write 32-bit VALUE to ADDR.")); + grub_register_command_lockdown ("write_dword", grub_cmd_write, + N_("ADDR VALUE [MASK]"), + N_("Write 32-bit VALUE to ADDR.")); } GRUB_MOD_FINI(memrw) diff --git a/grub-core/commands/memtools.c b/grub-core/commands/memtools.c new file mode 100644 index 000000000..ae0a9bec3 --- /dev/null +++ b/grub-core/commands/memtools.c @@ -0,0 +1,152 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Free Software Foundation, Inc. + * Copyright (C) 2022 IBM Corporation + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_cmd_lsmem (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) + +{ +#ifndef GRUB_MACHINE_EMU + grub_mm_dump (0); +#endif + + return 0; +} + +static grub_err_t +grub_cmd_lsfreemem (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) + +{ +#ifndef GRUB_MACHINE_EMU + grub_mm_dump_free (); +#endif + + return 0; +} + + +static grub_err_t +grub_cmd_stress_big_allocs (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + int i, max_mb, blocks_alloced; + void *mem; + void **blocklist; + + grub_printf ("Test 1: increasingly sized allocs to 1GB block\n"); + for (i = 1; i < 1024; i++) + { + grub_printf ("%4d MB . ", i); + mem = grub_malloc (i * 1024 * 1024); + if (mem == NULL) + { + grub_printf ("failed\n"); + break; + } + else + grub_free (mem); + + if (i % 7 == 0) + grub_printf ("\n"); + } + + max_mb = i - 1; + grub_printf ("\nMax sized allocation we did was %d MB\n", max_mb); + + grub_printf ("\nTest 2: 1MB at a time, max 4GB\n"); + blocklist = grub_calloc (4096, sizeof (void *)); + for (i = 0; i < 4096; i++) + { + blocklist[i] = grub_malloc (1024 * 1024); + if (blocklist[i] == NULL) + { + grub_printf ("Ran out of memory at iteration %d\n", i); + break; + } + } + blocks_alloced = i; + for (i = 0; i < blocks_alloced; i++) + grub_free (blocklist[i]); + + grub_printf ("\nTest 3: 1MB aligned 900kB + 100kB\n"); + /* grub_mm_debug=1;*/ + for (i = 0; i < 4096; i += 2) + { + blocklist[i] = grub_memalign (1024 * 1024, 900 * 1024); + if (blocklist[i] == NULL) + { + grub_printf ("Failed big allocation, iteration %d\n", i); + blocks_alloced = i; + break; + } + + blocklist[i + 1] = grub_malloc (100 * 1024); + if (blocklist[i + 1] == NULL) + { + grub_printf ("Failed small allocation, iteration %d\n", i); + blocks_alloced = i + 1; + break; + } + grub_printf ("."); + } + for (i = 0; i < blocks_alloced; i++) + grub_free (blocklist[i]); + + grub_free (blocklist); + +#if defined(__powerpc__) + grub_printf ("\nA reboot may now be required.\n"); +#endif + + grub_errno = GRUB_ERR_NONE; + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_lsmem, cmd_lsfreemem, cmd_sba; + +GRUB_MOD_INIT (memtools) +{ + cmd_lsmem = grub_register_command ("lsmem", grub_cmd_lsmem, + 0, N_("List free and allocated memory blocks.")); + cmd_lsfreemem = grub_register_command ("lsfreemem", grub_cmd_lsfreemem, + 0, N_("List free memory blocks.")); + cmd_sba = grub_register_command ("stress_big_allocs", grub_cmd_stress_big_allocs, + 0, N_("Stress test large allocations.")); +} + +GRUB_MOD_FINI (memtools) +{ + grub_unregister_command (cmd_lsmem); + grub_unregister_command (cmd_lsfreemem); + grub_unregister_command (cmd_sba); +} diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c index 58d4dadf6..720e6d8ea 100644 --- a/grub-core/commands/menuentry.c +++ b/grub-core/commands/menuentry.c @@ -52,8 +52,8 @@ static struct int key; } hotkey_aliases[] = { - {"backspace", '\b'}, - {"tab", '\t'}, + {"backspace", GRUB_TERM_BACKSPACE}, + {"tab", GRUB_TERM_TAB}, {"delete", GRUB_TERM_KEY_DC}, {"insert", GRUB_TERM_KEY_INSERT}, {"f1", GRUB_TERM_KEY_F1}, @@ -154,7 +154,7 @@ grub_normal_add_menu_entry (int argc, const char **args, goto fail; /* Save argc, args to pass as parameters to block arg later. */ - menu_args = grub_malloc (sizeof (char*) * (argc + 1)); + menu_args = grub_calloc (argc + 1, sizeof (char *)); if (! menu_args) goto fail; @@ -230,7 +230,7 @@ setparams_prefix (int argc, char **args) len += 3; /* 3 = 1 space + 2 quotes */ p = args[i]; while (*p) - len += (*p++ == '\'' ? 3 : 1); + len += (*p++ == '\'' ? 4 : 1); } result = grub_malloc (len + 2); diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c index 344ea7c18..ff4ff021c 100644 --- a/grub-core/commands/minicmd.c +++ b/grub-core/commands/minicmd.c @@ -29,6 +29,10 @@ #include #include +#ifdef GRUB_MACHINE_EFI +#include +#endif + GRUB_MOD_LICENSE ("GPLv3+"); /* cat FILE */ @@ -43,7 +47,7 @@ grub_mini_cmd_cat (struct grub_command *cmd __attribute__ ((unused)), if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); - file = grub_file_open (argv[0]); + file = grub_file_open (argv[0], GRUB_FILE_TYPE_CAT); if (! file) return grub_errno; @@ -101,12 +105,18 @@ grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)), if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no address specified"); - addr = (grub_uint8_t *) grub_strtoul (argv[0], 0, 0); +#if GRUB_CPU_SIZEOF_VOID_P == GRUB_CPU_SIZEOF_LONG +#define grub_strtoaddr grub_strtoul +#else +#define grub_strtoaddr grub_strtoull +#endif + + addr = (grub_uint8_t *) grub_strtoaddr (argv[0], 0, 0); if (grub_errno) return grub_errno; if (argc > 1) - size = (grub_size_t) grub_strtoul (argv[1], 0, 0); + size = (grub_size_t) grub_strtoaddr (argv[1], 0, 0); while (size--) { @@ -131,8 +141,14 @@ grub_mini_cmd_rmmod (struct grub_command *cmd __attribute__ ((unused)), if (! mod) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such module"); - if (grub_dl_unref (mod) <= 0) - grub_dl_unload (mod); + if (grub_dl_is_persistent (mod)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "cannot unload persistent module"); + + if (grub_dl_ref_count (mod) > 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "cannot unload referenced module"); + + grub_dl_unref (mod); + grub_dl_unload (mod); return 0; } @@ -155,7 +171,7 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)), { grub_dl_dep_t dep; - grub_printf ("%s\t%d\t\t", mod->name, mod->ref_count); + grub_printf ("%s\t%" PRIuGRUB_UINT64_T "\t\t", mod->name, mod->ref_count); for (dep = mod->dep; dep; dep = dep->next) { if (dep != mod->dep) @@ -175,6 +191,13 @@ grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) { +#ifdef GRUB_MACHINE_EFI + /* + * The "exit" command is often used to launch the next boot application. + * So, erase the secrets. + */ + grub_cryptodisk_erasesecrets (); +#endif grub_exit (); /* Not reached. */ } @@ -191,8 +214,8 @@ GRUB_MOD_INIT(minicmd) grub_register_command ("help", grub_mini_cmd_help, 0, N_("Show this message.")); cmd_dump = - grub_register_command ("dump", grub_mini_cmd_dump, - N_("ADDR [SIZE]"), N_("Show memory contents.")); + grub_register_command_lockdown ("dump", grub_mini_cmd_dump, + N_("ADDR [SIZE]"), N_("Show memory contents.")); cmd_rmmod = grub_register_command ("rmmod", grub_mini_cmd_rmmod, N_("MODULE"), N_("Remove a module.")); diff --git a/grub-core/commands/mips/loongson/lsspd.c b/grub-core/commands/mips/loongson/lsspd.c index a88ab87ac..97569816d 100644 --- a/grub-core/commands/mips/loongson/lsspd.c +++ b/grub-core/commands/mips/loongson/lsspd.c @@ -44,7 +44,7 @@ grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)), } grub_printf_ (N_("CS5536 at %d:%d.%d\n"), grub_pci_get_bus (dev), grub_pci_get_device (dev), grub_pci_get_function (dev)); - + err = grub_cs5536_init_smbus (dev, 0x7fff, &smbbase); if (err) return err; diff --git a/grub-core/commands/nativedisk.c b/grub-core/commands/nativedisk.c new file mode 100644 index 000000000..580c8d3b0 --- /dev/null +++ b/grub-core/commands/nativedisk.c @@ -0,0 +1,332 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static const char *modnames_def[] = { + /* FIXME: autogenerate this. */ +#if defined (__i386__) || defined (__x86_64__) || defined (GRUB_MACHINE_MIPS_LOONGSON) + "pata", "ahci", "usbms", "ohci", "uhci", "ehci" +#elif defined (GRUB_MACHINE_MIPS_QEMU_MIPS) + "pata" +#else +#error "Fill this" +#endif + }; + +static grub_err_t +get_uuid (const char *name, char **uuid, int getnative) +{ + grub_device_t dev; + grub_fs_t fs = 0; + + *uuid = 0; + + dev = grub_device_open (name); + if (!dev) + return grub_errno; + + if (!dev->disk) + { + grub_dprintf ("nativedisk", "Skipping non-disk\n"); + grub_device_close (dev); + return 0; + } + + switch (dev->disk->dev->id) + { + /* Firmware disks. */ + case GRUB_DISK_DEVICE_BIOSDISK_ID: + case GRUB_DISK_DEVICE_OFDISK_ID: + case GRUB_DISK_DEVICE_OBDISK_ID: + case GRUB_DISK_DEVICE_EFIDISK_ID: + case GRUB_DISK_DEVICE_NAND_ID: + case GRUB_DISK_DEVICE_ARCDISK_ID: + case GRUB_DISK_DEVICE_HOSTDISK_ID: + case GRUB_DISK_DEVICE_UBOOTDISK_ID: + break; + + /* Native disks. */ + case GRUB_DISK_DEVICE_ATA_ID: + case GRUB_DISK_DEVICE_SCSI_ID: + case GRUB_DISK_DEVICE_XEN: + if (getnative) + break; + /* FALLTHROUGH */ + + /* Virtual disks. */ + /* GRUB dynamically generated files. */ + case GRUB_DISK_DEVICE_PROCFS_ID: + /* To access through host OS routines (grub-emu only). */ + case GRUB_DISK_DEVICE_HOST_ID: + /* To access coreboot roms. */ + case GRUB_DISK_DEVICE_CBFSDISK_ID: + /* GRUB-only memdisk. Can't match any of firmware devices. */ + case GRUB_DISK_DEVICE_MEMDISK_ID: + grub_dprintf ("nativedisk", "Skipping native disk %s\n", + dev->disk->name); + grub_device_close (dev); + return 0; + + /* FIXME: those probably need special handling. */ + case GRUB_DISK_DEVICE_LOOPBACK_ID: + case GRUB_DISK_DEVICE_DISKFILTER_ID: + case GRUB_DISK_DEVICE_CRYPTODISK_ID: + break; + } + if (dev) + fs = grub_fs_probe (dev); + if (!fs) + { + grub_device_close (dev); + return grub_errno; + } + if (!fs->fs_uuid || fs->fs_uuid (dev, uuid) || !*uuid) + { + grub_device_close (dev); + + if (!grub_errno) + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("%s does not support UUIDs"), fs->name); + + return grub_errno; + } + grub_device_close (dev); + return GRUB_ERR_NONE; +} + +struct search_ctx +{ + char *root_uuid; + char *prefix_uuid; + const char *prefix_path; + int prefix_found, root_found; +}; + +static int +iterate_device (const char *name, void *data) +{ + struct search_ctx *ctx = data; + char *cur_uuid; + + if (get_uuid (name, &cur_uuid, 1)) + { + if (grub_errno == GRUB_ERR_UNKNOWN_FS) + grub_errno = 0; + grub_print_error (); + return 0; + } + + grub_dprintf ("nativedisk", "checking %s: %s\n", name, + cur_uuid); + if (ctx->prefix_uuid && grub_strcasecmp (cur_uuid, ctx->prefix_uuid) == 0) + { + char *prefix; + prefix = grub_xasprintf ("(%s)/%s", name, ctx->prefix_path); + grub_env_set ("prefix", prefix); + grub_free (prefix); + ctx->prefix_found = 1; + } + if (ctx->root_uuid && grub_strcasecmp (cur_uuid, ctx->root_uuid) == 0) + { + grub_env_set ("root", name); + ctx->root_found = 1; + } + return ctx->prefix_found && ctx->root_found; +} + +static grub_err_t +grub_cmd_nativedisk (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args_in) +{ + char *uuid_root = 0, *uuid_prefix, *prefdev = 0; + const char *prefix = 0; + const char *path_prefix = 0; + int mods_loaded = 0; + grub_dl_t *mods; + const char **args; + int i; + + if (argc == 0) + { + argc = ARRAY_SIZE (modnames_def); + args = modnames_def; + } + else + args = (const char **) args_in; + + prefix = grub_env_get ("prefix"); + + if (! prefix) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); + + if (prefix) + path_prefix = (prefix[0] == '(') ? grub_strchr (prefix, ')') : NULL; + if (path_prefix) + path_prefix++; + else + path_prefix = prefix; + + mods = grub_calloc (argc, sizeof (mods[0])); + if (!mods) + return grub_errno; + + if (get_uuid (NULL, &uuid_root, 0)) + { + grub_free (mods); + return grub_errno; + } + + prefdev = grub_file_get_device_name (prefix); + if (grub_errno) + { + grub_print_error (); + prefdev = 0; + } + + if (get_uuid (prefdev, &uuid_prefix, 0)) + { + grub_free (uuid_root); + grub_free (prefdev); + grub_free (mods); + return grub_errno; + } + + grub_dprintf ("nativedisk", "uuid_prefix = %s, uuid_root = %s\n", + uuid_prefix, uuid_root); + + for (mods_loaded = 0; mods_loaded < argc; mods_loaded++) + { + char *filename; + grub_dl_t mod; + grub_file_t file = NULL; + grub_ssize_t size; + void *core = 0; + + mod = grub_dl_get (args[mods_loaded]); + if (mod) + { + mods[mods_loaded] = 0; + continue; + } + + filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM "/%s.mod", + prefix, args[mods_loaded]); + if (! filename) + goto fail; + + file = grub_file_open (filename, + GRUB_FILE_TYPE_GRUB_MODULE); + grub_free (filename); + if (! file) + goto fail; + + size = grub_file_size (file); + core = grub_malloc (size); + if (! core) + { + grub_file_close (file); + goto fail; + } + + if (grub_file_read (file, core, size) != (grub_ssize_t) size) + { + grub_file_close (file); + grub_free (core); + goto fail; + } + + grub_file_close (file); + + mods[mods_loaded] = grub_dl_load_core_noinit (core, size); + if (! mods[mods_loaded]) + goto fail; + } + + for (i = 0; i < argc; i++) + if (mods[i]) + grub_dl_init (mods[i]); + + if (uuid_prefix || uuid_root) + { + struct search_ctx ctx; + grub_fs_autoload_hook_t saved_autoload; + + /* No need to autoload FS since obviously we already have the necessary fs modules. */ + saved_autoload = grub_fs_autoload_hook; + grub_fs_autoload_hook = 0; + + ctx.root_uuid = uuid_root; + ctx.prefix_uuid = uuid_prefix; + ctx.prefix_path = path_prefix; + ctx.prefix_found = !uuid_prefix; + ctx.root_found = !uuid_root; + + /* FIXME: try to guess the correct values. */ + grub_device_iterate (iterate_device, &ctx); + + grub_fs_autoload_hook = saved_autoload; + } + grub_free (uuid_root); + grub_free (uuid_prefix); + grub_free (prefdev); + grub_free (mods); + + return GRUB_ERR_NONE; + + fail: + grub_free (uuid_root); + grub_free (uuid_prefix); + grub_free (prefdev); + + for (i = 0; i < mods_loaded; i++) + if (mods[i]) + { + mods[i]->fini = 0; + grub_dl_unload (mods[i]); + } + grub_free (mods); + + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(nativedisk) +{ + cmd = grub_register_command ("nativedisk", grub_cmd_nativedisk, N_("[MODULE1 MODULE2 ...]"), + N_("Switch to native disk drivers. If no modules are specified default set (pata,ahci,usbms,ohci,uhci,ehci) is used")); +} + +GRUB_MOD_FINI(nativedisk) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c index fadf87327..ff45c65e6 100644 --- a/grub-core/commands/parttool.c +++ b/grub-core/commands/parttool.c @@ -59,7 +59,13 @@ grub_parttool_register(const char *part_name, for (nargs = 0; args[nargs].name != 0; nargs++); cur->nargs = nargs; cur->args = (struct grub_parttool_argdesc *) - grub_malloc ((nargs + 1) * sizeof (struct grub_parttool_argdesc)); + grub_calloc (nargs + 1, sizeof (struct grub_parttool_argdesc)); + if (!cur->args) + { + grub_free (cur); + curhandle--; + return -1; + } grub_memcpy (cur->args, args, (nargs + 1) * sizeof (struct grub_parttool_argdesc)); @@ -94,6 +100,50 @@ grub_parttool_unregister (int handle) grub_dl_unref (mymod); } +static grub_err_t +show_help (grub_device_t dev) +{ + int found = 0; + struct grub_parttool *cur; + + for (cur = parts; cur; cur = cur->next) + if (grub_strcmp (dev->disk->partition->partmap->name, cur->name) == 0) + { + struct grub_parttool_argdesc *curarg; + found = 1; + for (curarg = cur->args; curarg->name; curarg++) + { + int spacing = 20; + + spacing -= grub_strlen (curarg->name); + grub_printf ("%s", curarg->name); + + switch (curarg->type) + { + case GRUB_PARTTOOL_ARG_BOOL: + grub_printf ("+/-"); + spacing -= 3; + break; + + case GRUB_PARTTOOL_ARG_VAL: + grub_xputs (_("=VAL")); + spacing -= 4; + break; + + case GRUB_PARTTOOL_ARG_END: + break; + } + while (spacing-- > 0) + grub_printf (" "); + grub_puts_ (curarg->desc); + } + } + if (! found) + grub_printf_ (N_("Sorry, no parttool is available for %s\n"), + dev->disk->partition->partmap->name); + return GRUB_ERR_NONE; +} + static grub_err_t grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) @@ -104,48 +154,6 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), int i, j; grub_err_t err = GRUB_ERR_NONE; - auto grub_err_t show_help (void); - grub_err_t show_help (void) - { - int found = 0; - for (cur = parts; cur; cur = cur->next) - if (grub_strcmp (dev->disk->partition->partmap->name, cur->name) == 0) - { - struct grub_parttool_argdesc *curarg; - found = 1; - for (curarg = cur->args; curarg->name; curarg++) - { - int spacing = 20; - - spacing -= grub_strlen (curarg->name); - grub_printf ("%s", curarg->name); - - switch (curarg->type) - { - case GRUB_PARTTOOL_ARG_BOOL: - grub_printf ("+/-"); - spacing -= 3; - break; - - case GRUB_PARTTOOL_ARG_VAL: - grub_xputs (_("=VAL")); - spacing -= 4; - break; - - case GRUB_PARTTOOL_ARG_END: - break; - } - while (spacing-- > 0) - grub_printf (" "); - grub_puts_ (curarg->desc); - } - } - if (! found) - grub_printf_ (N_("Sorry no parttool is available for %s\n"), - dev->disk->partition->partmap->name); - return GRUB_ERR_NONE; - } - if (argc < 1) { grub_puts_ (helpmsg); @@ -177,7 +185,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), } /* Load modules. */ - if (! grub_no_autoload) + if (! grub_no_modules) { const char *prefix; prefix = grub_env_get ("prefix"); @@ -191,7 +199,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), { grub_file_t file; - file = grub_file_open (filename); + file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE_LIST); if (file) { char *buf = 0; @@ -241,13 +249,21 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), } if (argc == 1) - return show_help (); + { + err = show_help (dev); + grub_device_close (dev); + return err; + } for (i = 1; i < argc; i++) if (grub_strcmp (args[i], "help") == 0) - return show_help (); + { + err = show_help (dev); + grub_device_close (dev); + return err; + } - parsed = (int *) grub_zalloc (argc * sizeof (int)); + parsed = (int *) grub_calloc (argc, sizeof (int)); for (i = 1; i < argc; i++) if (! parsed[i]) @@ -272,11 +288,15 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), break; } if (! cur) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"), + { + grub_free (parsed); + grub_device_close (dev); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"), args[i]); + } ptool = cur; pargs = (struct grub_parttool_args *) - grub_zalloc (ptool->nargs * sizeof (struct grub_parttool_args)); + grub_calloc (ptool->nargs, sizeof (struct grub_parttool_args)); for (j = i; j < argc; j++) if (! parsed[j]) { @@ -295,7 +315,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), switch (curarg->type) { case GRUB_PARTTOOL_ARG_BOOL: - pargs[curarg - ptool->args].bool + pargs[curarg - ptool->args].b = (args[j][grub_strlen (curarg->name)] != '-'); break; diff --git a/grub-core/commands/password_pbkdf2.c b/grub-core/commands/password_pbkdf2.c index 0dd1aef3d..bcb902f97 100644 --- a/grub-core/commands/password_pbkdf2.c +++ b/grub-core/commands/password_pbkdf2.c @@ -45,6 +45,7 @@ check_password (const char *user, const char *entered, void *pin) grub_uint8_t *buf; struct pbkdf2_password *pass = pin; gcry_err_code_t err; + grub_err_t ret; buf = grub_malloc (pass->buflen); if (!buf) @@ -55,17 +56,17 @@ check_password (const char *user, const char *entered, void *pin) pass->salt, pass->saltlen, pass->c, buf, pass->buflen); if (err) + ret = grub_crypto_gcry_error (err); + else if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0) + ret = GRUB_ACCESS_DENIED; + else { - grub_free (buf); - return grub_crypto_gcry_error (err); + grub_auth_authenticate (user); + ret = GRUB_ERR_NONE; } - if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0) - return GRUB_ACCESS_DENIED; - - grub_auth_authenticate (user); - - return GRUB_ERR_NONE; + grub_free (buf); + return ret; } static inline int @@ -85,7 +86,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { grub_err_t err; - char *ptr, *ptr2; + const char *ptr, *ptr2; grub_uint8_t *ptro; struct pbkdf2_password *pass; @@ -104,7 +105,10 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), pass->c = grub_strtoul (ptr, &ptr, 0); if (grub_errno) - return grub_errno; + { + grub_free (pass); + return grub_errno; + } if (*ptr != '.') { grub_free (pass); @@ -158,7 +162,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), return grub_errno; } ptr = ptr2 + 1; - ptr2 += grub_strlen (ptr2); + ptr2 += grub_strlen (ptr2); while (ptr < ptr2) { int hex1, hex2; diff --git a/grub-core/commands/pcidump.c b/grub-core/commands/pcidump.c new file mode 100644 index 000000000..f72628fce --- /dev/null +++ b/grub-core/commands/pcidump.c @@ -0,0 +1,174 @@ +/* lspci.c - List PCI devices. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct iter_cxt +{ + grub_uint32_t pciid_check_mask, pciid_check_value; + int bus, device, function; + int check_bus, check_device, check_function; +}; + +static const struct grub_arg_option options[] = + { + {0, 'd', 0, N_("Select device by vendor and device IDs."), + N_("[vendor]:[device]"), ARG_TYPE_STRING}, + {0, 's', 0, N_("Select device by its position on the bus."), + N_("[bus]:[slot][.func]"), ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} + }; + +static int +grub_pcidump_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data) +{ + struct iter_cxt *ctx = data; + grub_pci_address_t addr; + int i; + + if ((pciid & ctx->pciid_check_mask) != ctx->pciid_check_value) + return 0; + + if (ctx->check_bus && grub_pci_get_bus (dev) != ctx->bus) + return 0; + + if (ctx->check_device && grub_pci_get_device (dev) != ctx->device) + return 0; + + if (ctx->check_function && grub_pci_get_function (dev) != ctx->function) + return 0; + + for (i = 0; i < 256; i += 4) + { + addr = grub_pci_make_address (dev, i); + grub_printf ("%08x ", grub_pci_read (addr)); + if ((i & 0xc) == 0xc) + grub_printf ("\n"); + } + + return 0; +} + +static grub_err_t +grub_cmd_pcidump (grub_extcmd_context_t ctxt, + int argc __attribute__ ((unused)), + char **argv __attribute__ ((unused))) +{ + const char *ptr; + struct iter_cxt ctx = + { + .pciid_check_value = 0, + .pciid_check_mask = 0, + .check_bus = 0, + .check_device = 0, + .check_function = 0, + .bus = 0, + .function = 0, + .device = 0 + }; + + if (ctxt->state[0].set) + { + ptr = ctxt->state[0].arg; + ctx.pciid_check_value |= (grub_strtoul (ptr, &ptr, 16) & 0xffff); + if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + grub_errno = GRUB_ERR_NONE; + ptr = ctxt->state[0].arg; + } + else + ctx.pciid_check_mask |= 0xffff; + if (grub_errno) + return grub_errno; + if (*ptr != ':') + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':'); + ptr++; + ctx.pciid_check_value |= (grub_strtoul (ptr, &ptr, 16) & 0xffff) << 16; + if (grub_errno == GRUB_ERR_BAD_NUMBER) + grub_errno = GRUB_ERR_NONE; + else + ctx.pciid_check_mask |= 0xffff0000; + } + + ctx.pciid_check_value &= ctx.pciid_check_mask; + + if (ctxt->state[1].set) + { + const char *optr; + + ptr = ctxt->state[1].arg; + optr = ptr; + ctx.bus = grub_strtoul (ptr, &ptr, 16); + if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + grub_errno = GRUB_ERR_NONE; + ptr = optr; + } + else + ctx.check_bus = 1; + if (grub_errno) + return grub_errno; + if (*ptr != ':') + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':'); + ptr++; + optr = ptr; + ctx.device = grub_strtoul (ptr, &ptr, 16); + if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + grub_errno = GRUB_ERR_NONE; + ptr = optr; + } + else + ctx.check_device = 1; + if (*ptr == '.') + { + ptr++; + ctx.function = grub_strtoul (ptr, &ptr, 16); + if (grub_errno) + return grub_errno; + ctx.check_function = 1; + } + } + + grub_pci_iterate (grub_pcidump_iter, &ctx); + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(pcidump) +{ + cmd = grub_register_extcmd ("pcidump", grub_cmd_pcidump, 0, + N_("[-s POSITION] [-d DEVICE]"), + N_("Show raw dump of the PCI configuration space."), options); +} + +GRUB_MOD_FINI(pcidump) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/commands/pgp.c b/grub-core/commands/pgp.c new file mode 100644 index 000000000..5fadc33c4 --- /dev/null +++ b/grub-core/commands/pgp.c @@ -0,0 +1,1020 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +enum + { + OPTION_SKIP_SIG = 0 + }; + +static const struct grub_arg_option options[] = + { + {"skip-sig", 's', 0, + N_("Skip signature-checking of the public key file."), 0, ARG_TYPE_NONE}, + {0, 0, 0, 0, 0, 0} + }; + +static grub_err_t +read_packet_header (grub_file_t sig, grub_uint8_t *out_type, grub_size_t *len) +{ + grub_uint8_t type; + grub_uint8_t l; + grub_uint16_t l16; + grub_uint32_t l32; + + /* New format. */ + switch (grub_file_read (sig, &type, sizeof (type))) + { + case 1: + break; + case 0: + { + *out_type = 0xff; + return 0; + } + default: + if (grub_errno) + return grub_errno; + /* TRANSLATORS: it's about GNUPG signatures. */ + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + } + + if (type == 0) + { + *out_type = 0xfe; + return 0; + } + + if (!(type & 0x80)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + if (type & 0x40) + { + *out_type = (type & 0x3f); + if (grub_file_read (sig, &l, sizeof (l)) != 1) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + if (l < 192) + { + *len = l; + return 0; + } + if (l < 224) + { + *len = (l - 192) << GRUB_CHAR_BIT; + if (grub_file_read (sig, &l, sizeof (l)) != 1) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + *len |= l; + return 0; + } + if (l == 255) + { + if (grub_file_read (sig, &l32, sizeof (l32)) != sizeof (l32)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + *len = grub_be_to_cpu32 (l32); + return 0; + } + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + } + *out_type = ((type >> 2) & 0xf); + switch (type & 0x3) + { + case 0: + if (grub_file_read (sig, &l, sizeof (l)) != sizeof (l)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + *len = l; + return 0; + case 1: + if (grub_file_read (sig, &l16, sizeof (l16)) != sizeof (l16)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + *len = grub_be_to_cpu16 (l16); + return 0; + case 2: + if (grub_file_read (sig, &l32, sizeof (l32)) != sizeof (l32)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + *len = grub_be_to_cpu32 (l32); + return 0; + } + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); +} + +struct signature_v4_header +{ + grub_uint8_t type; + grub_uint8_t pkeyalgo; + grub_uint8_t hash; + grub_uint16_t hashed_sub; +} GRUB_PACKED; + +const char *hashes[] = { + [0x01] = "md5", + [0x02] = "sha1", + [0x03] = "ripemd160", + [0x08] = "sha256", + [0x09] = "sha384", + [0x0a] = "sha512", + [0x0b] = "sha224" +}; + +struct gcry_pk_spec *grub_crypto_pk_dsa; +struct gcry_pk_spec *grub_crypto_pk_ecdsa; +struct gcry_pk_spec *grub_crypto_pk_rsa; + +static int +dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk); +static int +rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk); + +struct +{ + const char *name; + grub_size_t nmpisig; + grub_size_t nmpipub; + struct gcry_pk_spec **algo; + int (*pad) (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk); + const char *module; +} pkalgos[] = + { + [1] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" }, + [3] = { "rsa", 1, 2, &grub_crypto_pk_rsa, rsa_pad, "gcry_rsa" }, + [17] = { "dsa", 2, 4, &grub_crypto_pk_dsa, dsa_pad, "gcry_dsa" }, + }; + +struct grub_public_key +{ + struct grub_public_key *next; + struct grub_public_subkey *subkeys; +}; + +struct grub_public_subkey +{ + struct grub_public_subkey *next; + grub_uint8_t type; + grub_uint32_t fingerprint[5]; + gcry_mpi_t mpis[10]; +}; + +static void +free_pk (struct grub_public_key *pk) +{ + struct grub_public_subkey *nsk, *sk; + for (sk = pk->subkeys; sk; sk = nsk) + { + grub_size_t i; + for (i = 0; i < ARRAY_SIZE (sk->mpis); i++) + if (sk->mpis[i]) + gcry_mpi_release (sk->mpis[i]); + nsk = sk->next; + grub_free (sk); + } + grub_free (pk); +} + +#define READBUF_SIZE 4096 + +struct grub_public_key * +grub_load_public_key (grub_file_t f) +{ + grub_err_t err; + struct grub_public_key *ret; + struct grub_public_subkey **last = 0; + void *fingerprint_context = NULL; + grub_uint8_t *buffer = NULL; + + ret = grub_zalloc (sizeof (*ret)); + if (!ret) + { + grub_free (fingerprint_context); + return NULL; + } + + buffer = grub_zalloc (READBUF_SIZE); + fingerprint_context = grub_zalloc (GRUB_MD_SHA1->contextsize); + + if (!buffer || !fingerprint_context) + goto fail; + + last = &ret->subkeys; + + while (1) + { + grub_uint8_t type; + grub_size_t len; + grub_uint8_t v, pk; + grub_uint32_t creation_time; + grub_off_t pend; + struct grub_public_subkey *sk; + grub_size_t i; + grub_uint16_t len_be; + + err = read_packet_header (f, &type, &len); + + if (err) + goto fail; + if (type == 0xfe) + continue; + if (type == 0xff) + { + grub_free (fingerprint_context); + grub_free (buffer); + return ret; + } + + grub_dprintf ("crypt", "len = %x\n", (int) len); + + pend = grub_file_tell (f) + len; + if (type != 6 && type != 14 + && type != 5 && type != 7) + { + grub_file_seek (f, pend); + continue; + } + + if (grub_file_read (f, &v, sizeof (v)) != sizeof (v)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + + grub_dprintf ("crypt", "v = %x\n", v); + + if (v != 4) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + if (grub_file_read (f, &creation_time, sizeof (creation_time)) != sizeof (creation_time)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + + grub_dprintf ("crypt", "time = %x\n", creation_time); + + if (grub_file_read (f, &pk, sizeof (pk)) != sizeof (pk)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + goto fail; + } + + grub_dprintf ("crypt", "pk = %x\n", pk); + + if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL) + { + grub_file_seek (f, pend); + continue; + } + + sk = grub_zalloc (sizeof (struct grub_public_subkey)); + if (!sk) + goto fail; + + grub_memset (fingerprint_context, 0, GRUB_MD_SHA1->contextsize); + GRUB_MD_SHA1->init (fingerprint_context); + GRUB_MD_SHA1->write (fingerprint_context, "\x99", 1); + len_be = grub_cpu_to_be16 (len); + GRUB_MD_SHA1->write (fingerprint_context, &len_be, sizeof (len_be)); + GRUB_MD_SHA1->write (fingerprint_context, &v, sizeof (v)); + GRUB_MD_SHA1->write (fingerprint_context, &creation_time, sizeof (creation_time)); + GRUB_MD_SHA1->write (fingerprint_context, &pk, sizeof (pk)); + + for (i = 0; i < pkalgos[pk].nmpipub; i++) + { + grub_uint16_t l; + grub_size_t lb; + if (grub_file_read (f, &l, sizeof (l)) != sizeof (l)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + break; + } + + lb = (grub_be_to_cpu16 (l) + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT; + if (lb > READBUF_SIZE - sizeof (grub_uint16_t)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + break; + } + if (grub_file_read (f, buffer + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + break; + } + grub_memcpy (buffer, &l, sizeof (l)); + + GRUB_MD_SHA1->write (fingerprint_context, buffer, lb + sizeof (grub_uint16_t)); + + if (gcry_mpi_scan (&sk->mpis[i], GCRYMPI_FMT_PGP, + buffer, lb + sizeof (grub_uint16_t), 0)) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + break; + } + } + + if (i < pkalgos[pk].nmpipub) + { + grub_free (sk); + goto fail; + } + + GRUB_MD_SHA1->final (fingerprint_context); + + grub_memcpy (sk->fingerprint, GRUB_MD_SHA1->read (fingerprint_context), 20); + + *last = sk; + last = &sk->next; + + grub_dprintf ("crypt", "actual pos: %x, expected: %x\n", (int)grub_file_tell (f), (int)pend); + + grub_file_seek (f, pend); + } + fail: + free_pk (ret); + grub_free (fingerprint_context); + grub_free (buffer); + return NULL; +} + +struct grub_public_key *grub_pk_trusted; + +struct grub_public_subkey * +grub_crypto_pk_locate_subkey (grub_uint64_t keyid, struct grub_public_key *pkey) +{ + struct grub_public_subkey *sk; + for (sk = pkey->subkeys; sk; sk = sk->next) + if (grub_memcmp (sk->fingerprint + 3, &keyid, 8) == 0) + return sk; + return 0; +} + +struct grub_public_subkey * +grub_crypto_pk_locate_subkey_in_trustdb (grub_uint64_t keyid) +{ + struct grub_public_key *pkey; + struct grub_public_subkey *sk; + for (pkey = grub_pk_trusted; pkey; pkey = pkey->next) + { + sk = grub_crypto_pk_locate_subkey (keyid, pkey); + if (sk) + return sk; + } + return 0; +} + + +static int +dsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk) +{ + unsigned nbits = gcry_mpi_get_nbits (sk->mpis[1]); + grub_dprintf ("crypt", "must be %u bits got %d bits\n", nbits, + (int)(8 * hash->mdlen)); + return gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, hval, + nbits / 8 < (unsigned) hash->mdlen ? nbits / 8 + : (unsigned) hash->mdlen, 0); +} + +static int +rsa_pad (gcry_mpi_t *hmpi, grub_uint8_t *hval, + const gcry_md_spec_t *hash, struct grub_public_subkey *sk) +{ + grub_size_t tlen, emlen, fflen; + grub_uint8_t *em, *emptr; + unsigned nbits = gcry_mpi_get_nbits (sk->mpis[0]); + int ret; + tlen = hash->mdlen + hash->asnlen; + emlen = (nbits + 7) / 8; + if (emlen < tlen + 11) + return 1; + + em = grub_malloc (emlen); + if (!em) + return 1; + + em[0] = 0x00; + em[1] = 0x01; + fflen = emlen - tlen - 3; + for (emptr = em + 2; emptr < em + 2 + fflen; emptr++) + *emptr = 0xff; + *emptr++ = 0x00; + grub_memcpy (emptr, hash->asnoid, hash->asnlen); + emptr += hash->asnlen; + grub_memcpy (emptr, hval, hash->mdlen); + + ret = gcry_mpi_scan (hmpi, GCRYMPI_FMT_USG, em, emlen, 0); + grub_free (em); + return ret; +} + +struct grub_pubkey_context +{ + grub_file_t sig; + struct signature_v4_header v4; + grub_uint8_t v; + const gcry_md_spec_t *hash; + void *hash_context; +}; + +static grub_err_t +grub_verify_signature_init (struct grub_pubkey_context *ctxt, grub_file_t sig) +{ + grub_size_t len; + grub_uint8_t h; + grub_uint8_t t; + grub_uint8_t pk; + grub_err_t err; + grub_uint8_t type = 0; + + grub_memset (ctxt, 0, sizeof (*ctxt)); + + err = read_packet_header (sig, &type, &len); + if (err) + return err; + + if (type != 0x2) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + if (grub_file_read (sig, &ctxt->v, sizeof (ctxt->v)) != sizeof (ctxt->v)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + if (ctxt->v != 4) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + if (grub_file_read (sig, &ctxt->v4, sizeof (ctxt->v4)) != sizeof (ctxt->v4)) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + h = ctxt->v4.hash; + t = ctxt->v4.type; + pk = ctxt->v4.pkeyalgo; + + if (t != 0) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + if (h >= ARRAY_SIZE (hashes) || hashes[h] == NULL) + return grub_error (GRUB_ERR_BAD_SIGNATURE, "unknown hash"); + + if (pk >= ARRAY_SIZE (pkalgos) || pkalgos[pk].name == NULL) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + + ctxt->hash = grub_crypto_lookup_md_by_name (hashes[h]); + if (!ctxt->hash) + return grub_error (GRUB_ERR_BAD_SIGNATURE, "hash `%s' not loaded", hashes[h]); + + grub_dprintf ("crypt", "alive\n"); + + ctxt->hash_context = grub_zalloc (ctxt->hash->contextsize); + if (!ctxt->hash_context) + return grub_errno; + + ctxt->hash->init (ctxt->hash_context); + ctxt->sig = sig; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_pubkey_write (void *ctxt_, void *buf, grub_size_t size) +{ + struct grub_pubkey_context *ctxt = ctxt_; + ctxt->hash->write (ctxt->hash_context, buf, size); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_verify_signature_real (struct grub_pubkey_context *ctxt, + struct grub_public_key *pkey) +{ + gcry_mpi_t mpis[10]; + grub_uint8_t pk = ctxt->v4.pkeyalgo; + grub_size_t i; + grub_uint8_t *readbuf = NULL; + unsigned char *hval; + grub_ssize_t rem = grub_be_to_cpu16 (ctxt->v4.hashed_sub); + grub_uint32_t headlen = grub_cpu_to_be32 (rem + 6); + grub_uint8_t s; + grub_uint16_t unhashed_sub; + grub_ssize_t r; + grub_uint8_t hash_start[2]; + gcry_mpi_t hmpi; + grub_uint64_t keyid = 0; + struct grub_public_subkey *sk; + + readbuf = grub_malloc (READBUF_SIZE); + if (!readbuf) + goto fail; + + ctxt->hash->write (ctxt->hash_context, &ctxt->v, sizeof (ctxt->v)); + ctxt->hash->write (ctxt->hash_context, &ctxt->v4, sizeof (ctxt->v4)); + while (rem) + { + r = grub_file_read (ctxt->sig, readbuf, + rem < READBUF_SIZE ? rem : READBUF_SIZE); + if (r < 0) + goto fail; + if (r == 0) + break; + ctxt->hash->write (ctxt->hash_context, readbuf, r); + rem -= r; + } + ctxt->hash->write (ctxt->hash_context, &ctxt->v, sizeof (ctxt->v)); + s = 0xff; + ctxt->hash->write (ctxt->hash_context, &s, sizeof (s)); + ctxt->hash->write (ctxt->hash_context, &headlen, sizeof (headlen)); + r = grub_file_read (ctxt->sig, &unhashed_sub, sizeof (unhashed_sub)); + if (r != sizeof (unhashed_sub)) + goto fail; + { + grub_uint8_t *ptr; + grub_uint32_t l; + rem = grub_be_to_cpu16 (unhashed_sub); + if (rem > READBUF_SIZE) + goto fail; + r = grub_file_read (ctxt->sig, readbuf, rem); + if (r != rem) + goto fail; + for (ptr = readbuf; ptr < readbuf + rem; ptr += l) + { + if (*ptr < 192) + l = *ptr++; + else if (*ptr < 255) + { + if (ptr + 1 >= readbuf + rem) + break; + l = (((ptr[0] & ~192) << GRUB_CHAR_BIT) | ptr[1]) + 192; + ptr += 2; + } + else + { + if (ptr + 5 >= readbuf + rem) + break; + l = grub_be_to_cpu32 (grub_get_unaligned32 (ptr + 1)); + ptr += 5; + } + if (*ptr == 0x10 && l >= 8) + keyid = grub_get_unaligned64 (ptr + 1); + } + } + + ctxt->hash->final (ctxt->hash_context); + + grub_dprintf ("crypt", "alive\n"); + + hval = ctxt->hash->read (ctxt->hash_context); + + if (grub_file_read (ctxt->sig, hash_start, sizeof (hash_start)) != sizeof (hash_start)) + goto fail; + if (grub_memcmp (hval, hash_start, sizeof (hash_start)) != 0) + goto fail; + + grub_dprintf ("crypt", "@ %x\n", (int)grub_file_tell (ctxt->sig)); + + for (i = 0; i < pkalgos[pk].nmpisig; i++) + { + grub_uint16_t l; + grub_size_t lb; + grub_dprintf ("crypt", "alive\n"); + if (grub_file_read (ctxt->sig, &l, sizeof (l)) != sizeof (l)) + goto fail; + grub_dprintf ("crypt", "alive\n"); + lb = (grub_be_to_cpu16 (l) + 7) / 8; + grub_dprintf ("crypt", "l = 0x%04x\n", grub_be_to_cpu16 (l)); + if (lb > READBUF_SIZE - sizeof (grub_uint16_t)) + goto fail; + grub_dprintf ("crypt", "alive\n"); + if (grub_file_read (ctxt->sig, readbuf + sizeof (grub_uint16_t), lb) != (grub_ssize_t) lb) + goto fail; + grub_dprintf ("crypt", "alive\n"); + grub_memcpy (readbuf, &l, sizeof (l)); + grub_dprintf ("crypt", "alive\n"); + + if (gcry_mpi_scan (&mpis[i], GCRYMPI_FMT_PGP, + readbuf, lb + sizeof (grub_uint16_t), 0)) + goto fail; + grub_dprintf ("crypt", "alive\n"); + } + + if (pkey) + sk = grub_crypto_pk_locate_subkey (keyid, pkey); + else + sk = grub_crypto_pk_locate_subkey_in_trustdb (keyid); + if (!sk) + { + /* TRANSLATORS: %08x is 32-bit key id. */ + grub_error (GRUB_ERR_BAD_SIGNATURE, + N_("public key %08" PRIxGRUB_UINT64_T " not found"), keyid); + goto fail; + } + + if (pkalgos[pk].pad (&hmpi, hval, ctxt->hash, sk)) + goto fail; + if (!*pkalgos[pk].algo) + { + grub_dl_load (pkalgos[pk].module); + grub_errno = GRUB_ERR_NONE; + } + + if (!*pkalgos[pk].algo) + { + grub_error (GRUB_ERR_BAD_SIGNATURE, N_("module `%s' isn't loaded"), + pkalgos[pk].module); + goto fail; + } + if ((*pkalgos[pk].algo)->verify (0, hmpi, mpis, sk->mpis, 0, 0)) + goto fail; + + grub_free (readbuf); + + return GRUB_ERR_NONE; + + fail: + grub_free (readbuf); + if (!grub_errno) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad signature")); + return grub_errno; +} + +static void +grub_pubkey_close_real (struct grub_pubkey_context *ctxt) +{ + if (ctxt->sig) + grub_file_close (ctxt->sig); + if (ctxt->hash_context) + grub_free (ctxt->hash_context); +} + +static void +grub_pubkey_close (void *ctxt) +{ + grub_pubkey_close_real (ctxt); + grub_free (ctxt); +} + +grub_err_t +grub_verify_signature (grub_file_t f, const char *fsig, + struct grub_public_key *pkey) +{ + grub_file_t sig; + grub_err_t err; + struct grub_pubkey_context ctxt; + grub_uint8_t *readbuf = NULL; + + sig = grub_file_open (fsig, + GRUB_FILE_TYPE_SIGNATURE + | GRUB_FILE_TYPE_NO_DECOMPRESS); + if (!sig) + return grub_errno; + + err = grub_verify_signature_init (&ctxt, sig); + if (err) + { + grub_file_close (sig); + return err; + } + + readbuf = grub_zalloc (READBUF_SIZE); + if (!readbuf) + goto fail; + + while (1) + { + grub_ssize_t r; + r = grub_file_read (f, readbuf, READBUF_SIZE); + if (r < 0) + goto fail; + if (r == 0) + break; + err = grub_pubkey_write (&ctxt, readbuf, r); + if (err) + return err; + } + + grub_verify_signature_real (&ctxt, pkey); + fail: + grub_pubkey_close_real (&ctxt); + return grub_errno; +} + +static grub_err_t +grub_cmd_trust (grub_extcmd_context_t ctxt, + int argc, char **args) +{ + grub_file_t pkf; + struct grub_public_key *pk = NULL; + + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + + pkf = grub_file_open (args[0], + GRUB_FILE_TYPE_PUBLIC_KEY_TRUST + | GRUB_FILE_TYPE_NO_DECOMPRESS + | (ctxt->state[OPTION_SKIP_SIG].set + ? GRUB_FILE_TYPE_SKIP_SIGNATURE + : GRUB_FILE_TYPE_NONE)); + if (!pkf) + return grub_errno; + pk = grub_load_public_key (pkf); + if (!pk) + { + grub_file_close (pkf); + return grub_errno; + } + grub_file_close (pkf); + + pk->next = grub_pk_trusted; + grub_pk_trusted = pk; + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_list (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + struct grub_public_key *pk = NULL; + struct grub_public_subkey *sk = NULL; + + for (pk = grub_pk_trusted; pk; pk = pk->next) + for (sk = pk->subkeys; sk; sk = sk->next) + { + unsigned i; + for (i = 0; i < 20; i += 2) + grub_printf ("%02x%02x ", ((grub_uint8_t *) sk->fingerprint)[i], + ((grub_uint8_t *) sk->fingerprint)[i + 1]); + grub_printf ("\n"); + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_distrust (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_uint32_t keyid, keyid_be; + struct grub_public_key **pkey; + struct grub_public_subkey *sk; + + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + keyid = grub_strtoull (args[0], 0, 16); + if (grub_errno) + return grub_errno; + keyid_be = grub_cpu_to_be32 (keyid); + + for (pkey = &grub_pk_trusted; *pkey; pkey = &((*pkey)->next)) + { + struct grub_public_key *next; + for (sk = (*pkey)->subkeys; sk; sk = sk->next) + if (grub_memcmp (sk->fingerprint + 4, &keyid_be, 4) == 0) + break; + if (!sk) + continue; + next = (*pkey)->next; + free_pk (*pkey); + *pkey = next; + return GRUB_ERR_NONE; + } + /* TRANSLATORS: %08x is 32-bit key id. */ + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("public key %08x not found"), keyid); +} + +static grub_err_t +grub_cmd_verify_signature (grub_extcmd_context_t ctxt, + int argc, char **args) +{ + grub_file_t f = NULL; + grub_err_t err = GRUB_ERR_NONE; + struct grub_public_key *pk = NULL; + + grub_dprintf ("crypt", "alive\n"); + + if (argc < 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); + + grub_dprintf ("crypt", "alive\n"); + + if (argc > 2) + { + grub_file_t pkf; + pkf = grub_file_open (args[2], + GRUB_FILE_TYPE_PUBLIC_KEY + | GRUB_FILE_TYPE_NO_DECOMPRESS + | (ctxt->state[OPTION_SKIP_SIG].set + ? GRUB_FILE_TYPE_SKIP_SIGNATURE + : GRUB_FILE_TYPE_NONE)); + if (!pkf) + return grub_errno; + pk = grub_load_public_key (pkf); + if (!pk) + { + grub_file_close (pkf); + return grub_errno; + } + grub_file_close (pkf); + } + + f = grub_file_open (args[0], GRUB_FILE_TYPE_VERIFY_SIGNATURE); + if (!f) + { + err = grub_errno; + goto fail; + } + + err = grub_verify_signature (f, args[1], pk); + fail: + if (f) + grub_file_close (f); + if (pk) + free_pk (pk); + return err; +} + +static int sec = 0; + +static grub_err_t +grub_pubkey_init (grub_file_t io, enum grub_file_type type __attribute__ ((unused)), + void **context, enum grub_verify_flags *flags) +{ + grub_file_t sig; + char *fsuf, *ptr; + grub_err_t err; + struct grub_pubkey_context *ctxt; + + if (!sec) + { + *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; + return GRUB_ERR_NONE; + } + + fsuf = grub_malloc (grub_strlen (io->name) + sizeof (".sig")); + if (!fsuf) + return grub_errno; + ptr = grub_stpcpy (fsuf, io->name); + grub_memcpy (ptr, ".sig", sizeof (".sig")); + + sig = grub_file_open (fsuf, GRUB_FILE_TYPE_SIGNATURE); + grub_free (fsuf); + if (!sig) + return grub_errno; + + ctxt = grub_malloc (sizeof (*ctxt)); + if (!ctxt) + { + grub_file_close (sig); + return grub_errno; + } + err = grub_verify_signature_init (ctxt, sig); + if (err) + { + grub_free (ctxt); + grub_file_close (sig); + return err; + } + *context = ctxt; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_pubkey_fini (void *ctxt) +{ + return grub_verify_signature_real (ctxt, NULL); +} + +static char * +grub_env_write_sec (struct grub_env_var *var __attribute__ ((unused)), + const char *val) +{ + sec = (*val == '1') || (*val == 'e'); + return grub_strdup (sec ? "enforce" : "no"); +} + +static grub_ssize_t +pseudo_read (struct grub_file *file, char *buf, grub_size_t len) +{ + grub_memcpy (buf, (grub_uint8_t *) file->data + file->offset, len); + return len; +} + + +/* Filesystem descriptor. */ +struct grub_fs pseudo_fs = + { + .name = "pseudo", + .fs_read = pseudo_read + }; + +struct grub_file_verifier grub_pubkey_verifier = + { + .name = "pgp", + .init = grub_pubkey_init, + .fini = grub_pubkey_fini, + .write = grub_pubkey_write, + .close = grub_pubkey_close, + }; + +static grub_extcmd_t cmd, cmd_trust; +static grub_command_t cmd_distrust, cmd_list; + +GRUB_MOD_INIT(pgp) +{ + const char *val; + struct grub_module_header *header; + + val = grub_env_get ("check_signatures"); + if (val && (val[0] == '1' || val[0] == 'e')) + sec = 1; + else + sec = 0; + + grub_register_variable_hook ("check_signatures", 0, grub_env_write_sec); + grub_env_export ("check_signatures"); + + grub_pk_trusted = 0; + FOR_MODULES (header) + { + struct grub_file pseudo_file; + struct grub_public_key *pk = NULL; + + grub_memset (&pseudo_file, 0, sizeof (pseudo_file)); + + /* Not an ELF module, skip. */ + if (header->type != OBJ_TYPE_PUBKEY) + continue; + + pseudo_file.fs = &pseudo_fs; + pseudo_file.size = (header->size - sizeof (struct grub_module_header)); + pseudo_file.data = (char *) header + sizeof (struct grub_module_header); + + pk = grub_load_public_key (&pseudo_file); + if (!pk) + grub_fatal ("error loading initial key: %s\n", grub_errmsg); + + pk->next = grub_pk_trusted; + grub_pk_trusted = pk; + } + + if (!val) + grub_env_set ("check_signatures", grub_pk_trusted ? "enforce" : "no"); + + cmd = grub_register_extcmd ("verify_detached", grub_cmd_verify_signature, 0, + N_("[-s|--skip-sig] FILE SIGNATURE_FILE [PUBKEY_FILE]"), + N_("Verify detached signature."), + options); + cmd_trust = grub_register_extcmd ("trust", grub_cmd_trust, 0, + N_("[-s|--skip-sig] PUBKEY_FILE"), + N_("Add PUBKEY_FILE to trusted keys."), + options); + cmd_list = grub_register_command ("list_trusted", grub_cmd_list, + 0, + N_("Show the list of trusted keys.")); + cmd_distrust = grub_register_command ("distrust", grub_cmd_distrust, + N_("PUBKEY_ID"), + N_("Remove PUBKEY_ID from trusted keys.")); + + grub_verifier_register (&grub_pubkey_verifier); +} + +GRUB_MOD_FINI(pgp) +{ + grub_register_variable_hook ("check_signatures", NULL, NULL); + grub_env_unset ("check_signatures"); + grub_verifier_unregister (&grub_pubkey_verifier); + grub_unregister_extcmd (cmd); + grub_unregister_extcmd (cmd_trust); + grub_unregister_command (cmd_list); + grub_unregister_command (cmd_distrust); +} diff --git a/grub-core/commands/probe.c b/grub-core/commands/probe.c index eeece876d..be9637f33 100644 --- a/grub-core/commands/probe.c +++ b/grub-core/commands/probe.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -45,6 +47,7 @@ static const struct grub_arg_option options[] = {"fs", 'f', 0, N_("Determine filesystem type."), 0, 0}, {"fs-uuid", 'u', 0, N_("Determine filesystem UUID."), 0, 0}, {"label", 'l', 0, N_("Determine filesystem label."), 0, 0}, + {"part-uuid", 0, 0, N_("Determine partition UUID."), 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -83,6 +86,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) grub_env_set (state[0].arg, val); else grub_printf ("%s", val); + grub_device_close (dev); return GRUB_ERR_NONE; } if (state[2].set) @@ -94,61 +98,141 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) grub_env_set (state[0].arg, val); else grub_printf ("%s", val); + grub_device_close (dev); + return GRUB_ERR_NONE; + } + if (state[6].set) + { + /* AAAABBBB-CCCC-DDDD-EEEE-FFFFFFFFFFFF + null terminator */ + char val[37] = "none"; + if (dev->disk && dev->disk->partition) + { + struct grub_partition *p = dev->disk->partition; + grub_disk_t disk = grub_disk_open(dev->disk->name); + + if (!disk) + { + grub_device_close (dev); + return grub_errno; + } + + if (grub_strcmp(dev->disk->partition->partmap->name, "gpt") == 0) + { + struct grub_gpt_partentry entry; + grub_guid_t *guid; + + if (grub_disk_read(disk, p->offset, p->index, sizeof(entry), &entry)) + { + grub_error_push (); + grub_disk_close (disk); + grub_device_close (dev); + grub_error_pop (); + return grub_errno; + } + guid = &entry.guid; + guid->data1 = grub_le_to_cpu32 (guid->data1); + guid->data2 = grub_le_to_cpu16 (guid->data2); + guid->data3 = grub_le_to_cpu16 (guid->data3); + grub_snprintf (val, sizeof(val), "%pG", guid); + } + else if (grub_strcmp(dev->disk->partition->partmap->name, "msdos") == 0) + { + grub_uint32_t nt_disk_sig; + + if (grub_disk_read(disk, 0, GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + sizeof(nt_disk_sig), &nt_disk_sig) == 0) + grub_snprintf (val, sizeof(val), "%08x-%02x", + grub_le_to_cpu32(nt_disk_sig), 1 + p->number); + } + grub_disk_close(disk); + } + if (state[0].set) + grub_env_set (state[0].arg, val); + else + grub_printf ("%s", val); + grub_device_close (dev); return GRUB_ERR_NONE; } fs = grub_fs_probe (dev); if (! fs) - return grub_errno; + { + grub_error_push (); + grub_device_close (dev); + grub_error_pop (); + return grub_errno; + } if (state[3].set) { if (state[0].set) grub_env_set (state[0].arg, fs->name); else grub_printf ("%s", fs->name); + grub_device_close (dev); return GRUB_ERR_NONE; } if (state[4].set) { char *uuid; - if (! fs->uuid) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("%s does not support UUIDs"), fs->name); - err = fs->uuid (dev, &uuid); + if (! fs->fs_uuid) + { + grub_device_close (dev); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("%s does not support UUIDs"), fs->name); + } + err = fs->fs_uuid (dev, &uuid); if (err) - return err; + { + grub_device_close (dev); + return err; + } if (! uuid) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("%s does not support UUIDs"), fs->name); + { + grub_device_close (dev); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("%s does not support UUIDs"), fs->name); + } if (state[0].set) grub_env_set (state[0].arg, uuid); else grub_printf ("%s", uuid); grub_free (uuid); + grub_device_close (dev); return GRUB_ERR_NONE; } if (state[5].set) { char *label; - if (! fs->label) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("filesystem `%s' does not support labels"), - fs->name); - err = fs->label (dev, &label); + if (! fs->fs_label) + { + grub_device_close (dev); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("filesystem `%s' does not support labels"), + fs->name); + } + err = fs->fs_label (dev, &label); if (err) - return err; + { + grub_device_close (dev); + return err; + } if (! label) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("filesystem `%s' does not support labels"), - fs->name); + { + grub_device_close (dev); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("filesystem `%s' does not support labels"), + fs->name); + } if (state[0].set) grub_env_set (state[0].arg, label); else grub_printf ("%s", label); grub_free (label); + grub_device_close (dev); return GRUB_ERR_NONE; } + grub_device_close (dev); return grub_error (GRUB_ERR_BAD_ARGUMENT, "unrecognised target"); } diff --git a/grub-core/commands/read.c b/grub-core/commands/read.c index fe3e88b15..8d72e45c9 100644 --- a/grub-core/commands/read.c +++ b/grub-core/commands/read.c @@ -23,21 +23,29 @@ #include #include #include -#include +#include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); +static const struct grub_arg_option options[] = + { + {"silent", 's', 0, N_("Do not echo input"), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + static char * -grub_getline (void) +grub_getline (int silent) { - int i; + grub_size_t i; char *line; char *tmp; - char c; + int c; + grub_size_t alloc_size; i = 0; - line = grub_malloc (1 + i + sizeof('\0')); + line = grub_malloc (1 + sizeof('\0')); if (! line) return NULL; @@ -47,11 +55,23 @@ grub_getline (void) if ((c == '\n') || (c == '\r')) break; - line[i] = c; - if (grub_isprint (c)) + if (!grub_isprint (c)) + continue; + + line[i] = (char) c; + if (!silent) grub_printf ("%c", c); - i++; - tmp = grub_realloc (line, 1 + i + sizeof('\0')); + if (grub_add (i, 1, &i)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + return NULL; + } + if (grub_add (i, 1 + sizeof('\0'), &alloc_size)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + return NULL; + } + tmp = grub_realloc (line, alloc_size); if (! tmp) { grub_free (line); @@ -65,9 +85,11 @@ grub_getline (void) } static grub_err_t -grub_cmd_read (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) +grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **args) { - char *line = grub_getline (); + struct grub_arg_list *state = ctxt->state; + char *line = grub_getline (state[0].set); + if (! line) return grub_errno; if (argc > 0) @@ -77,16 +99,16 @@ grub_cmd_read (grub_command_t cmd __attribute__ ((unused)), int argc, char **arg return 0; } -static grub_command_t cmd; +static grub_extcmd_t cmd; GRUB_MOD_INIT(read) { - cmd = grub_register_command ("read", grub_cmd_read, - N_("[ENVVAR]"), - N_("Set variable with user input.")); + cmd = grub_register_extcmd ("read", grub_cmd_read, 0, + N_("[-s] [ENVVAR]"), + N_("Set variable with user input."), options); } GRUB_MOD_FINI(read) { - grub_unregister_command (cmd); + grub_unregister_extcmd (cmd); } diff --git a/grub-core/commands/regexp.c b/grub-core/commands/regexp.c index b0706d069..246af39f0 100644 --- a/grub-core/commands/regexp.c +++ b/grub-core/commands/regexp.c @@ -36,7 +36,7 @@ static const struct grub_arg_option options[] = groups with parentheses. These groups are then numbered and you can save some of them in variables. In other programs - those components aree often referenced with + those components are often referenced with back slash, e.g. \1. Compare sed -e 's,\([a-z][a-z]*\),lowercase=\1,g' The whole matching component is saved in VARNAME, not its number. @@ -46,28 +46,31 @@ static const struct grub_arg_option options[] = { 0, 0, 0, 0, 0, 0 } }; +static grub_err_t +setvar (char *str, char *v, regmatch_t *m) +{ + char ch; + grub_err_t err; + ch = str[m->rm_eo]; + str[m->rm_eo] = '\0'; + err = grub_env_set (v, str + m->rm_so); + str[m->rm_eo] = ch; + return err; +} + static grub_err_t set_matches (char **varnames, char *str, grub_size_t nmatches, regmatch_t *matches) { int i; char *p; - char *q; + const char * q; grub_err_t err; unsigned long j; - auto void setvar (char *v, regmatch_t *m); - void setvar (char *v, regmatch_t *m) - { - char ch; - ch = str[m->rm_eo]; - str[m->rm_eo] = '\0'; - err = grub_env_set (v, str + m->rm_so); - str[m->rm_eo] = ch; - } - for (i = 0; varnames && varnames[i]; i++) { + err = GRUB_ERR_NONE; p = grub_strchr (varnames[i], ':'); if (! p) { @@ -75,7 +78,7 @@ set_matches (char **varnames, char *str, grub_size_t nmatches, if (nmatches < 2 || matches[1].rm_so == -1) grub_env_unset (varnames[i]); else - setvar (varnames[i], &matches[1]); + err = setvar (str, varnames[i], &matches[1]); } else { @@ -87,7 +90,7 @@ set_matches (char **varnames, char *str, grub_size_t nmatches, if (nmatches <= j || matches[j].rm_so == -1) grub_env_unset (p + 1); else - setvar (p + 1, &matches[j]); + err = setvar (str, p + 1, &matches[j]); } if (err != GRUB_ERR_NONE) @@ -113,7 +116,7 @@ grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args) if (ret) goto fail; - matches = grub_zalloc (sizeof (*matches) * (regex.re_nsub + 1)); + matches = grub_calloc (regex.re_nsub + 1, sizeof (*matches)); if (! matches) goto fail; diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c index 5e9b7e381..49b679e80 100644 --- a/grub-core/commands/search.c +++ b/grub-core/commands/search.c @@ -42,23 +42,104 @@ struct cache_entry static struct cache_entry *cache; -void -FUNC_NAME (const char *key, const char *var, int no_floppy, - char **hints, unsigned nhints) +/* Context for FUNC_NAME. */ +struct search_ctx { - int count = 0; - int is_cache = 0; - grub_fs_autoload_hook_t saved_autoload; + const char *key; + const char *var; + enum search_flags flags; + char **hints; + unsigned nhints; + int count; + int is_cache; +}; - auto int iterate_device (const char *name); - int iterate_device (const char *name) - { - int found = 0; +static bool +is_unencrypted_disk (grub_disk_t disk) +{ + grub_command_t cmd; + char *disk_str; + int disk_str_len; + int res; - /* Skip floppy drives when requested. */ - if (no_floppy && - name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') - return 0; + if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) + return false; /* This is (crypto) disk. */ + + if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID) + { + char opt[] = "--quiet"; + char *args[2]; + + cmd = grub_command_find ("cryptocheck"); + if (cmd == NULL) /* No diskfilter module loaded for some reason. */ + return true; + + disk_str_len = grub_strlen (disk->name) + 2 + 1; + disk_str = grub_malloc (disk_str_len); + if (disk_str == NULL) /* Something is wrong, better report as unencrypted. */ + return true; + + grub_snprintf (disk_str, disk_str_len, "(%s)", disk->name); + args[0] = opt; + args[1] = disk_str; + res = cmd->func (cmd, 2, args); + grub_free (disk_str); + return (res != GRUB_ERR_NONE) ? true : false; /* GRUB_ERR_NONE for encrypted. */ + } + return true; +} + +/* Helper for FUNC_NAME. */ +static int +iterate_device (const char *name, void *data) +{ + struct search_ctx *ctx = data; + int found = 0; + + /* Skip floppy drives when requested. */ + if (ctx->flags & SEARCH_FLAGS_NO_FLOPPY && + name[0] == 'f' && name[1] == 'd' && name[2] >= '0' && name[2] <= '9') + return 0; + + /* Limit to EFI disks when requested. */ + if (ctx->flags & SEARCH_FLAGS_EFIDISK_ONLY) + { + grub_device_t dev; + + dev = grub_device_open (name); + if (dev == NULL) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (dev->disk == NULL || dev->disk->dev->id != GRUB_DISK_DEVICE_EFIDISK_ID) + { + grub_device_close (dev); + grub_errno = GRUB_ERR_NONE; + return 0; + } + grub_device_close (dev); + } + + /* Limit to encrypted disks when requested. */ + if (ctx->flags & SEARCH_FLAGS_CRYPTODISK_ONLY) + { + grub_device_t dev; + + dev = grub_device_open (name); + if (dev == NULL) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (dev->disk == NULL || is_unencrypted_disk (dev->disk) == true) + { + grub_device_close (dev); + grub_errno = GRUB_ERR_NONE; + return 0; + } + grub_device_close (dev); + } #ifdef DO_SEARCH_FS_UUID #define compare_fn grub_strcasecmp @@ -67,208 +148,226 @@ FUNC_NAME (const char *key, const char *var, int no_floppy, #endif #ifdef DO_SEARCH_FILE - { - char *buf; - grub_file_t file; + { + char *buf; + grub_file_t file; - buf = grub_xasprintf ("(%s)%s", name, key); - if (! buf) - return 1; + buf = grub_xasprintf ("(%s)%s", name, ctx->key); + if (! buf) + return 1; - grub_file_filter_disable_compression (); - file = grub_file_open (buf); - if (file) - { - found = 1; - grub_file_close (file); - } - grub_free (buf); - } + file = grub_file_open (buf, GRUB_FILE_TYPE_FS_SEARCH + | GRUB_FILE_TYPE_NO_DECOMPRESS); + if (file) + { + found = 1; + grub_file_close (file); + } + grub_free (buf); + } #else - { - /* SEARCH_FS_UUID or SEARCH_LABEL */ - grub_device_t dev; - grub_fs_t fs; - char *quid; + { + /* SEARCH_FS_UUID or SEARCH_LABEL */ + grub_device_t dev; + grub_fs_t fs; + char *quid; - dev = grub_device_open (name); - if (dev) - { - fs = grub_fs_probe (dev); + dev = grub_device_open (name); + if (dev) + { + fs = grub_fs_probe (dev); #ifdef DO_SEARCH_FS_UUID -#define read_fn uuid +#define read_fn fs_uuid #else -#define read_fn label +#define read_fn fs_label #endif - if (fs && fs->read_fn) - { - fs->read_fn (dev, &quid); + if (fs && fs->read_fn) + { + fs->read_fn (dev, &quid); - if (grub_errno == GRUB_ERR_NONE && quid) - { - if (compare_fn (quid, key) == 0) - found = 1; + if (grub_errno == GRUB_ERR_NONE && quid) + { + if (compare_fn (quid, ctx->key) == 0) + found = 1; - grub_free (quid); - } - } + grub_free (quid); + } + } - grub_device_close (dev); - } - } + grub_device_close (dev); + } + } #endif - if (!is_cache && found && count == 0) - { - struct cache_entry *cache_ent; - cache_ent = grub_malloc (sizeof (*cache_ent)); - if (cache_ent) - { - cache_ent->key = grub_strdup (key); - cache_ent->value = grub_strdup (name); - if (cache_ent->value && cache_ent->key) - { - cache_ent->next = cache; - cache = cache_ent; - } - else - { - grub_free (cache_ent->value); - grub_free (cache_ent->key); - grub_free (cache_ent); - grub_errno = GRUB_ERR_NONE; - } - } - else - grub_errno = GRUB_ERR_NONE; - } + if (!ctx->is_cache && found && ctx->count == 0) + { + struct cache_entry *cache_ent; + cache_ent = grub_malloc (sizeof (*cache_ent)); + if (cache_ent) + { + cache_ent->key = grub_strdup (ctx->key); + cache_ent->value = grub_strdup (name); + if (cache_ent->value && cache_ent->key) + { + cache_ent->next = cache; + cache = cache_ent; + } + else + { + grub_free (cache_ent->value); + grub_free (cache_ent->key); + grub_free (cache_ent); + grub_errno = GRUB_ERR_NONE; + } + } + else + grub_errno = GRUB_ERR_NONE; + } - if (found) - { - count++; - if (var) - grub_env_set (var, name); - else - grub_printf (" %s", name); - } + if (found) + { + ctx->count++; + if (ctx->var) + grub_env_set (ctx->var, name); + else + grub_printf (" %s", name); + } - grub_errno = GRUB_ERR_NONE; - return (found && var); - } + grub_errno = GRUB_ERR_NONE; + return (found && ctx->var); +} - auto int part_hook (grub_disk_t disk, const grub_partition_t partition); - int part_hook (grub_disk_t disk, const grub_partition_t partition) - { - char *partition_name, *devname; - int ret; +/* Helper for FUNC_NAME. */ +static int +part_hook (grub_disk_t disk, const grub_partition_t partition, void *data) +{ + struct search_ctx *ctx = data; + char *partition_name, *devname; + int ret; - partition_name = grub_partition_get_name (partition); - if (! partition_name) - return 1; + partition_name = grub_partition_get_name (partition); + if (! partition_name) + return 1; - devname = grub_xasprintf ("%s,%s", disk->name, partition_name); - grub_free (partition_name); - if (!devname) - return 1; - ret = iterate_device (devname); - grub_free (devname); + devname = grub_xasprintf ("%s,%s", disk->name, partition_name); + grub_free (partition_name); + if (!devname) + return 1; + ret = iterate_device (devname, ctx); + grub_free (devname); - return ret; - } + return ret; +} - auto void try (void); - void try (void) - { - unsigned i; - struct cache_entry **prev; - struct cache_entry *cache_ent; +/* Helper for FUNC_NAME. */ +static void +try (struct search_ctx *ctx) +{ + unsigned i; + struct cache_entry **prev; + struct cache_entry *cache_ent; - for (prev = &cache, cache_ent = *prev; cache_ent; - prev = &cache_ent->next, cache_ent = *prev) - if (compare_fn (cache_ent->key, key) == 0) - break; - if (cache_ent) - { - is_cache = 1; - if (iterate_device (cache_ent->value)) - { - is_cache = 0; + for (prev = &cache, cache_ent = *prev; cache_ent; + prev = &cache_ent->next, cache_ent = *prev) + if (compare_fn (cache_ent->key, ctx->key) == 0) + break; + if (cache_ent) + { + ctx->is_cache = 1; + if (iterate_device (cache_ent->value, ctx)) + { + ctx->is_cache = 0; + return; + } + ctx->is_cache = 0; + /* Cache entry was outdated. Remove it. */ + if (!ctx->count) + { + *prev = cache_ent->next; + grub_free (cache_ent->key); + grub_free (cache_ent->value); + grub_free (cache_ent); + } + } + + for (i = 0; i < ctx->nhints; i++) + { + char *end; + if (!ctx->hints[i][0]) + continue; + end = ctx->hints[i] + grub_strlen (ctx->hints[i]) - 1; + if (*end == ',') + *end = 0; + if (iterate_device (ctx->hints[i], ctx)) + { + if (!*end) + *end = ','; + return; + } + if (!*end) + { + grub_device_t dev; + int ret; + dev = grub_device_open (ctx->hints[i]); + if (!dev) + { + if (!*end) + *end = ','; + continue; + } + if (!dev->disk) + { + grub_device_close (dev); + if (!*end) + *end = ','; + continue; + } + ret = grub_partition_iterate (dev->disk, part_hook, ctx); + if (!*end) + *end = ','; + grub_device_close (dev); + if (ret) return; - } - is_cache = 0; - /* Cache entry was outdated. Remove it. */ - if (!count) - { - grub_free (cache_ent->key); - grub_free (cache_ent->value); - grub_free (cache_ent); - *prev = cache_ent->next; - } - } + } + } + grub_device_iterate (iterate_device, ctx); +} - for (i = 0; i < nhints; i++) - { - char *end; - if (!hints[i][0]) - continue; - end = hints[i] + grub_strlen (hints[i]) - 1; - if (*end == ',') - *end = 0; - if (iterate_device (hints[i])) - { - if (!*end) - *end = ','; - return; - } - if (!*end) - { - grub_device_t dev; - int ret; - dev = grub_device_open (hints[i]); - if (!dev) - { - if (!*end) - *end = ','; - continue; - } - if (!dev->disk) - { - grub_device_close (dev); - if (!*end) - *end = ','; - continue; - } - ret = grub_partition_iterate (dev->disk, part_hook); - if (!*end) - *end = ','; - grub_device_close (dev); - if (ret) - return; - } - } - grub_device_iterate (iterate_device); - } +void +FUNC_NAME (const char *key, const char *var, enum search_flags flags, + char **hints, unsigned nhints) +{ + struct search_ctx ctx = { + .key = key, + .var = var, + .flags = flags, + .hints = hints, + .nhints = nhints, + .count = 0, + .is_cache = 0 + }; + grub_fs_autoload_hook_t saved_autoload; /* First try without autoloading if we're setting variable. */ if (var) { saved_autoload = grub_fs_autoload_hook; grub_fs_autoload_hook = 0; - try (); + try (&ctx); /* Restore autoload hook. */ grub_fs_autoload_hook = saved_autoload; /* Retry with autoload if nothing found. */ - if (grub_errno == GRUB_ERR_NONE && count == 0) - try (); + if (grub_errno == GRUB_ERR_NONE && ctx.count == 0) + try (&ctx); } else - try (); + try (&ctx); - if (grub_errno == GRUB_ERR_NONE && count == 0) + if (grub_errno == GRUB_ERR_NONE && ctx.count == 0) grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key); } diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c index 3f75fecdf..5f536006c 100644 --- a/grub-core/commands/search_wrap.c +++ b/grub-core/commands/search_wrap.c @@ -40,6 +40,8 @@ static const struct grub_arg_option options[] = N_("Set a variable to the first device found."), N_("VARNAME"), ARG_TYPE_STRING}, {"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0}, + {"efidisk-only", 0, 0, N_("Only probe EFI disks."), 0, 0}, + {"cryptodisk-only", 0, 0, N_("Only probe encrypted disks."), 0, 0}, {"hint", 'h', GRUB_ARG_OPTION_REPEATABLE, N_("First try the device HINT. If HINT ends in comma, " "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, @@ -73,6 +75,8 @@ enum options SEARCH_FS_UUID, SEARCH_SET, SEARCH_NO_FLOPPY, + SEARCH_EFIDISK_ONLY, + SEARCH_CRYPTODISK_ONLY, SEARCH_HINT, SEARCH_HINT_IEEE1275, SEARCH_HINT_BIOS, @@ -89,6 +93,7 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) const char *id = 0; int i = 0, j = 0, nhints = 0; char **hints = NULL; + enum search_flags flags = SEARCH_FLAGS_NONE; if (state[SEARCH_HINT].set) for (i = 0; state[SEARCH_HINT].args[i]; i++) @@ -122,7 +127,7 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++) nhints++; - hints = grub_malloc (sizeof (hints[0]) * nhints); + hints = grub_calloc (nhints, sizeof (hints[0])); if (!hints) return grub_errno; j = 0; @@ -175,20 +180,31 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) var = "root"; } else - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + goto out; + } + + if (state[SEARCH_NO_FLOPPY].set) + flags |= SEARCH_FLAGS_NO_FLOPPY; + + if (state[SEARCH_EFIDISK_ONLY].set) + flags |= SEARCH_FLAGS_EFIDISK_ONLY; + + if (state[SEARCH_CRYPTODISK_ONLY].set) + flags |= SEARCH_FLAGS_CRYPTODISK_ONLY; if (state[SEARCH_LABEL].set) - grub_search_label (id, var, state[SEARCH_NO_FLOPPY].set, - hints, nhints); + grub_search_label (id, var, flags, hints, nhints); else if (state[SEARCH_FS_UUID].set) - grub_search_fs_uuid (id, var, state[SEARCH_NO_FLOPPY].set, - hints, nhints); + grub_search_fs_uuid (id, var, flags, hints, nhints); else if (state[SEARCH_FILE].set) - grub_search_fs_file (id, var, state[SEARCH_NO_FLOPPY].set, - hints, nhints); + grub_search_fs_file (id, var, flags, hints, nhints); else - return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); + grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); +out: + grub_free (hints); return grub_errno; } @@ -199,7 +215,7 @@ GRUB_MOD_INIT(search) cmd = grub_register_extcmd ("search", grub_cmd_search, GRUB_COMMAND_FLAG_EXTRACTOR | GRUB_COMMAND_ACCEPT_DASH, - N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]" + N_("[-f|-l|-u|-s|-n] [--cryptodisk-only] [--hint HINT [--hint HINT] ...]" " NAME"), N_("Search devices by file, filesystem label" " or filesystem UUID." diff --git a/grub-core/commands/setpci.c b/grub-core/commands/setpci.c index fcfec4058..5917625f8 100644 --- a/grub-core/commands/setpci.c +++ b/grub-core/commands/setpci.c @@ -83,8 +83,9 @@ static int regsize; static grub_uint16_t regaddr; static const char *varname; -static int NESTED_FUNC_ATTR -grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) +static int +grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { grub_uint32_t regval = 0; grub_pci_address_t addr; @@ -128,7 +129,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) if (!write_mask) { - grub_printf (_("Register %x of %d:%d.%d is %x\n"), regaddr, + grub_printf (_("Register %x of %x:%02x.%x is %x\n"), regaddr, grub_pci_get_bus (dev), grub_pci_get_device (dev), grub_pci_get_function (dev), @@ -168,7 +169,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (ctxt->state[0].set) { ptr = ctxt->state[0].arg; - pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff); + pciid_check_value |= (grub_strtoul (ptr, &ptr, 16) & 0xffff); if (grub_errno == GRUB_ERR_BAD_NUMBER) { grub_errno = GRUB_ERR_NONE; @@ -181,8 +182,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (*ptr != ':') return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':'); ptr++; - pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff) - << 16; + pciid_check_value |= (grub_strtoul (ptr, &ptr, 16) & 0xffff) << 16; if (grub_errno == GRUB_ERR_BAD_NUMBER) grub_errno = GRUB_ERR_NONE; else @@ -196,10 +196,10 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (ctxt->state[1].set) { const char *optr; - + ptr = ctxt->state[1].arg; optr = ptr; - bus = grub_strtoul (ptr, (char **) &ptr, 16); + bus = grub_strtoul (ptr, &ptr, 16); if (grub_errno == GRUB_ERR_BAD_NUMBER) { grub_errno = GRUB_ERR_NONE; @@ -213,7 +213,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':'); ptr++; optr = ptr; - device = grub_strtoul (ptr, (char **) &ptr, 16); + device = grub_strtoul (ptr, &ptr, 16); if (grub_errno == GRUB_ERR_BAD_NUMBER) { grub_errno = GRUB_ERR_NONE; @@ -224,7 +224,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (*ptr == '.') { ptr++; - function = grub_strtoul (ptr, (char **) &ptr, 16); + function = grub_strtoul (ptr, &ptr, 16); if (grub_errno) return grub_errno; check_function = 1; @@ -252,7 +252,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (i == ARRAY_SIZE (pci_registers)) { regsize = 0; - regaddr = grub_strtoul (ptr, (char **) &ptr, 16); + regaddr = grub_strtoul (ptr, &ptr, 16); if (grub_errno) return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown register"); } @@ -269,7 +269,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (*ptr == '+') { ptr++; - regaddr += grub_strtoul (ptr, (char **) &ptr, 16); + regaddr += grub_strtoul (ptr, &ptr, 16); if (grub_errno) return grub_errno; } @@ -301,17 +301,16 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (*ptr == '=') { ptr++; - regwrite = grub_strtoul (ptr, (char **) &ptr, 16); + regwrite = grub_strtoul (ptr, &ptr, 16); if (grub_errno) return grub_errno; write_mask = 0xffffffff; if (*ptr == ':') { ptr++; - write_mask = grub_strtoul (ptr, (char **) &ptr, 16); + write_mask = grub_strtoul (ptr, &ptr, 16); if (grub_errno) return grub_errno; - write_mask = 0xffffffff; } regwrite &= write_mask; } @@ -320,7 +319,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) return grub_error (GRUB_ERR_BAD_ARGUMENT, "option -v isn't valid for writes"); - grub_pci_iterate (grub_setpci_iter); + grub_pci_iterate (grub_setpci_iter, NULL); return GRUB_ERR_NONE; } @@ -328,10 +327,10 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(setpci) { - cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, 0, - N_("[-s POSITION] [-d DEVICE] [-v VAR] " - "[REGISTER][=VALUE[:MASK]]"), - N_("Manipulate PCI devices."), options); + cmd = grub_register_extcmd_lockdown ("setpci", grub_cmd_setpci, 0, + N_("[-s POSITION] [-d DEVICE] [-v VAR] " + "REGISTER[=VALUE[:MASK]]"), + N_("Manipulate PCI devices."), options); } GRUB_MOD_FINI(setpci) diff --git a/grub-core/commands/sleep.c b/grub-core/commands/sleep.c index 98e6280a5..a1370b710 100644 --- a/grub-core/commands/sleep.c +++ b/grub-core/commands/sleep.c @@ -34,7 +34,7 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -static grub_uint16_t *pos; +static struct grub_term_coordinate *pos; static void do_print (int n) @@ -55,7 +55,7 @@ grub_interruptible_millisleep (grub_uint32_t ms) start = grub_get_time_ms (); while (grub_get_time_ms () - start < ms) - if (grub_getkey_noblock () == GRUB_TERM_ESC) + if (grub_key_is_interrupt (grub_getkey_noblock ())) return 1; return 0; @@ -78,6 +78,8 @@ grub_cmd_sleep (grub_extcmd_context_t ctxt, int argc, char **args) return 0; } + grub_refresh (); + pos = grub_term_save_pos (); for (; n; n--) diff --git a/grub-core/commands/smbios.c b/grub-core/commands/smbios.c new file mode 100644 index 000000000..1a9086ddd --- /dev/null +++ b/grub-core/commands/smbios.c @@ -0,0 +1,398 @@ +/* smbios.c - retrieve smbios information. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2019 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* Abstract useful values found in either the SMBIOS3 or SMBIOS EPS. */ +static struct { + grub_addr_t start; + grub_addr_t end; + grub_uint16_t structures; +} table_desc; + +static grub_extcmd_t cmd; + +/* Locate the SMBIOS entry point structure depending on the hardware. */ +struct grub_smbios_eps * +grub_smbios_get_eps (void) +{ + static struct grub_smbios_eps *eps = NULL; + + if (eps != NULL) + return eps; + + eps = grub_machine_smbios_get_eps (); + + return eps; +} + +/* Locate the SMBIOS3 entry point structure depending on the hardware. */ +static struct grub_smbios_eps3 * +grub_smbios_get_eps3 (void) +{ + static struct grub_smbios_eps3 *eps = NULL; + + if (eps != NULL) + return eps; + + eps = grub_machine_smbios_get_eps3 (); + + return eps; +} + +static char * +linux_string (const char *value) +{ + char *out = grub_malloc( grub_strlen (value) + 1); + const char *src = value; + char *dst = out; + + for (; *src; src++) + if (*src > ' ' && *src < 127 && *src != ':') + *dst++ = *src; + + *dst = 0; + return out; +} + +/* + * These functions convert values from the various SMBIOS structure field types + * into a string formatted to be returned to the user. They expect that the + * structure and offset were already validated. When the requested data is + * successfully retrieved and formatted, the pointer to the string is returned; + * otherwise, NULL is returned on failure. Don't free the result. + */ + +static const char * +grub_smbios_format_byte (const grub_uint8_t *structure, grub_uint8_t offset) +{ + static char buffer[sizeof ("255")]; + + grub_snprintf (buffer, sizeof (buffer), "%u", structure[offset]); + + return (const char *)buffer; +} + +static const char * +grub_smbios_format_word (const grub_uint8_t *structure, grub_uint8_t offset) +{ + static char buffer[sizeof ("65535")]; + + grub_uint16_t value = grub_get_unaligned16 (structure + offset); + grub_snprintf (buffer, sizeof (buffer), "%u", value); + + return (const char *)buffer; +} + +static const char * +grub_smbios_format_dword (const grub_uint8_t *structure, grub_uint8_t offset) +{ + static char buffer[sizeof ("4294967295")]; + + grub_uint32_t value = grub_get_unaligned32 (structure + offset); + grub_snprintf (buffer, sizeof (buffer), "%" PRIuGRUB_UINT32_T, value); + + return (const char *)buffer; +} + +static const char * +grub_smbios_format_qword (const grub_uint8_t *structure, grub_uint8_t offset) +{ + static char buffer[sizeof ("18446744073709551615")]; + + grub_uint64_t value = grub_get_unaligned64 (structure + offset); + grub_snprintf (buffer, sizeof (buffer), "%" PRIuGRUB_UINT64_T, value); + + return (const char *)buffer; +} + +static const char * +grub_smbios_get_string (const grub_uint8_t *structure, grub_uint8_t offset) +{ + const grub_uint8_t *ptr = structure + structure[1]; + const grub_uint8_t *table_end = (const grub_uint8_t *)table_desc.end; + const grub_uint8_t referenced_string_number = structure[offset]; + grub_uint8_t i; + + /* A string referenced with zero is interpreted as unset. */ + if (referenced_string_number == 0) + return NULL; + + /* Search the string set. */ + for (i = 1; *ptr != 0 && ptr < table_end; i++) + if (i == referenced_string_number) + { + const char *str = (const char *)ptr; + while (*ptr++ != 0) + if (ptr >= table_end) + return NULL; /* The string isn't terminated. */ + return str; + } + else + while (*ptr++ != 0 && ptr < table_end); + + /* The string number is greater than the number of strings in the set. */ + return NULL; +} + +static const char * +grub_smbios_format_uuid (const grub_uint8_t *structure, grub_uint8_t offset) +{ + static char buffer[sizeof ("ffffffff-ffff-ffff-ffff-ffffffffffff")]; + const grub_uint8_t *f = structure + offset; /* little-endian fields */ + const grub_uint8_t *g = f + 8; /* byte-by-byte fields */ + + grub_snprintf (buffer, sizeof (buffer), + "%02x%02x%02x%02x-%02x%02x-%02x%02x-" + "%02x%02x-%02x%02x%02x%02x%02x%02x", + f[3], f[2], f[1], f[0], f[5], f[4], f[7], f[6], + g[0], g[1], g[2], g[3], g[4], g[5], g[6], g[7]); + + return (const char *)buffer; +} + +/* List the field formatting functions and the number of bytes they need. */ +static const struct { + const char *(*format) (const grub_uint8_t *structure, grub_uint8_t offset); + grub_uint8_t field_length; +} field_extractors[] = { + {grub_smbios_format_byte, 1}, + {grub_smbios_format_word, 2}, + {grub_smbios_format_dword, 4}, + {grub_smbios_format_qword, 8}, + {grub_smbios_get_string, 1}, + {grub_smbios_format_uuid, 16} +}; + +/* List command options, with structure field getters ordered as above. */ +#define FIRST_GETTER_OPT (3) +#define SETTER_OPT (FIRST_GETTER_OPT + ARRAY_SIZE(field_extractors)) +#define LINUX_OPT (FIRST_GETTER_OPT + ARRAY_SIZE(field_extractors) + 1) + +static const struct grub_arg_option options[] = { + {"type", 't', 0, N_("Match structures with the given type."), + N_("type"), ARG_TYPE_INT}, + {"handle", 'h', 0, N_("Match structures with the given handle."), + N_("handle"), ARG_TYPE_INT}, + {"match", 'm', 0, N_("Select a structure when several match."), + N_("match"), ARG_TYPE_INT}, + {"get-byte", 'b', 0, N_("Get the byte's value at the given offset."), + N_("offset"), ARG_TYPE_INT}, + {"get-word", 'w', 0, N_("Get two bytes' value at the given offset."), + N_("offset"), ARG_TYPE_INT}, + {"get-dword", 'd', 0, N_("Get four bytes' value at the given offset."), + N_("offset"), ARG_TYPE_INT}, + {"get-qword", 'q', 0, N_("Get eight bytes' value at the given offset."), + N_("offset"), ARG_TYPE_INT}, + {"get-string", 's', 0, N_("Get the string specified at the given offset."), + N_("offset"), ARG_TYPE_INT}, + {"get-uuid", 'u', 0, N_("Get the UUID's value at the given offset."), + N_("offset"), ARG_TYPE_INT}, + {"set", '\0', 0, N_("Store the value in the given variable name."), + N_("variable"), ARG_TYPE_STRING}, + {"linux", '\0', 0, N_("Filter the result like linux does."), + N_("variable"), ARG_TYPE_NONE}, + {0, 0, 0, 0, 0, 0} +}; + +/* + * Return a matching SMBIOS structure. + * + * This method can use up to three criteria for selecting a structure: + * - The "type" field (use -1 to ignore) + * - The "handle" field (use -1 to ignore) + * - Which to return if several match (use 0 to ignore) + * + * The return value is a pointer to the first matching structure. If no + * structures match the given parameters, NULL is returned. + */ +static const grub_uint8_t * +grub_smbios_match_structure (const grub_int16_t type, + const grub_int32_t handle, + const grub_uint16_t match) +{ + const grub_uint8_t *ptr = (const grub_uint8_t *)table_desc.start; + const grub_uint8_t *table_end = (const grub_uint8_t *)table_desc.end; + grub_uint16_t structures = table_desc.structures; + grub_uint16_t structure_count = 0; + grub_uint16_t matches = 0; + + while (ptr < table_end + && ptr[1] >= 4 /* Valid structures include the 4-byte header. */ + && (structure_count++ < structures || structures == 0)) + { + grub_uint16_t structure_handle = grub_get_unaligned16 (ptr + 2); + grub_uint8_t structure_type = ptr[0]; + + if ((handle < 0 || handle == structure_handle) + && (type < 0 || type == structure_type) + && (match == 0 || match == ++matches)) + return ptr; + else + { + ptr += ptr[1]; + while ((*ptr++ != 0 || *ptr++ != 0) && ptr < table_end); + } + + if (structure_type == GRUB_SMBIOS_TYPE_END_OF_TABLE) + break; + } + + return NULL; +} + +static grub_err_t +grub_cmd_smbios (grub_extcmd_context_t ctxt, + int argc __attribute__ ((unused)), + char **argv __attribute__ ((unused))) +{ + struct grub_arg_list *state = ctxt->state; + + grub_int16_t type = -1; + grub_int32_t handle = -1; + grub_uint16_t match = 0; + grub_uint8_t offset = 0; + + const grub_uint8_t *structure; + const char *value; + char *modified_value = NULL; + grub_int32_t option; + grub_int8_t field_type = -1; + grub_uint8_t i; + + if (table_desc.start == 0) + return grub_error (GRUB_ERR_IO, + N_("the SMBIOS entry point structure was not found")); + + /* Read the given filtering options. */ + if (state[0].set) + { + option = grub_strtol (state[0].arg, NULL, 0); + if (option < 0 || option > 255) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("the type must be between 0 and 255")); + type = (grub_int16_t)option; + } + if (state[1].set) + { + option = grub_strtol (state[1].arg, NULL, 0); + if (option < 0 || option > 65535) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("the handle must be between 0 and 65535")); + handle = (grub_int32_t)option; + } + if (state[2].set) + { + option = grub_strtol (state[2].arg, NULL, 0); + if (option <= 0 || option > 65535) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("the match must be a positive integer")); + match = (grub_uint16_t)option; + } + + /* Determine the data type of the structure field to retrieve. */ + for (i = 0; i < ARRAY_SIZE(field_extractors); i++) + if (state[FIRST_GETTER_OPT + i].set) + { + if (field_type >= 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("only one --get option is usable at a time")); + field_type = i; + } + + /* Require a choice of a structure field to return. */ + if (field_type < 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("one of the --get options is required")); + + /* Locate a matching SMBIOS structure. */ + structure = grub_smbios_match_structure (type, handle, match); + if (structure == NULL) + return grub_error (GRUB_ERR_IO, + N_("no structure matched the given options")); + + /* Ensure the requested byte offset is inside the structure. */ + option = grub_strtol (state[FIRST_GETTER_OPT + field_type].arg, NULL, 0); + if (option < 0 || option >= structure[1]) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("the given offset is outside the structure")); + + /* Ensure the requested data type at the offset is inside the structure. */ + offset = (grub_uint8_t)option; + if (offset + field_extractors[field_type].field_length > structure[1]) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("the field ends outside the structure")); + + /* Format the requested structure field into a readable string. */ + value = field_extractors[field_type].format (structure, offset); + if (value == NULL) + return grub_error (GRUB_ERR_IO, + N_("failed to retrieve the structure field")); + + if (state[LINUX_OPT].set) + value = modified_value = linux_string (value); + + /* Store or print the formatted value. */ + if (state[SETTER_OPT].set) + grub_env_set (state[SETTER_OPT].arg, value); + else + grub_printf ("%s\n", value); + + grub_free(modified_value); + + return GRUB_ERR_NONE; +} + +GRUB_MOD_INIT(smbios) +{ + struct grub_smbios_eps3 *eps3; + struct grub_smbios_eps *eps; + + if ((eps3 = grub_smbios_get_eps3 ())) + { + table_desc.start = (grub_addr_t)eps3->table_address; + table_desc.end = table_desc.start + eps3->maximum_table_length; + table_desc.structures = 0; /* SMBIOS3 drops the structure count. */ + } + else if ((eps = grub_smbios_get_eps ())) + { + table_desc.start = (grub_addr_t)eps->intermediate.table_address; + table_desc.end = table_desc.start + eps->intermediate.table_length; + table_desc.structures = eps->intermediate.structures; + } + + cmd = grub_register_extcmd ("smbios", grub_cmd_smbios, 0, + N_("[-t type] [-h handle] [-m match] " + "(-b|-w|-d|-q|-s|-u) offset " + "[--set variable]"), + N_("Retrieve SMBIOS information."), options); +} + +GRUB_MOD_FINI(smbios) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/commands/syslinuxcfg.c b/grub-core/commands/syslinuxcfg.c new file mode 100644 index 000000000..7be28fada --- /dev/null +++ b/grub-core/commands/syslinuxcfg.c @@ -0,0 +1,217 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* Helper for syslinux_file. */ +static grub_err_t +syslinux_file_getline (char **line, int cont __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + *line = 0; + return GRUB_ERR_NONE; +} + +static const struct grub_arg_option options[] = + { + {"root", 'r', 0, + N_("root directory of the syslinux disk [default=/]."), + N_("DIR"), ARG_TYPE_STRING}, + {"cwd", 'c', 0, + N_("current directory of syslinux [default is parent directory of input file]."), + N_("DIR"), ARG_TYPE_STRING}, + {"isolinux", 'i', 0, N_("assume input is an isolinux configuration file."), 0, 0}, + {"pxelinux", 'p', 0, N_("assume input is a pxelinux configuration file."), 0, 0}, + {"syslinux", 's', 0, N_("assume input is a syslinux configuration file."), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; + +enum + { + OPTION_ROOT, + OPTION_CWD, + OPTION_ISOLINUX, + OPTION_PXELINUX, + OPTION_SYSLINUX + }; + +static grub_err_t +syslinux_file (grub_extcmd_context_t ctxt, const char *filename) +{ + char *result; + const char *root = ctxt->state[OPTION_ROOT].set ? ctxt->state[OPTION_ROOT].arg : "/"; + const char *cwd = ctxt->state[OPTION_CWD].set ? ctxt->state[OPTION_CWD].arg : NULL; + grub_syslinux_flavour_t flav = GRUB_SYSLINUX_UNKNOWN; + char *cwdf = NULL; + grub_menu_t menu; + + if (ctxt->state[OPTION_ISOLINUX].set) + flav = GRUB_SYSLINUX_ISOLINUX; + if (ctxt->state[OPTION_PXELINUX].set) + flav = GRUB_SYSLINUX_PXELINUX; + if (ctxt->state[OPTION_SYSLINUX].set) + flav = GRUB_SYSLINUX_SYSLINUX; + + if (!cwd) + { + char *p; + cwdf = grub_strdup (filename); + if (!cwdf) + return grub_errno; + p = grub_strrchr (cwdf, '/'); + if (!p) + { + grub_free (cwdf); + cwd = "/"; + cwdf = NULL; + } + else + { + *p = '\0'; + cwd = cwdf; + } + } + + grub_dprintf ("syslinux", + "transforming syslinux config %s, root = %s, cwd = %s\n", + filename, root, cwd); + + result = grub_syslinux_config_file (root, root, cwd, cwd, filename, flav); + if (!result) + return grub_errno; + + grub_dprintf ("syslinux", "syslinux config transformed\n"); + + menu = grub_env_get_menu (); + if (! menu) + { + menu = grub_zalloc (sizeof (*menu)); + if (! menu) + { + grub_free (result); + return grub_errno; + } + + grub_env_set_menu (menu); + } + + grub_normal_parse_line (result, syslinux_file_getline, NULL); + grub_print_error (); + grub_free (result); + grub_free (cwdf); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_syslinux_source (grub_extcmd_context_t ctxt, + int argc, char **args) +{ + int new_env, extractor; + grub_err_t ret; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + extractor = (ctxt->extcmd->cmd->name[0] == 'e'); + new_env = (ctxt->extcmd->cmd->name[extractor ? (sizeof ("extract_syslinux_entries_") - 1) + : (sizeof ("syslinux_") - 1)] == 'c'); + + if (new_env) + grub_cls (); + + if (new_env && !extractor) + grub_env_context_open (); + if (extractor) + grub_env_extractor_open (!new_env); + + ret = syslinux_file (ctxt, args[0]); + + if (new_env) + { + grub_menu_t menu; + menu = grub_env_get_menu (); + if (menu && menu->size) + grub_show_menu (menu, 1, 0); + if (!extractor) + grub_env_context_close (); + } + if (extractor) + grub_env_extractor_close (!new_env); + + return ret; +} + + +static grub_extcmd_t cmd_source, cmd_configfile; +static grub_extcmd_t cmd_source_extract, cmd_configfile_extract; + +GRUB_MOD_INIT(syslinuxcfg) +{ + cmd_source + = grub_register_extcmd ("syslinux_source", + grub_cmd_syslinux_source, 0, + N_("FILE"), + /* TRANSLATORS: "syslinux config" means + "config as used by syslinux". */ + N_("Execute syslinux config in same context"), + options); + cmd_configfile + = grub_register_extcmd ("syslinux_configfile", + grub_cmd_syslinux_source, 0, + N_("FILE"), + N_("Execute syslinux config in new context"), + options); + cmd_source_extract + = grub_register_extcmd ("extract_syslinux_entries_source", + grub_cmd_syslinux_source, 0, + N_("FILE"), + N_("Execute syslinux config in same context taking only menu entries"), + options); + cmd_configfile_extract + = grub_register_extcmd ("extract_syslinux_entries_configfile", + grub_cmd_syslinux_source, 0, + N_("FILE"), + N_("Execute syslinux config in new context taking only menu entries"), + options); +} + +GRUB_MOD_FINI(syslinuxcfg) +{ + grub_unregister_extcmd (cmd_source); + grub_unregister_extcmd (cmd_configfile); + grub_unregister_extcmd (cmd_source_extract); + grub_unregister_extcmd (cmd_configfile_extract); +} diff --git a/grub-core/commands/terminal.c b/grub-core/commands/terminal.c index 425a41126..78a140099 100644 --- a/grub-core/commands/terminal.c +++ b/grub-core/commands/terminal.c @@ -87,7 +87,7 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, i++; if (i == argc) - return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified")); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("no terminal specified")); for (; i < argc; i++) { @@ -108,9 +108,9 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, if (term) break; if (again) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("terminal `%s' isn't found"), - args[i]); + args[i]); for (aut = autoloads; aut; aut = aut->next) if (grub_strcmp (args[i], aut->name) == 0 || (grub_strcmp (args[i], "ofconsole") == 0 @@ -126,6 +126,14 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, grub_errno = GRUB_ERR_NONE; break; } + if (grub_memcmp (args[i], "serial_usb", + sizeof ("serial_usb") - 1) == 0 + && grub_term_poll_usb) + { + grub_term_poll_usb (1); + again = 1; + continue; + } if (!aut) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("terminal `%s' isn't found"), @@ -191,9 +199,9 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, grub_list_remove (GRUB_AS_LIST (term)); grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term)); - } + } } - + { struct abstract_terminal *next; for (term = *enabled; term; term = next) @@ -233,8 +241,8 @@ grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)), (struct abstract_terminal **) (void *) &grub_term_inputs, (struct abstract_terminal **) (void *) &grub_term_inputs_disabled, grub_term_input_autoload, - N_ ("Active input terminals:"), - N_ ("Available input terminals:")); + N_("Active input terminals:"), + N_("Available input terminals:")); } static grub_err_t @@ -250,8 +258,8 @@ grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)), (struct abstract_terminal **) (void *) &grub_term_outputs, (struct abstract_terminal **) (void *) &grub_term_outputs_disabled, grub_term_output_autoload, - N_ ("Active output terminals:"), - N_ ("Available output terminals:")); + N_("Active output terminals:"), + N_("Available output terminals:")); } static grub_command_t cmd_terminal_input, cmd_terminal_output; diff --git a/grub-core/commands/test.c b/grub-core/commands/test.c index 3a0e0e069..b585c3d70 100644 --- a/grub-core/commands/test.c +++ b/grub-core/commands/test.c @@ -29,123 +29,137 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Set a limit on recursion to avoid stack overflow. */ +#define MAX_TEST_RECURSION_DEPTH 100 + /* A simple implementation for signed numbers. */ static int -grub_strtosl (char *arg, char **end, int base) +grub_strtosl (char *arg, const char ** const end, int base) { if (arg[0] == '-') return -grub_strtoul (arg + 1, end, base); return grub_strtoul (arg, end, base); } -/* Parse a test expression starting from *argn. */ -static int -test_parse (char **args, int *argn, int argc) +/* Context for test_parse. */ +struct test_parse_ctx { - int ret = 0, discard = 0, invert = 0; + int invert; + int or, and; int file_exists; struct grub_dirhook_info file_info; + char *filename; +}; - auto void update_val (int val); - auto void get_fileinfo (char *pathname); +/* Take care of discarding and inverting. */ +static void +update_val (int val, struct test_parse_ctx *ctx) +{ + ctx->and = ctx->and && (ctx->invert ? ! val : val); + ctx->invert = 0; +} - /* Take care of discarding and inverting. */ - void update_val (int val) - { - if (! discard) - ret = invert ? ! val : val; - invert = discard = 0; - } +/* A hook for iterating directories. */ +static int +find_file (const char *cur_filename, const struct grub_dirhook_info *info, + void *data) +{ + struct test_parse_ctx *ctx = data; - /* Check if file exists and fetch its information. */ - void get_fileinfo (char *path) - { - char *filename, *pathname; - char *device_name; - grub_fs_t fs; - grub_device_t dev; - - /* A hook for iterating directories. */ - auto int find_file (const char *cur_filename, - const struct grub_dirhook_info *info); - int find_file (const char *cur_filename, - const struct grub_dirhook_info *info) + if ((info->case_insensitive ? grub_strcasecmp (cur_filename, ctx->filename) + : grub_strcmp (cur_filename, ctx->filename)) == 0) { - if ((info->case_insensitive ? grub_strcasecmp (cur_filename, filename) - : grub_strcmp (cur_filename, filename)) == 0) - { - file_info = *info; - file_exists = 1; - return 1; - } - return 0; + ctx->file_info = *info; + ctx->file_exists = 1; + return 1; + } + return 0; +} + +/* Check if file exists and fetch its information. */ +static void +get_fileinfo (char *path, struct test_parse_ctx *ctx) +{ + char *pathname; + char *device_name; + grub_fs_t fs; + grub_device_t dev; + + ctx->file_exists = 0; + device_name = grub_file_get_device_name (path); + dev = grub_device_open (device_name); + if (! dev) + { + grub_free (device_name); + return; } - file_exists = 0; - device_name = grub_file_get_device_name (path); - dev = grub_device_open (device_name); - if (! dev) - { - grub_free (device_name); - return; - } + fs = grub_fs_probe (dev); + if (! fs) + { + grub_free (device_name); + grub_device_close (dev); + return; + } - fs = grub_fs_probe (dev); - if (! fs) - { - grub_free (device_name); - grub_device_close (dev); - return; - } + pathname = grub_strchr (path, ')'); + if (! pathname) + pathname = path; + else + pathname++; - pathname = grub_strchr (path, ')'); - if (! pathname) - pathname = path; - else - pathname++; + /* Remove trailing '/'. */ + while (*pathname && pathname[grub_strlen (pathname) - 1] == '/') + pathname[grub_strlen (pathname) - 1] = 0; - /* Remove trailing '/'. */ - while (*pathname && pathname[grub_strlen (pathname) - 1] == '/') - pathname[grub_strlen (pathname) - 1] = 0; + /* Split into path and filename. */ + ctx->filename = grub_strrchr (pathname, '/'); + if (! ctx->filename) + { + path = grub_strdup ("/"); + ctx->filename = pathname; + } + else + { + ctx->filename++; + path = grub_strdup (pathname); + path[ctx->filename - pathname] = 0; + } - /* Split into path and filename. */ - filename = grub_strrchr (pathname, '/'); - if (! filename) - { - path = grub_strdup ("/"); - filename = pathname; - } - else - { - filename++; - path = grub_strdup (pathname); - path[filename - pathname] = 0; - } + /* It's the whole device. */ + if (! *pathname) + { + ctx->file_exists = 1; + grub_memset (&ctx->file_info, 0, sizeof (ctx->file_info)); + /* Root is always a directory. */ + ctx->file_info.dir = 1; - /* It's the whole device. */ - if (! *pathname) - { - file_exists = 1; - grub_memset (&file_info, 0, sizeof (file_info)); - /* Root is always a directory. */ - file_info.dir = 1; + /* Fetch writing time. */ + ctx->file_info.mtimeset = 0; + if (fs->fs_mtime) + { + if (! fs->fs_mtime (dev, &ctx->file_info.mtime)) + ctx->file_info.mtimeset = 1; + grub_errno = GRUB_ERR_NONE; + } + } + else + (fs->fs_dir) (dev, path, find_file, ctx); - /* Fetch writing time. */ - file_info.mtimeset = 0; - if (fs->mtime) - { - if (! fs->mtime (dev, &file_info.mtime)) - file_info.mtimeset = 1; - grub_errno = GRUB_ERR_NONE; - } - } - else - (fs->dir) (dev, path, find_file); + grub_device_close (dev); + grub_free (path); + grub_free (device_name); +} - grub_device_close (dev); - grub_free (path); - grub_free (device_name); - } +/* Parse a test expression starting from *argn. */ +static int +test_parse (char **args, int *argn, int argc, int *depth) +{ + struct test_parse_ctx ctx = { + .and = 1, + .or = 0, + .invert = 0 + }; /* Here we have the real parsing. */ while (*argn < argc) @@ -157,14 +171,16 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "=") == 0 || grub_strcmp (args[*argn + 1], "==") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) == 0, + &ctx); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], "!=") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) != 0, + &ctx); (*argn) += 3; continue; } @@ -172,28 +188,32 @@ test_parse (char **args, int *argn, int argc) /* GRUB extension: lexicographical sorting. */ if (grub_strcmp (args[*argn + 1], "<") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) < 0, + &ctx); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], "<=") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) <= 0, + &ctx); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], ">") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) > 0, + &ctx); (*argn) += 3; continue; } if (grub_strcmp (args[*argn + 1], ">=") == 0) { - update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0); + update_val (grub_strcmp (args[*argn], args[*argn + 2]) >= 0, + &ctx); (*argn) += 3; continue; } @@ -202,7 +222,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-eq") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - == grub_strtosl (args[*argn + 2], 0, 0)); + == grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -210,7 +230,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-ge") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - >= grub_strtosl (args[*argn + 2], 0, 0)); + >= grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -218,7 +238,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-gt") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - > grub_strtosl (args[*argn + 2], 0, 0)); + > grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -226,7 +246,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-le") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - <= grub_strtosl (args[*argn + 2], 0, 0)); + <= grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -234,7 +254,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-lt") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - < grub_strtosl (args[*argn + 2], 0, 0)); + < grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -242,7 +262,7 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-ne") == 0) { update_val (grub_strtosl (args[*argn], 0, 0) - != grub_strtosl (args[*argn + 2], 0, 0)); + != grub_strtosl (args[*argn + 2], 0, 0), &ctx); (*argn) += 3; continue; } @@ -265,10 +285,10 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn + 1], "-pgt") == 0) update_val (grub_strtoul (args[*argn] + i, 0, 0) - > grub_strtoul (args[*argn + 2] + i, 0, 0)); + > grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx); else update_val (grub_strtoul (args[*argn] + i, 0, 0) - < grub_strtoul (args[*argn + 2] + i, 0, 0)); + < grub_strtoul (args[*argn + 2] + i, 0, 0), &ctx); (*argn) += 3; continue; } @@ -283,22 +303,24 @@ test_parse (char **args, int *argn, int argc) int bias = 0; /* Fetch fileinfo. */ - get_fileinfo (args[*argn]); - file1 = file_info; - file1exists = file_exists; - get_fileinfo (args[*argn + 2]); + get_fileinfo (args[*argn], &ctx); + file1 = ctx.file_info; + file1exists = ctx.file_exists; + get_fileinfo (args[*argn + 2], &ctx); if (args[*argn + 1][3]) bias = grub_strtosl (args[*argn + 1] + 3, 0, 0); if (grub_memcmp (args[*argn + 1], "-nt", 3) == 0) - update_val ((file1exists && ! file_exists) - || (file1.mtimeset && file_info.mtimeset - && file1.mtime + bias > file_info.mtime)); + update_val ((file1exists && ! ctx.file_exists) + || (file1.mtimeset && ctx.file_info.mtimeset + && file1.mtime + bias > ctx.file_info.mtime), + &ctx); else - update_val ((! file1exists && file_exists) - || (file1.mtimeset && file_info.mtimeset - && file1.mtime + bias < file_info.mtime)); + update_val ((! file1exists && ctx.file_exists) + || (file1.mtimeset && ctx.file_info.mtimeset + && file1.mtime + bias < ctx.file_info.mtime), + &ctx); (*argn) += 3; continue; } @@ -310,53 +332,53 @@ test_parse (char **args, int *argn, int argc) /* File tests. */ if (grub_strcmp (args[*argn], "-d") == 0) { - get_fileinfo (args[*argn + 1]); - update_val (file_exists && file_info.dir); + get_fileinfo (args[*argn + 1], &ctx); + update_val (ctx.file_exists && ctx.file_info.dir, &ctx); (*argn) += 2; - return ret; + continue; } if (grub_strcmp (args[*argn], "-e") == 0) { - get_fileinfo (args[*argn + 1]); - update_val (file_exists); + get_fileinfo (args[*argn + 1], &ctx); + update_val (ctx.file_exists, &ctx); (*argn) += 2; - return ret; + continue; } if (grub_strcmp (args[*argn], "-f") == 0) { - get_fileinfo (args[*argn + 1]); + get_fileinfo (args[*argn + 1], &ctx); /* FIXME: check for other types. */ - update_val (file_exists && ! file_info.dir); + update_val (ctx.file_exists && ! ctx.file_info.dir, &ctx); (*argn) += 2; - return ret; + continue; } if (grub_strcmp (args[*argn], "-s") == 0) { grub_file_t file; - grub_file_filter_disable_compression (); - file = grub_file_open (args[*argn + 1]); - update_val (file && (grub_file_size (file) != 0)); + file = grub_file_open (args[*argn + 1], GRUB_FILE_TYPE_GET_SIZE + | GRUB_FILE_TYPE_NO_DECOMPRESS); + update_val (file && (grub_file_size (file) != 0), &ctx); if (file) grub_file_close (file); grub_errno = GRUB_ERR_NONE; (*argn) += 2; - return ret; + continue; } /* String tests. */ if (grub_strcmp (args[*argn], "-n") == 0) { - update_val (args[*argn + 1][0]); + update_val (args[*argn + 1][0], &ctx); (*argn) += 2; continue; } if (grub_strcmp (args[*argn], "-z") == 0) { - update_val (! args[*argn + 1][0]); + update_val (! args[*argn + 1][0], &ctx); (*argn) += 2; continue; } @@ -368,42 +390,51 @@ test_parse (char **args, int *argn, int argc) if (grub_strcmp (args[*argn], ")") == 0) { (*argn)++; - return ret; + if (*depth > 0) + (*depth)--; + + return ctx.or || ctx.and; } /* Recursively invoke if parenthesis. */ if (grub_strcmp (args[*argn], "(") == 0) { (*argn)++; - update_val (test_parse (args, argn, argc)); + + if (++(*depth) > MAX_TEST_RECURSION_DEPTH) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("max recursion depth exceeded")); + depth--; + return ctx.or || ctx.and; + } + + update_val (test_parse (args, argn, argc, depth), &ctx); continue; } if (grub_strcmp (args[*argn], "!") == 0) { - invert = ! invert; + ctx.invert = ! ctx.invert; (*argn)++; continue; } if (grub_strcmp (args[*argn], "-a") == 0) { - /* If current value is 0 second value is to be discarded. */ - discard = ! ret; (*argn)++; continue; } if (grub_strcmp (args[*argn], "-o") == 0) { - /* If current value is 1 second value is to be discarded. */ - discard = ret; + ctx.or = ctx.or || ctx.and; + ctx.and = 1; (*argn)++; continue; } /* No test found. Interpret if as just a string. */ - update_val (args[*argn][0]); + update_val (args[*argn][0], &ctx); (*argn)++; } - return ret; + return ctx.or || ctx.and; } static grub_err_t @@ -411,11 +442,12 @@ grub_cmd_test (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { int argn = 0; + int depth = 0; if (argc >= 1 && grub_strcmp (args[argc - 1], "]") == 0) argc--; - return test_parse (args, &argn, argc) ? GRUB_ERR_NONE + return test_parse (args, &argn, argc, &depth) ? GRUB_ERR_NONE : grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); } diff --git a/grub-core/commands/testload.c b/grub-core/commands/testload.c index a1bf775b8..76a8af94c 100644 --- a/grub-core/commands/testload.c +++ b/grub-core/commands/testload.c @@ -31,6 +31,22 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* Helper for grub_cmd_testload. */ +static grub_err_t +read_progress (grub_disk_addr_t sector __attribute__ ((unused)), + unsigned offset __attribute__ ((unused)), + unsigned len, + char *buf __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + for (; len >= GRUB_DISK_SECTOR_SIZE; len -= GRUB_DISK_SECTOR_SIZE) + grub_xputs ("."); + if (len) + grub_xputs ("."); + grub_refresh (); + return GRUB_ERR_NONE; +} + static grub_err_t grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)), int argc, char *argv[]) @@ -39,20 +55,11 @@ grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)), char *buf; grub_size_t size; grub_off_t pos; - auto void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector, unsigned offset, unsigned len); - - void NESTED_FUNC_ATTR read_func (grub_disk_addr_t sector __attribute__ ((unused)), - unsigned offset __attribute__ ((unused)), - unsigned len __attribute__ ((unused))) - { - grub_xputs ("."); - grub_refresh (); - } if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); - file = grub_file_open (argv[0]); + file = grub_file_open (argv[0], GRUB_FILE_TYPE_TESTLOAD); if (! file) return grub_errno; @@ -68,7 +75,7 @@ grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)), goto fail; grub_printf ("Reading %s sequentially", argv[0]); - file->read_hook = read_func; + file->read_hook = read_progress; if (grub_file_read (file, buf, size) != (grub_ssize_t) size) goto fail; grub_printf (" Done.\n"); diff --git a/grub-core/commands/testspeed.c b/grub-core/commands/testspeed.c new file mode 100644 index 000000000..c13a9b8d8 --- /dev/null +++ b/grub-core/commands/testspeed.c @@ -0,0 +1,115 @@ +/* testspeed.c - Command to test file read speed */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define DEFAULT_BLOCK_SIZE 65536 + +static const struct grub_arg_option options[] = + { + {"size", 's', 0, N_("Specify size for each read operation"), 0, ARG_TYPE_INT}, + {0, 0, 0, 0, 0, 0} + }; + +static grub_err_t +grub_cmd_testspeed (grub_extcmd_context_t ctxt, int argc, char **args) +{ + struct grub_arg_list *state = ctxt->state; + grub_uint64_t start; + grub_uint64_t end; + grub_ssize_t block_size; + grub_disk_addr_t total_size; + char *buffer; + grub_file_t file; + grub_uint64_t whole, fraction; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + block_size = (state[0].set) ? + grub_strtoul (state[0].arg, 0, 0) : DEFAULT_BLOCK_SIZE; + + if (block_size <= 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid block size")); + + buffer = grub_malloc (block_size); + if (buffer == NULL) + return grub_errno; + + file = grub_file_open (args[0], GRUB_FILE_TYPE_TESTLOAD); + if (file == NULL) + goto quit; + + total_size = 0; + start = grub_get_time_ms (); + while (1) + { + grub_ssize_t size = grub_file_read (file, buffer, block_size); + if (size <= 0) + break; + total_size += size; + } + end = grub_get_time_ms (); + grub_file_close (file); + + grub_printf_ (N_("File size: %s\n"), + grub_get_human_size (total_size, GRUB_HUMAN_SIZE_NORMAL)); + whole = grub_divmod64 (end - start, 1000, &fraction); + grub_printf_ (N_("Elapsed time: %d.%03d s \n"), + (unsigned) whole, + (unsigned) fraction); + + if (end != start) + { + grub_uint64_t speed = + grub_divmod64 (total_size * 100ULL * 1000ULL, end - start, 0); + + grub_printf_ (N_("Speed: %s \n"), + grub_get_human_size (speed, + GRUB_HUMAN_SIZE_SPEED)); + } + + quit: + grub_free (buffer); + + return grub_errno; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(testspeed) +{ + cmd = grub_register_extcmd ("testspeed", grub_cmd_testspeed, 0, N_("[-s SIZE] FILENAME"), + N_("Test file read speed."), + options); +} + +GRUB_MOD_FINI(testspeed) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/commands/tpm.c b/grub-core/commands/tpm.c new file mode 100644 index 000000000..dde74ab83 --- /dev/null +++ b/grub-core/commands/tpm.c @@ -0,0 +1,125 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + * + * Core TPM support code. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_tpm_verify_init (grub_file_t io, + enum grub_file_type type __attribute__ ((unused)), + void **context, enum grub_verify_flags *flags) +{ + *context = io->name; + *flags |= GRUB_VERIFY_FLAGS_SINGLE_CHUNK; + + /* + * The loopback image is mapped as a disk allowing it to function like + * a block device. However, we measure files read from the block device + * not the device itself. For example, we don't measure block devices like + * hd0 disk directly. This process is crucial to prevent out-of-memory + * errors as loopback images are inherently large. + */ + if ((type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_LOOPBACK) + *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_tpm_verify_write (void *context, void *buf, grub_size_t size) +{ + grub_err_t status = grub_tpm_measure (buf, size, GRUB_BINARY_PCR, context); + + if (status == GRUB_ERR_NONE) + return GRUB_ERR_NONE; + + grub_dprintf ("tpm", "Measuring buffer failed: %d\n", status); + return grub_is_tpm_fail_fatal () ? status : GRUB_ERR_NONE; +} + +static grub_err_t +grub_tpm_verify_string (char *str, enum grub_verify_string_type type) +{ + const char *prefix = NULL; + char *description; + grub_err_t status; + + switch (type) + { + case GRUB_VERIFY_KERNEL_CMDLINE: + prefix = "kernel_cmdline: "; + break; + case GRUB_VERIFY_MODULE_CMDLINE: + prefix = "module_cmdline: "; + break; + case GRUB_VERIFY_COMMAND: + prefix = "grub_cmd: "; + break; + } + description = grub_malloc (grub_strlen (str) + grub_strlen (prefix) + 1); + if (!description) + return grub_errno; + grub_memcpy (description, prefix, grub_strlen (prefix)); + grub_memcpy (description + grub_strlen (prefix), str, + grub_strlen (str) + 1); + status = + grub_tpm_measure ((unsigned char *) str, grub_strlen (str), + GRUB_STRING_PCR, description); + grub_free (description); + if (status == GRUB_ERR_NONE) + return GRUB_ERR_NONE; + + grub_dprintf ("tpm", "Measuring string %s failed: %d\n", str, status); + return grub_is_tpm_fail_fatal () ? status : GRUB_ERR_NONE; +} + +struct grub_file_verifier grub_tpm_verifier = { + .name = "tpm", + .init = grub_tpm_verify_init, + .write = grub_tpm_verify_write, + .verify_string = grub_tpm_verify_string, +}; + +GRUB_MOD_INIT (tpm) +{ + /* + * Even though this now calls ibmvtpm's grub_tpm_present() from GRUB_MOD_INIT(), + * it does seem to call it late enough in the initialization sequence so + * that whatever discovered "device nodes" before this GRUB_MOD_INIT() is + * called, enables the ibmvtpm driver to see the device nodes. + */ + if (!grub_tpm_present()) + return; + grub_verifier_register (&grub_tpm_verifier); +} + +GRUB_MOD_FINI (tpm) +{ + if (!grub_tpm_present()) + return; + grub_verifier_unregister (&grub_tpm_verifier); +} diff --git a/grub-core/commands/tpm2_key_protector/args.c b/grub-core/commands/tpm2_key_protector/args.c new file mode 100644 index 000000000..48c39de01 --- /dev/null +++ b/grub-core/commands/tpm2_key_protector/args.c @@ -0,0 +1,127 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Microsoft Corporation + * Copyright (C) 2024 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include + +#include "tpm2_args.h" + +grub_err_t +grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs, + grub_uint8_t *pcr_count) +{ + char *current_pcr = value; + char *next_pcr; + const char *pcr_end; + grub_uint64_t pcr; + grub_uint8_t i; + + if (grub_strlen (value) == 0) + return GRUB_ERR_BAD_ARGUMENT; + + *pcr_count = 0; + for (i = 0; i < TPM_MAX_PCRS; i++) + { + next_pcr = grub_strchr (current_pcr, ','); + if (next_pcr == current_pcr) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("empty entry in PCR list")); + if (next_pcr != NULL) + *next_pcr = '\0'; + + pcr = grub_strtoul (current_pcr, &pcr_end, 10); + if (*current_pcr == '\0' || *pcr_end != '\0') + return grub_error (GRUB_ERR_BAD_NUMBER, N_("entry '%s' in PCR list is not a number"), current_pcr); + + if (pcr > TPM_MAX_PCRS - 1) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("entry %llu in PCR list is too large to be a PCR number, PCR numbers range from 0 to %u"), (unsigned long long)pcr, TPM_MAX_PCRS - 1); + + pcrs[i] = (grub_uint8_t) pcr; + ++(*pcr_count); + + if (next_pcr == NULL) + break; + + current_pcr = next_pcr + 1; + if (*current_pcr == '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("trailing comma at the end of PCR list")); + } + + if (i == TPM_MAX_PCRS) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("too many PCRs in PCR list, the maximum number of PCRs is %u"), TPM_MAX_PCRS); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_tpm2_protector_parse_asymmetric (const char *value, + grub_srk_type_t *srk_type) +{ + if (grub_strcasecmp (value, "ECC") == 0 || + grub_strcasecmp (value, "ECC_NIST_P256") == 0) + { + srk_type->type = TPM_ALG_ECC; + srk_type->detail.ecc_curve = TPM_ECC_NIST_P256; + } + else if (grub_strcasecmp (value, "RSA") == 0 || + grub_strcasecmp (value, "RSA2048") == 0) + { + srk_type->type = TPM_ALG_RSA; + srk_type->detail.rsa_bits = 2048; + } + else + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value '%s' is not a valid asymmetric key type"), value); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID_t *bank) +{ + if (grub_strcasecmp (value, "SHA1") == 0) + *bank = TPM_ALG_SHA1; + else if (grub_strcasecmp (value, "SHA256") == 0) + *bank = TPM_ALG_SHA256; + else if (grub_strcasecmp (value, "SHA384") == 0) + *bank = TPM_ALG_SHA384; + else if (grub_strcasecmp (value, "SHA512") == 0) + *bank = TPM_ALG_SHA512; + else + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value '%s' is not a valid PCR bank"), value); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE_t *handle) +{ + grub_uint64_t num; + const char *str_end; + + num = grub_strtoul (value, &str_end, 0); + if (*value == '\0' || *str_end != '\0') + return grub_error (GRUB_ERR_BAD_NUMBER, N_("TPM handle value '%s' is not a number"), value); + + if (num > GRUB_UINT_MAX) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value %llu is too large to be a TPM handle, TPM handles are unsigned 32-bit integers"), (unsigned long long)num); + + *handle = (TPM_HANDLE_t) num; + + return GRUB_ERR_NONE; +} diff --git a/grub-core/commands/tpm2_key_protector/module.c b/grub-core/commands/tpm2_key_protector/module.c new file mode 100644 index 000000000..857f3753f --- /dev/null +++ b/grub-core/commands/tpm2_key_protector/module.c @@ -0,0 +1,1489 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Microsoft Corporation + * Copyright (C) 2024 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "tpm2_args.h" +#include "tpm2.h" +#include "tpm2key.h" + +GRUB_MOD_LICENSE ("GPLv3+"); + +typedef enum tpm2_protector_mode +{ + TPM2_PROTECTOR_MODE_UNSET, + TPM2_PROTECTOR_MODE_SRK, + TPM2_PROTECTOR_MODE_NV +} tpm2_protector_mode_t; + +typedef enum tpm2_protector_options +{ + OPTION_MODE, + OPTION_PCRS, + OPTION_BANK, + OPTION_TPM2KEY, + OPTION_KEYFILE, + OPTION_SRK, + OPTION_ASYMMETRIC, + OPTION_NVINDEX +} tpm2_protector_options_t; + +typedef struct tpm2_protector_context +{ + tpm2_protector_mode_t mode; + grub_uint8_t pcrs[TPM_MAX_PCRS]; + grub_uint8_t pcr_count; + grub_srk_type_t srk_type; + TPM_ALG_ID_t bank; + const char *tpm2key; + const char *keyfile; + TPM_HANDLE_t srk; + TPM_HANDLE_t nv; +} tpm2_protector_context_t; + +static const struct grub_arg_option tpm2_protector_init_cmd_options[] = + { + /* Options for all modes */ + { + .longarg = "mode", + .shortarg = 'm', + .flags = 0, + .arg = NULL, + .type = ARG_TYPE_STRING, + .doc = + N_("Unseal key using SRK ('srk') (default) or retrieve it from an NV " + "Index ('nv')."), + }, + { + .longarg = "pcrs", + .shortarg = 'p', + .flags = 0, + .arg = NULL, + .type = ARG_TYPE_STRING, + .doc = + N_("Comma-separated list of PCRs used to authorize key release " + "e.g., '7,11'. (default: 7)"), + }, + { + .longarg = "bank", + .shortarg = 'b', + .flags = 0, + .arg = NULL, + .type = ARG_TYPE_STRING, + .doc = + N_("Bank of PCRs used to authorize key release: " + "SHA1, SHA256, SHA384 or SHA512. (default: SHA256)"), + }, + /* SRK-mode options */ + { + .longarg = "tpm2key", + .shortarg = 'T', + .flags = 0, + .arg = NULL, + .type = ARG_TYPE_STRING, + .doc = + N_("In SRK mode, path to the key file in the TPM 2.0 Key File format " + "to unseal using the TPM (e.g., (hd0,gpt1)/boot/grub2/sealed.tpm)."), + }, + { + .longarg = "keyfile", + .shortarg = 'k', + .flags = 0, + .arg = NULL, + .type = ARG_TYPE_STRING, + .doc = + N_("In SRK mode, path to the key file in the raw format to unseal " + "using the TPM (e.g., (hd0,gpt1)/boot/grub2/sealed.key). " + "(Mainly for backward compatibility. Please use '--tpm2key'.)"), + }, + { + .longarg = "srk", + .shortarg = 's', + .flags = 0, + .arg = NULL, + .type = ARG_TYPE_STRING, + .doc = + N_("In SRK mode, the SRK handle if the SRK is persistent."), + }, + { + .longarg = "asymmetric", + .shortarg = 'a', + .flags = 0, + .arg = NULL, + .type = ARG_TYPE_STRING, + .doc = + N_("In SRK mode, the type of SRK: RSA (RSA2048) and ECC (ECC_NIST_P256)" + "(default: ECC)"), + }, + /* NV Index-mode options */ + { + .longarg = "nvindex", + .shortarg = 'n', + .flags = 0, + .arg = NULL, + .type = ARG_TYPE_STRING, + .doc = + N_("Required in NV Index mode, the NV handle to read which must " + "readily exist on the TPM and which contains the key."), + }, + /* End of list */ + {0, 0, 0, 0, 0, 0} + }; + +static grub_extcmd_t tpm2_protector_init_cmd; +static grub_extcmd_t tpm2_protector_clear_cmd; +static tpm2_protector_context_t tpm2_protector_ctx = {0}; + +static grub_command_t tpm2_dump_pcr_cmd; + +static grub_err_t +tpm2_protector_srk_read_file (const char *filepath, void **buffer, grub_size_t *buffer_size) +{ + grub_file_t file; + grub_off_t file_size; + void *read_buffer; + grub_off_t read_n; + grub_err_t err; + + /* + * Using GRUB_FILE_TYPE_SIGNATURE ensures we do not hash the keyfile into PCR9 + * otherwise we'll never be able to predict the value of PCR9 at unseal time + */ + file = grub_file_open (filepath, GRUB_FILE_TYPE_SIGNATURE); + if (file == NULL) + { + /* Push errno from grub_file_open() into the error message stack */ + grub_error_push(); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("could not open file: %s"), filepath); + goto error; + } + + file_size = grub_file_size (file); + if (file_size == 0) + { + err = grub_error (GRUB_ERR_OUT_OF_RANGE, N_("could not read file size: %s"), filepath); + goto error; + } + + read_buffer = grub_malloc (file_size); + if (read_buffer == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("could not allocate buffer for %s"), filepath); + goto error; + } + + read_n = grub_file_read (file, read_buffer, file_size); + if (read_n != file_size) + { + grub_free (read_buffer); + err = grub_error (GRUB_ERR_FILE_READ_ERROR, N_("could not retrieve file contents: %s"), filepath); + goto error; + } + + *buffer = read_buffer; + *buffer_size = file_size; + + err = GRUB_ERR_NONE; + + error: + if (file != NULL) + grub_file_close (file); + + return err; +} + +/* Check if the data is in TPM 2.0 Key File format */ +static bool +tpm2_protector_is_tpm2key (grub_uint8_t *buffer, grub_size_t buffer_size) +{ + /* id-sealedkey OID (2.23.133.10.1.5) in DER */ + const grub_uint8_t sealed_key_oid[] = {0x06, 0x06, 0x67, 0x81, 0x05, 0x0a}; + grub_size_t skip = 0; + + /* Need at least the first two bytes to check the tag and the length */ + if (buffer_size < 2) + return false; + + /* The first byte is always 0x30 (SEQUENCE). */ + if (buffer[0] != 0x30) + return false; + + /* + * Get the bytes of the length + * + * If the bit 8 of the second byte is 0, it is in the short form, so the second byte + * alone represents the length. Thus, the first two bytes are skipped. + * + * Otherwise, it is in the long form, and bits 1~7 indicate how many more bytes are in + * the length field, so we skip the first two bytes plus the bytes for the length. + */ + if ((buffer[1] & 0x80) == 0) + skip = 2; + else + skip = (buffer[1] & 0x7F) + 2; + + /* Make sure the buffer is large enough to contain id-sealedkey OID */ + if (buffer_size < skip + sizeof (sealed_key_oid)) + return false; + + /* Check id-sealedkey OID */ + if (grub_memcmp (buffer + skip, sealed_key_oid, sizeof (sealed_key_oid)) != 0) + return false; + + return true; +} + +static grub_err_t +tpm2_protector_unmarshal_raw (void *sealed_key, + grub_size_t sealed_key_size, + tpm2_sealed_key_t *sk) +{ + struct grub_tpm2_buffer buf; + + grub_tpm2_buffer_init (&buf); + if (sealed_key_size > buf.cap) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("sealed key larger than %llu bytes"), (unsigned long long)buf.cap); + + grub_memcpy (buf.data, sealed_key, sealed_key_size); + buf.size = sealed_key_size; + + grub_Tss2_MU_TPM2B_PUBLIC_Unmarshal (&buf, &sk->public); + grub_Tss2_MU_TPM2B_PRIVATE_Unmarshal (&buf, &sk->private); + + if (buf.error != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("malformed TPM wire key file")); + + return GRUB_ERR_NONE; +} + +static grub_err_t +tpm2_protector_unmarshal_tpm2key (void *sealed_key, + grub_size_t sealed_key_size, + tpm2key_policy_t *policy_seq, + tpm2key_authpolicy_t *authpol_seq, + grub_uint8_t *rsaparent, + grub_uint32_t *parent, + tpm2_sealed_key_t *sk) +{ + asn1_node tpm2key = NULL; + grub_uint8_t rsaparent_tmp; + grub_uint32_t parent_tmp; + void *sealed_pub = NULL; + grub_size_t sealed_pub_size; + void *sealed_priv = NULL; + grub_size_t sealed_priv_size; + struct grub_tpm2_buffer buf; + grub_err_t err; + + /* + * Start to parse the tpm2key file + * TPMKey ::= SEQUENCE { + * type OBJECT IDENTIFIER, + * emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL, + * policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL, + * secret [2] EXPLICIT OCTET STRING OPTIONAL, + * authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL, + * description [4] EXPLICIT UTF8String OPTIONAL, + * rsaParent [5] EXPLICIT BOOLEAN OPTIONAL, + * parent INTEGER, + * pubkey OCTET STRING, + * privkey OCTET STRING + * } + */ + err = grub_tpm2key_start_parsing (&tpm2key, sealed_key, sealed_key_size); + if (err != GRUB_ERR_NONE) + return err; + + /* + * Retrieve the policy sequence from 'policy' + * policy_seq will be NULL when 'policy' is not available + */ + err = grub_tpm2key_get_policy_seq (tpm2key, policy_seq); + if (err != GRUB_ERR_NONE) + goto error; + + /* + * Retrieve the authpolicy sequence from 'authPolicy' + * authpol_seq will be NULL when 'authPolicy' is not available + */ + err = grub_tpm2key_get_authpolicy_seq (tpm2key, authpol_seq); + if (err != GRUB_ERR_NONE) + goto error; + + /* Retrieve rsaParent */ + err = grub_tpm2key_get_rsaparent (tpm2key, &rsaparent_tmp); + if (err != GRUB_ERR_NONE) + goto error; + + *rsaparent = rsaparent_tmp; + + /* Retrieve the parent handle */ + err = grub_tpm2key_get_parent (tpm2key, &parent_tmp); + if (err != GRUB_ERR_NONE) + goto error; + + /* The parent handle should be either PERMANENT or PERSISTENT. */ + if (!TPM_HT_IS_PERMANENT (parent_tmp) && !TPM_HT_IS_PERSISTENT (parent_tmp)) + { + err = GRUB_ERR_OUT_OF_RANGE; + goto error; + } + + *parent = parent_tmp; + + /* Retrieve the public part of the sealed key */ + err = grub_tpm2key_get_pubkey (tpm2key, &sealed_pub, &sealed_pub_size); + if (err != GRUB_ERR_NONE) + goto error; + + /* Retrieve the private part of the sealed key */ + err = grub_tpm2key_get_privkey (tpm2key, &sealed_priv, &sealed_priv_size); + if (err != GRUB_ERR_NONE) + goto error; + + /* Unmarshal the sealed key */ + grub_tpm2_buffer_init (&buf); + if (sealed_pub_size + sealed_priv_size > buf.cap) + { + err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("sealed key larger than %llu bytes"), (unsigned long long)buf.cap); + goto error; + } + + grub_tpm2_buffer_pack (&buf, sealed_pub, sealed_pub_size); + grub_tpm2_buffer_pack (&buf, sealed_priv, sealed_priv_size); + + buf.offset = 0; + + grub_Tss2_MU_TPM2B_PUBLIC_Unmarshal (&buf, &sk->public); + grub_Tss2_MU_TPM2B_PRIVATE_Unmarshal (&buf, &sk->private); + + if (buf.error != 0) + { + err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("malformed TPM 2.0 key file")); + goto error; + } + + err = GRUB_ERR_NONE; + + error: + /* End the parsing */ + grub_tpm2key_end_parsing (tpm2key); + grub_free (sealed_pub); + grub_free (sealed_priv); + + return err; +} + +/* Check if the SRK exists in the specified handle */ +static grub_err_t +tpm2_protector_srk_check (const TPM_HANDLE_t srk_handle) +{ + TPM_RC_t rc; + TPM2B_PUBLIC_t public; + + /* Find SRK */ + rc = grub_tpm2_readpublic (srk_handle, NULL, &public); + if (rc == TPM_RC_SUCCESS) + return GRUB_ERR_NONE; + + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to retrieve SRK from 0x%x (TPM2_ReadPublic: 0x%x)", srk_handle, rc); +} + +/* Get the SRK with the template */ +static grub_err_t +tpm2_protector_srk_get (const grub_srk_type_t srk_type, + const TPM_HANDLE_t parent, + TPM_HANDLE_t *srk_handle) +{ + TPM_RC_t rc; + TPMT_PUBLIC_PARMS_t parms = {0}; + TPMS_AUTH_COMMAND_t authCommand = {0}; + TPM2B_SENSITIVE_CREATE_t inSensitive = {0}; + TPM2B_PUBLIC_t inPublic = {0}; + TPM2B_DATA_t outsideInfo = {0}; + TPML_PCR_SELECTION_t creationPcr = {0}; + TPM2B_PUBLIC_t outPublic = {0}; + TPM2B_CREATION_DATA_t creationData = {0}; + TPM2B_DIGEST_t creationHash = {0}; + TPMT_TK_CREATION_t creationTicket = {0}; + TPM2B_NAME_t srkName = {0}; + TPM_HANDLE_t tmp_handle = 0; + + inPublic.publicArea.type = srk_type.type; + inPublic.publicArea.nameAlg = TPM_ALG_SHA256; + inPublic.publicArea.objectAttributes.restricted = 1; + inPublic.publicArea.objectAttributes.userWithAuth = 1; + inPublic.publicArea.objectAttributes.decrypt = 1; + inPublic.publicArea.objectAttributes.fixedTPM = 1; + inPublic.publicArea.objectAttributes.fixedParent = 1; + inPublic.publicArea.objectAttributes.sensitiveDataOrigin = 1; + inPublic.publicArea.objectAttributes.noDA = 1; + + if (srk_type.type == TPM_ALG_RSA) + { + inPublic.publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES; + inPublic.publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128; + inPublic.publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_CFB; + inPublic.publicArea.parameters.rsaDetail.scheme.scheme = TPM_ALG_NULL; + inPublic.publicArea.parameters.rsaDetail.keyBits = srk_type.detail.rsa_bits; + inPublic.publicArea.parameters.rsaDetail.exponent = 0; + } + else if (srk_type.type == TPM_ALG_ECC) + { + inPublic.publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_AES; + inPublic.publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128; + inPublic.publicArea.parameters.eccDetail.symmetric.mode.aes = TPM_ALG_CFB; + inPublic.publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_NULL; + inPublic.publicArea.parameters.eccDetail.curveID = srk_type.detail.ecc_curve; + inPublic.publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL; + } + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown SRK algorithm"); + + /* Test the parameters before SRK generation */ + parms.type = srk_type.type; + grub_memcpy (&parms.parameters, &inPublic.publicArea.parameters, + sizeof (TPMU_PUBLIC_PARMS_t)); + + rc = grub_tpm2_testparms (&parms, NULL); + if (rc != TPM_RC_SUCCESS) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported SRK template (TPM2_TestParms: 0x%x)", rc); + + /* Create SRK */ + authCommand.sessionHandle = TPM_RS_PW; + rc = grub_tpm2_createprimary (parent, &authCommand, &inSensitive, &inPublic, + &outsideInfo, &creationPcr, &tmp_handle, &outPublic, + &creationData, &creationHash, &creationTicket, + &srkName, NULL); + if (rc != TPM_RC_SUCCESS) + return grub_error (GRUB_ERR_BAD_DEVICE, "could not create SRK (TPM2_CreatePrimary: 0x%x)", rc); + + *srk_handle = tmp_handle; + + return GRUB_ERR_NONE; +} + +/* + * Load the SRK from the persistent handle or create one with a given type of + * template, and then associate the sealed key with the SRK + * Return values: + * - GRUB_ERR_NONE: Everything is fine. + * - GRUB_ERR_BAD_ARGUMENT: The SRK doesn't match. Try another one. + * - Other: Something went wrong. + */ +static grub_err_t +tpm2_protector_srk_load (const grub_srk_type_t srk_type, + const tpm2_sealed_key_t *sealed_key, + const TPM_HANDLE_t parent, + TPM_HANDLE_t *sealed_handle, + TPM_HANDLE_t *srk_handle) +{ + TPMS_AUTH_COMMAND_t authCmd = {0}; + TPM2B_NAME_t name = {0}; + TPM_RC_t rc; + grub_err_t err; + + if (srk_handle == NULL) + return GRUB_ERR_BUG; + + if (*srk_handle != 0) + { + err = tpm2_protector_srk_check (*srk_handle); + if (err != GRUB_ERR_NONE) + return err; + } + else + { + err = tpm2_protector_srk_get (srk_type, parent, srk_handle); + if (err != GRUB_ERR_NONE) + return err; + } + + /* Load the sealed key and associate it with the SRK */ + authCmd.sessionHandle = TPM_RS_PW; + rc = grub_tpm2_load (*srk_handle, &authCmd, &sealed_key->private, &sealed_key->public, + sealed_handle, &name, NULL); + /* + * If TPM2_Load returns (TPM_RC_INTEGRITY | TPM_RC_P | TPM_RC_1), then it + * implies the wrong SRK is used. + */ + if (rc == (TPM_RC_INTEGRITY | TPM_RC_P | TPM_RC_1)) + { + err = grub_error (GRUB_ERR_BAD_ARGUMENT, "SRK not matched"); + goto error; + } + else if (rc != TPM_RC_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to load sealed key (TPM2_Load: 0x%x)", rc); + goto error; + } + + return GRUB_ERR_NONE; + + error: + if (!TPM_HT_IS_PERSISTENT (*srk_handle)) + grub_tpm2_flushcontext (*srk_handle); + + return err; +} + +static const char * +srk_type_to_name (grub_srk_type_t srk_type) +{ + if (srk_type.type == TPM_ALG_ECC && srk_type.detail.ecc_curve == TPM_ECC_NIST_P256) + return "ECC_NIST_P256"; + else if (srk_type.type == TPM_ALG_RSA && srk_type.detail.rsa_bits == 2048) + return "RSA2048"; + + return "Unknown"; +} + +static grub_err_t +tpm2_protector_load_key (const tpm2_protector_context_t *ctx, + const tpm2_sealed_key_t *sealed_key, + const TPM_HANDLE_t parent_handle, + TPM_HANDLE_t *sealed_handle, + TPM_HANDLE_t *srk_handle) +{ + grub_err_t err; + int i; + grub_srk_type_t fallback_srks[] = { + { + .type = TPM_ALG_ECC, + .detail.ecc_curve = TPM_ECC_NIST_P256, + }, + { + .type = TPM_ALG_RSA, + .detail.rsa_bits = 2048, + }, + { + .type = TPM_ALG_ERROR, + } + }; + + /* Try the given persistent SRK if exists */ + if (*srk_handle != 0) + { + err = tpm2_protector_srk_load (ctx->srk_type, sealed_key, + parent_handle, sealed_handle, + srk_handle); + if (err != GRUB_ERR_BAD_ARGUMENT) + return err; + + grub_print_error (); + grub_printf ("Trying the specified SRK algorithm: %s\n", srk_type_to_name (ctx->srk_type)); + grub_errno = GRUB_ERR_NONE; + *srk_handle = 0; + } + + /* Try the specified algorithm for the SRK template */ + if (*srk_handle == 0) + { + err = tpm2_protector_srk_load (ctx->srk_type, sealed_key, + parent_handle, sealed_handle, + srk_handle); + if (err != GRUB_ERR_BAD_ARGUMENT) + return err; + + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + *srk_handle = 0; + } + + /* Try all the fallback SRK templates */ + for (i = 0; fallback_srks[i].type != TPM_ALG_ERROR; i++) + { + /* Skip the specified algorithm */ + if (fallback_srks[i].type == ctx->srk_type.type && + (fallback_srks[i].detail.rsa_bits == ctx->srk_type.detail.rsa_bits || + fallback_srks[i].detail.ecc_curve == ctx->srk_type.detail.ecc_curve)) + continue; + + grub_printf ("Trying fallback %s template\n", srk_type_to_name (fallback_srks[i])); + + *srk_handle = 0; + + err = tpm2_protector_srk_load (fallback_srks[i], sealed_key, + parent_handle, sealed_handle, + srk_handle); + if (err != GRUB_ERR_BAD_ARGUMENT) + return err; + + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + + return err; +} + +static grub_err_t +tpm2_protector_policypcr (TPMI_SH_AUTH_SESSION_t session, struct grub_tpm2_buffer *cmd_buf) +{ + TPM2B_DIGEST_t pcr_digest; + TPML_PCR_SELECTION_t pcr_sel; + TPM_RC_t rc; + + grub_Tss2_MU_TPM2B_DIGEST_Unmarshal (cmd_buf, &pcr_digest); + grub_Tss2_MU_TPML_PCR_SELECTION_Unmarshal (cmd_buf, &pcr_sel); + if (cmd_buf->error != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to unmarshal commandPolicy for TPM2_PolicyPCR"); + + rc = grub_tpm2_policypcr (session, NULL, &pcr_digest, &pcr_sel, NULL); + if (rc != TPM_RC_SUCCESS) + return grub_error (GRUB_ERR_BAD_DEVICE, "failed to submit PCR policy (TPM2_PolicyPCR: 0x%x)", rc); + + return GRUB_ERR_NONE; +} + +static grub_err_t +tpm2_protector_policyauthorize (TPMI_SH_AUTH_SESSION_t session, struct grub_tpm2_buffer *cmd_buf) +{ + TPM2B_PUBLIC_t pubkey; + TPM2B_DIGEST_t policy_ref; + TPMT_SIGNATURE_t signature; + TPM2B_DIGEST_t pcr_policy; + TPM2B_DIGEST_t pcr_policy_hash; + TPMI_ALG_HASH_t sig_hash; + TPMT_TK_VERIFIED_t verification_ticket; + TPM_HANDLE_t pubkey_handle = 0; + TPM2B_NAME_t pubname; + TPM_RC_t rc; + grub_err_t err; + + grub_Tss2_MU_TPM2B_PUBLIC_Unmarshal (cmd_buf, &pubkey); + grub_Tss2_MU_TPM2B_DIGEST_Unmarshal (cmd_buf, &policy_ref); + grub_Tss2_MU_TPMT_SIGNATURE_Unmarshal (cmd_buf, &signature); + if (cmd_buf->error != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to unmarshal the buffer for TPM2_PolicyAuthorize"); + + /* Retrieve Policy Digest */ + rc = grub_tpm2_policygetdigest (session, NULL, &pcr_policy, NULL); + if (rc != TPM_RC_SUCCESS) + return grub_error (GRUB_ERR_BAD_DEVICE, "failed to get policy digest (TPM2_PolicyGetDigest: 0x%x).", rc); + + /* Calculate the digest of the polcy for VerifySignature */ + sig_hash = TPMT_SIGNATURE_get_hash_alg (&signature); + if (sig_hash == TPM_ALG_NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to get the hash algorithm of the signature"); + + rc = grub_tpm2_hash (NULL, (TPM2B_MAX_BUFFER_t *) &pcr_policy, sig_hash, + TPM_RH_NULL, &pcr_policy_hash, NULL, NULL); + if (rc != TPM_RC_SUCCESS) + return grub_error (GRUB_ERR_BAD_DEVICE, "failed to create PCR policy hash (TPM2_Hash: 0x%x)", rc); + + /* Load the public key */ + rc = grub_tpm2_loadexternal (NULL, NULL, &pubkey, TPM_RH_OWNER, &pubkey_handle, &pubname, NULL); + if (rc != TPM_RC_SUCCESS) + return grub_error (GRUB_ERR_BAD_DEVICE, "failed to load public key (TPM2_LoadExternal: 0x%x)", rc); + + /* Verify the signature against the public key and the policy digest */ + rc = grub_tpm2_verifysignature (pubkey_handle, NULL, &pcr_policy_hash, &signature, + &verification_ticket, NULL); + if (rc != TPM_RC_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to verify signature (TPM2_VerifySignature: 0x%x)", rc); + goto error; + } + + /* Authorize the signed policy with the public key and the verification ticket */ + rc = grub_tpm2_policyauthorize (session, NULL, &pcr_policy, &policy_ref, &pubname, + &verification_ticket, NULL); + if (rc != TPM_RC_SUCCESS) + { + err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to authorize PCR policy (TPM2_PolicyAuthorize: 0x%x)", rc); + goto error; + } + + err = GRUB_ERR_NONE; + + error: + grub_tpm2_flushcontext (pubkey_handle); + + return err; +} + +static grub_err_t +tpm2_protector_enforce_policy (tpm2key_policy_t policy, TPMI_SH_AUTH_SESSION_t session) +{ + struct grub_tpm2_buffer buf; + grub_err_t err; + + grub_tpm2_buffer_init (&buf); + if (policy->cmd_policy_len > buf.cap) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "CommandPolicy larger than TPM buffer"); + + grub_memcpy (buf.data, policy->cmd_policy, policy->cmd_policy_len); + buf.size = policy->cmd_policy_len; + + switch (policy->cmd_code) + { + case TPM_CC_PolicyPCR: + err = tpm2_protector_policypcr (session, &buf); + break; + case TPM_CC_PolicyAuthorize: + err = tpm2_protector_policyauthorize (session, &buf); + break; + default: + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown TPM Command: 0x%x", policy->cmd_code); + } + + return err; +} + +static grub_err_t +tpm2_protector_enforce_policy_seq (tpm2key_policy_t policy_seq, TPMI_SH_AUTH_SESSION_t session) +{ + tpm2key_policy_t policy; + grub_err_t err; + + FOR_LIST_ELEMENTS (policy, policy_seq) + { + err = tpm2_protector_enforce_policy (policy, session); + if (err != GRUB_ERR_NONE) + return err; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +tpm2_protector_simple_policy_seq (const tpm2_protector_context_t *ctx, + tpm2key_policy_t *policy_seq) +{ + tpm2key_policy_t policy = NULL; + struct grub_tpm2_buffer buf; + TPML_PCR_SELECTION_t pcr_sel = { + .count = 1, + .pcrSelections = { + { + .hash = ctx->bank, + .sizeOfSelect = 3, + .pcrSelect = {0} + }, + } + }; + grub_uint8_t i; + grub_err_t err; + + if (policy_seq == NULL) + return GRUB_ERR_BAD_ARGUMENT; + + grub_tpm2_buffer_init (&buf); + + for (i = 0; i < ctx->pcr_count; i++) + TPMS_PCR_SELECTION_SelectPCR (&pcr_sel.pcrSelections[0], ctx->pcrs[i]); + + grub_tpm2_buffer_pack_u16 (&buf, 0); + grub_Tss2_MU_TPML_PCR_SELECTION_Marshal (&buf, &pcr_sel); + + if (buf.error != 0) + return GRUB_ERR_BAD_ARGUMENT; + + policy = grub_malloc (sizeof(struct tpm2key_policy)); + if (policy == NULL) + { + err = GRUB_ERR_OUT_OF_MEMORY; + goto error; + } + policy->cmd_code = TPM_CC_PolicyPCR; + policy->cmd_policy = grub_malloc (buf.size); + if (policy->cmd_policy == NULL) + { + err = GRUB_ERR_OUT_OF_MEMORY; + goto error; + } + grub_memcpy (policy->cmd_policy, buf.data, buf.size); + policy->cmd_policy_len = buf.size; + + grub_list_push (GRUB_AS_LIST_P (policy_seq), GRUB_AS_LIST (policy)); + + return GRUB_ERR_NONE; + + error: + grub_free (policy); + + return err; +} + +static grub_err_t +tpm2_protector_unseal (tpm2key_policy_t policy_seq, TPM_HANDLE_t sealed_handle, + grub_uint8_t **key, grub_size_t *key_size, bool *dump_pcr) +{ + TPMS_AUTH_COMMAND_t authCmd = {0}; + TPM2B_SENSITIVE_DATA_t data; + TPM2B_NONCE_t nonceCaller = {0}; + TPMT_SYM_DEF_t symmetric = {0}; + TPMI_SH_AUTH_SESSION_t session; + grub_uint8_t *key_out; + TPM_RC_t rc; + grub_err_t err; + + *dump_pcr = false; + + /* Start Auth Session */ + nonceCaller.size = TPM_SHA256_DIGEST_SIZE; + symmetric.algorithm = TPM_ALG_NULL; + rc = grub_tpm2_startauthsession (TPM_RH_NULL, TPM_RH_NULL, NULL, &nonceCaller, NULL, + TPM_SE_POLICY, &symmetric, TPM_ALG_SHA256, + &session, NULL, NULL); + if (rc != TPM_RC_SUCCESS) + return grub_error (GRUB_ERR_BAD_DEVICE, "failed to start auth session (TPM2_StartAuthSession: 0x%x)", rc); + + /* Enforce the policy command sequence */ + err = tpm2_protector_enforce_policy_seq (policy_seq, session); + if (err != GRUB_ERR_NONE) + goto error; + + /* Unseal Sealed Key */ + authCmd.sessionHandle = session; + rc = grub_tpm2_unseal (sealed_handle, &authCmd, &data, NULL); + if (rc != TPM_RC_SUCCESS) + { + /* + * Trigger PCR dump on policy fail + * TPM_RC_S (0x800) | TPM_RC_1 (0x100) | RC_FMT (0x80) | TPM_RC_POLICY_FAIL (0x1D) + */ + if (rc == 0x99D) + *dump_pcr = true; + + err = grub_error (GRUB_ERR_BAD_DEVICE, "failed to unseal sealed key (TPM2_Unseal: 0x%x)", rc); + goto error; + } + + /* Epilogue */ + key_out = grub_malloc (data.size); + if (key_out == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("no memory left to allocate unlock key buffer")); + goto error; + } + + grub_memcpy (key_out, data.buffer, data.size); + + *key = key_out; + *key_size = data.size; + + err = GRUB_ERR_NONE; + + error: + grub_tpm2_flushcontext (session); + + return err; +} + +#define TPM_PCR_STR_SIZE (sizeof (TPMU_HA_t) * 2 + 1) + +static grub_err_t +tpm2_protector_get_pcr_str (const TPM_ALG_ID_t algo, grub_uint32_t index, char *pcr_str, grub_uint16_t buf_size) +{ + TPML_PCR_SELECTION_t pcr_sel = { + .count = 1, + .pcrSelections = { + { + .hash = algo, + .sizeOfSelect = 3, + .pcrSelect = {0} + }, + } + }; + TPML_DIGEST_t digest = {0}; + grub_uint16_t i; + TPM_RC_t rc; + + if (buf_size < TPM_PCR_STR_SIZE) + { + grub_snprintf (pcr_str, buf_size, "insufficient buffer"); + return GRUB_ERR_OUT_OF_MEMORY; + } + + TPMS_PCR_SELECTION_SelectPCR (&pcr_sel.pcrSelections[0], index); + + rc = grub_tpm2_pcr_read (NULL, &pcr_sel, NULL, NULL, &digest, NULL); + if (rc != TPM_RC_SUCCESS) + { + grub_snprintf (pcr_str, buf_size, "TPM2_PCR_Read: 0x%x", rc); + return GRUB_ERR_BAD_DEVICE; + } + + /* Check the returned digest number and size */ + if (digest.count != 1 || digest.digests[0].size > sizeof (TPMU_HA_t)) + { + grub_snprintf (pcr_str, buf_size, "invalid digest"); + return GRUB_ERR_BAD_DEVICE; + } + + /* Print the digest to the buffer */ + for (i = 0; i < digest.digests[0].size; i++) + grub_snprintf (pcr_str + 2 * i, buf_size - 2 * i, "%02x", digest.digests[0].buffer[i]); + + return GRUB_ERR_NONE; +} + +static void +tpm2_protector_dump_pcr (const TPM_ALG_ID_t bank) +{ + const char *algo_name; + char pcr_str[TPM_PCR_STR_SIZE]; + grub_uint8_t i; + grub_err_t err; + + if (bank == TPM_ALG_SHA1) + algo_name = "sha1"; + else if (bank == TPM_ALG_SHA256) + algo_name = "sha256"; + else if (bank == TPM_ALG_SHA384) + algo_name = "sha384"; + else if (bank == TPM_ALG_SHA512) + algo_name = "sha512"; + else + algo_name = "other"; + + /* Try to fetch PCR 0 */ + err = tpm2_protector_get_pcr_str (bank, 0, pcr_str, sizeof (pcr_str)); + if (err != GRUB_ERR_NONE) + { + grub_printf ("Unsupported PCR bank [%s]: %s\n", algo_name, pcr_str); + return; + } + + grub_printf ("TPM PCR [%s]:\n", algo_name); + + grub_printf (" %02d: %s\n", 0, pcr_str); + for (i = 1; i < TPM_MAX_PCRS; i++) + { + tpm2_protector_get_pcr_str (bank, i, pcr_str, sizeof (pcr_str)); + grub_printf (" %02d: %s\n", i, pcr_str); + } +} + +static grub_err_t +tpm2_protector_key_from_buffer (const tpm2_protector_context_t *ctx, + void *buffer, grub_size_t buf_size, + grub_uint8_t **key, grub_size_t *key_size) +{ + tpm2_sealed_key_t sealed_key = {0}; + grub_uint8_t rsaparent = 0; + TPM_HANDLE_t parent_handle = 0; + TPM_HANDLE_t srk_handle = 0; + TPM_HANDLE_t sealed_handle = 0; + tpm2key_policy_t policy_seq = NULL; + tpm2key_authpolicy_t authpol = NULL; + tpm2key_authpolicy_t authpol_seq = NULL; + bool dump_pcr = false; + grub_err_t err; + + /* + * Retrieve sealed key, parent handle, policy sequence, and authpolicy + * sequence from the buffer + */ + if (tpm2_protector_is_tpm2key (buffer, buf_size) == true) + { + err = tpm2_protector_unmarshal_tpm2key (buffer, + buf_size, + &policy_seq, + &authpol_seq, + &rsaparent, + &parent_handle, + &sealed_key); + if (err != GRUB_ERR_NONE) + goto exit1; + + if (rsaparent == 1) + { + tpm2_protector_context_t *ctx_w; + + /* Overwrite the SRK type as noted in the key */ + ctx_w = (tpm2_protector_context_t *)ctx; + ctx_w->srk_type.type = TPM_ALG_RSA; + ctx_w->srk_type.detail.rsa_bits = 2048; + } + } + else + { + parent_handle = TPM_RH_OWNER; + err = tpm2_protector_unmarshal_raw (buffer, buf_size, &sealed_key); + if (err != GRUB_ERR_NONE) + goto exit1; + } + + /* Set the SRK handle if it is specified with '--srk' or inside the key file */ + if (ctx->srk != 0) + srk_handle = ctx->srk; + else if (TPM_HT_IS_PERSISTENT (parent_handle)) + srk_handle = parent_handle; + + /* Load the sealed key into TPM and associate it with the SRK */ + err = tpm2_protector_load_key (ctx, &sealed_key, parent_handle, &sealed_handle, &srk_handle); + if (err != GRUB_ERR_NONE) + goto exit1; + + /* + * Set err to an error code to trigger the standalone policy sequence + * if there is no authpolicy sequence + */ + err = GRUB_ERR_READ_ERROR; + + /* Iterate the authpolicy sequence to find one that unseals the key */ + FOR_LIST_ELEMENTS (authpol, authpol_seq) + { + err = tpm2_protector_unseal (authpol->policy_seq, sealed_handle, key, key_size, &dump_pcr); + if (err == GRUB_ERR_NONE) + break; + + /* + * Push the error message into the grub_error stack + * Note: The grub_error stack may overflow if there are too many policy + * sequences. Anyway, we still can keep the error messages from + * the first few policy sequences which are usually most likely to + * unseal the key. + */ + grub_error_push(); + } + + /* Give the standalone policy sequence a try */ + if (err != GRUB_ERR_NONE) + { + /* + * Create a basic policy sequence based on the given PCR selection if the + * key file doesn't provide one + */ + if (policy_seq == NULL) + { + err = tpm2_protector_simple_policy_seq (ctx, &policy_seq); + if (err != GRUB_ERR_NONE) + goto exit2; + } + + err = tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size, &dump_pcr); + } + + /* Pop error messages on success */ + if (err == GRUB_ERR_NONE) + while (grub_error_pop ()); + + /* Dump PCRs if necessary */ + if (dump_pcr == true) + { + grub_printf ("PCR Mismatch! Check firmware and bootloader before typing passphrase!\n"); + tpm2_protector_dump_pcr (ctx->bank); + } + + exit2: + grub_tpm2_flushcontext (sealed_handle); + + if (!TPM_HT_IS_PERSISTENT (srk_handle)) + grub_tpm2_flushcontext (srk_handle); + + exit1: + grub_tpm2key_free_policy_seq (policy_seq); + grub_tpm2key_free_authpolicy_seq (authpol_seq); + return err; +} + +static grub_err_t +tpm2_protector_srk_recover (const tpm2_protector_context_t *ctx, + grub_uint8_t **key, grub_size_t *key_size) +{ + const char *filepath; + void *file_bytes = NULL; + grub_size_t file_size = 0; + grub_err_t err; + + if (ctx->tpm2key != NULL) + filepath = ctx->tpm2key; + else if (ctx->keyfile != NULL) + filepath = ctx->keyfile; + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("key file not specified")); + + err = tpm2_protector_srk_read_file (filepath, &file_bytes, &file_size); + if (err != GRUB_ERR_NONE) + return err; + + err = tpm2_protector_key_from_buffer (ctx, file_bytes, file_size, key, key_size); + + grub_free (file_bytes); + return err; +} + +static grub_err_t +tpm2_protector_load_persistent (const tpm2_protector_context_t *ctx, TPM_HANDLE_t sealed_handle, + grub_uint8_t **key, grub_size_t *key_size) +{ + tpm2key_policy_t policy_seq = NULL; + bool dump_pcr = false; + grub_err_t err; + + /* Create a basic policy sequence based on the given PCR selection */ + err = tpm2_protector_simple_policy_seq (ctx, &policy_seq); + if (err != GRUB_ERR_NONE) + goto exit; + + err = tpm2_protector_unseal (policy_seq, sealed_handle, key, key_size, &dump_pcr); + + /* Dump PCRs if necessary */ + if (dump_pcr == true) + { + grub_printf ("PCR Mismatch! Check firmware and bootloader before typing passphrase!\n"); + tpm2_protector_dump_pcr (ctx->bank); + } + + exit: + grub_tpm2_flushcontext (sealed_handle); + + grub_tpm2key_free_policy_seq (policy_seq); + + return err; +} + +static grub_err_t +tpm2_protector_key_from_nvindex (const tpm2_protector_context_t *ctx, TPM_HANDLE_t nvindex, + grub_uint8_t **key, grub_size_t *key_size) +{ + TPMS_AUTH_COMMAND_t authCmd = {0}; + TPM2B_NV_PUBLIC_t nv_public; + TPM2B_NAME_t nv_name; + grub_uint16_t data_size; + TPM2B_MAX_NV_BUFFER_t data; + TPM_RC_t rc; + + /* Get the data size in the NV index handle */ + rc = grub_tpm2_nv_readpublic (nvindex, NULL, &nv_public, &nv_name); + if (rc != TPM_RC_SUCCESS) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to retrieve info from 0x%x (TPM2_NV_ReadPublic: 0x%x)", nvindex, rc); + + data_size = nv_public.nvPublic.dataSize; + if (data_size > TPM_MAX_NV_BUFFER_SIZE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "insufficient data buffer"); + + /* Read the data from the NV index handle */ + authCmd.sessionHandle = TPM_RS_PW; + rc = grub_tpm2_nv_read (TPM_RH_OWNER, nvindex, &authCmd, data_size, 0, &data); + if (rc != TPM_RC_SUCCESS) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to read data from 0x%x (TPM2_NV_Read: 0x%x)", nvindex, rc); + + return tpm2_protector_key_from_buffer (ctx, data.buffer, data_size, key, key_size); +} + +static grub_err_t +tpm2_protector_nv_recover (const tpm2_protector_context_t *ctx, + grub_uint8_t **key, grub_size_t *key_size) +{ + grub_err_t err; + + if (TPM_HT_IS_PERSISTENT (ctx->nv) == true) + err = tpm2_protector_load_persistent (ctx, ctx->nv, key, key_size); + else if (TPM_HT_IS_NVINDEX (ctx->nv) == true) + err = tpm2_protector_key_from_nvindex (ctx, ctx->nv, key, key_size); + else + err = GRUB_ERR_BAD_ARGUMENT; + + return err; +} + +static grub_err_t +tpm2_protector_recover (const tpm2_protector_context_t *ctx, + grub_uint8_t **key, grub_size_t *key_size) +{ + switch (ctx->mode) + { + case TPM2_PROTECTOR_MODE_SRK: + return tpm2_protector_srk_recover (ctx, key, key_size); + case TPM2_PROTECTOR_MODE_NV: + return tpm2_protector_nv_recover (ctx, key, key_size); + default: + return GRUB_ERR_BAD_ARGUMENT; + } +} + +static grub_err_t +tpm2_protector_recover_key (grub_uint8_t **key, grub_size_t *key_size) +{ + /* Expect a call to tpm2_protector_init before anybody tries to use us */ + if (tpm2_protector_ctx.mode == TPM2_PROTECTOR_MODE_UNSET) + return grub_error (GRUB_ERR_INVALID_COMMAND, N_("cannot use TPM2 key protector without initializing it, call tpm2_protector_init first")); + + if (key == NULL || key_size == NULL) + return GRUB_ERR_BAD_ARGUMENT; + + return tpm2_protector_recover (&tpm2_protector_ctx, key, key_size); +} + +static grub_err_t +tpm2_protector_check_args (tpm2_protector_context_t *ctx) +{ + if (ctx->mode == TPM2_PROTECTOR_MODE_UNSET) + ctx->mode = TPM2_PROTECTOR_MODE_SRK; + + /* Checks for SRK mode */ + if (ctx->mode == TPM2_PROTECTOR_MODE_SRK && + (ctx->keyfile == NULL && ctx->tpm2key == NULL)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in SRK mode, a key file must be specified: --tpm2key/-T or --keyfile/-k")); + + if (ctx->mode == TPM2_PROTECTOR_MODE_SRK && + (ctx->keyfile != NULL && ctx->tpm2key != NULL)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in SRK mode, please specify a key file with only --tpm2key/-T or --keyfile/-k")); + + if (ctx->mode == TPM2_PROTECTOR_MODE_SRK && ctx->nv != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in SRK mode, an NV Index cannot be specified")); + + /* Checks for NV mode */ + if (ctx->mode == TPM2_PROTECTOR_MODE_NV && ctx->nv == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("in NV Index mode, an NV Index must be specified: --nvindex or -n")); + + if (ctx->mode == TPM2_PROTECTOR_MODE_NV && + (ctx->tpm2key != NULL || ctx->keyfile != NULL)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("a key file cannot be specified when using NV index mode")); + + if (ctx->mode == TPM2_PROTECTOR_MODE_NV && TPM_HT_IS_PERSISTENT (ctx->nv) == true && + (ctx->srk != 0 || ctx->srk_type.type != TPM_ALG_ERROR)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("an SRK cannot be specified when using NV index mode with a persistent handle")); + + if (ctx->mode == TPM2_PROTECTOR_MODE_NV && + (TPM_HT_IS_PERSISTENT (ctx->nv) == false && TPM_HT_IS_NVINDEX (ctx->nv) == false)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("an NV index must be either a persistent handle or an NV index handle when using NV index mode")); + + /* Defaults assignment */ + if (ctx->bank == TPM_ALG_ERROR) + ctx->bank = TPM_ALG_SHA256; + + if (ctx->pcr_count == 0) + { + ctx->pcrs[0] = 7; + ctx->pcr_count = 1; + } + + /* + * Set ECC_NIST_P256 as the default SRK when using SRK mode or NV mode with + * an NV index handle + */ + if (ctx->srk_type.type == TPM_ALG_ERROR && + (ctx->mode == TPM2_PROTECTOR_MODE_SRK || + (ctx->mode == TPM2_PROTECTOR_MODE_NV && TPM_HT_IS_NVINDEX (ctx->nv) == true))) + { + ctx->srk_type.type = TPM_ALG_ECC; + ctx->srk_type.detail.ecc_curve = TPM_ECC_NIST_P256; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +tpm2_protector_parse_file (const char *value, const char **file) +{ + if (grub_strlen (value) == 0) + return GRUB_ERR_BAD_ARGUMENT; + + *file = grub_strdup (value); + if (*file == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("no memory to duplicate file path")); + + return GRUB_ERR_NONE; +} + +static grub_err_t +tpm2_protector_parse_mode (const char *value, tpm2_protector_mode_t *mode) +{ + if (grub_strcmp (value, "srk") == 0) + *mode = TPM2_PROTECTOR_MODE_SRK; + else if (grub_strcmp (value, "nv") == 0) + *mode = TPM2_PROTECTOR_MODE_NV; + else + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("value '%s' is not a valid TPM2 key protector mode"), value); + + return GRUB_ERR_NONE; +} + +static grub_err_t +tpm2_protector_init_cmd_handler (grub_extcmd_context_t ctxt, int argc, + char **args __attribute__ ((unused))) +{ + struct grub_arg_list *state = ctxt->state; + grub_err_t err; + + if (argc) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("the TPM2 key protector does not accept any non-option arguments (i.e., like -o and/or --option only)")); + + grub_free ((void *) tpm2_protector_ctx.keyfile); + grub_memset (&tpm2_protector_ctx, 0, sizeof (tpm2_protector_ctx)); + + if (state[OPTION_MODE].set) /* mode */ + { + err = tpm2_protector_parse_mode (state[OPTION_MODE].arg, &tpm2_protector_ctx.mode); + if (err != GRUB_ERR_NONE) + return err; + } + + if (state[OPTION_PCRS].set) /* pcrs */ + { + err = grub_tpm2_protector_parse_pcrs (state[OPTION_PCRS].arg, + tpm2_protector_ctx.pcrs, + &tpm2_protector_ctx.pcr_count); + if (err != GRUB_ERR_NONE) + return err; + } + + if (state[OPTION_BANK].set) /* bank */ + { + err = grub_tpm2_protector_parse_bank (state[OPTION_BANK].arg, + &tpm2_protector_ctx.bank); + if (err != GRUB_ERR_NONE) + return err; + } + + if (state[OPTION_TPM2KEY].set) /* tpm2key */ + { + err = tpm2_protector_parse_file (state[OPTION_TPM2KEY].arg, + &tpm2_protector_ctx.tpm2key); + if (err != GRUB_ERR_NONE) + return err; + } + + if (state[OPTION_KEYFILE].set) /* keyfile */ + { + err = tpm2_protector_parse_file (state[OPTION_KEYFILE].arg, + &tpm2_protector_ctx.keyfile); + if (err != GRUB_ERR_NONE) + return err; + } + + if (state[OPTION_SRK].set) /* srk */ + { + err = grub_tpm2_protector_parse_tpm_handle (state[OPTION_SRK].arg, + &tpm2_protector_ctx.srk); + if (err != GRUB_ERR_NONE) + return err; + } + + if (state[OPTION_ASYMMETRIC].set) /* asymmetric */ + { + err = grub_tpm2_protector_parse_asymmetric (state[OPTION_ASYMMETRIC].arg, + &tpm2_protector_ctx.srk_type); + if (err != GRUB_ERR_NONE) + return err; + } + + if (state[OPTION_NVINDEX].set) /* nvindex */ + { + err = grub_tpm2_protector_parse_tpm_handle (state[OPTION_NVINDEX].arg, + &tpm2_protector_ctx.nv); + if (err != GRUB_ERR_NONE) + return err; + } + + err = tpm2_protector_check_args (&tpm2_protector_ctx); + + /* This command only initializes the protector, so nothing else to do. */ + + return err; +} + +static grub_err_t +tpm2_protector_clear_cmd_handler (grub_extcmd_context_t ctxt __attribute__ ((unused)), + int argc, char **args __attribute__ ((unused))) +{ + if (argc != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("tpm2_key_protector_clear accepts no arguments")); + + grub_free ((void *) tpm2_protector_ctx.keyfile); + grub_memset (&tpm2_protector_ctx, 0, sizeof (tpm2_protector_ctx)); + + return GRUB_ERR_NONE; +} + +static struct grub_key_protector tpm2_key_protector = + { + .name = "tpm2", + .recover_key = tpm2_protector_recover_key + }; + +static grub_err_t +tpm2_dump_pcr (grub_command_t cmd __attribute__((__unused__)), + int argc, char *argv[]) +{ + TPM_ALG_ID_t pcr_bank; + + if (argc == 0) + pcr_bank = TPM_ALG_SHA256; + else if (grub_strcmp (argv[0], "sha1") == 0) + pcr_bank = TPM_ALG_SHA1; + else if (grub_strcmp (argv[0], "sha256") == 0) + pcr_bank = TPM_ALG_SHA256; + else if (grub_strcmp (argv[0], "sha384") == 0) + pcr_bank = TPM_ALG_SHA384; + else if (grub_strcmp (argv[0], "sha512") == 0) + pcr_bank = TPM_ALG_SHA512; + else + { + grub_printf ("Unknown PCR bank\n"); + return GRUB_ERR_BAD_ARGUMENT; + } + + tpm2_protector_dump_pcr (pcr_bank); + + return GRUB_ERR_NONE; +} + +GRUB_MOD_INIT (tpm2_key_protector) +{ + tpm2_protector_init_cmd = + grub_register_extcmd ("tpm2_key_protector_init", + tpm2_protector_init_cmd_handler, 0, + N_("[-m mode] " + "[-p pcr_list] " + "[-b pcr_bank] " + "[-T tpm2_key_file_path] " + "[-k sealed_key_file_path] " + "[-s srk_handle] " + "[-a asymmetric_key_type] " + "[-n nv_index]"), + N_("Initialize the TPM2 key protector."), + tpm2_protector_init_cmd_options); + tpm2_protector_clear_cmd = + grub_register_extcmd ("tpm2_key_protector_clear", + tpm2_protector_clear_cmd_handler, 0, NULL, + N_("Clear the TPM2 key protector if previously initialized."), + NULL); + grub_key_protector_register (&tpm2_key_protector); + + tpm2_dump_pcr_cmd = + grub_register_command ("tpm2_dump_pcr", tpm2_dump_pcr, N_("Dump TPM2 PCRs"), + N_("Print all PCRs of the specified TPM 2.0 bank")); +} + +GRUB_MOD_FINI (tpm2_key_protector) +{ + grub_free ((void *) tpm2_protector_ctx.keyfile); + + grub_key_protector_unregister (&tpm2_key_protector); + grub_unregister_extcmd (tpm2_protector_clear_cmd); + grub_unregister_extcmd (tpm2_protector_init_cmd); + + grub_unregister_command (tpm2_dump_pcr_cmd); +} diff --git a/grub-core/commands/tpm2_key_protector/tpm2.h b/grub-core/commands/tpm2_key_protector/tpm2.h new file mode 100644 index 000000000..1c1d871b4 --- /dev/null +++ b/grub-core/commands/tpm2_key_protector/tpm2.h @@ -0,0 +1,36 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Microsoft Corporation + * Copyright (C) 2024 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#ifndef GRUB_TPM2_TPM2_HEADER +#define GRUB_TPM2_TPM2_HEADER 1 + +#include +#include +#include + +/* Well-Known Windows SRK handle */ +#define TPM2_SRK_HANDLE 0x81000001 + +struct tpm2_sealed_key { + TPM2B_PUBLIC_t public; + TPM2B_PRIVATE_t private; +}; +typedef struct tpm2_sealed_key tpm2_sealed_key_t; + +#endif /* ! GRUB_TPM2_TPM2_HEADER */ diff --git a/grub-core/commands/tpm2_key_protector/tpm2_args.h b/grub-core/commands/tpm2_key_protector/tpm2_args.h new file mode 100644 index 000000000..bdbf9f373 --- /dev/null +++ b/grub-core/commands/tpm2_key_protector/tpm2_args.h @@ -0,0 +1,49 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Microsoft Corporation + * Copyright (C) 2024 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#ifndef GRUB_TPM2_INTERNAL_ARGS_HEADER +#define GRUB_TPM2_INTERNAL_ARGS_HEADER 1 + +#include + +#include "tpm2.h" + +struct grub_srk_type +{ + TPMI_ALG_PUBLIC_t type; + union { + TPM_KEY_BITS_t rsa_bits; + TPM_ECC_CURVE_t ecc_curve; + } detail; +}; +typedef struct grub_srk_type grub_srk_type_t; + +extern grub_err_t +grub_tpm2_protector_parse_pcrs (char *value, grub_uint8_t *pcrs, grub_uint8_t *pcr_count); + +extern grub_err_t +grub_tpm2_protector_parse_asymmetric (const char *value, grub_srk_type_t *srk_type); + +extern grub_err_t +grub_tpm2_protector_parse_bank (const char *value, TPM_ALG_ID_t *bank); + +extern grub_err_t +grub_tpm2_protector_parse_tpm_handle (const char *value, TPM_HANDLE_t *handle); + +#endif /* ! GRUB_TPM2_INTERNAL_ARGS_HEADER */ diff --git a/grub-core/commands/tpm2_key_protector/tpm2key.asn b/grub-core/commands/tpm2_key_protector/tpm2key.asn new file mode 100644 index 000000000..e1fb51545 --- /dev/null +++ b/grub-core/commands/tpm2_key_protector/tpm2key.asn @@ -0,0 +1,49 @@ +-- +-- GRUB: GRand Unified Bootloader +-- Copyright (C) 2024 Free Software Foundation, Inc. +-- +-- GRUB is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- GRUB 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 GRUB. If not, see . +-- +-- This file describes TPM 2.0 Key File format for libtasn1. +-- To generate tpm2key_asn1_tab.c: asn1Parser tpm2key.asn +-- +TPM2KEY {} +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + +TPMPolicy ::= SEQUENCE { + CommandCode [0] EXPLICIT INTEGER, + CommandPolicy [1] EXPLICIT OCTET STRING +} + +TPMAuthPolicy ::= SEQUENCE { + Name [0] EXPLICIT UTF8String OPTIONAL, + Policy [1] EXPLICIT SEQUENCE OF TPMPolicy +} + +TPMKey ::= SEQUENCE { + type OBJECT IDENTIFIER, + emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL, + policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL, + secret [2] EXPLICIT OCTET STRING OPTIONAL, + authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL, + description [4] EXPLICIT UTF8String OPTIONAL, + rsaParent [5] EXPLICIT BOOLEAN OPTIONAL, + parent INTEGER, + pubkey OCTET STRING, + privkey OCTET STRING +} + +END diff --git a/grub-core/commands/tpm2_key_protector/tpm2key.c b/grub-core/commands/tpm2_key_protector/tpm2key.c new file mode 100644 index 000000000..3b6001d84 --- /dev/null +++ b/grub-core/commands/tpm2_key_protector/tpm2key.c @@ -0,0 +1,499 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2023 SUSE LLC + * Copyright (C) 2024 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include + +#include + +#include "tpm2key.h" + +extern asn1_static_node tpm2key_asn1_tab[]; +const char *sealed_key_oid = "2.23.133.10.1.5"; + +static int +asn1_allocate_and_read (asn1_node node, const char *name, void **content, grub_size_t *content_size) +{ + grub_uint8_t *tmpstr = NULL; + int tmpstr_size = 0; + int ret; + + if (content == NULL) + return ASN1_MEM_ERROR; + + ret = asn1_read_value (node, name, NULL, &tmpstr_size); + if (ret != ASN1_MEM_ERROR) + return ret; + + tmpstr = grub_malloc (tmpstr_size); + if (tmpstr == NULL) + return ASN1_MEM_ERROR; + + ret = asn1_read_value (node, name, tmpstr, &tmpstr_size); + if (ret != ASN1_SUCCESS) + return ret; + + *content = tmpstr; + *content_size = tmpstr_size; + + return ASN1_SUCCESS; +} + +static int +asn1_read_uint32 (asn1_node node, const char *name, grub_uint32_t *out) +{ + grub_uint32_t tmp = 0; + grub_uint8_t *ptr; + void *data = NULL; + grub_size_t data_size; + int ret; + + ret = asn1_allocate_and_read (node, name, &data, &data_size); + if (ret != ASN1_SUCCESS) + return ret; + + /* + * ASN.1 INTEGER is encoded in the following format: + * + * TAG LENGTH OCTECTS + * + * The integer TAG is 02 and LENGTH is the number of followed OCTECTS in + * big endian. For example: + * + * 0x1: 02 01 01 + * 0xabcd: 02 02 ab cd + * + * To decribe 0x1, it only takes 1 octect, so LENGTH is 0x01 and the + * octect is 0x01. On the other hand, 0xabcd requires 2 octects: 'ab" and + * 'cd', so LENGTH is 0x02. + * + * This function only expects a uint32 integer, so it rejects any integer + * containing more than 4 octects. + */ + if (data_size > 4) + { + ret = ASN1_MEM_ERROR; + goto error; + } + + /* Copy the octects into 'tmp' to make it a big-endian uint32 */ + ptr = (grub_uint8_t *) &tmp + (4 - data_size); + grub_memcpy (ptr, data, data_size); + + /* Convert the big-endian integer to host uint32 */ + tmp = grub_be_to_cpu32 (tmp); + + *out = tmp; + error: + if (data) + grub_free (data); + return ret; +} + +grub_err_t +grub_tpm2key_start_parsing (asn1_node *parsed_tpm2key, void *data, grub_size_t size) +{ + asn1_node tpm2key; + asn1_node tpm2key_asn1 = NULL; + void *type_oid = NULL; + grub_size_t type_oid_size = 0; + void *empty_auth = NULL; + grub_size_t empty_auth_size = 0; + int tmp_size = 0; + int ret; + grub_err_t err; + + /* + * TPMKey ::= SEQUENCE { + * type OBJECT IDENTIFIER, + * emptyAuth [0] EXPLICIT BOOLEAN OPTIONAL, + * policy [1] EXPLICIT SEQUENCE OF TPMPolicy OPTIONAL, + * secret [2] EXPLICIT OCTET STRING OPTIONAL, + * authPolicy [3] EXPLICIT SEQUENCE OF TPMAuthPolicy OPTIONAL, + * description [4] EXPLICIT UTF8String OPTIONAL, + * rsaParent [5] EXPLICIT BOOLEAN OPTIONAL, + * parent INTEGER, + * pubkey OCTET STRING, + * privkey OCTET STRING + * } + */ + ret = asn1_array2tree (tpm2key_asn1_tab, &tpm2key_asn1, NULL); + if (ret != ASN1_SUCCESS) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to parse TPM2KEY ASN.1 array"); + + ret = asn1_create_element (tpm2key_asn1, "TPM2KEY.TPMKey", &tpm2key); + if (ret != ASN1_SUCCESS) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to create TPM2KEY.TPMKey"); + + ret = asn1_der_decoding (&tpm2key, data, size, NULL); + if (ret != ASN1_SUCCESS) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "failed to decode TPM2KEY DER"); + + /* Check if 'type' is Sealed Key or not */ + ret = asn1_allocate_and_read (tpm2key, "type", &type_oid, &type_oid_size); + if (ret != ASN1_SUCCESS) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a valid TPM2KEY file"); + + if (grub_memcmp (sealed_key_oid, type_oid, type_oid_size) != 0) + { + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a valid TPM2KEY file"); + goto error; + } + + /* 'emptyAuth' must be 'TRUE' since we don't support password authorization */ + ret = asn1_allocate_and_read (tpm2key, "emptyAuth", &empty_auth, &empty_auth_size); + if (ret != ASN1_SUCCESS || grub_strncmp ("TRUE", empty_auth, empty_auth_size) != 0) + { + err = grub_error (GRUB_ERR_BAD_ARGUMENT, "emptyAuth not TRUE"); + goto error; + } + + /* 'secret' should not be in a sealed key */ + ret = asn1_read_value (tpm2key, "secret", NULL, &tmp_size); + if (ret != ASN1_ELEMENT_NOT_FOUND) + { + err = grub_error (GRUB_ERR_BAD_ARGUMENT, "\"secret\" not allowed for Sealed Key"); + goto error; + } + + *parsed_tpm2key = tpm2key; + + err = GRUB_ERR_NONE; + + error: + grub_free (type_oid); + grub_free (empty_auth); + + return err; +} + +void +grub_tpm2key_end_parsing (asn1_node tpm2key) +{ + asn1_delete_structure (&tpm2key); + tpm2key = NULL; +} + +grub_err_t +grub_tpm2key_get_rsaparent (asn1_node tpm2key, grub_uint8_t *rsaparent) +{ + void *bool_str = NULL; + grub_size_t bool_str_size = 0; + int ret; + + if (rsaparent == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "NULL pointer detected"); + + if (tpm2key == NULL) + return grub_error (GRUB_ERR_READ_ERROR, "invalid parent node"); + + ret = asn1_allocate_and_read (tpm2key, "rsaParent", &bool_str, &bool_str_size); + if (ret == ASN1_SUCCESS) + { + if (grub_strncmp ("TRUE", bool_str, bool_str_size) == 0) + *rsaparent = 1; + else + *rsaparent = 0; + } + else if (ret == ASN1_ELEMENT_NOT_FOUND) + *rsaparent = 0; + else + return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve rsaParent"); + + grub_free (bool_str); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_tpm2key_get_parent (asn1_node tpm2key, grub_uint32_t *parent) +{ + int ret; + + if (parent == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "NULL pointer detected"); + + if (tpm2key == NULL) + return grub_error (GRUB_ERR_READ_ERROR, "invalid parent node"); + + ret = asn1_read_uint32 (tpm2key, "parent", parent); + if (ret != ASN1_SUCCESS) + return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve parent"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +tpm2key_get_octstring (asn1_node tpm2key, const char *name, void **data, grub_size_t *size) +{ + int ret; + + if (name == NULL || data == NULL || size == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid parameter(s)"); + + if (tpm2key == NULL) + return grub_error (GRUB_ERR_READ_ERROR, "invalid %s node", name); + + ret = asn1_allocate_and_read (tpm2key, name, data, size); + if (ret != ASN1_SUCCESS) + return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve %s", name); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_tpm2key_get_pubkey (asn1_node tpm2key, void **data, grub_size_t *size) +{ + return tpm2key_get_octstring (tpm2key, "pubkey", data, size); +} + +grub_err_t +grub_tpm2key_get_privkey (asn1_node tpm2key, void **data, grub_size_t *size) +{ + return tpm2key_get_octstring (tpm2key, "privkey", data, size); +} + +/* + * The maximum and minimum number of elements for 'policy' and 'authPolicy' sequences + * + * Although there is no limit for the number of sequences elements, we set the upper + * bound to 99 to make it easier to implement the code. + * + * Any 'policy' or 'authPolicy' contains more than 99 commands/policies would become + * extremely complex to manage so it is impractical to support such use case. + */ +#define TPM2KEY_ELEMENTS_MAX 99 +#define TPM2KEY_ELEMENTS_MIN 1 + +/* + * The string to fetch 'Policy' from 'authPolicy': + * authPolicy.?XX.Policy + */ +#define AUTHPOLICY_POL_MAX_STR "authPolicy.?XX.Policy" +#define AUTHPOLICY_POL_MAX (sizeof (AUTHPOLICY_POL_MAX_STR)) + +/* + * Expected strings for CommandCode and CommandPolicy: + * policy.?XX.CommandCode + * policy.?XX.CommandPolicy + * authPolicy.?XX.Policy.?YY.CommandCode + * authPolicy.?XX.Policy.?YY.CommandPolicy + */ +#define CMD_CODE_MAX_STR AUTHPOLICY_POL_MAX_STR".?YY.CommandCode" +#define CMD_POL_MAX_STR AUTHPOLICY_POL_MAX_STR".?YY.CommandPolicy" +#define CMD_CODE_MAX (sizeof (CMD_CODE_MAX_STR)) +#define CMD_POL_MAX (sizeof (CMD_POL_MAX_STR)) + +static int +tpm2key_get_policy_seq (asn1_node tpm2key, const char *prefix, + tpm2key_policy_t *policy_seq) +{ + tpm2key_policy_t tmp_seq = NULL; + tpm2key_policy_t policy = NULL; + int policy_n; + char cmd_code[CMD_CODE_MAX]; + char cmd_pol[CMD_POL_MAX]; + grub_size_t cmd_policy_len; + int i; + int ret; + + ret = asn1_number_of_elements (tpm2key, prefix, &policy_n); + if (ret != ASN1_SUCCESS) + return ret; + + /* + * Limit the number of policy commands to two digits (99) + * Although there is no upper bound for the number of policy commands, + * in practice, it takes one or two policy commands to unseal the key, + * so the 99 commands limit is more than enough. + */ + if (policy_n > TPM2KEY_ELEMENTS_MAX || policy_n < TPM2KEY_ELEMENTS_MIN) + return ASN1_VALUE_NOT_VALID; + + /* + * Iterate the policy commands backwards since grub_list_push() prepends + * the item into the list. + */ + for (i = policy_n; i >= 1; i--) { + policy = grub_zalloc (sizeof (struct tpm2key_policy)); + if (policy == NULL) + { + ret = ASN1_MEM_ALLOC_ERROR; + goto error; + } + grub_snprintf (cmd_code, CMD_CODE_MAX, "%s.?%d.CommandCode", prefix, i); + grub_snprintf (cmd_pol, CMD_POL_MAX, "%s.?%d.CommandPolicy", prefix, i); + + /* CommandCode [0] EXPLICIT INTEGER */ + ret = asn1_read_uint32 (tpm2key, cmd_code, &policy->cmd_code); + if (ret != ASN1_SUCCESS) + return ret; + + /* CommandPolicy [1] EXPLICIT OCTET STRING */ + ret = tpm2key_get_octstring (tpm2key, cmd_pol, &policy->cmd_policy, + &cmd_policy_len); + if (ret != ASN1_SUCCESS) + { + goto error; + } + else if (cmd_policy_len > GRUB_TPM2_BUFFER_CAPACITY) + { + /* + * CommandPolicy is the marshalled parameters for the TPM command so + * it should not be larger than the maximum TPM2 buffer. + */ + ret = ASN1_VALUE_NOT_VALID; + goto error; + } + policy->cmd_policy_len = (grub_uint16_t)cmd_policy_len; + + /* Prepend the policy command into the sequence */ + grub_list_push (GRUB_AS_LIST_P (&tmp_seq), GRUB_AS_LIST (policy)); + } + + *policy_seq = tmp_seq; + + return ASN1_SUCCESS; + + error: + if (policy != NULL) + { + grub_free (policy->cmd_policy); + grub_free (policy); + } + grub_tpm2key_free_policy_seq (tmp_seq); + + return ret; +} + +grub_err_t +grub_tpm2key_get_policy_seq (asn1_node tpm2key, tpm2key_policy_t *policy_seq) +{ + int ret; + + ret = tpm2key_get_policy_seq (tpm2key, "policy", policy_seq); + if (ret == ASN1_ELEMENT_NOT_FOUND) + { + /* "policy" is optional, so it may not be available */ + *policy_seq = NULL; + return GRUB_ERR_NONE; + } + else if (ret != ASN1_SUCCESS) + return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve policy"); + + return GRUB_ERR_NONE; +} + +void +grub_tpm2key_free_policy_seq (tpm2key_policy_t policy_seq) +{ + tpm2key_policy_t policy; + tpm2key_policy_t next; + + if (policy_seq == NULL) + return; + + FOR_LIST_ELEMENTS_SAFE (policy, next, policy_seq) + { + grub_free (policy->cmd_policy); + grub_free (policy); + } +} + +grub_err_t +grub_tpm2key_get_authpolicy_seq (asn1_node tpm2key, tpm2key_authpolicy_t *authpol_seq) +{ + tpm2key_authpolicy_t tmp_seq = NULL; + tpm2key_authpolicy_t authpol = NULL; + int authpol_n; + char authpol_pol[AUTHPOLICY_POL_MAX]; + int i; + int ret; + grub_err_t err; + + ret = asn1_number_of_elements (tpm2key, "authPolicy", &authpol_n); + if (ret == ASN1_ELEMENT_NOT_FOUND) + { + /* "authPolicy" is optional, so it may not be available */ + *authpol_seq = NULL; + return GRUB_ERR_NONE; + } + else if (ret != ASN1_SUCCESS) + return grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve authPolicy"); + + /* Limit the number of authPolicy elements to two digits (99) */ + if (authpol_n > TPM2KEY_ELEMENTS_MAX || authpol_n < TPM2KEY_ELEMENTS_MIN) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid number of authPolicy elements"); + + /* + * Iterate the authPolicy elements backwards since grub_list_push() prepends + * the item into the list. + */ + for (i = authpol_n; i >= 1; i--) { + authpol = grub_zalloc (sizeof (struct tpm2key_authpolicy)); + if (authpol == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to allocate memory for authPolicy"); + goto error; + } + grub_snprintf (authpol_pol, AUTHPOLICY_POL_MAX, "authPolicy.?%d.Policy", i); + + ret = tpm2key_get_policy_seq (tpm2key, authpol_pol, &authpol->policy_seq); + if (ret != ASN1_SUCCESS) + { + err = grub_error (GRUB_ERR_READ_ERROR, "failed to retrieve policy from authPolicy"); + goto error; + } + + /* Prepend the authPolicy element into the sequence */ + grub_list_push (GRUB_AS_LIST_P (&tmp_seq), GRUB_AS_LIST (authpol)); + } + + *authpol_seq = tmp_seq; + + return GRUB_ERR_NONE; + + error: + if (authpol != NULL) + { + grub_tpm2key_free_policy_seq (authpol->policy_seq); + grub_free (authpol); + } + + grub_tpm2key_free_authpolicy_seq (tmp_seq); + + return err; +} + +void +grub_tpm2key_free_authpolicy_seq (tpm2key_authpolicy_t authpol_seq) +{ + tpm2key_authpolicy_t authpol; + tpm2key_authpolicy_t next; + + if (authpol_seq == NULL) + return; + + FOR_LIST_ELEMENTS_SAFE (authpol, next, authpol_seq) + { + grub_tpm2key_free_policy_seq (authpol->policy_seq); + grub_free (authpol); + } +} diff --git a/grub-core/commands/tpm2_key_protector/tpm2key.h b/grub-core/commands/tpm2_key_protector/tpm2key.h new file mode 100644 index 000000000..f749d62c2 --- /dev/null +++ b/grub-core/commands/tpm2_key_protector/tpm2key.h @@ -0,0 +1,87 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2023 SUSE LLC + * Copyright (C) 2024 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#ifndef GRUB_TPM2_TPM2KEY_HEADER +#define GRUB_TPM2_TPM2KEY_HEADER 1 + +#include +#include + +/* + * TPMPolicy ::= SEQUENCE { + * CommandCode [0] EXPLICIT INTEGER, + * CommandPolicy [1] EXPLICIT OCTET STRING + * } + */ +struct tpm2key_policy { + struct tpm2key_policy *next; + struct tpm2key_policy **prev; + grub_uint32_t cmd_code; + void *cmd_policy; + grub_uint16_t cmd_policy_len; +}; +typedef struct tpm2key_policy *tpm2key_policy_t; + +/* + * TPMAuthPolicy ::= SEQUENCE { + * Name [0] EXPLICIT UTF8String OPTIONAL, + * Policy [1] EXPLICIT SEQUENCE OF TPMPolicy + * } + * + * Name is not a necessary part to unseal the key. Ignore it. + */ +struct tpm2key_authpolicy { + struct tpm2key_authpolicy *next; + struct tpm2key_authpolicy **prev; + /* char *name; */ + tpm2key_policy_t policy_seq; +}; +typedef struct tpm2key_authpolicy *tpm2key_authpolicy_t; + +extern grub_err_t +grub_tpm2key_start_parsing (asn1_node *parsed_tpm2key, void *data, grub_size_t size); + +extern void +grub_tpm2key_end_parsing (asn1_node tpm2key); + +extern grub_err_t +grub_tpm2key_get_rsaparent (asn1_node tpm2key, grub_uint8_t *rsaparent); + +extern grub_err_t +grub_tpm2key_get_parent (asn1_node tpm2key, grub_uint32_t *parent); + +extern grub_err_t +grub_tpm2key_get_pubkey (asn1_node tpm2key, void **data, grub_size_t *size); + +extern grub_err_t +grub_tpm2key_get_privkey (asn1_node tpm2key, void **data, grub_size_t *size); + +extern grub_err_t +grub_tpm2key_get_policy_seq (asn1_node tpm2key, tpm2key_policy_t *policy_seq); + +extern void +grub_tpm2key_free_policy_seq (tpm2key_policy_t policy_seq); + +extern grub_err_t +grub_tpm2key_get_authpolicy_seq (asn1_node tpm2key, tpm2key_authpolicy_t *authpol_seq); + +extern void +grub_tpm2key_free_authpolicy_seq (tpm2key_authpolicy_t authpol_seq); + +#endif /* GRUB_TPM2_TPM2KEY_HEADER */ diff --git a/grub-core/commands/tpm2_key_protector/tpm2key_asn1_tab.c b/grub-core/commands/tpm2_key_protector/tpm2key_asn1_tab.c new file mode 100644 index 000000000..bebe108a3 --- /dev/null +++ b/grub-core/commands/tpm2_key_protector/tpm2key_asn1_tab.c @@ -0,0 +1,63 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2024 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +/* + * This file is generated by 'asn1Parser tpm2key.asn' and the '#include' + * headers are replaced with the ones in grub2. + * - 'grub/mm.h' for the definition of 'NULL' + * - 'libtasn1.h' for the definition of 'asn1_static_node' + */ + +#include +#include + +const asn1_static_node tpm2key_asn1_tab[] = { + { "TPM2KEY", 536875024, NULL }, + { NULL, 1073741836, NULL }, + { "TPMPolicy", 1610612741, NULL }, + { "CommandCode", 1610620931, NULL }, + { NULL, 2056, "0"}, + { "CommandPolicy", 536879111, NULL }, + { NULL, 2056, "1"}, + { "TPMAuthPolicy", 1610612741, NULL }, + { "Name", 1610637346, NULL }, + { NULL, 2056, "0"}, + { "Policy", 536879115, NULL }, + { NULL, 1073743880, "1"}, + { NULL, 2, "TPMPolicy"}, + { "TPMKey", 536870917, NULL }, + { "type", 1073741836, NULL }, + { "emptyAuth", 1610637316, NULL }, + { NULL, 2056, "0"}, + { "policy", 1610637323, NULL }, + { NULL, 1073743880, "1"}, + { NULL, 2, "TPMPolicy"}, + { "secret", 1610637319, NULL }, + { NULL, 2056, "2"}, + { "authPolicy", 1610637323, NULL }, + { NULL, 1073743880, "3"}, + { NULL, 2, "TPMAuthPolicy"}, + { "description", 1610637346, NULL }, + { NULL, 2056, "4"}, + { "rsaParent", 1610637316, NULL }, + { NULL, 2056, "5"}, + { "parent", 1073741827, NULL }, + { "pubkey", 1073741831, NULL }, + { "privkey", 7, NULL }, + { NULL, 0, NULL } +}; diff --git a/grub-core/commands/tr.c b/grub-core/commands/tr.c new file mode 100644 index 000000000..ef72841a2 --- /dev/null +++ b/grub-core/commands/tr.c @@ -0,0 +1,126 @@ +/* tr.c -- The tr command. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static const struct grub_arg_option options[] = + { + { "set", 's', 0, N_("Set a variable to return value."), N_("VARNAME"), ARG_TYPE_STRING }, + { "upcase", 'U', 0, N_("Translate to upper case."), 0, 0 }, + { "downcase", 'D', 0, N_("Translate to lower case."), 0, 0 }, + { 0, 0, 0, 0, 0, 0 } + }; + +static const char *letters_lowercase = "abcdefghijklmnopqrstuvwxyz"; +static const char *letters_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +static grub_err_t +grub_cmd_tr (grub_extcmd_context_t ctxt, int argc, char **args) +{ + char *var = 0; + const char *input = 0; + char *output = 0, *optr; + const char *s1 = 0; + const char *s2 = 0; + const char *iptr; + + /* Select the defaults from options. */ + if (ctxt->state[0].set) { + var = ctxt->state[0].arg; + input = grub_env_get (var); + } + + if (ctxt->state[1].set) { + s1 = letters_lowercase; + s2 = letters_uppercase; + } + + if (ctxt->state[2].set) { + s1 = letters_uppercase; + s2 = letters_lowercase; + } + + /* Check for arguments and update the defaults. */ + if (argc == 1) + input = args[0]; + + else if (argc == 2) { + s1 = args[0]; + s2 = args[1]; + + } else if (argc == 3) { + s1 = args[0]; + s2 = args[1]; + input = args[2]; + + } else if (argc > 3) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many parameters"); + + if (!s1 || !s2 || !input) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing parameters"); + + if (grub_strlen (s1) != grub_strlen (s2)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "set sizes did not match"); + + /* Translate input into output buffer. */ + + output = grub_malloc (grub_strlen (input) + 1); + if (! output) + return grub_errno; + + optr = output; + for (iptr = input; *iptr; iptr++) + { + char *p = grub_strchr (s1, *iptr); + if (p) + *optr++ = s2[p - s1]; + else + *optr++ = *iptr; + } + *optr = '\0'; + + if (ctxt->state[0].set) + grub_env_set (var, output); + else + grub_printf ("%s\n", output); + + grub_free (output); + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(tr) +{ + cmd = grub_register_extcmd ("tr", grub_cmd_tr, 0, N_("[OPTIONS] [SET1] [SET2] [STRING]"), + N_("Translate SET1 characters to SET2 in STRING."), options); +} + +GRUB_MOD_FINI(tr) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/commands/usbtest.c b/grub-core/commands/usbtest.c index 72475901d..2c6d93fe6 100644 --- a/grub-core/commands/usbtest.c +++ b/grub-core/commands/usbtest.c @@ -63,6 +63,11 @@ static const char *usb_devspeed[] = "High" }; +#if __GNUC__ >= 9 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" +#endif + static grub_usb_err_t grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index, int langid, char **string) @@ -108,6 +113,10 @@ grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index, int langid, return GRUB_USB_ERR_NONE; } +#if __GNUC__ >= 9 +#pragma GCC diagnostic pop +#endif + static void usb_print_str (const char *description, grub_usb_device_t dev, int idx) { @@ -129,7 +138,7 @@ usb_print_str (const char *description, grub_usb_device_t dev, int idx) } static int -usb_iterate (grub_usb_device_t dev) +usb_iterate (grub_usb_device_t dev, void *data __attribute__ ((unused))) { struct grub_usb_desc_device *descdev; int i; @@ -196,10 +205,10 @@ grub_cmd_usbtest (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - grub_usb_poll_devices (); + grub_usb_poll_devices (1); grub_printf ("USB devices:\n\n"); - grub_usb_iterate (usb_iterate); + grub_usb_iterate (usb_iterate, NULL); return 0; } diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 4a1157615..205ba78c9 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -27,23 +27,28 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static unsigned height, width, depth; -static struct grub_video_mode_info *current_mode; +struct hook_ctx +{ + unsigned height, width, depth; + struct grub_video_mode_info *current_mode; +}; static int -hook (const struct grub_video_mode_info *info) +hook (const struct grub_video_mode_info *info, void *hook_arg) { - if (height && width && (info->width != width || info->height != height)) + struct hook_ctx *ctx = hook_arg; + + if (ctx->height && ctx->width && (info->width != ctx->width || info->height != ctx->height)) return 0; - if (depth && info->bpp != depth) + if (ctx->depth && info->bpp != ctx->depth) return 0; if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID) grub_printf (" "); else { - if (current_mode && info->mode_number == current_mode->mode_number) + if (ctx->current_mode && info->mode_number == ctx->current_mode->mode_number) grub_printf ("*"); else grub_printf (" "); @@ -68,9 +73,9 @@ hook (const struct grub_video_mode_info *info) info->blue_field_pos, info->reserved_field_pos); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) - /* TRANSLATORS: In "packed pixel" mode you write the index of the color - in the palette. Synonyms include "paletted color". */ - grub_xputs (_("Packed pixel ")); + /* TRANSLATORS: In "paletted color" mode you write the index of the color + in the palette. Synonyms include "packed pixel". */ + grub_xputs (_("Paletted ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV) grub_xputs (_("YUV ")); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR) @@ -126,13 +131,14 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), { grub_video_adapter_t adapter; grub_video_driver_id_t id; + struct hook_ctx ctx; - height = width = depth = 0; + ctx.height = ctx.width = ctx.depth = 0; if (argc) { - char *ptr; + const char *ptr; ptr = args[0]; - width = grub_strtoul (ptr, &ptr, 0); + ctx.width = grub_strtoul (ptr, &ptr, 0); if (grub_errno) return grub_errno; if (*ptr != 'x') @@ -140,13 +146,13 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), N_("invalid video mode specification `%s'"), args[0]); ptr++; - height = grub_strtoul (ptr, &ptr, 0); + ctx.height = grub_strtoul (ptr, &ptr, 0); if (grub_errno) return grub_errno; if (*ptr == 'x') { ptr++; - depth = grub_strtoul (ptr, &ptr, 0); + ctx.depth = grub_strtoul (ptr, &ptr, 0); if (grub_errno) return grub_errno; } @@ -175,16 +181,21 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), continue; } - current_mode = NULL; + ctx.current_mode = NULL; if (adapter->id == id) { if (grub_video_get_info (&info) == GRUB_ERR_NONE) - current_mode = &info; + ctx.current_mode = &info; else /* Don't worry about errors. */ grub_errno = GRUB_ERR_NONE; } + else if (id != GRUB_VIDEO_DRIVER_NONE) + { + grub_puts_ (N_(" A video driver is active, cannot initialize this driver until it is deactivated\n")); + continue; + } else { if (adapter->init ()) @@ -198,14 +209,14 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), if (adapter->print_adapter_specific_info) adapter->print_adapter_specific_info (); - adapter->iterate (hook); + adapter->iterate (hook, &ctx); if (adapter->get_edid && adapter->get_edid (&edid_info) == GRUB_ERR_NONE) print_edid (&edid_info); else grub_errno = GRUB_ERR_NONE; - current_mode = NULL; + ctx.current_mode = NULL; if (adapter->id != id) { diff --git a/grub-core/commands/videotest.c b/grub-core/commands/videotest.c index 2e4b3a23c..ac145afc2 100644 --- a/grub-core/commands/videotest.c +++ b/grub-core/commands/videotest.c @@ -49,7 +49,6 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), if (grub_strcmp (cmd->name, "vbetest") == 0) grub_dl_load ("vbe"); #endif - mode = grub_env_get ("gfxmode"); if (argc) mode = args[0]; @@ -71,10 +70,10 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_font_t fixed; struct grub_font_glyph *glyph; - grub_video_create_render_target (&text_layer, width, height, - GRUB_VIDEO_MODE_TYPE_RGB - | GRUB_VIDEO_MODE_TYPE_ALPHA); - if (!text_layer) + if (grub_video_create_render_target (&text_layer, width, height, + GRUB_VIDEO_MODE_TYPE_RGB + | GRUB_VIDEO_MODE_TYPE_ALPHA) + || !text_layer) goto fail; grub_video_set_active_render_target (text_layer); @@ -155,26 +154,38 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); - for (i = 0; i < 2; i++) - { - color = grub_video_map_rgb (0, 0, 0); - grub_video_fill_rect (color, 0, 0, width, height); - - color = grub_video_map_rgb (255, 0, 0); - grub_video_fill_rect (color, 0, 0, 100, 100); - - color = grub_video_map_rgb (0, 255, 255); - grub_video_fill_rect (color, 100, 100, 100, 100); - - grub_video_set_viewport (x + 150, y + 150, - width - 150 * 2, height - 150 * 2); - color = grub_video_map_rgb (77, 33, 77); - grub_video_fill_rect (color, 0, 0, width, height); - grub_video_swap_buffers (); - } - for (i = 0; i < 5; i++) { + + if (i == 0 || i == 1) + { + color = grub_video_map_rgb (0, 0, 0); + grub_video_fill_rect (color, 0, 0, width, height); + + color = grub_video_map_rgb (255, 0, 0); + grub_video_fill_rect (color, 0, 0, 100, 100); + + color = grub_video_map_rgb (0, 255, 0); + grub_video_fill_rect (color, 100, 0, 100, 100); + + color = grub_video_map_rgb (0, 0, 255); + grub_video_fill_rect (color, 200, 0, 100, 100); + + color = grub_video_map_rgb (0, 255, 255); + grub_video_fill_rect (color, 0, 100, 100, 100); + + color = grub_video_map_rgb (255, 0, 255); + grub_video_fill_rect (color, 100, 100, 100, 100); + + color = grub_video_map_rgb (255, 255, 0); + grub_video_fill_rect (color, 200, 100, 100, 100); + + grub_video_set_viewport (x + 150, y + 150, + width - 150 * 2, height - 150 * 2); + color = grub_video_map_rgb (77, 33, 77); + grub_video_fill_rect (color, 0, 0, width, height); + } + color = grub_video_map_rgb (i, 33, 77); grub_video_fill_rect (color, 0, 0, width, height); grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 0, 0, diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index 2b73d9ad8..ed6586505 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -48,6 +49,7 @@ merge (char **dest, char **ps) int i; int j; char **p; + grub_size_t sz; if (! dest) return ps; @@ -60,7 +62,12 @@ merge (char **dest, char **ps) for (j = 0; ps[j]; j++) ; - p = grub_realloc (dest, sizeof (char*) * (i + j + 1)); + if (grub_add (i, j, &sz) || + grub_add (sz, 1, &sz) || + grub_mul (sz, sizeof (char *), &sz)) + return dest; + + p = grub_realloc (dest, sz); if (! p) { grub_free (dest); @@ -115,8 +122,15 @@ make_regex (const char *start, const char *end, regex_t *regexp) char ch; int i = 0; unsigned len = end - start; - char *buffer = grub_malloc (len * 2 + 2 + 1); /* worst case size. */ + char *buffer; + grub_size_t sz; + /* Worst case size is (len * 2 + 2 + 1). */ + if (grub_mul (len, 2, &sz) || + grub_add (sz, 3, &sz)) + return 1; + + buffer = grub_malloc (sz); if (! buffer) return 1; @@ -210,120 +224,160 @@ split_path (const char *str, const char **noregexop, const char **regexop) *noregexop = split; } +/* Context for match_devices. */ +struct match_devices_ctx +{ + const regex_t *regexp; + int noparts; + int ndev; + char **devs; +}; + +/* Helper for match_devices. */ +static int +match_devices_iter (const char *name, void *data) +{ + struct match_devices_ctx *ctx = data; + char **t; + char *buffer; + grub_size_t sz; + + /* skip partitions if asked to. */ + if (ctx->noparts && grub_strchr (name, ',')) + return 0; + + buffer = grub_xasprintf ("(%s)", name); + if (! buffer) + return 1; + + grub_dprintf ("expand", "matching: %s\n", buffer); + if (regexec (ctx->regexp, buffer, 0, 0, 0)) + { + grub_dprintf ("expand", "not matched\n"); + fail: + grub_free (buffer); + return 0; + } + + if (grub_add (ctx->ndev, 2, &sz) || + grub_mul (sz, sizeof (char *), &sz)) + goto fail; + + t = grub_realloc (ctx->devs, sz); + if (! t) + { + grub_free (buffer); + return 1; + } + + ctx->devs = t; + ctx->devs[ctx->ndev++] = buffer; + ctx->devs[ctx->ndev] = 0; + return 0; +} + static char ** match_devices (const regex_t *regexp, int noparts) { + struct match_devices_ctx ctx = { + .regexp = regexp, + .noparts = noparts, + .ndev = 0, + .devs = 0 + }; int i; - int ndev; - char **devs; - auto int match (const char *name); - int match (const char *name) - { - char **t; - char *buffer; - - /* skip partitions if asked to. */ - if (noparts && grub_strchr(name, ',')) - return 0; - - buffer = grub_xasprintf ("(%s)", name); - if (! buffer) - return 1; - - grub_dprintf ("expand", "matching: %s\n", buffer); - if (regexec (regexp, buffer, 0, 0, 0)) - { - grub_dprintf ("expand", "not matched\n"); - grub_free (buffer); - return 0; - } - - t = grub_realloc (devs, sizeof (char*) * (ndev + 2)); - if (! t) - return 1; - - devs = t; - devs[ndev++] = buffer; - devs[ndev] = 0; - return 0; - } - - ndev = 0; - devs = 0; - - if (grub_device_iterate (match)) + if (grub_device_iterate (match_devices_iter, &ctx)) goto fail; - return devs; + return ctx.devs; fail: - for (i = 0; devs && devs[i]; i++) - grub_free (devs[i]); + for (i = 0; ctx.devs && ctx.devs[i]; i++) + grub_free (ctx.devs[i]); - grub_free (devs); + grub_free (ctx.devs); return 0; } +/* Context for match_files. */ +struct match_files_ctx +{ + const regex_t *regexp; + char **files; + unsigned nfile; + char *dir; +}; + +/* Helper for match_files. */ +static int +match_files_iter (const char *name, + const struct grub_dirhook_info *info __attribute__((unused)), + void *data) +{ + struct match_files_ctx *ctx = data; + char **t; + char *buffer; + grub_size_t sz; + + /* skip . and .. names */ + if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0) + return 0; + + grub_dprintf ("expand", "matching: %s in %s\n", name, ctx->dir); + if (regexec (ctx->regexp, name, 0, 0, 0)) + return 0; + + grub_dprintf ("expand", "matched\n"); + + buffer = grub_xasprintf ("%s%s", ctx->dir, name); + if (! buffer) + return 1; + + if (grub_add (ctx->nfile, 2, &sz) || + grub_mul (sz, sizeof (char *), &sz)) + goto fail; + + t = grub_realloc (ctx->files, sz); + if (!t) + { + fail: + grub_free (buffer); + return 1; + } + + ctx->files = t; + ctx->files[ctx->nfile++] = buffer; + ctx->files[ctx->nfile] = 0; + return 0; +} + static char ** match_files (const char *prefix, const char *suffix, const char *end, const regex_t *regexp) { + struct match_files_ctx ctx = { + .regexp = regexp, + .nfile = 0, + .files = 0 + }; int i; - char **files; - unsigned nfile; - char *dir; const char *path; char *device_name; grub_fs_t fs; grub_device_t dev; - auto int match (const char *name, const struct grub_dirhook_info *info); - int match (const char *name, const struct grub_dirhook_info *info) - { - char **t; - char *buffer; - - /* skip . and .. names */ - if (grub_strcmp(".", name) == 0 || grub_strcmp("..", name) == 0) - return 0; - - grub_dprintf ("expand", "matching: %s in %s\n", name, dir); - if (regexec (regexp, name, 0, 0, 0)) - return 0; - - grub_dprintf ("expand", "matched\n"); - - buffer = grub_xasprintf ("%s%s", dir, name); - if (! buffer) - return 1; - - t = grub_realloc (files, sizeof (char*) * (nfile + 2)); - if (! t) - { - grub_free (buffer); - return 1; - } - - files = t; - files[nfile++] = buffer; - files[nfile] = 0; - return 0; - } - - nfile = 0; - files = 0; dev = 0; device_name = 0; grub_error_push (); - dir = make_dir (prefix, suffix, end); - if (! dir) + ctx.dir = make_dir (prefix, suffix, end); + if (! ctx.dir) goto fail; - device_name = grub_file_get_device_name (dir); + device_name = grub_file_get_device_name (ctx.dir); dev = grub_device_open (device_name); if (! dev) goto fail; @@ -332,33 +386,33 @@ match_files (const char *prefix, const char *suffix, const char *end, if (! fs) goto fail; - if (dir[0] == '(') + if (ctx.dir[0] == '(') { - path = grub_strchr (dir, ')'); + path = grub_strchr (ctx.dir, ')'); if (!path) goto fail; path++; } else - path = dir; + path = ctx.dir; - if (fs->dir (dev, path, match)) + if (fs->fs_dir (dev, path, match_files_iter, &ctx)) goto fail; - grub_free (dir); + grub_free (ctx.dir); grub_device_close (dev); grub_free (device_name); grub_error_pop (); - return files; + return ctx.files; fail: - grub_free (dir); + grub_free (ctx.dir); - for (i = 0; files && files[i]; i++) - grub_free (files[i]); + for (i = 0; ctx.files && ctx.files[i]; i++) + grub_free (ctx.files[i]); - grub_free (files); + grub_free (ctx.files); if (dev) grub_device_close (dev); @@ -369,28 +423,42 @@ match_files (const char *prefix, const char *suffix, const char *end, return 0; } +/* Context for check_file. */ +struct check_file_ctx +{ + const char *basename; + int found; +}; + +/* Helper for check_file. */ +static int +check_file_iter (const char *name, const struct grub_dirhook_info *info, + void *data) +{ + struct check_file_ctx *ctx = data; + + if (ctx->basename[0] == 0 + || (info->case_insensitive ? grub_strcasecmp (name, ctx->basename) == 0 + : grub_strcmp (name, ctx->basename) == 0)) + { + ctx->found = 1; + return 1; + } + + return 0; +} + static int check_file (const char *dir, const char *basename) { + struct check_file_ctx ctx = { + .basename = basename, + .found = 0 + }; grub_fs_t fs; grub_device_t dev; - int found = 0; const char *device_name, *path; - auto int match (const char *name, const struct grub_dirhook_info *info); - int match (const char *name, const struct grub_dirhook_info *info) - { - if (basename[0] == 0 - || (info->case_insensitive ? grub_strcasecmp (name, basename) == 0 - : grub_strcmp (name, basename) == 0)) - { - found = 1; - return 1; - } - - return 0; - } - device_name = grub_file_get_device_name (dir); dev = grub_device_open (device_name); if (! dev) @@ -410,14 +478,14 @@ check_file (const char *dir, const char *basename) else path = dir; - fs->dir (dev, path[0] ? path : "/", match); + fs->fs_dir (dev, path[0] ? path : "/", check_file_iter, &ctx); if (grub_errno == 0 && basename[0] == 0) - found = 1; + ctx.found = 1; fail: grub_errno = 0; - return found; + return ctx.found; } static void diff --git a/grub-core/commands/xen/lsxen.c b/grub-core/commands/xen/lsxen.c new file mode 100644 index 000000000..97713102c --- /dev/null +++ b/grub-core/commands/xen/lsxen.c @@ -0,0 +1,90 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static int +hook (const char *dir, void *hook_data __attribute__ ((unused))) +{ + grub_printf ("%s\n", dir); + return 0; +} + +static grub_err_t +grub_cmd_lsxen (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + char *dir; + grub_err_t err; + char *buf; + + if (argc >= 1) + return grub_xenstore_dir (args[0], hook, NULL); + + buf = grub_xenstore_get_file ("domid", NULL); + if (!buf) + return grub_errno; + dir = grub_xasprintf ("/local/domain/%s", buf); + grub_free (buf); + err = grub_xenstore_dir (dir, hook, NULL); + grub_free (dir); + return err; +} + +static grub_err_t +grub_cmd_catxen (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + const char *dir = "domid"; + char *buf; + + if (argc >= 1) + dir = args[0]; + + buf = grub_xenstore_get_file (dir, NULL); + if (!buf) + return grub_errno; + grub_xputs (buf); + grub_xputs ("\n"); + grub_free (buf); + return GRUB_ERR_NONE; + +} + +static grub_command_t cmd_ls, cmd_cat; + +GRUB_MOD_INIT (lsxen) +{ + cmd_ls = grub_register_command ("xen_ls", grub_cmd_lsxen, N_("[DIR]"), + N_("List Xen storage.")); + cmd_cat = grub_register_command ("xen_cat", grub_cmd_catxen, N_("[DIR]"), + N_("List Xen storage.")); +} + +GRUB_MOD_FINI (lsxen) +{ + grub_unregister_command (cmd_ls); + grub_unregister_command (cmd_cat); +} diff --git a/grub-core/commands/xnu_uuid.c b/grub-core/commands/xnu_uuid.c index 8161d570e..ae4b3a415 100644 --- a/grub-core/commands/xnu_uuid.c +++ b/grub-core/commands/xnu_uuid.c @@ -50,7 +50,7 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), grub_uint8_t *xnu_uuid; char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; char *ptr; - grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; + void *ctx; int low = 0; if (argc < 1) @@ -65,11 +65,14 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16)); - GRUB_MD_MD5->init (&ctx); - GRUB_MD_MD5->write (&ctx, hash_prefix, sizeof (hash_prefix)); - GRUB_MD_MD5->write (&ctx, &serial, sizeof (serial)); - GRUB_MD_MD5->final (&ctx); - xnu_uuid = GRUB_MD_MD5->read (&ctx); + ctx = grub_zalloc (GRUB_MD_MD5->contextsize); + if (!ctx) + return grub_errno; + GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->write (ctx, hash_prefix, sizeof (hash_prefix)); + GRUB_MD_MD5->write (ctx, &serial, sizeof (serial)); + GRUB_MD_MD5->final (ctx); + xnu_uuid = GRUB_MD_MD5->read (ctx); grub_snprintf (uuid_string, sizeof (uuid_string), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", @@ -91,6 +94,8 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), if (argc > 1) grub_env_set (args[1], uuid_string); + grub_free (ctx); + return GRUB_ERR_NONE; } diff --git a/grub-core/disk/AFSplitter.c b/grub-core/disk/AFSplitter.c index ebcc35221..249163ff0 100644 --- a/grub-core/disk/AFSplitter.c +++ b/grub-core/disk/AFSplitter.c @@ -21,9 +21,12 @@ */ #include +#include #include #include +GRUB_MOD_LICENSE ("GPLv2+"); + gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst, grub_size_t blocksize, grub_size_t blocknumbers); @@ -37,8 +40,8 @@ diffuse (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_size_t fullblocks = size / hash->mdlen; int padding = size % hash->mdlen; - grub_uint8_t final[hash->mdlen]; - grub_uint8_t temp[sizeof (IV) + hash->mdlen]; + grub_uint8_t final[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t temp[sizeof (IV) + GRUB_CRYPTO_MAX_MDLEN]; /* hash block the whole data set with different IVs to produce * more than just a single data block @@ -72,6 +75,9 @@ AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_uint8_t * dst, grub_size_t i; grub_uint8_t *bufblock; + if (hash->mdlen > GRUB_CRYPTO_MAX_MDLEN || hash->mdlen == 0) + return GPG_ERR_INV_ARG; + bufblock = grub_zalloc (blocksize); if (bufblock == NULL) return GPG_ERR_OUT_OF_MEMORY; diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 4ab2d18db..f3c968195 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -32,7 +32,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); struct grub_ahci_cmd_head { grub_uint32_t config; - grub_uint32_t transfered; + grub_uint32_t transferred; grub_uint64_t command_table_base; grub_uint32_t unused[4]; }; @@ -75,11 +75,27 @@ struct grub_ahci_hba_port enum grub_ahci_hba_port_command { GRUB_AHCI_HBA_PORT_CMD_ST = 0x01, + GRUB_AHCI_HBA_PORT_CMD_SPIN_UP = 0x02, + GRUB_AHCI_HBA_PORT_CMD_POWER_ON = 0x04, GRUB_AHCI_HBA_PORT_CMD_FRE = 0x10, GRUB_AHCI_HBA_PORT_CMD_CR = 0x8000, GRUB_AHCI_HBA_PORT_CMD_FR = 0x4000, }; +enum grub_ahci_hba_port_int_status + { + GRUB_AHCI_HBA_PORT_IS_IFS = (1UL << 27), + GRUB_AHCI_HBA_PORT_IS_HBDS = (1UL << 28), + GRUB_AHCI_HBA_PORT_IS_HBFS = (1UL << 29), + GRUB_AHCI_HBA_PORT_IS_TFES = (1UL << 30), + }; + +#define GRUB_AHCI_HBA_PORT_IS_FATAL_MASK ( \ + GRUB_AHCI_HBA_PORT_IS_IFS | \ + GRUB_AHCI_HBA_PORT_IS_HBDS | \ + GRUB_AHCI_HBA_PORT_IS_HBFS | \ + GRUB_AHCI_HBA_PORT_IS_TFES) + struct grub_ahci_hba { grub_uint32_t cap; @@ -131,12 +147,12 @@ struct grub_ahci_device volatile struct grub_ahci_cmd_table *command_table; struct grub_pci_dma_chunk *rfis; int present; + int atapi; }; -static grub_err_t +static grub_err_t grub_ahci_readwrite_real (struct grub_ahci_device *dev, - struct grub_disk_ata_pass_through_parms *parms, - int spinup); + struct grub_disk_ata_pass_through_parms *parms, int reset); enum @@ -162,8 +178,531 @@ enum static struct grub_ahci_device *grub_ahci_devices; static int numdevs; -static int -init_port (struct grub_ahci_device *dev) +static int +grub_ahci_pciinit (grub_pci_device_t dev, + grub_pci_id_t pciid __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + grub_pci_address_t addr; + grub_uint32_t class; + grub_uint32_t bar; + unsigned i, nports; + volatile struct grub_ahci_hba *hba; + + /* Read class. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + /* Check if this class ID matches that of a PCI IDE Controller. */ + if (class >> 8 != 0x010601) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5); + + bar = grub_pci_read (addr); + + if ((bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK + | GRUB_PCI_ADDR_MEM_PREFETCH)) + != (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32)) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, grub_pci_read_word (addr) + | GRUB_PCI_COMMAND_MEM_ENABLED | GRUB_PCI_COMMAND_BUS_MASTER); + + hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, + sizeof (*hba)); + grub_dprintf ("ahci", "dev: %x:%x.%x\n", dev.bus, dev.device, dev.function); + + grub_dprintf ("ahci", "tfd[0]: %x\n", + hba->ports[0].task_file_data); + grub_dprintf ("ahci", "cmd[0]: %x\n", + hba->ports[0].command); + grub_dprintf ("ahci", "st[0]: %x\n", + hba->ports[0].status); + grub_dprintf ("ahci", "err[0]: %x\n", + hba->ports[0].sata_error); + + grub_dprintf ("ahci", "tfd[1]: %x\n", + hba->ports[1].task_file_data); + grub_dprintf ("ahci", "cmd[1]: %x\n", + hba->ports[1].command); + grub_dprintf ("ahci", "st[1]: %x\n", + hba->ports[1].status); + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + hba->ports[1].sata_error = hba->ports[1].sata_error; + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + grub_dprintf ("ahci", "BH:%x\n", hba->bios_handoff); + + if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED)) + { + grub_uint64_t endtime; + + grub_dprintf ("ahci", "Requesting AHCI ownership\n"); + hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC) + | GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; + grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n"); + endtime = grub_get_time_ms () + 1000; + while ((hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) + && grub_get_time_ms () < endtime); + if (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) + { + grub_dprintf ("ahci", "Forcibly taking ownership\n"); + hba->bios_handoff = GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; + hba->bios_handoff |= GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED; + } + else + grub_dprintf ("ahci", "AHCI ownership obtained\n"); + } + else + grub_dprintf ("ahci", "AHCI is already in OS mode\n"); + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + if (!(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)) + grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n"); + else + grub_dprintf ("ahci", "AHCI is in AHCI mode.\n"); + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + /* { + grub_uint64_t endtime; + hba->global_control |= 1; + endtime = grub_get_time_ms () + 1000; + while (hba->global_control & 1) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't reset AHCI\n"); + return 0; + } + }*/ + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + for (i = 0; i < 5; i++) + { + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + grub_millisleep (1); + if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) + break; + } + if (i == 5) + { + grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); + return 0; + } + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + for (i = 0; i < 5; i++) + { + hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; + grub_millisleep (1); + if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) + break; + } + if (i == 5) + { + grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); + return 0; + } + + grub_dprintf ("ahci", "err[1]: %x\n", + hba->ports[1].sata_error); + + grub_dprintf ("ahci", "GLC:%x\n", hba->global_control); + + nports = (GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; + + grub_dprintf ("ahci", "%d AHCI ports, PI = 0x%x\n", nports, + hba->ports_implemented); + + struct grub_ahci_device *adevs[GRUB_AHCI_HBA_CAP_NPORTS_MASK + 1]; + struct grub_ahci_device *failed_adevs[GRUB_AHCI_HBA_CAP_NPORTS_MASK + 1]; + grub_uint32_t fr_running = 0; + + for (i = 0; i < nports; i++) + failed_adevs[i] = 0; + for (i = 0; i < nports; i++) + { + if (!(hba->ports_implemented & (1 << i))) + { + adevs[i] = 0; + continue; + } + + adevs[i] = grub_zalloc (sizeof (*adevs[i])); + if (!adevs[i]) + return 1; + + adevs[i]->hba = hba; + adevs[i]->port = i; + adevs[i]->present = 1; + adevs[i]->num = numdevs++; + } + + for (i = 0; i < nports; i++) + if (adevs[i]) + { + adevs[i]->hba->ports[adevs[i]->port].sata_error = adevs[i]->hba->ports[adevs[i]->port].sata_error; + grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port, + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + adevs[i]->command_list_chunk = grub_memalign_dma32 (1024, sizeof (struct grub_ahci_cmd_head) * 32); + if (!adevs[i]->command_list_chunk) + { + adevs[i] = 0; + continue; + } + + adevs[i]->command_table_chunk = grub_memalign_dma32 (1024, + sizeof (struct grub_ahci_cmd_table)); + if (!adevs[i]->command_table_chunk) + { + grub_dma_free (adevs[i]->command_list_chunk); + adevs[i] = 0; + continue; + } + + adevs[i]->command_list = grub_dma_get_virt (adevs[i]->command_list_chunk); + adevs[i]->command_table = grub_dma_get_virt (adevs[i]->command_table_chunk); + + grub_memset ((void *) adevs[i]->command_list, 0, + sizeof (struct grub_ahci_cmd_table)); + grub_memset ((void *) adevs[i]->command_table, 0, + sizeof (struct grub_ahci_cmd_head) * 32); + + adevs[i]->command_list->command_table_base + = grub_dma_get_phys (adevs[i]->command_table_chunk); + + grub_dprintf ("ahci", "found device ahci%d (port %d), command_table = %p, command_list = %p\n", + adevs[i]->num, adevs[i]->port, grub_dma_get_virt (adevs[i]->command_table_chunk), + grub_dma_get_virt (adevs[i]->command_list_chunk)); + + adevs[i]->hba->ports[adevs[i]->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + } + + grub_uint64_t endtime; + endtime = grub_get_time_ms () + 1000; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + { + grub_dprintf ("ahci", "couldn't stop FR on port %d\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + + for (i = 0; i < nports; i++) + if (adevs[i]) + adevs[i]->hba->ports[adevs[i]->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + endtime = grub_get_time_ms () + 1000; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + { + grub_dprintf ("ahci", "couldn't stop CR on port %d\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + for (i = 0; i < nports; i++) + if (adevs[i]) + { + adevs[i]->hba->ports[adevs[i]->port].inten = 0; + adevs[i]->hba->ports[adevs[i]->port].intstatus = ~0; + // adevs[i]->hba->ports[adevs[i]->port].fbs = 0; + + grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port, + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + adevs[i]->rfis = grub_memalign_dma32 (4096, + sizeof (struct grub_ahci_received_fis)); + grub_memset ((char *) grub_dma_get_virt (adevs[i]->rfis), 0, + sizeof (struct grub_ahci_received_fis)); + grub_memset ((char *) grub_dma_get_virt (adevs[i]->command_list_chunk), 0, + sizeof (struct grub_ahci_cmd_head)); + grub_memset ((char *) grub_dma_get_virt (adevs[i]->command_table_chunk), 0, + sizeof (struct grub_ahci_cmd_table)); + adevs[i]->hba->ports[adevs[i]->port].fis_base = grub_dma_get_phys (adevs[i]->rfis); + adevs[i]->hba->ports[adevs[i]->port].command_list_base + = grub_dma_get_phys (adevs[i]->command_list_chunk); + adevs[i]->hba->ports[adevs[i]->port].command_issue = 0; + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_FRE; + } + + endtime = grub_get_time_ms () + 1000; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && !(adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && !(adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + { + grub_dprintf ("ahci", "couldn't start FR on port %d\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + + for (i = 0; i < nports; i++) + if (adevs[i]) + { + grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port, + adevs[i]->hba->ports[adevs[i]->port].sata_error); + fr_running |= (1 << i); + + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_SPIN_UP; + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_POWER_ON; + adevs[i]->hba->ports[adevs[i]->port].command |= 1 << 28; + + grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port, + adevs[i]->hba->ports[adevs[i]->port].sata_error); + } + + /* 10ms should actually be enough. */ + endtime = grub_get_time_ms () + 100; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].status & 7) != 3) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].status & 7) != 3) + { + grub_dprintf ("ahci", "couldn't detect device on port %d\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + + for (i = 0; i < nports; i++) + if (adevs[i]) + { + grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port, + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_POWER_ON; + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_SPIN_UP; + + grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port, + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + adevs[i]->hba->ports[adevs[i]->port].sata_error = ~0; + grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port, + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + grub_dprintf ("ahci", "port %d, offset: %x, tfd:%x, CMD: %x\n", adevs[i]->port, + (int) ((char *) &adevs[i]->hba->ports[adevs[i]->port].task_file_data - + (char *) adevs[i]->hba), + adevs[i]->hba->ports[adevs[i]->port].task_file_data, + adevs[i]->hba->ports[adevs[i]->port].command); + + grub_dprintf ("ahci", "port %d, err: %x\n", adevs[i]->port, + adevs[i]->hba->ports[adevs[i]->port].sata_error); + } + + + for (i = 0; i < nports; i++) + if (adevs[i]) + { + grub_dprintf ("ahci", "port %d, offset: %x, tfd:%x, CMD: %x\n", adevs[i]->port, + (int) ((char *) &adevs[i]->hba->ports[adevs[i]->port].task_file_data - + (char *) adevs[i]->hba), + adevs[i]->hba->ports[adevs[i]->port].task_file_data, + adevs[i]->hba->ports[adevs[i]->port].command); + + grub_dprintf ("ahci", "port: %d, err: %x\n", adevs[i]->port, + adevs[i]->hba->ports[adevs[i]->port].sata_error); + + adevs[i]->hba->ports[adevs[i]->port].command + = (adevs[i]->hba->ports[adevs[i]->port].command & 0x0fffffff) | (1 << 28) + | GRUB_AHCI_HBA_PORT_CMD_SPIN_UP + | GRUB_AHCI_HBA_PORT_CMD_POWER_ON; + + /* struct grub_disk_ata_pass_through_parms parms2; + grub_memset (&parms2, 0, sizeof (parms2)); + parms2.taskfile.cmd = 8; + grub_ahci_readwrite_real (dev, &parms2, 1);*/ + } + + endtime = grub_get_time_ms () + 32000; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ))) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].task_file_data & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ))) + { + grub_dprintf ("ahci", "port %d is busy\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + + for (i = 0; i < nports; i++) + if (adevs[i]) + adevs[i]->hba->ports[adevs[i]->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; + + endtime = grub_get_time_ms () + 1000; + + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (adevs[i] && !(adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + break; + if (i == nports) + break; + } + + for (i = 0; i < nports; i++) + if (adevs[i] && !(adevs[i]->hba->ports[adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + { + grub_dprintf ("ahci", "couldn't start CR on port %d\n", i); + failed_adevs[i] = adevs[i]; + adevs[i] = 0; + } + + grub_dprintf ("ahci", "cleaning up failed devs\n"); + + for (i = 0; i < nports; i++) + if (failed_adevs[i] && (fr_running & (1 << i))) + failed_adevs[i]->hba->ports[failed_adevs[i]->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + + endtime = grub_get_time_ms () + 1000; + while (grub_get_time_ms () < endtime) + { + for (i = 0; i < nports; i++) + if (failed_adevs[i] && (fr_running & (1 << i)) && (failed_adevs[i]->hba->ports[failed_adevs[i]->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + break; + if (i == nports) + break; + } + for (i = 0; i < nports; i++) + if (failed_adevs[i]) + { + grub_dma_free (failed_adevs[i]->command_list_chunk); + grub_dma_free (failed_adevs[i]->command_table_chunk); + grub_dma_free (failed_adevs[i]->rfis); + } + + for (i = 0; i < nports; i++) + if (adevs[i] && (adevs[i]->hba->ports[adevs[i]->port].sig >> 16) == 0xeb14) + adevs[i]->atapi = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, grub_pci_read_word (addr) + | GRUB_PCI_COMMAND_BUS_MASTER); + + for (i = 0; i < nports; i++) + if (adevs[i]) + { + grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices), + GRUB_AS_LIST (adevs[i])); + } + + return 0; +} + +static grub_err_t +grub_ahci_initialize (void) +{ + grub_pci_iterate (grub_ahci_pciinit, NULL); + return grub_errno; +} + +static grub_err_t +grub_ahci_fini_hw (int noreturn __attribute__ ((unused))) +{ + struct grub_ahci_device *dev; + + for (dev = grub_ahci_devices; dev; dev = dev->next) + { + grub_uint64_t endtime; + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop FR\n"); + break; + } + + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR\n"); + break; + } + grub_dma_free (dev->command_list_chunk); + grub_dma_free (dev->command_table_chunk); + grub_dma_free (dev->rfis); + dev->command_list_chunk = NULL; + dev->command_table_chunk = NULL; + dev->rfis = NULL; + } + return GRUB_ERR_NONE; +} + +static int +reinit_port (struct grub_ahci_device *dev) { struct grub_pci_dma_chunk *command_list; struct grub_pci_dma_chunk *command_table; @@ -203,7 +742,7 @@ init_port (struct grub_ahci_device *dev) dev->hba->ports[dev->port].fbs = 2; - dev->rfis = grub_memalign_dma32 (4096, + dev->rfis = grub_memalign_dma32 (4096, sizeof (struct grub_ahci_received_fis)); grub_memset ((char *) grub_dma_get_virt (dev->rfis), 0, sizeof (struct grub_ahci_received_fis)); @@ -254,193 +793,13 @@ init_port (struct grub_ahci_device *dev) return 1; } -static int NESTED_FUNC_ATTR -grub_ahci_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__ ((unused))) -{ - grub_pci_address_t addr; - grub_uint32_t class; - grub_uint32_t bar; - unsigned i, nports; - volatile struct grub_ahci_hba *hba; - - /* Read class. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - /* Check if this class ID matches that of a PCI IDE Controller. */ - if (class >> 8 != 0x010601) - return 0; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG5); - bar = grub_pci_read (addr); - - if ((bar & (GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_TYPE_MASK - | GRUB_PCI_ADDR_MEM_PREFETCH)) - != (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32)) - return 0; - - hba = grub_pci_device_map_range (dev, bar & GRUB_PCI_ADDR_MEM_MASK, - sizeof (hba)); - - if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED)) - { - grub_uint64_t endtime; - - grub_dprintf ("ahci", "Requesting AHCI ownership\n"); - hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC) - | GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; - grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n"); - endtime = grub_get_time_ms () + 1000; - while ((hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) - && grub_get_time_ms () < endtime); - if (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_BIOS_OWNED) - { - grub_dprintf ("ahci", "Forcibly taking ownership\n"); - hba->bios_handoff = GRUB_AHCI_BIOS_HANDOFF_OS_OWNED; - hba->bios_handoff |= GRUB_AHCI_BIOS_HANDOFF_OS_OWNERSHIP_CHANGED; - } - else - grub_dprintf ("ahci", "AHCI ownership obtained\n"); - } - else - grub_dprintf ("ahci", "AHCI is already in OS mode\n"); - - if (!(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)) - grub_dprintf ("ahci", "AHCI is in compat mode. Switching\n"); - else - grub_dprintf ("ahci", "AHCI is in AHCI mode.\n"); - - for (i = 0; i < 5; i++) - { - hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; - grub_millisleep (1); - if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) - break; - } - if (i == 5) - { - grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); - return 0; - } - - /* - { - grub_uint64_t endtime; - hba->global_control |= 1; - endtime = grub_get_time_ms () + 1000; - while (hba->global_control & 1) - if (grub_get_time_ms () > endtime) - { - grub_dprintf ("ahci", "couldn't reset AHCI\n"); - return 0; - } - } - - for (i = 0; i < 5; i++) - { - hba->global_control |= GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN; - grub_millisleep (1); - if (hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN) - break; - } - if (i == 5) - { - grub_dprintf ("ahci", "Couldn't put AHCI in AHCI mode\n"); - return 0; - } - */ - - nports = (hba->cap & GRUB_AHCI_HBA_CAP_NPORTS_MASK) + 1; - - grub_dprintf ("ahci", "%d AHCI ports\n", nports); - - for (i = 0; i < nports; i++) - { - struct grub_ahci_device *adev; - grub_uint32_t st; - - if (!(hba->ports_implemented & (1 << i))) - continue; - - grub_dprintf ("ahci", "status %d:%x\n", i, hba->ports[i].status); - /* FIXME: support hotplugging. */ - st = hba->ports[i].status; - if ((st & 0xf) != 0x3 && (st & 0xf) != 0x1) - continue; - - adev = grub_malloc (sizeof (*adev)); - if (!adev) - return 1; - - adev->hba = hba; - adev->port = i; - adev->present = 1; - adev->num = numdevs++; - - if (init_port (adev)) - { - grub_free (adev); - return 1; - } - - grub_list_push (GRUB_AS_LIST_P (&grub_ahci_devices), - GRUB_AS_LIST (adev)); - } - - return 0; -} - -static grub_err_t -grub_ahci_initialize (void) -{ - grub_pci_iterate (grub_ahci_pciinit); - return grub_errno; -} - -static grub_err_t -grub_ahci_fini_hw (int noreturn __attribute__ ((unused))) -{ - struct grub_ahci_device *dev; - - for (dev = grub_ahci_devices; dev; dev = dev->next) - { - grub_uint64_t endtime; - - dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; - endtime = grub_get_time_ms () + 1000; - while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_FR)) - if (grub_get_time_ms () > endtime) - { - grub_dprintf ("ahci", "couldn't stop FR\n"); - break; - } - - dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; - endtime = grub_get_time_ms () + 1000; - while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) - if (grub_get_time_ms () > endtime) - { - grub_dprintf ("ahci", "couldn't stop CR\n"); - break; - } - grub_dma_free (dev->command_list_chunk); - grub_dma_free (dev->command_table_chunk); - grub_dma_free (dev->rfis); - dev->command_list_chunk = NULL; - dev->command_table_chunk = NULL; - dev->rfis = NULL; - } - return GRUB_ERR_NONE; -} - static grub_err_t grub_ahci_restore_hw (void) { struct grub_ahci_device **pdev; for (pdev = &grub_ahci_devices; *pdev; pdev = &((*pdev)->next)) - if (init_port (*pdev)) + if (reinit_port (*pdev)) { struct grub_ahci_device *odev; odev = *pdev; @@ -454,8 +813,8 @@ grub_ahci_restore_hw (void) static int -grub_ahci_iterate (int (*hook) (int id, int bus), - grub_disk_pull_t pull) +grub_ahci_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) { struct grub_ahci_device *dev; @@ -463,7 +822,7 @@ grub_ahci_iterate (int (*hook) (int id, int bus), return 0; FOR_LIST_ELEMENTS(dev, grub_ahci_devices) - if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num)) + if (hook (GRUB_SCSI_SUBSYSTEM_AHCI, dev->num, hook_data)) return 1; return 0; @@ -501,12 +860,61 @@ static const int register_map[11] = { 3 /* Features */, 13 /* Sectors 48 */, 8 /* LBA48 low */, 9 /* LBA48 mid */, - 10 /* LBA48 high */ }; + 10 /* LBA48 high */ }; -static grub_err_t +static grub_err_t +grub_ahci_reset_port (struct grub_ahci_device *dev, int force) +{ + grub_uint64_t endtime; + + dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error; + + if (force || (dev->hba->ports[dev->port].command_issue & 1) + || (dev->hba->ports[dev->port].task_file_data & 0x80)) + { + struct grub_disk_ata_pass_through_parms parms2; + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + dev->hba->ports[dev->port].command_issue = 0; + dev->command_list[0].config = 0; + dev->command_table[0].prdt[0].unused = 0; + dev->command_table[0].prdt[0].size = 0; + dev->command_table[0].prdt[0].data_base = 0; + + endtime = grub_get_time_ms () + 1000; + while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR"); + return grub_error (GRUB_ERR_IO, "couldn't stop CR"); + } + dev->hba->ports[dev->port].command |= 8; + while (dev->hba->ports[dev->port].command & 8) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't set CLO\n"); + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_FRE; + return grub_error (GRUB_ERR_IO, "couldn't set CLO"); + } + + dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; + while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) + if (grub_get_time_ms () > endtime) + { + grub_dprintf ("ahci", "couldn't stop CR"); + dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; + return grub_error (GRUB_ERR_IO, "couldn't stop CR"); + } + dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error; + grub_memset (&parms2, 0, sizeof (parms2)); + parms2.taskfile.cmd = 8; + return grub_ahci_readwrite_real (dev, &parms2, 1); + } + return GRUB_ERR_NONE; +} + +static grub_err_t grub_ahci_readwrite_real (struct grub_ahci_device *dev, - struct grub_disk_ata_pass_through_parms *parms, - int spinup) + struct grub_disk_ata_pass_through_parms *parms, int reset) { struct grub_pci_dma_chunk *bufc; grub_uint64_t endtime; @@ -516,25 +924,15 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, grub_dprintf ("ahci", "AHCI tfd = %x\n", dev->hba->ports[dev->port].task_file_data); - if ((dev->hba->ports[dev->port].task_file_data & 0x80)) - { - dev->hba->ports[dev->port].command &= ~GRUB_AHCI_HBA_PORT_CMD_ST; - endtime = grub_get_time_ms () + 1000; - while ((dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) - if (grub_get_time_ms () > endtime) - { - grub_dprintf ("ahci", "couldn't stop CR\n"); - break; - } - dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST; - endtime = grub_get_time_ms () + (spinup ? 10000 : 1000); - while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR)) - if (grub_get_time_ms () > endtime) - { - grub_dprintf ("ahci", "couldn't start CR\n"); - break; - } - } + if (!reset) + grub_ahci_reset_port (dev, 0); + + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + dev->hba->ports[dev->port].task_file_data = 0; + dev->hba->ports[dev->port].command_issue = 0; + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); dev->hba->ports[dev->port].sata_error = dev->hba->ports[dev->port].sata_error; @@ -548,36 +946,49 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH) return grub_error (GRUB_ERR_BUG, "too big data buffer"); - bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); + if (parms->size) + bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); + else + bufc = grub_memalign_dma32 (1024, 512); - dev->hba->ports[dev->port].command |= 8; - - grub_dprintf ("ahci", "AHCI tfd = %x\n", - dev->hba->ports[dev->port].task_file_data); + grub_dprintf ("ahci", "AHCI tfd = %x, CL=%p\n", + dev->hba->ports[dev->port].task_file_data, + dev->command_list); /* FIXME: support port multipliers. */ dev->command_list[0].config = (5 << GRUB_AHCI_CONFIG_CFIS_LENGTH_SHIFT) // | GRUB_AHCI_CONFIG_CLEAR_R_OK | (0 << GRUB_AHCI_CONFIG_PMP_SHIFT) - | (1 << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT) + | ((parms->size ? 1 : 0) << GRUB_AHCI_CONFIG_PRDT_LENGTH_SHIFT) | (parms->cmdsize ? GRUB_AHCI_CONFIG_ATAPI : 0) | (parms->write ? GRUB_AHCI_CONFIG_WRITE : GRUB_AHCI_CONFIG_READ) | (parms->taskfile.cmd == 8 ? (1 << 8) : 0); - dev->command_list[0].transfered = 0; + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + + dev->command_list[0].transferred = 0; dev->command_list[0].command_table_base = grub_dma_get_phys (dev->command_table_chunk); + grub_memset ((char *) dev->command_list[0].unused, 0, sizeof (dev->command_list[0].unused)); + grub_memset ((char *) &dev->command_table[0], 0, sizeof (dev->command_table[0])); + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + if (parms->cmdsize) grub_memcpy ((char *) dev->command_table[0].command, parms->cmd, parms->cmdsize); + grub_dprintf ("ahci", "AHCI tfd = %x\n", + dev->hba->ports[dev->port].task_file_data); + dev->command_table[0].cfis[0] = GRUB_AHCI_FIS_REG_H2D; dev->command_table[0].cfis[1] = 0x80; for (i = 0; i < sizeof (parms->taskfile.raw); i++) - dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; + dev->command_table[0].cfis[register_map[i]] = parms->taskfile.raw[i]; grub_dprintf ("ahci", "cfis: %02x %02x %02x %02x %02x %02x %02x %02x\n", dev->command_table[0].cfis[0], dev->command_table[0].cfis[1], @@ -592,41 +1003,56 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, dev->command_table[0].prdt[0].data_base = grub_dma_get_phys (bufc); dev->command_table[0].prdt[0].unused = 0; - dev->command_table[0].prdt[0].size = (parms->size + (parms->size & 1) - 1) - | GRUB_AHCI_INTERRUPT_ON_COMPLETE; + dev->command_table[0].prdt[0].size = (parms->size - 1); grub_dprintf ("ahci", "PRDT = %" PRIxGRUB_UINT64_T ", %x, %x (%" PRIuGRUB_SIZE ")\n", dev->command_table[0].prdt[0].data_base, dev->command_table[0].prdt[0].unused, dev->command_table[0].prdt[0].size, - (char *) &dev->command_table[0].prdt[0] - - (char *) &dev->command_table[0]); + (grub_size_t) ((char *) &dev->command_table[0].prdt[0] + - (char *) &dev->command_table[0])); if (parms->write) grub_memcpy ((char *) grub_dma_get_virt (bufc), parms->buffer, parms->size); - grub_dprintf ("ahci", "AHCI command schedulded\n"); + grub_dprintf ("ahci", "AHCI command scheduled\n"); grub_dprintf ("ahci", "AHCI tfd = %x\n", dev->hba->ports[dev->port].task_file_data); + grub_dprintf ("ahci", "AHCI inten = %x\n", + dev->hba->ports[dev->port].inten); + grub_dprintf ("ahci", "AHCI intstatus = %x\n", + dev->hba->ports[dev->port].intstatus); + dev->hba->ports[dev->port].inten = 0xffffffff;//(1 << 2) | (1 << 5); dev->hba->ports[dev->port].intstatus = 0xffffffff;//(1 << 2) | (1 << 5); + grub_dprintf ("ahci", "AHCI inten = %x\n", + dev->hba->ports[dev->port].inten); grub_dprintf ("ahci", "AHCI tfd = %x\n", dev->hba->ports[dev->port].task_file_data); - dev->hba->ports[dev->port].command_issue |= 1; + dev->hba->ports[dev->port].sata_active = 1; + dev->hba->ports[dev->port].command_issue = 1; grub_dprintf ("ahci", "AHCI sig = %x\n", dev->hba->ports[dev->port].sig); grub_dprintf ("ahci", "AHCI tfd = %x\n", dev->hba->ports[dev->port].task_file_data); - endtime = grub_get_time_ms () + (spinup ? 10000 : 1000); + endtime = grub_get_time_ms () + 20000; while ((dev->hba->ports[dev->port].command_issue & 1)) - if (grub_get_time_ms () > endtime) + if (grub_get_time_ms () > endtime || + (dev->hba->ports[dev->port].intstatus & GRUB_AHCI_HBA_PORT_IS_FATAL_MASK)) { - grub_dprintf ("ahci", "AHCI status <%x %x %x>\n", + grub_dprintf ("ahci", "AHCI status <%x %x %x %x>\n", dev->hba->ports[dev->port].command_issue, + dev->hba->ports[dev->port].sata_active, dev->hba->ports[dev->port].intstatus, dev->hba->ports[dev->port].task_file_data); - err = grub_error (GRUB_ERR_IO, "AHCI transfer timed out"); + dev->hba->ports[dev->port].command_issue = 0; + if (dev->hba->ports[dev->port].intstatus & GRUB_AHCI_HBA_PORT_IS_FATAL_MASK) + err = grub_error (GRUB_ERR_IO, "AHCI transfer error"); + else + err = grub_error (GRUB_ERR_IO, "AHCI transfer timed out"); + if (!reset) + grub_ahci_reset_port (dev, 1); break; } @@ -634,7 +1060,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, dev->hba->ports[dev->port].command_issue, dev->hba->ports[dev->port].intstatus, dev->hba->ports[dev->port].task_file_data, - dev->command_list[0].transfered, + dev->command_list[0].transferred, dev->hba->ports[dev->port].sata_error, ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x00], ((grub_uint32_t *) grub_dma_get_virt (dev->rfis))[0x18]); @@ -666,12 +1092,12 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, return err; } -static grub_err_t +static grub_err_t grub_ahci_readwrite (grub_ata_t disk, struct grub_disk_ata_pass_through_parms *parms, - int spinup) + int spinup __attribute__((__unused__))) { - return grub_ahci_readwrite_real (disk->data, parms, spinup); + return grub_ahci_readwrite_real (disk->data, parms, 0); } static grub_err_t @@ -693,6 +1119,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata) ata->data = dev; ata->dma = 1; + ata->atapi = dev->atapi; ata->maxbuffer = GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH; ata->present = &dev->present; @@ -712,13 +1139,7 @@ static struct grub_preboot *fini_hnd; GRUB_MOD_INIT(ahci) { - /* To prevent two drivers operating on the same disks. */ - grub_disk_firmware_is_tainted = 1; - if (grub_disk_firmware_fini) - { - grub_disk_firmware_fini (); - grub_disk_firmware_fini = NULL; - } + grub_stop_disk_firmware (); /* AHCI initialization. */ grub_ahci_initialize (); diff --git a/grub-core/disk/arc/arcdisk.c b/grub-core/disk/arc/arcdisk.c index 10cbc8759..c94039a3d 100644 --- a/grub-core/disk/arc/arcdisk.c +++ b/grub-core/disk/arc/arcdisk.c @@ -80,26 +80,44 @@ arcdisk_hash_add (char *devpath) } +/* Context for grub_arcdisk_iterate. */ +struct grub_arcdisk_iterate_ctx +{ + grub_disk_dev_iterate_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_arcdisk_iterate. */ static int -grub_arcdisk_iterate (int (*hook_in) (const char *name), +grub_arcdisk_iterate_iter (const char *name, + const struct grub_arc_component *comp, void *data) +{ + struct grub_arcdisk_iterate_ctx *ctx = data; + + if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK + || comp->type == GRUB_ARC_COMPONENT_TYPE_FLOPPY + || comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE)) + return 0; + return ctx->hook (name, ctx->hook_data); +} + +static int +grub_arcdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { - auto int hook (const char *name, const struct grub_arc_component *comp); - int hook (const char *name, const struct grub_arc_component *comp) - { - if (!(comp->type == GRUB_ARC_COMPONENT_TYPE_DISK - || comp->type == GRUB_ARC_COMPONENT_TYPE_DISK - || comp->type == GRUB_ARC_COMPONENT_TYPE_TAPE)) - return 0; - return hook_in (name); - } + struct grub_arcdisk_iterate_ctx ctx = { hook, hook_data }; + if (pull != GRUB_DISK_PULL_NONE) return 0; - return grub_arc_iterate_devs (hook, 1); + return grub_arc_iterate_devs (grub_arcdisk_iterate_iter, &ctx, 1); } +#ifdef GRUB_CPU_MIPSEL +#define RAW_SUFFIX "partition(0)" +#else #define RAW_SUFFIX "partition(10)" +#endif static grub_err_t reopen (const char *name, int writable) @@ -139,9 +157,7 @@ reopen (const char *name, int writable) static grub_err_t grub_arcdisk_open (const char *name, grub_disk_t disk) { - char *fullname, *optr; - const char *iptr; - int state = 0; + char *fullname; grub_err_t err; grub_arc_err_t r; struct grub_arc_fileinfo info; @@ -149,35 +165,7 @@ grub_arcdisk_open (const char *name, grub_disk_t disk) if (grub_memcmp (name, "arc/", 4) != 0) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not arc device"); - fullname = grub_malloc (2 * grub_strlen (name) + sizeof (RAW_SUFFIX)); - if (!fullname) - return grub_errno; - optr = fullname; - for (iptr = name + 4; *iptr; iptr++) - if (state == 0) - { - if (!grub_isdigit (*iptr)) - *optr++ = *iptr; - else - { - *optr++ = '('; - *optr++ = *iptr; - state = 1; - } - } - else - { - if (grub_isdigit (*iptr)) - *optr++ = *iptr; - else - { - *optr++ = ')'; - state = 0; - } - } - if (state) - *optr++ = ')'; - grub_memcpy (optr, RAW_SUFFIX, sizeof (RAW_SUFFIX)); + fullname = grub_arc_alt_name_to_norm (name, RAW_SUFFIX); disk->data = fullname; grub_dprintf ("arcdisk", "opening %s\n", fullname); @@ -308,11 +296,11 @@ static struct grub_disk_dev grub_arcdisk_dev = { .name = "arcdisk", .id = GRUB_DISK_DEVICE_ARCDISK_ID, - .iterate = grub_arcdisk_iterate, - .open = grub_arcdisk_open, - .close = grub_arcdisk_close, - .read = grub_arcdisk_read, - .write = grub_arcdisk_write, + .disk_iterate = grub_arcdisk_iterate, + .disk_open = grub_arcdisk_open, + .disk_close = grub_arcdisk_close, + .disk_read = grub_arcdisk_read, + .disk_write = grub_arcdisk_write, .next = 0 }; diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index c0d378c1a..a2433e29e 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -108,11 +108,14 @@ grub_ata_identify (struct grub_ata *dev) grub_uint16_t *info16; grub_err_t err; + if (dev->atapi) + return grub_atapi_identify (dev); + info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE); + if (info64 == NULL) + return grub_errno; info32 = (grub_uint32_t *) info64; info16 = (grub_uint16_t *) info64; - if (! info16) - return grub_errno; grub_memset (&parms, 0, sizeof (parms)); parms.buffer = info16; @@ -129,7 +132,7 @@ grub_ata_identify (struct grub_ata *dev) grub_free (info16); grub_errno = GRUB_ERR_NONE; if ((sts & (GRUB_ATA_STATUS_BUSY | GRUB_ATA_STATUS_DRQ - | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR + | GRUB_ATA_STATUS_ERR)) == GRUB_ATA_STATUS_ERR && (parms.taskfile.error & 0x04 /* ABRT */)) /* Device without ATA IDENTIFY, try ATAPI. */ return grub_atapi_identify (dev); @@ -178,10 +181,7 @@ grub_ata_identify (struct grub_ata *dev) if (secsize & (secsize - 1) || !secsize || secsize > 1048576) secsize = 256; - for (dev->log_sector_size = 0; - (1U << dev->log_sector_size) < secsize; - dev->log_sector_size++); - dev->log_sector_size++; + dev->log_sector_size = grub_log2ull (secsize) + 1; } else dev->log_sector_size = 9; @@ -213,6 +213,13 @@ grub_ata_setaddress (struct grub_ata *dev, unsigned int head; unsigned int sect; + if (dev->sectors_per_track == 0 + || dev->heads == 0) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "sector %" PRIxGRUB_UINT64_T " cannot be " + "addressed using CHS addressing", + sector); + /* Calculate the sector, cylinder and head to use. */ sect = ((grub_uint32_t) sector % dev->sectors_per_track) + 1; cylinder = (((grub_uint32_t) sector / dev->sectors_per_track) @@ -223,9 +230,10 @@ grub_ata_setaddress (struct grub_ata *dev, || cylinder > dev->cylinders || head > dev->heads) return grub_error (GRUB_ERR_OUT_OF_RANGE, - "sector %d cannot be addressed " - "using CHS addressing", sector); - + "sector %" PRIxGRUB_UINT64_T " cannot be " + "addressed using CHS addressing", + sector); + parms->taskfile.disk = 0xE0 | head; parms->taskfile.sectnum = sect; parms->taskfile.cyllsb = cylinder & 0xFF; @@ -285,7 +293,6 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, if (addressing == GRUB_ATA_LBA48 && ((sector + size) >> 28) != 0) { - batch = 65536; if (ata->dma) { cmd = GRUB_ATA_CMD_READ_SECTORS_DMA_EXT; @@ -301,10 +308,6 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, { if (addressing == GRUB_ATA_LBA48) addressing = GRUB_ATA_LBA; - if (addressing != GRUB_ATA_CHS) - batch = 256; - else - batch = 1; if (ata->dma) { cmd = GRUB_ATA_CMD_READ_SECTORS_DMA; @@ -317,8 +320,10 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, } } - if (batch > (ata->maxbuffer >> ata->log_sector_size)) - batch = (ata->maxbuffer >> ata->log_sector_size); + if (addressing != GRUB_ATA_CHS) + batch = 256; + else + batch = 1; while (nsectors < size) { @@ -337,7 +342,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, parms.write = rw; if (ata->dma) parms.dma = 1; - + err = ata->dev->readwrite (ata, &parms, 0); if (err) return err; @@ -366,7 +371,7 @@ grub_ata_real_open (int id, int bus) struct grub_ata *ata; grub_ata_dev_t p; - ata = grub_malloc (sizeof (*ata)); + ata = grub_zalloc (sizeof (*ata)); if (!ata) return NULL; for (p = grub_ata_dev_list; p; p = p->next) @@ -382,6 +387,8 @@ grub_ata_real_open (int id, int bus) err = grub_ata_identify (ata); if (err) { + if (!grub_errno) + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATA device"); grub_free (ata); return NULL; } @@ -392,40 +399,50 @@ grub_ata_real_open (int id, int bus) return NULL; } +/* Context for grub_ata_iterate. */ +struct grub_ata_iterate_ctx +{ + grub_disk_dev_iterate_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_ata_iterate. */ static int -grub_ata_iterate (int (*hook_in) (const char *name), +grub_ata_iterate_iter (int id, int bus, void *data) +{ + struct grub_ata_iterate_ctx *ctx = data; + struct grub_ata *ata; + int ret; + char devname[40]; + + ata = grub_ata_real_open (id, bus); + + if (!ata) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (ata->atapi) + { + grub_ata_real_close (ata); + return 0; + } + grub_snprintf (devname, sizeof (devname), + "%s%d", grub_scsi_names[id], bus); + ret = ctx->hook (devname, ctx->hook_data); + grub_ata_real_close (ata); + return ret; +} + +static int +grub_ata_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { - auto int hook (int id, int bus); - int hook (int id, int bus) - { - struct grub_ata *ata; - int ret; - char devname[40]; - - ata = grub_ata_real_open (id, bus); - - if (!ata) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (ata->atapi) - { - grub_ata_real_close (ata); - return 0; - } - grub_snprintf (devname, sizeof (devname), - "%s%d", grub_scsi_names[id], bus); - ret = hook_in (devname); - grub_ata_real_close (ata); - return ret; - } - + struct grub_ata_iterate_ctx ctx = { hook, hook_data }; grub_ata_dev_t p; - + for (p = grub_ata_dev_list; p; p = p->next) - if (p->iterate && p->iterate (hook, pull)) + if (p->iterate && p->iterate (grub_ata_iterate_iter, &ctx, pull)) return 1; return 0; } @@ -452,6 +469,10 @@ grub_ata_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not an ATA harddisk"); disk->total_sectors = ata->size; + disk->max_agglomerate = (ata->maxbuffer >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS)); + if (disk->max_agglomerate > (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size))) + disk->max_agglomerate = (256U >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS - ata->log_sector_size)); + disk->log_sector_size = ata->log_sector_size; disk->id = grub_make_scsi_id (id, bus, 0); @@ -488,11 +509,11 @@ static struct grub_disk_dev grub_atadisk_dev = { .name = "ATA", .id = GRUB_DISK_DEVICE_ATA_ID, - .iterate = grub_ata_iterate, - .open = grub_ata_open, - .close = grub_ata_close, - .read = grub_ata_read, - .write = grub_ata_write, + .disk_iterate = grub_ata_iterate, + .disk_open = grub_ata_open, + .disk_close = grub_ata_close, + .disk_read = grub_ata_read, + .disk_write = grub_ata_write, .next = 0 }; @@ -522,7 +543,7 @@ grub_atapi_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, parms.size = size; parms.buffer = buf; - + err = dev->dev->readwrite (dev, &parms, 0); if (err) return err; @@ -551,7 +572,7 @@ grub_atapi_open (int id, int bus, struct grub_scsi *scsi) ata = grub_ata_real_open (id, bus); if (!ata) return grub_errno; - + if (! ata->atapi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such ATAPI device"); @@ -561,37 +582,47 @@ grub_atapi_open (int id, int bus, struct grub_scsi *scsi) return GRUB_ERR_NONE; } +/* Context for grub_atapi_iterate. */ +struct grub_atapi_iterate_ctx +{ + grub_scsi_dev_iterate_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_atapi_iterate. */ static int -grub_atapi_iterate (int NESTED_FUNC_ATTR (*hook_in) (int id, int bus, int luns), +grub_atapi_iterate_iter (int id, int bus, void *data) +{ + struct grub_atapi_iterate_ctx *ctx = data; + struct grub_ata *ata; + int ret; + + ata = grub_ata_real_open (id, bus); + + if (!ata) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (!ata->atapi) + { + grub_ata_real_close (ata); + return 0; + } + ret = ctx->hook (id, bus, 1, ctx->hook_data); + grub_ata_real_close (ata); + return ret; +} + +static int +grub_atapi_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { - auto int hook (int id, int bus); - int hook (int id, int bus) - { - struct grub_ata *ata; - int ret; - - ata = grub_ata_real_open (id, bus); - - if (!ata) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (!ata->atapi) - { - grub_ata_real_close (ata); - return 0; - } - ret = hook_in (id, bus, 1); - grub_ata_real_close (ata); - return ret; - } - + struct grub_atapi_iterate_ctx ctx = { hook, hook_data }; grub_ata_dev_t p; - + for (p = grub_ata_dev_list; p; p = p->next) - if (p->iterate && p->iterate (hook, pull)) + if (p->iterate && p->iterate (grub_atapi_iterate_iter, &ctx, pull)) return 1; return 0; } diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 1ac906d90..7065bcdcb 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003,2007,2010,2011 Free Software Foundation, Inc. + * Copyright (C) 2003,2007,2010,2011,2019 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,35 +17,63 @@ */ #include +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include #ifdef GRUB_UTIL -#include -#include -#include -#include #include -#include -#include #endif GRUB_MOD_LICENSE ("GPLv3+"); grub_cryptodisk_dev_t grub_cryptodisk_list; +enum + { + OPTION_UUID, + OPTION_ALL, + OPTION_BOOT, + OPTION_PASSWORD, + OPTION_KEYFILE, + OPTION_KEYFILE_OFFSET, + OPTION_KEYFILE_SIZE, + OPTION_HEADER, + OPTION_PROTECTOR + }; + static const struct grub_arg_option options[] = { {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0}, /* TRANSLATORS: It's still restricted to cryptodisks only. */ {"all", 'a', 0, N_("Mount all."), 0, 0}, {"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0}, + {"password", 'p', 0, N_("Password to open volumes."), 0, ARG_TYPE_STRING}, + {"key-file", 'k', 0, N_("Key file"), 0, ARG_TYPE_STRING}, + {"keyfile-offset", 'O', 0, N_("Key file offset (bytes)"), 0, ARG_TYPE_INT}, + {"keyfile-size", 'S', 0, N_("Key file data size (bytes)"), 0, ARG_TYPE_INT}, + {"header", 'H', 0, N_("Read header from file"), 0, ARG_TYPE_STRING}, + {"protector", 'P', GRUB_ARG_OPTION_REPEATABLE, + N_("Unlock volume(s) using key protector(s)."), 0, ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; +struct cryptodisk_read_hook_ctx +{ + grub_file_t hdr_file; + grub_disk_addr_t part_start; +}; +typedef struct cryptodisk_read_hook_ctx *cryptodisk_read_hook_ctx_t; + /* Our irreducible polynom is x^128+x^7+x^2+x+1. Lowest byte of it is: */ #define GF_POLYNOM 0x87 static inline int GF_PER_SECTOR (const struct grub_cryptodisk *dev) @@ -54,7 +82,7 @@ static inline int GF_PER_SECTOR (const struct grub_cryptodisk *dev) } static grub_cryptodisk_t cryptodisk_list = NULL; -static grub_uint8_t n = 0; +static grub_uint8_t last_cryptodisk_id = 0; static void gf_mul_x (grub_uint8_t *g) @@ -100,7 +128,7 @@ gf_mul_be (grub_uint8_t *o, const grub_uint8_t *a, const grub_uint8_t *b) grub_memcpy (t, b, GRUB_CRYPTODISK_GF_BYTES); for (i = 0; i < GRUB_CRYPTODISK_GF_SIZE; i++) { - if (((a[GRUB_CRYPTODISK_GF_BYTES - i / 8 - 1] >> (i % 8))) & 1) + if (((a[GRUB_CRYPTODISK_GF_BYTES - i / GRUB_CHAR_BIT - 1] >> (i % GRUB_CHAR_BIT))) & 1) grub_crypto_xor (o, o, t, GRUB_CRYPTODISK_GF_BYTES); gf_mul_x_be (t); } @@ -112,19 +140,24 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher, void *iv) { grub_uint8_t *inptr, *outptr, *end; - grub_uint8_t ivt[cipher->cipher->blocksize]; + grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; + grub_size_t blocksize; if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; - if (size % cipher->cipher->blocksize != 0) + blocksize = cipher->cipher->blocksize; + if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) + || ((size & (blocksize - 1)) != 0)) + return GPG_ERR_INV_ARG; + if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) return GPG_ERR_INV_ARG; end = (grub_uint8_t *) in + size; for (inptr = in, outptr = out; inptr < end; - inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) + inptr += blocksize, outptr += blocksize) { - grub_memcpy (ivt, inptr, cipher->cipher->blocksize); + grub_memcpy (ivt, inptr, blocksize); cipher->cipher->decrypt (cipher->ctx, outptr, inptr); - grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); - grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize); + grub_crypto_xor (outptr, outptr, iv, blocksize); + grub_crypto_xor (iv, ivt, outptr, blocksize); } return GPG_ERR_NO_ERROR; } @@ -135,19 +168,24 @@ grub_crypto_pcbc_encrypt (grub_crypto_cipher_handle_t cipher, void *iv) { grub_uint8_t *inptr, *outptr, *end; - grub_uint8_t ivt[cipher->cipher->blocksize]; - if (!cipher->cipher->decrypt) + grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; + grub_size_t blocksize; + if (!cipher->cipher->encrypt) return GPG_ERR_NOT_SUPPORTED; - if (size % cipher->cipher->blocksize != 0) + blocksize = cipher->cipher->blocksize; + if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) + return GPG_ERR_INV_ARG; + if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) + || ((size & (blocksize - 1)) != 0)) return GPG_ERR_INV_ARG; end = (grub_uint8_t *) in + size; for (inptr = in, outptr = out; inptr < end; - inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) + inptr += blocksize, outptr += blocksize) { - grub_memcpy (ivt, inptr, cipher->cipher->blocksize); - grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); + grub_memcpy (ivt, inptr, blocksize); + grub_crypto_xor (outptr, outptr, iv, blocksize); cipher->cipher->encrypt (cipher->ctx, outptr, inptr); - grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize); + grub_crypto_xor (iv, ivt, outptr, blocksize); } return GPG_ERR_NO_ERROR; } @@ -216,22 +254,26 @@ lrw_xor (const struct lrw_sector *sec, static gcry_err_code_t grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, grub_uint8_t * data, grub_size_t len, - grub_disk_addr_t sector, int do_encrypt) + grub_disk_addr_t sector, grub_size_t log_sector_size, + int do_encrypt) { grub_size_t i; gcry_err_code_t err; + if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) + return GPG_ERR_INV_ARG; + /* The only mode without IV. */ if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey) return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len) : grub_crypto_ecb_decrypt (dev->cipher, data, data, len)); - for (i = 0; i < len; i += (1U << dev->log_sector_size)) + for (i = 0; i < len; i += ((grub_size_t) 1 << log_sector_size)) { grub_size_t sz = ((dev->cipher->cipher->blocksize + sizeof (grub_uint32_t) - 1) / sizeof (grub_uint32_t)); - grub_uint32_t iv[sz]; + grub_uint32_t iv[(GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE + 3) / 4]; if (dev->rekey) { @@ -245,7 +287,7 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, } } - grub_memset (iv, 0, sz * sizeof (iv[0])); + grub_memset (iv, 0, sizeof (iv)); switch (dev->mode_iv) { case GRUB_CRYPTODISK_MODE_IV_NULL: @@ -253,38 +295,55 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH: { grub_uint64_t tmp; - grub_uint64_t ctx[(dev->iv_hash->contextsize + 7) / 8]; + void *ctx; - grub_memset (ctx, 0, sizeof (ctx)); + ctx = grub_zalloc (dev->iv_hash->contextsize); + if (!ctx) + return GPG_ERR_OUT_OF_MEMORY; - tmp = grub_cpu_to_le64 (sector << dev->log_sector_size); + tmp = grub_cpu_to_le64 (sector << log_sector_size); dev->iv_hash->init (ctx); dev->iv_hash->write (ctx, dev->iv_prefix, dev->iv_prefix_len); dev->iv_hash->write (ctx, &tmp, sizeof (tmp)); dev->iv_hash->final (ctx); grub_memcpy (iv, dev->iv_hash->read (ctx), sizeof (iv)); + grub_free (ctx); } break; case GRUB_CRYPTODISK_MODE_IV_PLAIN64: - iv[1] = grub_cpu_to_le32 (sector >> 32); case GRUB_CRYPTODISK_MODE_IV_PLAIN: - iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); + /* + * The IV is a 32 or 64 bit value of the dm-crypt native sector + * number. If using 32 bit IV mode, zero out the most significant + * 32 bits. + */ + { + grub_uint64_t iv64; + + iv64 = grub_cpu_to_le64 (sector << (log_sector_size + - GRUB_CRYPTODISK_IV_LOG_SIZE)); + grub_set_unaligned64 (iv, iv64); + if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_PLAIN) + iv[1] = 0; + } break; case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64: - iv[1] = grub_cpu_to_le32 (sector >> (32 - dev->log_sector_size)); - iv[0] = grub_cpu_to_le32 ((sector << dev->log_sector_size) - & 0xFFFFFFFF); + /* The IV is the 64 bit byte offset of the sector. */ + iv[1] = grub_cpu_to_le32 (sector >> (GRUB_TYPE_BITS (iv[1]) + - log_sector_size)); + iv[0] = grub_cpu_to_le32 ((sector << log_sector_size) + & GRUB_TYPE_U_MAX (iv[0])); break; case GRUB_CRYPTODISK_MODE_IV_BENBI: { grub_uint64_t num = (sector << dev->benbi_log) + 1; - iv[sz - 2] = grub_cpu_to_be32 (num >> 32); - iv[sz - 1] = grub_cpu_to_be32 (num & 0xFFFFFFFF); + iv[sz - 2] = grub_cpu_to_be32 (num >> GRUB_TYPE_BITS (iv[0])); + iv[sz - 1] = grub_cpu_to_be32 (num & GRUB_TYPE_U_MAX (iv[0])); } break; case GRUB_CRYPTODISK_MODE_IV_ESSIV: - iv[0] = grub_cpu_to_le32 (sector & 0xFFFFFFFF); + iv[0] = grub_cpu_to_le32 (sector & GRUB_TYPE_U_MAX (iv[0])); err = grub_crypto_ecb_encrypt (dev->essiv_cipher, iv, iv, dev->cipher->cipher->blocksize); if (err) @@ -296,10 +355,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_CBC: if (do_encrypt) err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size), iv); + ((grub_size_t) 1 << log_sector_size), iv); else err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size), iv); + ((grub_size_t) 1 << log_sector_size), iv); if (err) return err; break; @@ -307,10 +366,10 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, case GRUB_CRYPTODISK_MODE_PCBC: if (do_encrypt) err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size), iv); + ((grub_size_t) 1 << log_sector_size), iv); else err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size), iv); + ((grub_size_t) 1 << log_sector_size), iv); if (err) return err; break; @@ -321,18 +380,18 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, dev->cipher->cipher->blocksize); if (err) return err; - - for (j = 0; j < (1U << dev->log_sector_size); + + for (j = 0; j < (1U << log_sector_size); j += dev->cipher->cipher->blocksize) { grub_crypto_xor (data + i + j, data + i + j, iv, dev->cipher->cipher->blocksize); if (do_encrypt) - err = grub_crypto_ecb_encrypt (dev->cipher, data + i + j, + err = grub_crypto_ecb_encrypt (dev->cipher, data + i + j, data + i + j, dev->cipher->cipher->blocksize); else - err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j, + err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j, data + i + j, dev->cipher->cipher->blocksize); if (err) @@ -351,13 +410,13 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, lrw_xor (&sec, dev, data + i); if (do_encrypt) - err = grub_crypto_ecb_encrypt (dev->cipher, data + i, + err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size)); + (1U << log_sector_size)); else - err = grub_crypto_ecb_decrypt (dev->cipher, data + i, + err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size)); + (1U << log_sector_size)); if (err) return err; lrw_xor (&sec, dev, data + i); @@ -365,11 +424,13 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, break; case GRUB_CRYPTODISK_MODE_ECB: if (do_encrypt) - grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size)); + err = grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i, + (1U << log_sector_size)); else - grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size)); + err = grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i, + (1U << log_sector_size)); + if (err) + return err; break; default: return GPG_ERR_NOT_IMPLEMENTED; @@ -382,9 +443,174 @@ grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, gcry_err_code_t grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, grub_uint8_t * data, grub_size_t len, - grub_disk_addr_t sector) + grub_disk_addr_t sector, grub_size_t log_sector_size) { - return grub_cryptodisk_endecrypt (dev, data, len, sector, 0); + return grub_cryptodisk_endecrypt (dev, data, len, sector, log_sector_size, 0); +} + +grub_err_t +grub_cryptodisk_setcipher (grub_cryptodisk_t crypt, const char *ciphername, const char *ciphermode) +{ + const char *cipheriv = NULL; + grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL; + grub_crypto_cipher_handle_t essiv_cipher = NULL; + const gcry_md_spec_t *essiv_hash = NULL; + const struct gcry_cipher_spec *ciph; + grub_cryptodisk_mode_t mode; + grub_cryptodisk_mode_iv_t mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64; + int benbi_log = 0; + grub_err_t ret = GRUB_ERR_NONE; + + ciph = grub_crypto_lookup_cipher_by_name (ciphername); + if (!ciph) + { + ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available", + ciphername); + goto err; + } + + /* Configure the cipher used for the bulk data. */ + cipher = grub_crypto_cipher_open (ciph); + if (!cipher) + { + ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s could not be initialized", + ciphername); + goto err; + } + + /* Configure the cipher mode. */ + if (grub_strcmp (ciphermode, "ecb") == 0) + { + mode = GRUB_CRYPTODISK_MODE_ECB; + mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN; + cipheriv = NULL; + } + else if (grub_strcmp (ciphermode, "plain") == 0) + { + mode = GRUB_CRYPTODISK_MODE_CBC; + mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN; + cipheriv = NULL; + } + else if (grub_memcmp (ciphermode, "cbc-", sizeof ("cbc-") - 1) == 0) + { + mode = GRUB_CRYPTODISK_MODE_CBC; + cipheriv = ciphermode + sizeof ("cbc-") - 1; + } + else if (grub_memcmp (ciphermode, "pcbc-", sizeof ("pcbc-") - 1) == 0) + { + mode = GRUB_CRYPTODISK_MODE_PCBC; + cipheriv = ciphermode + sizeof ("pcbc-") - 1; + } + else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0) + { + mode = GRUB_CRYPTODISK_MODE_XTS; + cipheriv = ciphermode + sizeof ("xts-") - 1; + secondary_cipher = grub_crypto_cipher_open (ciph); + if (!secondary_cipher) + { + ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, + "Secondary cipher %s isn't available", ciphername); + goto err; + } + if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unsupported XTS block size: %" PRIuGRUB_SIZE, + cipher->cipher->blocksize); + goto err; + } + if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unsupported XTS block size: %" PRIuGRUB_SIZE, + secondary_cipher->cipher->blocksize); + goto err; + } + } + else if (grub_memcmp (ciphermode, "lrw-", sizeof ("lrw-") - 1) == 0) + { + mode = GRUB_CRYPTODISK_MODE_LRW; + cipheriv = ciphermode + sizeof ("lrw-") - 1; + if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unsupported LRW block size: %" PRIuGRUB_SIZE, + cipher->cipher->blocksize); + goto err; + } + } + else + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s", + ciphermode); + goto err; + } + + if (cipheriv == NULL) + ; + else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0) + mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64; + else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0) + mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN; + else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0) + { + if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1) + || cipher->cipher->blocksize == 0) + grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unsupported benbi blocksize: %" PRIuGRUB_SIZE, + cipher->cipher->blocksize); + /* FIXME should we return an error here? */ + for (benbi_log = 0; + (cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE; + benbi_log++); + mode_iv = GRUB_CRYPTODISK_MODE_IV_BENBI; + } + else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0) + mode_iv = GRUB_CRYPTODISK_MODE_IV_NULL; + else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0) + { + const char *hash_str = cipheriv + 6; + + mode_iv = GRUB_CRYPTODISK_MODE_IV_ESSIV; + + /* Configure the hash and cipher used for ESSIV. */ + essiv_hash = grub_crypto_lookup_md_by_name (hash_str); + if (!essiv_hash) + { + ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, + "Couldn't load %s hash", hash_str); + goto err; + } + essiv_cipher = grub_crypto_cipher_open (ciph); + if (!essiv_cipher) + { + ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, + "Couldn't load %s cipher", ciphername); + goto err; + } + } + else + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s", + cipheriv); + goto err; + } + + crypt->cipher = cipher; + crypt->benbi_log = benbi_log; + crypt->mode = mode; + crypt->mode_iv = mode_iv; + crypt->secondary_cipher = secondary_cipher; + crypt->essiv_cipher = essiv_cipher; + crypt->essiv_hash = essiv_hash; + +err: + if (ret) + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (secondary_cipher); + } + return ret; } gcry_err_code_t @@ -398,17 +624,21 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t ke real_keysize /= 2; if (dev->mode == GRUB_CRYPTODISK_MODE_LRW) real_keysize -= dev->cipher->cipher->blocksize; - + /* Set the PBKDF2 output as the cipher key. */ err = grub_crypto_cipher_set_key (dev->cipher, key, real_keysize); if (err) return err; + grub_memcpy (dev->key, key, keysize); + dev->keysize = keysize; /* Configure ESSIV if necessary. */ if (dev->mode_iv == GRUB_CRYPTODISK_MODE_IV_ESSIV) { grub_size_t essiv_keysize = dev->essiv_hash->mdlen; - grub_uint8_t hashed_key[essiv_keysize]; + grub_uint8_t hashed_key[GRUB_CRYPTO_MAX_MDLEN]; + if (essiv_keysize > GRUB_CRYPTO_MAX_MDLEN) + return GPG_ERR_INV_ARG; grub_crypto_hash (dev->essiv_hash, hashed_key, key, keysize); err = grub_crypto_cipher_set_key (dev->essiv_cipher, @@ -448,8 +678,8 @@ grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t ke } static int -grub_cryptodisk_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull) +grub_cryptodisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) { grub_cryptodisk_t i; @@ -460,7 +690,7 @@ grub_cryptodisk_iterate (int (*hook) (const char *name), { char buf[30]; grub_snprintf (buf, sizeof (buf), "crypto%lu", i->id); - if (hook (buf)) + if (hook (buf, hook_data)) return 1; } @@ -478,7 +708,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk) if (grub_memcmp (name, "cryptouuid/", sizeof ("cryptouuid/") - 1) == 0) { for (dev = cryptodisk_list; dev != NULL; dev = dev->next) - if (grub_strcasecmp (name + sizeof ("cryptouuid/") - 1, dev->uuid) == 0) + if (grub_uuidcasecmp (name + sizeof ("cryptouuid/") - 1, dev->uuid, sizeof (dev->uuid)) == 0) break; } else @@ -494,16 +724,31 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk) if (!dev) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "No such device"); - disk->log_sector_size = dev->log_sector_size; - #ifdef GRUB_UTIL if (dev->cheat) { - if (dev->cheat_fd == -1) - dev->cheat_fd = open (dev->cheat, O_RDONLY); - if (dev->cheat_fd == -1) + grub_uint64_t cheat_dev_size; + unsigned int cheat_log_sector_size; + + if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd)) + dev->cheat_fd = grub_util_fd_open (dev->cheat, GRUB_UTIL_FD_O_RDONLY); + if (!GRUB_UTIL_FD_IS_VALID (dev->cheat_fd)) return grub_error (GRUB_ERR_IO, N_("cannot open `%s': %s"), - dev->cheat, strerror (errno)); + dev->cheat, grub_util_fd_strerror ()); + + /* Use the sector size and count of the cheat device. */ + cheat_dev_size = grub_util_get_fd_size (dev->cheat_fd, dev->cheat, &cheat_log_sector_size); + if (cheat_dev_size == -1) + { + const char *errmsg = grub_util_fd_strerror (); + grub_util_fd_close (dev->cheat_fd); + dev->cheat_fd = GRUB_UTIL_FD_INVALID; + return grub_error (GRUB_ERR_IO, N_("failed to query size of device `%s': %s"), + dev->cheat, errmsg); + } + + dev->log_sector_size = cheat_log_sector_size; + dev->total_sectors = cheat_dev_size >> cheat_log_sector_size; } #endif @@ -517,7 +762,9 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk) } disk->data = dev; - disk->total_sectors = dev->total_length; + disk->log_sector_size = dev->log_sector_size; + disk->total_sectors = dev->total_sectors; + disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; disk->id = dev->id; dev->ref++; return GRUB_ERR_NONE; @@ -536,8 +783,8 @@ grub_cryptodisk_close (grub_disk_t disk) #ifdef GRUB_UTIL if (dev->cheat) { - close (dev->cheat_fd); - dev->cheat_fd = -1; + grub_util_fd_close (dev->cheat_fd); + dev->cheat_fd = GRUB_UTIL_FD_INVALID; } #endif grub_disk_close (dev->source_disk); @@ -555,14 +802,15 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector, #ifdef GRUB_UTIL if (dev->cheat) { - err = grub_util_fd_seek (dev->cheat_fd, dev->cheat, - sector << disk->log_sector_size); - if (err) - return err; + int r; + r = grub_util_fd_seek (dev->cheat_fd, sector << disk->log_sector_size); + if (r) + return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), + dev->cheat, grub_util_fd_strerror ()); if (grub_util_fd_read (dev->cheat_fd, buf, size << disk->log_sector_size) != (ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"), - dev->cheat, strerror (errno)); + dev->cheat, grub_util_fd_strerror ()); return GRUB_ERR_NONE; } #endif @@ -570,12 +818,11 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_dprintf ("cryptodisk", "Reading %" PRIuGRUB_SIZE " sectors from sector 0x%" PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n", - size, sector, dev->offset); + size, sector, dev->offset_sectors); err = grub_disk_read (dev->source_disk, - (sector << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) + dev->offset, 0, - size << disk->log_sector_size, buf); + grub_disk_from_native_sector (disk, sector + dev->offset_sectors), + 0, size << disk->log_sector_size, buf); if (err) { grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err); @@ -583,7 +830,7 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector, } gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf, size << disk->log_sector_size, - sector, 0); + sector, dev->log_sector_size, 0); return grub_crypto_gcry_error (gcry_err); } @@ -599,14 +846,15 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector, #ifdef GRUB_UTIL if (dev->cheat) { - err = grub_util_fd_seek (dev->cheat_fd, dev->cheat, - sector << disk->log_sector_size); - if (err) - return err; + int r; + r = grub_util_fd_seek (dev->cheat_fd, sector << disk->log_sector_size); + if (r) + return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), + dev->cheat, grub_util_fd_strerror ()); if (grub_util_fd_write (dev->cheat_fd, buf, size << disk->log_sector_size) != (ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"), - dev->cheat, strerror (errno)); + dev->cheat, grub_util_fd_strerror ()); return GRUB_ERR_NONE; } #endif @@ -619,21 +867,25 @@ grub_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector, grub_dprintf ("cryptodisk", "Writing %" PRIuGRUB_SIZE " sectors to sector 0x%" PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n", - size, sector, dev->offset); + size, sector, dev->offset_sectors); gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp, size << disk->log_sector_size, - sector, 1); + sector, disk->log_sector_size, 1); if (gcry_err) { grub_free (tmp); return grub_crypto_gcry_error (gcry_err); } - err = grub_disk_write (dev->source_disk, - (sector << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) + dev->offset, - 0, size << disk->log_sector_size, tmp); + /* Since ->write was called so disk.mod is loaded but be paranoid */ + sector = sector + dev->offset_sectors; + if (grub_disk_write_weak) + err = grub_disk_write_weak (dev->source_disk, + grub_disk_from_native_sector (disk, sector), + 0, size << disk->log_sector_size, tmp); + else + err = grub_error (GRUB_ERR_BUG, "disk.mod not loaded"); grub_free (tmp); return err; } @@ -682,14 +934,12 @@ grub_cryptodisk_insert (grub_cryptodisk_t newdev, const char *name, { newdev->source = grub_strdup (name); if (!newdev->source) - { - grub_free (newdev); - return grub_errno; - } + return grub_errno; - newdev->id = n++; + newdev->id = last_cryptodisk_id++; newdev->source_id = source->id; newdev->source_dev_id = source->dev->id; + newdev->partition_start = grub_partition_get_start (source->partition); newdev->next = cryptodisk_list; cryptodisk_list = newdev; @@ -701,7 +951,7 @@ grub_cryptodisk_get_by_uuid (const char *uuid) { grub_cryptodisk_t dev; for (dev = cryptodisk_list; dev != NULL; dev = dev->next) - if (grub_strcasecmp (dev->uuid, uuid) == 0) + if (grub_uuidcasecmp (dev->uuid, uuid, sizeof (dev->uuid)) == 0) return dev; return NULL; } @@ -712,7 +962,9 @@ grub_cryptodisk_get_by_source_disk (grub_disk_t disk) grub_cryptodisk_t dev; for (dev = cryptodisk_list; dev != NULL; dev = dev->next) if (dev->source_id == disk->id && dev->source_dev_id == disk->dev->id) - return dev; + if ((disk->partition && grub_partition_get_start (disk->partition) == dev->partition_start) || + (!disk->partition && dev->partition_start == 0)) + return dev; return NULL; } @@ -730,10 +982,11 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name, return grub_errno; } - newdev->cheat_fd = -1; + newdev->cheat_fd = GRUB_UTIL_FD_INVALID; newdev->source_id = source->id; newdev->source_dev_id = source->dev->id; - newdev->id = n++; + newdev->partition_start = grub_partition_get_start (source->partition); + newdev->id = last_cryptodisk_id++; newdev->next = cryptodisk_list; cryptodisk_list = newdev; @@ -741,38 +994,38 @@ grub_cryptodisk_cheat_insert (grub_cryptodisk_t newdev, const char *name, } void -grub_util_cryptodisk_print_abstraction (grub_disk_t disk) +grub_util_cryptodisk_get_abstraction (grub_disk_t disk, + void (*cb) (const char *val, void *data), + void *data) { grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; - grub_printf ("cryptodisk %s ", dev->modname); + cb ("cryptodisk", data); + cb (dev->modname, data); if (dev->cipher) - grub_printf ("%s ", dev->cipher->cipher->modname); + cb (dev->cipher->cipher->modname, data); if (dev->secondary_cipher) - grub_printf ("%s ", dev->secondary_cipher->cipher->modname); + cb (dev->secondary_cipher->cipher->modname, data); if (dev->essiv_cipher) - grub_printf ("%s ", dev->essiv_cipher->cipher->modname); + cb (dev->essiv_cipher->cipher->modname, data); if (dev->hash) - grub_printf ("%s ", dev->hash->modname); + cb (dev->hash->modname, data); if (dev->essiv_hash) - grub_printf ("%s ", dev->essiv_hash->modname); + cb (dev->essiv_hash->modname, data); if (dev->iv_hash) - grub_printf ("%s ", dev->iv_hash->modname); + cb (dev->iv_hash->modname, data); } -void -grub_util_cryptodisk_print_uuid (grub_disk_t disk) +const char * +grub_util_cryptodisk_get_uuid (grub_disk_t disk) { grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; - grub_printf ("%s ", dev->uuid); + return dev->uuid; } #endif -static int check_boot, have_it; -static char *search_uuid; - static void cryptodisk_close (grub_cryptodisk_t dev) { @@ -783,39 +1036,277 @@ cryptodisk_close (grub_cryptodisk_t dev) } static grub_err_t -grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source) +cryptodisk_read_hook (grub_disk_addr_t sector, unsigned offset, + unsigned length, char *buf, void *data) { - grub_err_t err; + cryptodisk_read_hook_ctx_t ctx = data; + + if (ctx->hdr_file == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("header file not found")); + + if (grub_file_seek (ctx->hdr_file, + ((sector - ctx->part_start) * GRUB_DISK_SECTOR_SIZE) + offset) + == (grub_off_t) -1) + return grub_errno; + + if (grub_file_read (ctx->hdr_file, buf, length) != (grub_ssize_t) length) + { + if (grub_errno == GRUB_ERR_NONE) + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("header file too small")); + return grub_errno; + } + + return GRUB_ERR_NONE; +} + +static grub_cryptodisk_t +grub_cryptodisk_scan_device_real (const char *name, + grub_disk_t source, + grub_cryptomount_args_t cargs) +{ + grub_err_t ret = GRUB_ERR_NONE; grub_cryptodisk_t dev; grub_cryptodisk_dev_t cr; + int i; + struct cryptodisk_read_hook_ctx read_hook_data = {0}; + int askpass = 0; + char *part = NULL; dev = grub_cryptodisk_get_by_source_disk (source); if (dev) - return GRUB_ERR_NONE; + return dev; + + if (cargs->hdr_file != NULL) + { + /* + * Set read hook to read header from a file instead of the source disk. + * Disk read hooks are executed after the data has been read from the + * disk. This is okay, because the read hook is given the read buffer + * before its sent back to the caller. In this case, the hook can then + * overwrite the data read from the disk device with data from the + * header file sent in as the read hook data. This is transparent to the + * read caller. Since the callers of this function have just opened the + * source disk, there are no current read hooks, so there's no need to + * save/restore them nor consider if they should be called or not. + * + * This hook assumes that the header is at the start of the volume, which + * is not the case for some formats (eg. GELI). It also can only be used + * with formats where the detached header file can be written to the + * first blocks of the volume and the volume could still be unlocked. + * So the header file can not be formatted differently from the on-disk + * header. If these assumpts are not met, detached header file processing + * must be specially handled in the cryptodisk backend module. + * + * This hook needs only be set once and will be called potentially many + * times by a backend. This is fine because of the assumptions mentioned + * and the read hook reads from absolute offsets and is stateless. + */ + read_hook_data.part_start = grub_partition_get_start (source->partition); + read_hook_data.hdr_file = cargs->hdr_file; + source->read_hook = cryptodisk_read_hook; + source->read_hook_data = (void *) &read_hook_data; + } FOR_CRYPTODISK_DEVS (cr) { - dev = cr->scan (source, search_uuid, check_boot); + /* + * Loop through each cryptodisk backend that is registered (ie. loaded). + * If the scan returns NULL, then the backend being tested does not + * recognize the source disk, so move on to the next backend. + */ + dev = cr->scan (source, cargs); if (grub_errno) - return grub_errno; + goto error_no_close; if (!dev) continue; - - err = cr->recover_key (source, dev); - if (err) + break; + } + + if (dev == NULL) { - cryptodisk_close (dev); - return err; + grub_error (GRUB_ERR_BAD_MODULE, + "no cryptodisk module can handle this device"); + goto error_no_close; } - grub_cryptodisk_insert (dev, name, source); + if (cargs->protectors) + { + for (i = 0; cargs->protectors[i]; i++) + { + if (cargs->key_cache[i].invalid) + continue; - have_it = 1; + if (cargs->key_cache[i].key == NULL) + { + ret = grub_key_protector_recover_key (cargs->protectors[i], + &cargs->key_cache[i].key, + &cargs->key_cache[i].key_len); + if (ret != GRUB_ERR_NONE) + { + if (grub_errno) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } - return GRUB_ERR_NONE; - } - return GRUB_ERR_NONE; + grub_dprintf ("cryptodisk", + "failed to recover a key from key protector " + "%s, will not try it again for any other " + "disks, if any, during this invocation of " + "cryptomount\n", + cargs->protectors[i]); + + cargs->key_cache[i].invalid = 1; + continue; + } + } + + cargs->key_data = cargs->key_cache[i].key; + cargs->key_len = cargs->key_cache[i].key_len; + + ret = cr->recover_key (source, dev, cargs); + if (ret != GRUB_ERR_NONE) + { + /* Reset key data to trigger the passphrase prompt later */ + cargs->key_data = NULL; + cargs->key_len = 0; + + part = grub_partition_get_name (source->partition); + grub_dprintf ("cryptodisk", + "recovered a key from key protector %s but it " + "failed to unlock %s%s%s (%s)\n", + cargs->protectors[i], source->name, + source->partition != NULL ? "," : "", + part != NULL ? part : N_("UNKNOWN"), dev->uuid); + grub_free (part); + continue; + } + else + { + ret = grub_cryptodisk_insert (dev, name, source); + if (ret != GRUB_ERR_NONE) + goto error; +#ifndef GRUB_UTIL + grub_cli_set_auth_needed (); +#endif + goto cleanup; + } + } + + part = grub_partition_get_name (source->partition); + grub_error (GRUB_ERR_ACCESS_DENIED, + N_("no key protector provided a usable key for %s%s%s (%s)"), + source->name, source->partition != NULL ? "," : "", + part != NULL ? part : N_("UNKNOWN"), dev->uuid); + grub_free (part); + } + + if (cargs->key_len) + { + ret = cr->recover_key (source, dev, cargs); + if (ret != GRUB_ERR_NONE) + goto error; + } + else + { + /* Get the passphrase from the user, if no key data. */ + unsigned long tries = 3; + const char *tries_env; + + /* + * Print the error from key protectors and clear grub_errno. + * + * Since '--protector' cannot coexist with '--password' and + * '--key-file', in case key protectors fail, only + * "cargs->key_len == 0" is expected, so cryptomount falls back + * here to request the passphrase. + * + * To avoid the error from key protectors stops the further code, + * print the error to notify the user why key protectors fail and + * clear grub_errno to have a fresh start. + */ + if (grub_errno != GRUB_ERR_NONE) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + + askpass = 1; + cargs->key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE); + if (cargs->key_data == NULL) + goto error_no_close; + + tries_env = grub_env_get ("cryptodisk_passphrase_tries"); + if (tries_env != NULL && tries_env[0] != '\0') + { + unsigned long tries_env_val; + const char *p; + + tries_env_val = grub_strtoul (tries_env, &p, 0); + if (*p == '\0' && tries_env_val != ~0UL) + tries = tries_env_val; + else + grub_printf_ (N_("Invalid cryptodisk_passphrase_tries value `%s'. Defaulting to %lu.\n"), + tries_env, + tries); + } + + for (; tries > 0; tries--) + { + part = grub_partition_get_name (source->partition); + grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, + source->partition != NULL ? "," : "", + part != NULL ? part : N_("UNKNOWN"), + dev->uuid); + grub_free (part); + + if (!grub_password_get ((char *) cargs->key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE)) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied"); + goto error; + } + cargs->key_len = grub_strlen ((char *) cargs->key_data); + + ret = cr->recover_key (source, dev, cargs); + if (ret == GRUB_ERR_NONE) + break; + if (ret != GRUB_ERR_ACCESS_DENIED || tries == 1) + goto error; + grub_puts_ (N_("Invalid passphrase.")); + + /* + * Since recover_key() calls a function that returns grub_errno, + * a leftover error value from a previously rejected passphrase + * will trigger a phantom failure. We therefore clear it before + * trying a new passphrase. + */ + grub_errno = GRUB_ERR_NONE; + } + } + + ret = grub_cryptodisk_insert (dev, name, source); + if (ret != GRUB_ERR_NONE) + goto error; + + goto cleanup; + + error: + cryptodisk_close (dev); + error_no_close: + dev = NULL; + + cleanup: + if (cargs->hdr_file != NULL) + source->read_hook = NULL; + + if (askpass) + { + grub_memset (cargs->key_data, 0, cargs->key_len); + cargs->key_len = 0; + grub_free (cargs->key_data); + } + return dev; } #ifdef GRUB_UTIL @@ -827,6 +1318,7 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat) grub_cryptodisk_t dev; grub_cryptodisk_dev_t cr; grub_disk_t source; + struct grub_cryptomount_args cargs = {0}; /* Try to open disk. */ source = grub_disk_open (sourcedev); @@ -837,13 +1329,13 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat) if (dev) { - grub_disk_close (source); + grub_disk_close (source); return GRUB_ERR_NONE; } FOR_CRYPTODISK_DEVS (cr) { - dev = cr->scan (source, search_uuid, check_boot); + dev = cr->scan (source, &cargs); if (grub_errno) return grub_errno; if (!dev) @@ -866,117 +1358,559 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat) #endif static int -grub_cryptodisk_scan_device (const char *name) +grub_cryptodisk_scan_device (const char *name, + void *data) { - grub_err_t err; + int ret = 0; grub_disk_t source; + grub_cryptodisk_t dev; + grub_cryptomount_args_t cargs = data; + grub_errno = GRUB_ERR_NONE; /* Try to open disk. */ source = grub_disk_open (name); if (!source) - return grub_errno; + { + grub_print_error (); + return 0; + } - err = grub_cryptodisk_scan_device_real (name, source); + dev = grub_cryptodisk_scan_device_real (name, source, cargs); + if (dev) + { + ret = (cargs->search_uuid != NULL + && grub_uuidcasecmp (cargs->search_uuid, dev->uuid, sizeof (dev->uuid)) == 0); + goto cleanup; + } - grub_disk_close (source); - - if (err) + /* + * Do not print error when err is GRUB_ERR_BAD_MODULE to avoid many unhelpful + * error messages. + */ + if (grub_errno == GRUB_ERR_BAD_MODULE) + grub_error_pop (); + + if (cargs->search_uuid != NULL) + /* Push error onto stack to save for cryptomount. */ + grub_error_push (); + else grub_print_error (); - return have_it && search_uuid ? 1 : 0; + + cleanup: + grub_disk_close (source); + return ret; +} + +static void +grub_cryptodisk_clear_key_cache (struct grub_cryptomount_args *cargs) +{ + int i; + + if (cargs->key_cache == NULL || cargs->protectors == NULL) + return; + + for (i = 0; cargs->protectors[i]; i++) + { + if (cargs->key_cache[i].key) + grub_memset (cargs->key_cache[i].key, 0, cargs->key_cache[i].key_len); + grub_free (cargs->key_cache[i].key); + } + + grub_free (cargs->key_cache); } static grub_err_t grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; + struct grub_cryptomount_args cargs = {0}; - if (argc < 1 && !state[1].set && !state[2].set) + if (argc < 1 && !state[OPTION_ALL].set && !state[OPTION_BOOT].set) return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); - have_it = 0; - if (state[0].set) + if (grub_cryptodisk_list == NULL) + return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded"); + + if (state[OPTION_PASSWORD].set && state[OPTION_PROTECTOR].set) /* password and key protector */ + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "a password and a key protector cannot both be set"); + + if (state[OPTION_KEYFILE].set && state[OPTION_PROTECTOR].set) /* key file and key protector */ + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "a key file and a key protector cannot both be set"); + + if (state[OPTION_PASSWORD].set) /* password */ { + cargs.key_data = (grub_uint8_t *) state[OPTION_PASSWORD].arg; + cargs.key_len = grub_strlen (state[OPTION_PASSWORD].arg); + } + + if (state[OPTION_KEYFILE].set) /* keyfile */ + { + const char *p = NULL; + grub_file_t keyfile; + unsigned long long keyfile_offset = 0, keyfile_size = 0; + + if (state[OPTION_KEYFILE_OFFSET].set) /* keyfile-offset */ + { + grub_errno = GRUB_ERR_NONE; + keyfile_offset = grub_strtoull (state[OPTION_KEYFILE_OFFSET].arg, &p, 0); + + if (state[OPTION_KEYFILE_OFFSET].arg[0] == '\0' || *p != '\0') + return grub_error (grub_errno, + N_("non-numeric or invalid keyfile offset `%s'"), + state[OPTION_KEYFILE_OFFSET].arg); + } + + if (state[OPTION_KEYFILE_SIZE].set) /* keyfile-size */ + { + grub_errno = GRUB_ERR_NONE; + keyfile_size = grub_strtoull (state[OPTION_KEYFILE_SIZE].arg, &p, 0); + + if (state[OPTION_KEYFILE_SIZE].arg[0] == '\0' || *p != '\0') + return grub_error (grub_errno, + N_("non-numeric or invalid keyfile size `%s'"), + state[OPTION_KEYFILE_SIZE].arg); + + if (keyfile_size == 0) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("key file size is 0")); + + if (keyfile_size > GRUB_CRYPTODISK_MAX_KEYFILE_SIZE) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("key file size exceeds maximum (%d)"), + GRUB_CRYPTODISK_MAX_KEYFILE_SIZE); + } + + keyfile = grub_file_open (state[OPTION_KEYFILE].arg, + GRUB_FILE_TYPE_CRYPTODISK_ENCRYPTION_KEY); + if (keyfile == NULL) + return grub_errno; + + if (keyfile_offset > keyfile->size) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("Keyfile offset, %llu, is greater than " + "keyfile size, %llu"), + keyfile_offset, (unsigned long long) keyfile->size); + + if (grub_file_seek (keyfile, (grub_off_t) keyfile_offset) == (grub_off_t) -1) + return grub_errno; + + if (keyfile_size != 0) + { + if (keyfile_size > (keyfile->size - keyfile_offset)) + return grub_error (GRUB_ERR_FILE_READ_ERROR, + N_("keyfile is too small: requested %llu bytes," + " but the file only has %" PRIuGRUB_UINT64_T + " bytes left at offset %llu"), + keyfile_size, + (grub_off_t) (keyfile->size - keyfile_offset), + keyfile_offset); + + cargs.key_len = keyfile_size; + } + else + cargs.key_len = keyfile->size - keyfile_offset; + + cargs.key_data = grub_malloc (cargs.key_len); + if (cargs.key_data == NULL) + return GRUB_ERR_OUT_OF_MEMORY; + + if (grub_file_read (keyfile, cargs.key_data, cargs.key_len) != (grub_ssize_t) cargs.key_len) + return grub_error (GRUB_ERR_FILE_READ_ERROR, (N_("failed to read key file"))); + } + + if (state[OPTION_HEADER].set) /* header */ + { + if (state[OPTION_UUID].set) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("cannot use UUID lookup with detached header")); + + cargs.hdr_file = grub_file_open (state[OPTION_HEADER].arg, + GRUB_FILE_TYPE_CRYPTODISK_DETACHED_HEADER); + if (cargs.hdr_file == NULL) + return grub_errno; + } + + if (state[OPTION_PROTECTOR].set) /* key protector(s) */ + { + cargs.key_cache = grub_calloc (state[OPTION_PROTECTOR].set, sizeof (*cargs.key_cache)); + if (cargs.key_cache == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "no memory for key protector key cache"); + cargs.protectors = state[OPTION_PROTECTOR].args; + } + + if (state[OPTION_UUID].set) /* uuid */ + { + int found_uuid; grub_cryptodisk_t dev; dev = grub_cryptodisk_get_by_uuid (args[0]); if (dev) { + grub_cryptodisk_clear_key_cache (&cargs); grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id); return GRUB_ERR_NONE; } - check_boot = state[2].set; - search_uuid = args[0]; - grub_device_iterate (&grub_cryptodisk_scan_device); - search_uuid = NULL; + cargs.check_boot = state[OPTION_BOOT].set; + cargs.search_uuid = args[0]; + found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs); + grub_cryptodisk_clear_key_cache (&cargs); - if (!have_it) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found"); - return GRUB_ERR_NONE; + if (found_uuid) + return GRUB_ERR_NONE; + else if (grub_errno == GRUB_ERR_NONE) + { + /* + * Try to pop the next error on the stack. If there is not one, then + * no device matched the given UUID. + */ + grub_error_pop (); + if (grub_errno == GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no such cryptodisk found, perhaps a needed disk or cryptodisk module is not loaded"); + } + return grub_errno; } - else if (state[1].set || (argc == 0 && state[2].set)) + else if (state[OPTION_ALL].set || (argc == 0 && state[OPTION_BOOT].set)) /* -a|-b */ { - search_uuid = NULL; - check_boot = state[2].set; - grub_device_iterate (&grub_cryptodisk_scan_device); - search_uuid = NULL; + cargs.check_boot = state[OPTION_BOOT].set; + grub_device_iterate (&grub_cryptodisk_scan_device, &cargs); + grub_cryptodisk_clear_key_cache (&cargs); return GRUB_ERR_NONE; } else { - grub_err_t err; grub_disk_t disk; grub_cryptodisk_t dev; + char *diskname; + char *disklast = NULL; + grub_size_t len; - search_uuid = NULL; - check_boot = state[2].set; - disk = grub_disk_open (args[0]); + cargs.check_boot = state[OPTION_BOOT].set; + diskname = args[0]; + len = grub_strlen (diskname); + if (len && diskname[0] == '(' && diskname[len - 1] == ')') + { + disklast = &diskname[len - 1]; + *disklast = '\0'; + diskname++; + } + + disk = grub_disk_open (diskname); if (!disk) - return grub_errno; + { + grub_cryptodisk_clear_key_cache (&cargs); + if (disklast) + *disklast = ')'; + return grub_errno; + } dev = grub_cryptodisk_get_by_source_disk (disk); if (dev) { grub_dprintf ("cryptodisk", "already mounted as crypto%lu\n", dev->id); grub_disk_close (disk); + grub_cryptodisk_clear_key_cache (&cargs); + if (disklast) + *disklast = ')'; return GRUB_ERR_NONE; } - err = grub_cryptodisk_scan_device_real (args[0], disk); + dev = grub_cryptodisk_scan_device_real (diskname, disk, &cargs); + grub_cryptodisk_clear_key_cache (&cargs); grub_disk_close (disk); + if (disklast) + *disklast = ')'; - return err; + return (dev == NULL) ? grub_errno : GRUB_ERR_NONE; } } static struct grub_disk_dev grub_cryptodisk_dev = { .name = "cryptodisk", .id = GRUB_DISK_DEVICE_CRYPTODISK_ID, - .iterate = grub_cryptodisk_iterate, - .open = grub_cryptodisk_open, - .close = grub_cryptodisk_close, - .read = grub_cryptodisk_read, - .write = grub_cryptodisk_write, + .disk_iterate = grub_cryptodisk_iterate, + .disk_open = grub_cryptodisk_open, + .disk_close = grub_cryptodisk_close, + .disk_read = grub_cryptodisk_read, + .disk_write = grub_cryptodisk_write, #ifdef GRUB_UTIL - .memberlist = grub_cryptodisk_memberlist, + .disk_memberlist = grub_cryptodisk_memberlist, #endif .next = 0 }; +static char +hex (grub_uint8_t val) +{ + if (val < 10) + return '0' + val; + return 'a' + val - 10; +} + +/* Open a file named NAME and initialize FILE. */ +static char * +luks_script_get (grub_size_t *sz) +{ + grub_cryptodisk_t i; + grub_size_t size = 0, mul; + char *ptr, *ret; + + *sz = 0; + + for (i = cryptodisk_list; i != NULL; i = i->next) + if (grub_strcmp (i->modname, "luks") == 0 || + grub_strcmp (i->modname, "luks2") == 0) + { + /* + * Add space in the line for (in order) spaces, cipher mode, cipher IV + * mode, sector offset, sector size and the trailing newline. This is + * an upper bound on the size of this data. There are 15 extra bytes + * in an earlier version of this code that are unaccounted for. It is + * left in the calculations in case it is needed. At worst, its short- + * lived wasted space. + * + * 60 = 5 + 5 + 8 + 20 + 6 + 1 + 15 + */ + if (grub_add (size, grub_strlen (i->modname), &size) || + grub_add (size, sizeof ("_mount") + 60, &size) || + grub_add (size, grub_strlen (i->uuid), &size) || + grub_add (size, grub_strlen (i->cipher->cipher->name), &size) || + grub_mul (i->keysize, 2, &mul) || + grub_add (size, mul, &size)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script"); + return 0; + } + if (i->essiv_hash) + { + if (grub_add (size, grub_strlen (i->essiv_hash->name), &size)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script"); + return 0; + } + } + } + if (grub_add (size, 1, &size)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while obtaining size of luks script"); + return 0; + } + + ret = grub_malloc (size); + if (!ret) + return 0; + + ptr = ret; + + for (i = cryptodisk_list; i != NULL; i = i->next) + if (grub_strcmp (i->modname, "luks") == 0 || + grub_strcmp (i->modname, "luks2") == 0) + { + unsigned j; + const char *iptr; + ptr = grub_stpcpy (ptr, i->modname); + ptr = grub_stpcpy (ptr, "_mount "); + ptr = grub_stpcpy (ptr, i->uuid); + *ptr++ = ' '; + ptr += grub_snprintf (ptr, 21, "%" PRIxGRUB_OFFSET, i->offset_sectors); + *ptr++ = ' '; + ptr += grub_snprintf (ptr, 7, "%u", 1 << i->log_sector_size); + *ptr++ = ' '; + for (iptr = i->cipher->cipher->name; *iptr; iptr++) + *ptr++ = grub_tolower (*iptr); + switch (i->mode) + { + case GRUB_CRYPTODISK_MODE_ECB: + ptr = grub_stpcpy (ptr, "-ecb"); + break; + case GRUB_CRYPTODISK_MODE_CBC: + ptr = grub_stpcpy (ptr, "-cbc"); + break; + case GRUB_CRYPTODISK_MODE_PCBC: + ptr = grub_stpcpy (ptr, "-pcbc"); + break; + case GRUB_CRYPTODISK_MODE_XTS: + ptr = grub_stpcpy (ptr, "-xts"); + break; + case GRUB_CRYPTODISK_MODE_LRW: + ptr = grub_stpcpy (ptr, "-lrw"); + break; + } + + switch (i->mode_iv) + { + case GRUB_CRYPTODISK_MODE_IV_NULL: + ptr = grub_stpcpy (ptr, "-null"); + break; + case GRUB_CRYPTODISK_MODE_IV_PLAIN: + ptr = grub_stpcpy (ptr, "-plain"); + break; + case GRUB_CRYPTODISK_MODE_IV_PLAIN64: + ptr = grub_stpcpy (ptr, "-plain64"); + break; + case GRUB_CRYPTODISK_MODE_IV_BENBI: + ptr = grub_stpcpy (ptr, "-benbi"); + break; + case GRUB_CRYPTODISK_MODE_IV_ESSIV: + ptr = grub_stpcpy (ptr, "-essiv:"); + ptr = grub_stpcpy (ptr, i->essiv_hash->name); + break; + case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64: + case GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH: + break; + } + *ptr++ = ' '; + for (j = 0; j < i->keysize; j++) + { + *ptr++ = hex (i->key[j] >> 4); + *ptr++ = hex (i->key[j] & 0xf); + } + *ptr++ = '\n'; + } + *ptr = '\0'; + *sz = ptr - ret; + return ret; +} + +#ifdef GRUB_MACHINE_EFI +grub_err_t +grub_cryptodisk_challenge_password (void) +{ + grub_cryptodisk_t cr_dev; + + for (cr_dev = cryptodisk_list; cr_dev != NULL; cr_dev = cr_dev->next) + { + grub_cryptodisk_dev_t cr; + grub_disk_t source = NULL; + grub_err_t ret = GRUB_ERR_NONE; + grub_cryptodisk_t dev = NULL; + char *part = NULL; + struct grub_cryptomount_args cargs = {0}; + + cargs.check_boot = 0; + cargs.search_uuid = cr_dev->uuid; + + source = grub_disk_open (cr_dev->source); + + if (source == NULL) + { + ret = grub_errno; + goto error_out; + } + + FOR_CRYPTODISK_DEVS (cr) + { + dev = cr->scan (source, &cargs); + if (grub_errno) + { + ret = grub_errno; + goto error_out; + } + if (dev == NULL) + continue; + break; + } + + if (dev == NULL) + { + ret = grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk module can handle this device"); + goto error_out; + } + + part = grub_partition_get_name (source->partition); + grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, + source->partition != NULL ? "," : "", + part != NULL ? part : N_("UNKNOWN"), cr_dev->uuid); + grub_free (part); + + cargs.key_data = grub_malloc (GRUB_CRYPTODISK_MAX_PASSPHRASE); + if (cargs.key_data == NULL) + { + ret = grub_errno; + goto error_out; + } + + if (!grub_password_get ((char *) cargs.key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE)) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "passphrase not supplied"); + goto error_out; + } + cargs.key_len = grub_strlen ((char *) cargs.key_data); + ret = cr->recover_key (source, dev, &cargs); + + error_out: + grub_disk_close (source); + if (dev != NULL) + cryptodisk_close (dev); + if (cargs.key_data) + { + grub_memset (cargs.key_data, 0, cargs.key_len); + grub_free (cargs.key_data); + } + + return ret; + } + + return GRUB_ERR_NONE; +} + +void +grub_cryptodisk_erasesecrets (void) +{ + grub_cryptodisk_t i; + grub_uint8_t *buf; + + buf = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN); + if (buf == NULL) + grub_fatal ("grub_cryptodisk_erasesecrets: cannot allocate memory"); + + for (i = cryptodisk_list; i != NULL; i = i->next) + if (grub_cryptodisk_setkey (i, buf, i->keysize)) + grub_fatal ("grub_cryptodisk_erasesecrets: cannot erase secrets for %s", i->source); + else + grub_printf ("Erased crypto secrets for %s\n", i->source); + /* + * Unfortunately, there is no way to "force unmount" a given disk, it may + * have mounted "child" disks as well, e.g., an LVM volume. So, this + * function MUST be called when there is no way back, e.g., when exiting. + * Otherwise, subsequent read calls for a cryptodisk will return garbage. + */ + + grub_free (buf); +} +#endif /* GRUB_MACHINE_EFI */ + +struct grub_procfs_entry luks_script = +{ + .name = "luks_script", + .get_contents = luks_script_get +}; + static grub_extcmd_t cmd; GRUB_MOD_INIT (cryptodisk) { grub_disk_dev_register (&grub_cryptodisk_dev); cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0, - N_("SOURCE|-u UUID|-a|-b"), + N_("[ [-p password] | [-k keyfile" + " [-O keyoffset] [-S keysize] ] ] [-H file]" + " [-P protector [-P protector ...]]" + " "), N_("Mount a crypto device."), options); + grub_procfs_register ("luks_script", &luks_script); } GRUB_MOD_FINI (cryptodisk) { +#ifdef GRUB_MACHINE_EFI + grub_cryptodisk_erasesecrets (); +#endif grub_disk_dev_unregister (&grub_cryptodisk_dev); cryptodisk_cleanup (); + grub_unregister_extcmd (cmd); + grub_procfs_unregister (&luks_script); } diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c index 6e9745e35..3a26de60c 100644 --- a/grub-core/disk/diskfilter.c +++ b/grub-core/disk/diskfilter.c @@ -20,10 +20,12 @@ #include #include #include +#include #include #include #include #include +#include #ifdef GRUB_UTIL #include #include @@ -71,10 +73,12 @@ is_lv_readable (struct grub_diskfilter_lv *lv, int easily) case GRUB_DISKFILTER_RAID6: if (!easily) need--; + /* Fallthrough. */ case GRUB_DISKFILTER_RAID4: case GRUB_DISKFILTER_RAID5: if (!easily) need--; + /* Fallthrough. */ case GRUB_DISKFILTER_STRIPED: break; @@ -117,68 +121,72 @@ is_valid_diskfilter_name (const char *name) { return (grub_memcmp (name, "md", sizeof ("md") - 1) == 0 || grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) == 0 + || grub_memcmp (name, "lvmid/", sizeof ("lvmid/") - 1) == 0 || grub_memcmp (name, "ldm/", sizeof ("ldm/") - 1) == 0); } +/* Helper for scan_disk. */ +static int +scan_disk_partition_iter (grub_disk_t disk, grub_partition_t p, void *data) +{ + const char *name = data; + struct grub_diskfilter_vg *arr; + grub_disk_addr_t start_sector; + struct grub_diskfilter_pv_id id; + grub_diskfilter_t diskfilter; + + grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n", + name); +#ifdef GRUB_UTIL + grub_util_info ("Scanning for DISKFILTER devices on disk %s", name); +#endif + + disk->partition = p; + + for (arr = array_list; arr != NULL; arr = arr->next) + { + struct grub_diskfilter_pv *m; + for (m = arr->pvs; m; m = m->next) + if (m->disk && m->disk->id == disk->id + && m->disk->dev->id == disk->dev->id + && m->part_start == grub_partition_get_start (disk->partition) + && m->part_size == grub_disk_native_sectors (disk)) + return 0; + } + + for (diskfilter = grub_diskfilter_list; diskfilter; diskfilter = diskfilter->next) + { +#ifdef GRUB_UTIL + grub_util_info ("Scanning for %s devices on disk %s", + diskfilter->name, name); +#endif + id.uuid = 0; + id.uuidlen = 0; + arr = diskfilter->detect (disk, &id, &start_sector); + if (arr && + (! insert_array (disk, &id, arr, start_sector, diskfilter))) + { + if (id.uuidlen) + grub_free (id.uuid); + return 0; + } + if (arr && id.uuidlen) + grub_free (id.uuid); + + /* This error usually means it's not diskfilter, no need to display + it. */ + if (grub_errno != GRUB_ERR_OUT_OF_RANGE) + grub_print_error (); + + grub_errno = GRUB_ERR_NONE; + } + + return 0; +} + static int scan_disk (const char *name, int accept_diskfilter) { - auto int hook (grub_disk_t disk, grub_partition_t p); - int hook (grub_disk_t disk, grub_partition_t p) - { - struct grub_diskfilter_vg *arr; - grub_disk_addr_t start_sector; - struct grub_diskfilter_pv_id id; - grub_diskfilter_t diskfilter; - - grub_dprintf ("diskfilter", "Scanning for DISKFILTER devices on disk %s\n", - name); -#ifdef GRUB_UTIL - grub_util_info ("Scanning for DISKFILTER devices on disk %s", name); -#endif - - disk->partition = p; - - for (arr = array_list; arr != NULL; arr = arr->next) - { - struct grub_diskfilter_pv *m; - for (m = arr->pvs; m; m = m->next) - if (m->disk && m->disk->id == disk->id - && m->disk->dev->id == disk->dev->id - && m->part_start == grub_partition_get_start (disk->partition) - && m->part_size == grub_disk_get_size (disk)) - return 0; - } - - for (diskfilter = grub_diskfilter_list; diskfilter; diskfilter = diskfilter->next) - { -#ifdef GRUB_UTIL - grub_util_info ("Scanning for %s devices on disk %s", - diskfilter->name, name); -#endif - id.uuid = 0; - id.uuidlen = 0; - arr = diskfilter->detect (disk, &id, &start_sector); - if (arr && - (! insert_array (disk, &id, arr, start_sector, diskfilter))) - { - if (id.uuidlen) - grub_free (id.uuid); - return 0; - } - if (arr && id.uuidlen) - grub_free (id.uuid); - - /* This error usually means it's not diskfilter, no need to display - it. */ - if (grub_errno != GRUB_ERR_OUT_OF_RANGE) - grub_print_error (); - - grub_errno = GRUB_ERR_NONE; - } - - return 0; - } grub_disk_t disk; static int scan_depth = 0; @@ -196,23 +204,15 @@ scan_disk (const char *name, int accept_diskfilter) scan_depth--; return 0; } - if (hook (disk, 0)) - { - scan_depth--; - return 1; - } - if (grub_partition_iterate (disk, hook)) - { - scan_depth--; - return 1; - } + scan_disk_partition_iter (disk, 0, (void *) name); + grub_partition_iterate (disk, scan_disk_partition_iter, (void *) name); grub_disk_close (disk); scan_depth--; return 0; } static int -scan_disk_hook (const char *name) +scan_disk_hook (const char *name, void *data __attribute__ ((unused))) { return scan_disk (name, 0); } @@ -224,33 +224,58 @@ scan_devices (const char *arname) grub_disk_pull_t pull; struct grub_diskfilter_vg *vg; struct grub_diskfilter_lv *lv = NULL; + int scan_depth; + int need_rescan; for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++) - for (p = grub_disk_dev_list; p; p = p->next) - if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID - && p->iterate) - { - if ((p->iterate) (scan_disk_hook, pull)) - return; - if (arname && is_lv_readable (find_lv (arname), 1)) - return; - } - - for (vg = array_list; vg; vg = vg->next) { - if (vg->lvs) - for (lv = vg->lvs; lv; lv = lv->next) - if (!lv->scanned && lv->fullname && lv->became_readable_at) - { - scan_disk (lv->fullname, 1); - lv->scanned = 1; - } + /* look up the crytodisk devices first */ + for (p = grub_disk_dev_list; p; p = p->next) + if (p->id == GRUB_DISK_DEVICE_CRYPTODISK_ID && p->disk_iterate) + { + if ((p->disk_iterate) (scan_disk_hook, NULL, pull)) + return; + if (arname && is_lv_readable (find_lv (arname), 1)) + return; + break; + } + + /* check the devices other than crytodisk */ + for (p = grub_disk_dev_list; p; p = p->next) + if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID && p->disk_iterate) + { + if ((p->disk_iterate) (scan_disk_hook, NULL, pull)) + return; + if (arname && is_lv_readable (find_lv (arname), 1)) + return; + } } + + scan_depth = 0; + need_rescan = 1; + while (need_rescan && scan_depth++ < 100) + { + need_rescan = 0; + for (vg = array_list; vg; vg = vg->next) + { + if (vg->lvs) + for (lv = vg->lvs; lv; lv = lv->next) + if (!lv->scanned && lv->fullname && lv->became_readable_at) + { + scan_disk (lv->fullname, 1); + lv->scanned = 1; + need_rescan = 1; + } + } + } + + if (need_rescan) + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "DISKFILTER scan depth exceeded"); } static int -grub_diskfilter_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull) +grub_diskfilter_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) { struct grub_diskfilter_vg *array; int islcnt = 0; @@ -271,7 +296,7 @@ grub_diskfilter_iterate (int (*hook) (const char *name), for (lv = array->lvs; lv; lv = lv->next) if (lv->visible && lv->fullname && lv->became_readable_at >= islcnt) { - if (hook (lv->fullname)) + if (hook (lv->fullname, hook_data)) return 1; } } @@ -290,6 +315,8 @@ grub_diskfilter_memberlist (grub_disk_t disk) grub_disk_dev_t p; struct grub_diskfilter_vg *vg; struct grub_diskfilter_lv *lv2 = NULL; + struct grub_diskfilter_segment *seg; + unsigned int i, j; if (!lv->vg->pvs) return NULL; @@ -301,9 +328,9 @@ grub_diskfilter_memberlist (grub_disk_t disk) for (pull = 0; pv && pull < GRUB_DISK_PULL_MAX; pull++) for (p = grub_disk_dev_list; pv && p; p = p->next) if (p->id != GRUB_DISK_DEVICE_DISKFILTER_ID - && p->iterate) + && p->disk_iterate) { - (p->iterate) (scan_disk_hook, pull); + (p->disk_iterate) (scan_disk_hook, NULL, pull); while (pv && pv->disk) pv = pv->next; } @@ -321,31 +348,58 @@ grub_diskfilter_memberlist (grub_disk_t disk) } } - for (pv = lv->vg->pvs; pv; pv = pv->next) - { - if (!pv->disk) + for (i = 0, seg = lv->segments; i < lv->segment_count; i++, seg++) + for (j = 0; j < seg->node_count; ++j) + if (seg->nodes[j].pv != NULL) { - /* TRANSLATORS: This message kicks in during the detection of - which modules needs to be included in core image. This happens - in the case of degraded RAID and means that autodetection may - fail to include some of modules. It's an installation time - message, not runtime message. */ - grub_util_warn (_("Couldn't find physical volume `%s'." - " Some modules may be missing from core image."), - pv->name); - continue; + pv = seg->nodes[j].pv; + + if (pv->disk == NULL) + { + /* + * TRANSLATORS: This message kicks in during the detection of + * which modules needs to be included in core image. This happens + * in the case of degraded RAID and means that autodetection may + * fail to include some of modules. It's an installation time + * message, not runtime message. + */ + grub_util_warn (_("Couldn't find physical volume `%s'." + " Some modules may be missing from core image."), + pv->name); + continue; + } + + for (tmp = list; tmp != NULL; tmp = tmp->next) + if (!grub_strcmp (tmp->disk->name, pv->disk->name)) + break; + if (tmp != NULL) + continue; + + tmp = grub_malloc (sizeof (*tmp)); + if (tmp == NULL) + goto fail; + tmp->disk = pv->disk; + tmp->next = list; + list = tmp; } - tmp = grub_malloc (sizeof (*tmp)); - tmp->disk = pv->disk; - tmp->next = list; - list = tmp; - } return list; + + fail: + while (list != NULL) + { + tmp = list; + list = list->next; + grub_free (tmp); + } + + return NULL; } void -grub_diskfilter_print_partmap (grub_disk_t disk) +grub_diskfilter_get_partmap (grub_disk_t disk, + void (*cb) (const char *pm, void *data), + void *data) { struct grub_diskfilter_lv *lv = disk->data; struct grub_diskfilter_pv *pv; @@ -367,7 +421,7 @@ grub_diskfilter_print_partmap (grub_disk_t disk) continue; } for (s = 0; pv->partmaps[s]; s++) - grub_printf ("%s ", pv->partmaps[s]); + cb (pv->partmaps[s], data); } } @@ -380,16 +434,12 @@ grub_diskfilter_getname (struct grub_disk *disk) } #endif -static inline int -ascii2hex (char c) +static inline char +hex2ascii (int c) { - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return 0; + if (c >= 10) + return 'a' + c - 10; + return c + '0'; } static struct grub_diskfilter_lv * @@ -398,30 +448,12 @@ find_lv (const char *name) struct grub_diskfilter_vg *vg; struct grub_diskfilter_lv *lv = NULL; - if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0) - { - const char *uuidstr = name + sizeof ("mduuid/") - 1; - grub_size_t uuid_len = grub_strlen (uuidstr) / 2; - grub_uint8_t uuidbin[uuid_len]; - unsigned i; - for (i = 0; i < uuid_len; i++) - uuidbin[i] = ascii2hex (uuidstr[2 * i + 1]) - | (ascii2hex (uuidstr[2 * i]) << 4); - - for (vg = array_list; vg; vg = vg->next) - { - if (uuid_len == vg->uuid_len - && grub_memcmp (uuidbin, vg->uuid, uuid_len) == 0) - if (is_lv_readable (vg->lvs, 0)) - return vg->lvs; - } - } - for (vg = array_list; vg; vg = vg->next) { if (vg->lvs) for (lv = vg->lvs; lv; lv = lv->next) - if (lv->fullname && grub_strcmp (lv->fullname, name) == 0 + if (((lv->fullname && grub_strcmp (lv->fullname, name) == 0) + || (lv->idname && grub_strcmp (lv->idname, name) == 0)) && is_lv_readable (lv, 0)) return lv; } @@ -433,9 +465,7 @@ grub_diskfilter_open (const char *name, grub_disk_t disk) { struct grub_diskfilter_lv *lv; - if (grub_memcmp (name, "md", sizeof ("md") - 1) != 0 - && grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) != 0 - && grub_memcmp (name, "ldm/", sizeof ("ldm/") - 1) != 0) + if (!is_valid_diskfilter_name (name)) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown DISKFILTER device %s", name); @@ -460,6 +490,7 @@ grub_diskfilter_open (const char *name, grub_disk_t disk) disk->data = lv; disk->total_sectors = lv->size; + disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; return 0; } @@ -496,6 +527,96 @@ grub_diskfilter_read_node (const struct grub_diskfilter_node *node, return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name); } + +static grub_err_t +validate_segment (struct grub_diskfilter_segment *seg); + +static grub_err_t +validate_lv (struct grub_diskfilter_lv *lv) +{ + unsigned int i; + if (!lv) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume"); + + if (!lv->vg || lv->vg->extent_size == 0) + return grub_error (GRUB_ERR_READ_ERROR, "invalid volume"); + + for (i = 0; i < lv->segment_count; i++) + { + grub_err_t err; + err = validate_segment (&lv->segments[i]); + if (err) + return err; + } + return GRUB_ERR_NONE; +} + + +static grub_err_t +validate_node (const struct grub_diskfilter_node *node) +{ + /* Check whether we actually know the physical volume we want to + read from. */ + if (node->pv) + return GRUB_ERR_NONE; + if (node->lv) + return validate_lv (node->lv); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name); +} + +static grub_err_t +validate_segment (struct grub_diskfilter_segment *seg) +{ + grub_err_t err; + + if (seg->stripe_size == 0 || seg->node_count == 0) + return grub_error(GRUB_ERR_BAD_FS, "invalid segment"); + + switch (seg->type) + { + case GRUB_DISKFILTER_RAID10: + { + grub_uint8_t near, far; + near = seg->layout & 0xFF; + far = (seg->layout >> 8) & 0xFF; + if ((seg->layout >> 16) == 0 && far == 0) + return grub_error(GRUB_ERR_BAD_FS, "invalid segment"); + if (near > seg->node_count) + return grub_error(GRUB_ERR_BAD_FS, "invalid segment"); + break; + } + + case GRUB_DISKFILTER_STRIPED: + case GRUB_DISKFILTER_MIRROR: + break; + + case GRUB_DISKFILTER_RAID4: + case GRUB_DISKFILTER_RAID5: + if (seg->node_count <= 1) + return grub_error(GRUB_ERR_BAD_FS, "invalid segment"); + break; + + case GRUB_DISKFILTER_RAID6: + if (seg->node_count <= 2) + return grub_error(GRUB_ERR_BAD_FS, "invalid segment"); + break; + + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported RAID level %d", seg->type); + } + + unsigned i; + for (i = 0; i < seg->node_count; i++) + { + err = validate_node (&seg->nodes[i]); + if (err) + return err; + } + return GRUB_ERR_NONE; + +} + static grub_err_t read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector, grub_size_t size, char *buf) @@ -507,13 +628,14 @@ read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector, if (seg->node_count == 1) return grub_diskfilter_read_node (&seg->nodes[0], sector, size, buf); + /* Fallthrough. */ case GRUB_DISKFILTER_MIRROR: case GRUB_DISKFILTER_RAID10: { grub_disk_addr_t read_sector, far_ofs; grub_uint64_t disknr, b, near, far, ofs; unsigned int i, j; - + read_sector = grub_divmod64 (sector, seg->stripe_size, &b); far = ofs = near = 1; far_ofs = 0; @@ -532,17 +654,17 @@ read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector, else far_ofs = grub_divmod64 (seg->raid_member_size, far * seg->stripe_size, 0); - + far_ofs *= seg->stripe_size; } - read_sector = grub_divmod64 (read_sector * near, + read_sector = grub_divmod64 (read_sector * near, seg->node_count, &disknr); ofs *= seg->stripe_size; read_sector *= ofs; - + while (1) { grub_size_t read_size; @@ -597,7 +719,7 @@ read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector, size -= read_size; if (! size) return GRUB_ERR_NONE; - + b = 0; disknr += (near - i); while (disknr >= seg->node_count) @@ -613,7 +735,7 @@ read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector, case GRUB_DISKFILTER_RAID6: { grub_disk_addr_t read_sector; - grub_uint64_t b, p, n, disknr, e; + grub_uint64_t b, p, n, disknr; /* n = 1 for level 4 and 5, 2 for level 6. */ n = seg->type / 3; @@ -658,12 +780,11 @@ read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector, { grub_size_t read_size; int next_level; - + read_size = seg->stripe_size - b; if (read_size > size) read_size = size; - e = 0; /* Reset read error. */ if (grub_errno == GRUB_ERR_READ_ERROR || grub_errno == GRUB_ERR_UNKNOWN_DEVICE) @@ -677,7 +798,6 @@ read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector, if ((err) && (err != GRUB_ERR_READ_ERROR && err != GRUB_ERR_UNKNOWN_DEVICE)) return err; - e++; if (err) { @@ -763,7 +883,7 @@ read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector, disknr = 0; } } - } + } return GRUB_ERR_NONE; default: return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, @@ -787,7 +907,7 @@ read_lv (struct grub_diskfilter_lv *lv, grub_disk_addr_t sector, grub_uint64_t to_read; extent = grub_divmod64 (sector, vg->extent_size, NULL); - + /* Find the right segment. */ { unsigned int i; @@ -831,7 +951,8 @@ grub_diskfilter_write (grub_disk_t disk __attribute ((unused)), grub_size_t size __attribute ((unused)), const char *buf __attribute ((unused))) { - return GRUB_ERR_NOT_IMPLEMENTED_YET; + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "diskfilter writes are not supported"); } struct grub_diskfilter_vg * @@ -860,6 +981,25 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg) for (lv = vg->lvs; lv; lv = lv->next) { + /* RAID 1 and single-disk RAID 0 don't use a chunksize but code + assumes one so set one. */ + for (i = 0; i < lv->segment_count; i++) + { + if (lv->segments[i].type == 1) + lv->segments[i].stripe_size = 64; + if (lv->segments[i].type == GRUB_DISKFILTER_STRIPED + && lv->segments[i].node_count == 1 + && lv->segments[i].stripe_size == 0) + lv->segments[i].stripe_size = 64; + } + } + for (lv = vg->lvs; lv; lv = lv->next) + { + grub_err_t err; + + err = validate_lv(lv); + if (err) + return err; lv->number = lv_num++; if (lv->fullname) @@ -871,7 +1011,8 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg) for (p = vgp->lvs; p; p = p->next) { int cur_num; - char *num, *end; + char *num; + const char *end; if (!p->fullname) continue; if (grub_strncmp (p->fullname, lv->fullname, len) != 0) @@ -900,12 +1041,6 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg) lv->fullname = tmp; } } - /* RAID 1 doesn't use a chunksize but code assumes one so set - one. */ - for (i = 0; i < lv->segment_count; i++) - if (lv->segments[i].type == 1) - lv->segments[i].stripe_size = 64; - lv->vg = vg; } /* Add our new array to the list. */ vg->next = array_list; @@ -915,16 +1050,24 @@ grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg) struct grub_diskfilter_vg * grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, - char *name, grub_uint64_t disk_size, + const char *name, grub_uint64_t disk_size, grub_uint64_t stripe_size, int layout, int level) { struct grub_diskfilter_vg *array; int i; + grub_size_t j, sz; grub_uint64_t totsize; struct grub_diskfilter_pv *pv; grub_err_t err; + /* We choose not to support more than the specified number of disks. */ + if (nmemb < 1 || nmemb > GRUB_MDRAID_MAX_DISKS) + { + grub_free (uuid); + return NULL; + } + switch (level) { case 1: @@ -937,6 +1080,11 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, n = layout & 0xFF; if (n == 1) n = (layout >> 8) & 0xFF; + if (n == 0) + { + grub_free (uuid); + return NULL; + } totsize = grub_divmod64 (nmemb * disk_size, n, 0); } @@ -946,10 +1094,11 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, case 4: case 5: case 6: - totsize = (nmemb - level / 3) * disk_size; + totsize = (nmemb - ((unsigned) level / 3U)) * disk_size; break; default: + grub_free (uuid); return NULL; } @@ -963,7 +1112,7 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, array->lvs->segments->extent_count = totsize; } - if (array->lvs->segments + if (array->lvs && array->lvs->segments && array->lvs->segments->raid_member_size > disk_size) array->lvs->segments->raid_member_size = disk_size; @@ -972,7 +1121,10 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, } array = grub_zalloc (sizeof (*array)); if (!array) - return NULL; + { + grub_free (uuid); + return NULL; + } array->uuid = uuid; array->uuid_len = uuidlen; if (name) @@ -987,14 +1139,41 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, array->name = new_name; } + array->extent_size = 1; array->lvs = grub_zalloc (sizeof (*array->lvs)); if (!array->lvs) goto fail; array->lvs->segment_count = 1; array->lvs->visible = 1; - array->lvs->name = array->name; - array->lvs->fullname = array->name; + if (array->name) + { + array->lvs->name = grub_strdup (array->name); + if (!array->lvs->name) + goto fail; + array->lvs->fullname = grub_strdup (array->name); + if (!array->lvs->fullname) + goto fail; + } + array->lvs->vg = array; + + if (grub_mul (uuidlen, 2, &sz) || + grub_add (sz, sizeof ("mduuid/"), &sz)) + goto fail; + + array->lvs->idname = grub_malloc (sz); + if (!array->lvs->idname) + goto fail; + + grub_memcpy (array->lvs->idname, "mduuid/", sizeof ("mduuid/") - 1); + for (j = 0; j < uuidlen; j++) + { + array->lvs->idname[sizeof ("mduuid/") - 1 + 2 * j] + = hex2ascii (((unsigned char) uuid[j] >> 4)); + array->lvs->idname[sizeof ("mduuid/") - 1 + 2 * j + 1] + = hex2ascii (((unsigned char) uuid[j] & 0xf)); + } + array->lvs->idname[sizeof ("mduuid/") - 1 + 2 * uuidlen] = '\0'; array->lvs->size = totsize; @@ -1009,7 +1188,10 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, array->lvs->segments->node_count = nmemb; array->lvs->segments->raid_member_size = disk_size; array->lvs->segments->nodes - = grub_zalloc (nmemb * sizeof (array->lvs->segments->nodes[0])); + = grub_calloc (nmemb, sizeof (array->lvs->segments->nodes[0])); + if (array->lvs->segments->nodes == NULL) + goto fail; + array->lvs->segments->stripe_size = stripe_size; for (i = 0; i < nmemb; i++) { @@ -1030,13 +1212,26 @@ grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, return array; fail: - grub_free (array->lvs); + if (array->lvs) + { + grub_free (array->lvs->name); + grub_free (array->lvs->fullname); + grub_free (array->lvs->idname); + if (array->lvs->segments) + { + grub_free (array->lvs->segments->nodes); + grub_free (array->lvs->segments); + } + grub_free (array->lvs); + } while (array->pvs) { pv = array->pvs->next; grub_free (array->pvs); array->pvs = pv; } + grub_free (array->name); + grub_free (array->uuid); grub_free (array); return NULL; } @@ -1049,24 +1244,29 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, { struct grub_diskfilter_pv *pv; - grub_dprintf ("diskfilter", "Inserting %s into %s (%s)\n", disk->name, + grub_dprintf ("diskfilter", "Inserting %s (+%lld,%lld) into %s (%s)\n", disk->name, + (unsigned long long) grub_partition_get_start (disk->partition), + (unsigned long long) grub_disk_native_sectors (disk), array->name, diskfilter->name); #ifdef GRUB_UTIL - grub_util_info ("Inserting %s into %s (%s)\n", disk->name, + grub_util_info ("Inserting %s (+%" GRUB_HOST_PRIuLONG_LONG ",%" + GRUB_HOST_PRIuLONG_LONG ") into %s (%s)\n", disk->name, + (unsigned long long) grub_partition_get_start (disk->partition), + (unsigned long long) grub_disk_native_sectors (disk), array->name, diskfilter->name); array->driver = diskfilter; #endif for (pv = array->pvs; pv; pv = pv->next) if (id->uuidlen == pv->id.uuidlen - && id->uuidlen - ? (grub_memcmp (pv->id.uuid, id->uuid, id->uuidlen) == 0) + && id->uuidlen + ? (grub_memcmp (pv->id.uuid, id->uuid, id->uuidlen) == 0) : (pv->id.id == id->id)) { struct grub_diskfilter_lv *lv; /* FIXME: Check whether the update time of the superblocks are the same. */ - if (pv->disk && grub_disk_get_size (disk) >= pv->part_size) + if (pv->disk && grub_disk_native_sectors (disk) >= pv->part_size) return GRUB_ERR_NONE; pv->disk = grub_disk_open (disk->name); if (!pv->disk) @@ -1075,7 +1275,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, raid device, we shouldn't change it. */ pv->start_sector -= pv->part_start; pv->part_start = grub_partition_get_start (disk->partition); - pv->part_size = grub_disk_get_size (disk); + pv->part_size = grub_disk_native_sectors (disk); #ifdef GRUB_UTIL { @@ -1083,7 +1283,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, grub_partition_t p; for (p = disk->partition; p; p = p->parent) s++; - pv->partmaps = xmalloc (s * sizeof (pv->partmaps[0])); + pv->partmaps = xcalloc (s, sizeof (pv->partmaps[0])); s = 0; for (p = disk->partition; p; p = p->parent) pv->partmaps[s++] = xstrdup (p->partmap->name); @@ -1096,14 +1296,7 @@ insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, /* Add the device to the array. */ for (lv = array->lvs; lv; lv = lv->next) if (!lv->became_readable_at && lv->fullname && is_lv_readable (lv, 0)) - { - lv->became_readable_at = ++inscnt; - if (is_lv_readable (lv, 1)) - { - scan_disk (lv->fullname, 1); - lv->scanned = 1; - } - } + lv->became_readable_at = ++inscnt; break; } @@ -1130,6 +1323,9 @@ free_array (void) grub_disk_close (pv->disk); if (pv->id.uuidlen) grub_free (pv->id.uuid); +#ifdef GRUB_UTIL + grub_free (pv->partmaps); +#endif grub_free (pv->internal_id); grub_free (pv); } @@ -1138,10 +1334,9 @@ free_array (void) { unsigned i; vg->lvs = lv->next; - if (lv->name != lv->fullname) - grub_free (lv->fullname); - if (lv->name != vg->name) - grub_free (lv->name); + grub_free (lv->fullname); + grub_free (lv->name); + grub_free (lv->idname); for (i = 0; i < lv->segment_count; i++) grub_free (lv->segments[i].nodes); grub_free (lv->segments); @@ -1172,7 +1367,7 @@ grub_diskfilter_get_pv_from_disk (grub_disk_t disk, if (pv->disk && pv->disk->id == disk->id && pv->disk->dev->id == disk->dev->id && pv->part_start == grub_partition_get_start (disk->partition) - && pv->part_size == grub_disk_get_size (disk)) + && pv->part_size == grub_disk_native_sectors (disk)) { if (vg_out) *vg_out = vg; @@ -1183,30 +1378,117 @@ grub_diskfilter_get_pv_from_disk (grub_disk_t disk, } #endif +static int +grub_diskfilter_check_pvs_encrypted (grub_disk_t disk, int *pvs_cnt) +{ + struct grub_diskfilter_lv *lv = disk->data; + struct grub_diskfilter_pv *pv; + + *pvs_cnt = 0; + + if (lv->vg->pvs) + for (pv = lv->vg->pvs; pv; pv = pv->next) + { + (*pvs_cnt)++; + + if (pv->disk == NULL) + { + /* Can be a partially activated VG, bail out. */ + return GRUB_ERR_TEST_FAILURE; + } + + if (pv->disk->dev->id != GRUB_DISK_DEVICE_CRYPTODISK_ID) + { + /* All backing devices must be cryptodisks, stop. */ + return GRUB_ERR_TEST_FAILURE; + } + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_cryptocheck (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_disk_t disk; + int check_pvs_res; + int namelen; + int pvs_cnt; + int opt_quiet = 0; + + if (argc == 2) + { + if (grub_strcmp (args[0], "--quiet") == 0) + { + opt_quiet = 1; + argc--; + args++; + } + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized option: %s"), args[0]); + } + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("disk name expected")); + + namelen = grub_strlen (args[0]); + if (namelen > 2 && (args[0][0] == '(') && (args[0][namelen - 1] == ')')) + args[0][namelen - 1] = 0; + else + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("invalid disk: %s"), + args[0]); + + if (!is_valid_diskfilter_name (&args[0][1])) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("unrecognized disk: %s"), + &args[0][1]); + + disk = grub_disk_open (&args[0][1]); + if (disk == NULL) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("no such disk: %s"), + &args[0][1]); + + check_pvs_res = grub_diskfilter_check_pvs_encrypted (disk, &pvs_cnt); + grub_disk_close (disk); + if (!opt_quiet) + grub_printf ("%s is %sencrypted (%d pv%s examined)\n", &args[0][1], + (check_pvs_res == GRUB_ERR_NONE) ? "" : "un", + pvs_cnt, + (pvs_cnt > 1) ? "s" : ""); + + return check_pvs_res; +} + static struct grub_disk_dev grub_diskfilter_dev = { .name = "diskfilter", .id = GRUB_DISK_DEVICE_DISKFILTER_ID, - .iterate = grub_diskfilter_iterate, - .open = grub_diskfilter_open, - .close = grub_diskfilter_close, - .read = grub_diskfilter_read, - .write = grub_diskfilter_write, + .disk_iterate = grub_diskfilter_iterate, + .disk_open = grub_diskfilter_open, + .disk_close = grub_diskfilter_close, + .disk_read = grub_diskfilter_read, + .disk_write = grub_diskfilter_write, #ifdef GRUB_UTIL - .memberlist = grub_diskfilter_memberlist, - .raidname = grub_diskfilter_getname, + .disk_memberlist = grub_diskfilter_memberlist, + .disk_raidname = grub_diskfilter_getname, #endif .next = 0 }; +static grub_command_t cmd; + GRUB_MOD_INIT(diskfilter) { grub_disk_dev_register (&grub_diskfilter_dev); + cmd = grub_register_command ("cryptocheck", grub_cmd_cryptocheck, + N_("[--quiet] DEVICE"), + N_("Check if a logical volume resides on encrypted disks.")); } GRUB_MOD_FINI(diskfilter) { grub_disk_dev_unregister (&grub_diskfilter_dev); + if (cmd != NULL) + grub_unregister_command (cmd); free_array (); } diff --git a/grub-core/disk/dmraid_nvidia.c b/grub-core/disk/dmraid_nvidia.c index 7b03e9036..6372663e6 100644 --- a/grub-core/disk/dmraid_nvidia.c +++ b/grub-core/disk/dmraid_nvidia.c @@ -88,7 +88,7 @@ struct grub_nv_super char prodrev[NV_PRODREV_LEN]; /* 0x2C - 0x2F Array product revision */ grub_uint32_t unit_flags; /* 0x30 - 0x33 Flags for this disk */ struct grub_nv_array array; /* Array information */ -} __attribute__ ((packed)); +} GRUB_PACKED; static struct grub_diskfilter_vg * grub_dmraid_nv_detect (grub_disk_t disk, @@ -98,15 +98,16 @@ grub_dmraid_nv_detect (grub_disk_t disk, grub_disk_addr_t sector; struct grub_nv_super sb; int level; - int layout; grub_uint64_t disk_size; + grub_uint32_t capacity; + grub_uint8_t total_volumes; char *uuid; if (disk->partition) /* Skip partition. */ return NULL; - sector = grub_disk_get_size (disk); + sector = grub_disk_native_sectors (disk); if (sector == GRUB_DISK_SIZE_UNKNOWN) /* Not raid. */ return NULL; @@ -121,15 +122,21 @@ grub_dmraid_nv_detect (grub_disk_t disk, if (sb.version != NV_VERSION) { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unknown version: %d.%d", sb.version); + "unknown version: %d.%d", sb.version >> 8, sb.version & 0xFF); return NULL; } + capacity = grub_le_to_cpu32 (sb.capacity); + total_volumes = sb.array.total_volumes; + switch (sb.array.raid_level) { case NV_LEVEL_0: level = 0; - disk_size = sb.capacity / sb.array.total_volumes; + if (total_volumes == 0) + /* Not RAID. */ + return NULL; + disk_size = capacity / total_volumes; break; case NV_LEVEL_1: @@ -139,8 +146,10 @@ grub_dmraid_nv_detect (grub_disk_t disk, case NV_LEVEL_5: level = 5; - layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC; - disk_size = sb.capacity / (sb.array.total_volumes - 1); + if (total_volumes == 0 || total_volumes == 1) + /* Not RAID. */ + return NULL; + disk_size = capacity / (total_volumes - 1); break; default: @@ -163,8 +172,9 @@ grub_dmraid_nv_detect (grub_disk_t disk, return grub_diskfilter_make_raid (sizeof (sb.array.signature), uuid, sb.array.total_volumes, - NULL, disk_size, - sb.array.stripe_block_size, layout, + "nv", disk_size, + sb.array.stripe_block_size, + GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC, level); } diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index d9d788c41..3b5ed5691 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -37,53 +37,12 @@ struct grub_efidisk_data }; /* GUID. */ -static grub_efi_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID; +static grub_guid_t block_io_guid = GRUB_EFI_BLOCK_IO_GUID; static struct grub_efidisk_data *fd_devices; static struct grub_efidisk_data *hd_devices; static struct grub_efidisk_data *cd_devices; -/* Duplicate a device path. */ -static grub_efi_device_path_t * -duplicate_device_path (const grub_efi_device_path_t *dp) -{ - grub_efi_device_path_t *p; - grub_size_t total_size = 0; - - for (p = (grub_efi_device_path_t *) dp; - ; - p = GRUB_EFI_NEXT_DEVICE_PATH (p)) - { - total_size += GRUB_EFI_DEVICE_PATH_LENGTH (p); - if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p)) - break; - } - - p = grub_malloc (total_size); - if (! p) - return 0; - - grub_memcpy (p, dp, total_size); - return p; -} - -/* Return the device path node right before the end node. */ -static grub_efi_device_path_t * -find_last_device_path (const grub_efi_device_path_t *dp) -{ - grub_efi_device_path_t *next, *p; - - if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) - return 0; - - for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p); - ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next); - p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next)) - ; - - return p; -} - static struct grub_efidisk_data * make_devices (void) { @@ -110,7 +69,7 @@ make_devices (void) if (! dp) continue; - ldp = find_last_device_path (dp); + ldp = grub_efi_find_last_device_path (dp); if (! ldp) /* This is empty. Why? */ continue; @@ -121,11 +80,26 @@ make_devices (void) /* This should not happen... Why? */ continue; + /* iPXE adds stub Block IO protocol to loaded image device handle. It is + completely non-functional and simply returns an error for every method. + So attempt to detect and skip it. Magic number is literal "iPXE" and + check block size as well */ + /* FIXME: shoud we close it? We do not do it elsewhere */ + if (bio->media && bio->media->media_id == 0x69505845U && + bio->media->block_size == 1) + continue; + d = grub_malloc (sizeof (*d)); if (! d) { /* Uggh. */ grub_free (handles); + while (devices) + { + d = devices->next; + grub_free (devices); + devices = d; + } return 0; } @@ -150,15 +124,17 @@ find_parent_device (struct grub_efidisk_data *devices, grub_efi_device_path_t *dp, *ldp; struct grub_efidisk_data *parent; - dp = duplicate_device_path (d->device_path); + dp = grub_efi_duplicate_device_path (d->device_path); if (! dp) return 0; - ldp = find_last_device_path (dp); + ldp = grub_efi_find_last_device_path (dp); + if (! ldp) + return 0; + ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; - ldp->length[0] = sizeof (*ldp); - ldp->length[1] = 0; + ldp->length = sizeof (*ldp); for (parent = devices; parent; parent = parent->next) { @@ -175,39 +151,31 @@ find_parent_device (struct grub_efidisk_data *devices, } static int -iterate_child_devices (struct grub_efidisk_data *devices, - struct grub_efidisk_data *d, - int (*hook) (struct grub_efidisk_data *child)) +is_child (struct grub_efidisk_data *child, + struct grub_efidisk_data *parent) { - struct grub_efidisk_data *p; + grub_efi_device_path_t *dp, *ldp; + int ret; - for (p = devices; p; p = p->next) - { - grub_efi_device_path_t *dp, *ldp; + dp = grub_efi_duplicate_device_path (child->device_path); + if (! dp) + return 0; - dp = duplicate_device_path (p->device_path); - if (! dp) - return 0; + ldp = grub_efi_find_last_device_path (dp); + if (! ldp) + return 0; - ldp = find_last_device_path (dp); - ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; - ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; - ldp->length[0] = sizeof (*ldp); - ldp->length[1] = 0; + ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; + ldp->length = sizeof (*ldp); - if (grub_efi_compare_device_paths (dp, d->device_path) == 0) - if (hook (p)) - { - grub_free (dp); - return 1; - } - - grub_free (dp); - } - - return 0; + ret = (grub_efi_compare_device_paths (dp, parent->device_path) == 0); + grub_free (dp); + return ret; } +#define FOR_CHILDREN(p, dev) for (p = dev; p; p = p->next) if (is_child (p, d)) + /* Add a device into a list of devices in an ascending order. */ static void add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d) @@ -219,8 +187,8 @@ add_device (struct grub_efidisk_data **devices, struct grub_efidisk_data *d) { int ret; - ret = grub_efi_compare_device_paths (find_last_device_path ((*p)->device_path), - find_last_device_path (d->device_path)); + ret = grub_efi_compare_device_paths (grub_efi_find_last_device_path ((*p)->device_path), + grub_efi_find_last_device_path (d->device_path)); if (ret == 0) ret = grub_efi_compare_device_paths ((*p)->device_path, d->device_path); @@ -262,7 +230,7 @@ name_devices (struct grub_efidisk_data *devices) { case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE: is_hard_drive = 1; - /* Fall through by intention. */ + /* Intentionally fall through. */ case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE: { struct grub_efidisk_data *parent, *parent2; @@ -339,18 +307,43 @@ name_devices (struct grub_efidisk_data *devices) { grub_efi_device_path_t *dp; grub_efi_block_io_media_t *m; + int is_floppy = 0; dp = d->last_device_path; if (! dp) continue; - m = d->block_io->media; - if (m->logical_partition) + /* Ghosts proudly presented by Apple. */ + if (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) + == GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE) + { + grub_efi_vendor_device_path_t *vendor = (grub_efi_vendor_device_path_t *) dp; + static const grub_guid_t apple = GRUB_EFI_VENDOR_APPLE_GUID; + + if (vendor->header.length == sizeof (*vendor) + && grub_memcmp (&vendor->vendor_guid, &apple, + sizeof (vendor->vendor_guid)) == 0 + && find_parent_device (devices, d)) + continue; + } + + m = d->block_io->media; + if (GRUB_EFI_DEVICE_PATH_TYPE (dp) == GRUB_EFI_ACPI_DEVICE_PATH_TYPE + && GRUB_EFI_DEVICE_PATH_SUBTYPE (dp) + == GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE) + { + grub_efi_acpi_device_path_t *acpi + = (grub_efi_acpi_device_path_t *) dp; + /* Floppy EISA ID. */ + if (acpi->hid == 0x60441d0 || acpi->hid == 0x70041d0 + || acpi->hid == 0x70141d1) + is_floppy = 1; + } + if (is_floppy) { - /* Only one partition in a non-media device. Assume that this - is a floppy drive. */ #ifdef DEBUG_NAMES - grub_printf ("adding a floppy by guessing: "); + grub_printf ("adding a floppy: "); grub_efi_print_device_path (d->device_path); #endif add_device (&fd_devices, d); @@ -404,7 +397,7 @@ enumerate_disks (void) } static int -grub_efidisk_iterate (int (*hook) (const char *name), +grub_efidisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { struct grub_efidisk_data *d; @@ -418,7 +411,7 @@ grub_efidisk_iterate (int (*hook) (const char *name), { grub_snprintf (buf, sizeof (buf), "hd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); - if (hook (buf)) + if (hook (buf, hook_data)) return 1; } break; @@ -427,7 +420,7 @@ grub_efidisk_iterate (int (*hook) (const char *name), { grub_snprintf (buf, sizeof (buf), "fd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); - if (hook (buf)) + if (hook (buf, hook_data)) return 1; } @@ -435,7 +428,7 @@ grub_efidisk_iterate (int (*hook) (const char *name), { grub_snprintf (buf, sizeof (buf), "cd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); - if (hook (buf)) + if (hook (buf, hook_data)) return 1; } break; @@ -511,19 +504,26 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) if (! d) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device"); - disk->id = ((num << 8) | name[0]); + disk->id = ((num << GRUB_CHAR_BIT) | name[0]); m = d->block_io->media; /* FIXME: Probably it is better to store the block size in the disk, and total sectors should be replaced with total blocks. */ - grub_dprintf ("efidisk", "m = %p, last block = %llx, block size = %x\n", - m, (unsigned long long) m->last_block, m->block_size); + grub_dprintf ("efidisk", + "m = %p, last block = %llx, block size = %x, io align = %x\n", + m, (unsigned long long) m->last_block, m->block_size, + m->io_align); + + /* Ensure required buffer alignment is a power of two (or is zero). */ + if (m->io_align & (m->io_align - 1)) + return grub_error (GRUB_ERR_IO, "invalid buffer alignment %d", m->io_align); + disk->total_sectors = m->last_block + 1; + /* Don't increase this value due to bug in some EFI. */ + disk->max_agglomerate = 0xa0000 >> (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS); if (m->block_size & (m->block_size - 1) || !m->block_size) return grub_error (GRUB_ERR_IO, "invalid sector size %d", m->block_size); - for (disk->log_sector_size = 0; - (1U << disk->log_sector_size) < m->block_size; - disk->log_sector_size++); + disk->log_sector_size = grub_log2ull (m->block_size); disk->data = d; grub_dprintf ("efidisk", "opening %s succeeded\n", name); @@ -538,27 +538,77 @@ grub_efidisk_close (struct grub_disk *disk __attribute__ ((unused))) grub_dprintf ("efidisk", "closing %s\n", disk->name); } +static grub_efi_status_t +grub_efidisk_readwrite (struct grub_disk *disk, grub_disk_addr_t sector, + grub_size_t size, char *buf, int wr) +{ + struct grub_efidisk_data *d; + grub_efi_block_io_t *bio; + grub_efi_status_t status; + grub_size_t io_align, num_bytes; + char *aligned_buf; + + d = disk->data; + bio = d->block_io; + + /* + * If IoAlign is > 1, it should represent the required alignment. However, + * some UEFI implementations seem to report IoAlign=2 but require 2^IoAlign. + * Some implementation seem to require alignment despite not reporting any + * specific requirements. + * + * Make sure to use buffers which are at least aligned to block size. + */ + if (bio->media->io_align < bio->media->block_size) + io_align = bio->media->block_size; + else + io_align = bio->media->io_align; + + num_bytes = size << disk->log_sector_size; + + if ((grub_addr_t) buf & (io_align - 1)) + { + aligned_buf = grub_memalign (io_align, num_bytes); + if (! aligned_buf) + return GRUB_EFI_OUT_OF_RESOURCES; + if (wr) + grub_memcpy (aligned_buf, buf, num_bytes); + } + else + { + aligned_buf = buf; + } + + status = (wr ? bio->write_blocks : bio->read_blocks) (bio, bio->media->media_id, + (grub_efi_uint64_t) sector, + (grub_efi_uintn_t) num_bytes, + aligned_buf); + + if ((grub_addr_t) buf & (io_align - 1)) + { + if (!wr) + grub_memcpy (buf, aligned_buf, num_bytes); + grub_free (aligned_buf); + } + + return status; +} + static grub_err_t grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector, grub_size_t size, char *buf) { - /* For now, use the disk io interface rather than the block io's. */ - struct grub_efidisk_data *d; - grub_efi_block_io_t *bio; grub_efi_status_t status; - d = disk->data; - bio = d->block_io; - grub_dprintf ("efidisk", "reading 0x%lx sectors at the sector 0x%llx from %s\n", (unsigned long) size, (unsigned long long) sector, disk->name); - status = efi_call_5 (bio->read_blocks, bio, bio->media->media_id, - (grub_efi_uint64_t) sector, - (grub_efi_uintn_t) size << disk->log_sector_size, - buf); - if (status != GRUB_EFI_SUCCESS) + status = grub_efidisk_readwrite (disk, sector, size, buf, 0); + + if (status == GRUB_EFI_NO_MEDIA) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("no media in `%s'"), disk->name); + else if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx from `%s'"), (unsigned long long) sector, @@ -571,23 +621,17 @@ static grub_err_t grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector, grub_size_t size, const char *buf) { - /* For now, use the disk io interface rather than the block io's. */ - struct grub_efidisk_data *d; - grub_efi_block_io_t *bio; grub_efi_status_t status; - d = disk->data; - bio = d->block_io; - grub_dprintf ("efidisk", "writing 0x%lx sectors at the sector 0x%llx to %s\n", (unsigned long) size, (unsigned long long) sector, disk->name); - status = efi_call_5 (bio->write_blocks, bio, bio->media->media_id, - (grub_efi_uint64_t) sector, - (grub_efi_uintn_t) size << disk->log_sector_size, - (void *) buf); - if (status != GRUB_EFI_SUCCESS) + status = grub_efidisk_readwrite (disk, sector, size, (char *) buf, 1); + + if (status == GRUB_EFI_NO_MEDIA) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("no media in `%s'"), disk->name); + else if (status != GRUB_EFI_SUCCESS) return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx to `%s'"), (unsigned long long) sector, disk->name); @@ -599,30 +643,35 @@ static struct grub_disk_dev grub_efidisk_dev = { .name = "efidisk", .id = GRUB_DISK_DEVICE_EFIDISK_ID, - .iterate = grub_efidisk_iterate, - .open = grub_efidisk_open, - .close = grub_efidisk_close, - .read = grub_efidisk_read, - .write = grub_efidisk_write, + .disk_iterate = grub_efidisk_iterate, + .disk_open = grub_efidisk_open, + .disk_close = grub_efidisk_close, + .disk_read = grub_efidisk_read, + .disk_write = grub_efidisk_write, .next = 0 }; -void -grub_efidisk_init (void) -{ - enumerate_disks (); - grub_disk_dev_register (&grub_efidisk_dev); -} - void grub_efidisk_fini (void) { free_devices (fd_devices); free_devices (hd_devices); free_devices (cd_devices); + fd_devices = 0; + hd_devices = 0; + cd_devices = 0; grub_disk_dev_unregister (&grub_efidisk_dev); } +void +grub_efidisk_init (void) +{ + grub_disk_firmware_fini = grub_efidisk_fini; + + enumerate_disks (); + grub_disk_dev_register (&grub_efidisk_dev); +} + /* Some utility functions to map GRUB devices with EFI devices. */ grub_efi_handle_t grub_efidisk_get_device_handle (grub_disk_t disk) @@ -655,32 +704,31 @@ grub_efidisk_get_device_handle (grub_disk_t disk) { struct grub_efidisk_data *devices; grub_efi_handle_t handle = 0; - auto int find_partition (struct grub_efidisk_data *c); + struct grub_efidisk_data *c; - int find_partition (struct grub_efidisk_data *c) + devices = make_devices (); + FOR_CHILDREN (c, devices) { - grub_efi_hard_drive_device_path_t hd; + grub_efi_hard_drive_device_path_t *hd; - grub_memcpy (&hd, c->last_device_path, sizeof (hd)); + hd = (grub_efi_hard_drive_device_path_t *) c->last_device_path; if ((GRUB_EFI_DEVICE_PATH_TYPE (c->last_device_path) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE) && (GRUB_EFI_DEVICE_PATH_SUBTYPE (c->last_device_path) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE) && (grub_partition_get_start (disk->partition) - == hd.partition_start) + == (hd->partition_start << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS))) && (grub_partition_get_len (disk->partition) - == hd.partition_size)) + == (hd->partition_size << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)))) { handle = c->handle; - return 1; + break; } - - return 0; } - devices = make_devices (); - iterate_child_devices (devices, d, find_partition); free_devices (devices); if (handle != 0) @@ -736,6 +784,35 @@ get_diskname_from_path (const grub_efi_device_path_t *path, return 0; } +/* Context for grub_efidisk_get_device_name. */ +struct grub_efidisk_get_device_name_ctx +{ + char *partition_name; + grub_efi_hard_drive_device_path_t *hd; +}; + +/* Helper for grub_efidisk_get_device_name. + Find the identical partition. */ +static int +grub_efidisk_get_device_name_iter (grub_disk_t disk, + const grub_partition_t part, void *data) +{ + struct grub_efidisk_get_device_name_ctx *ctx = data; + + if (grub_partition_get_start (part) + == (ctx->hd->partition_start << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) + && grub_partition_get_len (part) + == (ctx->hd->partition_size << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS))) + { + ctx->partition_name = grub_partition_get_name (part); + return 1; + } + + return 0; +} + char * grub_efidisk_get_device_name (grub_efi_handle_t *handle) { @@ -746,50 +823,48 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) if (! dp) return 0; - ldp = find_last_device_path (dp); + ldp = grub_efi_find_last_device_path (dp); if (! ldp) return 0; if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE - && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) - == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)) + && (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE + || GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)) { - char *partition_name = NULL; + struct grub_efidisk_get_device_name_ctx ctx; char *dev_name; - grub_efi_device_path_t *dup_dp, *dup_ldp; - grub_efi_hard_drive_device_path_t hd; + grub_efi_device_path_t *dup_dp; grub_disk_t parent = 0; - auto int find_partition (grub_disk_t disk, const grub_partition_t part); - - /* Find the identical partition. */ - int find_partition (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t part) - { - if (grub_partition_get_start (part) == hd.partition_start - && grub_partition_get_len (part) == hd.partition_size) - { - partition_name = grub_partition_get_name (part); - return 1; - } - - return 0; - } - /* It is necessary to duplicate the device path so that GRUB can overwrite it. */ - dup_dp = duplicate_device_path (dp); + dup_dp = grub_efi_duplicate_device_path (dp); if (! dup_dp) return 0; - dup_ldp = find_last_device_path (dup_dp); - dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; - dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; - dup_ldp->length[0] = sizeof (*dup_ldp); - dup_ldp->length[1] = 0; + while (1) + { + grub_efi_device_path_t *dup_ldp; + dup_ldp = grub_efi_find_last_device_path (dup_dp); + if (! dup_ldp) + break; + + if (!(GRUB_EFI_DEVICE_PATH_TYPE (dup_ldp) == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE + && (GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE + || GRUB_EFI_DEVICE_PATH_SUBTYPE (dup_ldp) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE))) + break; + + dup_ldp->type = GRUB_EFI_END_DEVICE_PATH_TYPE; + dup_ldp->subtype = GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; + dup_ldp->length = sizeof (*dup_ldp); + } if (!get_diskname_from_path (dup_dp, device_name)) - return 0; + { + grub_free (dup_dp); + return 0; + } + parent = grub_disk_open (device_name); grub_free (dup_dp); @@ -797,34 +872,41 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) return 0; /* Find a partition which matches the hard drive device path. */ - grub_memcpy (&hd, ldp, sizeof (hd)); - if (hd.partition_start == 0 - && hd.partition_size == grub_disk_get_size (parent)) + ctx.partition_name = NULL; + ctx.hd = (grub_efi_hard_drive_device_path_t *) ldp; + if (ctx.hd->partition_start == 0 + && (ctx.hd->partition_size << (parent->log_sector_size + - GRUB_DISK_SECTOR_BITS)) + == grub_disk_native_sectors (parent)) { dev_name = grub_strdup (parent->name); } else { - grub_partition_iterate (parent, find_partition); + grub_partition_iterate (parent, grub_efidisk_get_device_name_iter, + &ctx); - if (! partition_name) + if (! ctx.partition_name) { + /* No partition found. In most cases partition is embed in + the root path anyway, so this is not critical. + This happens only if partition is on partmap that GRUB + doesn't need to access root. + */ grub_disk_close (parent); - return 0; + return grub_strdup (device_name); } - dev_name = grub_xasprintf ("%s,%s", parent->name, partition_name); - grub_free (partition_name); + dev_name = grub_xasprintf ("%s,%s", parent->name, + ctx.partition_name); + grub_free (ctx.partition_name); } grub_disk_close (parent); return dev_name; } - else - { - /* This should be an entire disk. */ - if (!get_diskname_from_path (dp, device_name)) - return 0; - return grub_strdup (device_name); - } + /* This may be guessed device - floppy, cdrom or entire disk. */ + if (!get_diskname_from_path (dp, device_name)) + return 0; + return grub_strdup (device_name); } diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index f9315df0d..722910d64 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -95,7 +95,7 @@ struct grub_geli_key grub_uint8_t iv_key[64]; grub_uint8_t cipher_key[64]; grub_uint8_t hmac[64]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_geli_phdr { @@ -111,7 +111,7 @@ struct grub_geli_phdr grub_uint32_t niter; grub_uint8_t salt[64]; struct grub_geli_key keys[2]; -} __attribute__ ((packed)); +} GRUB_PACKED; enum { @@ -135,8 +135,6 @@ const char *algorithms[] = { [0x16] = "aes" }; -#define MAX_PASSPHRASE 256 - static gcry_err_code_t geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno) { @@ -144,42 +142,35 @@ geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno) const struct { char magic[4]; grub_uint64_t zone; - } __attribute__ ((packed)) tohash + } GRUB_PACKED tohash = { {'e', 'k', 'e', 'y'}, grub_cpu_to_le64 (zoneno) }; - grub_uint64_t key[(dev->hash->mdlen + 7) / 8]; + GRUB_PROPERLY_ALIGNED_ARRAY (key, GRUB_CRYPTO_MAX_MDLEN); + + if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return GPG_ERR_INV_ARG; grub_dprintf ("geli", "rekeying %" PRIuGRUB_UINT64_T " keysize=%d\n", zoneno, dev->rekey_derived_size); gcry_err = grub_crypto_hmac_buffer (dev->hash, dev->rekey_key, 64, &tohash, sizeof (tohash), key); if (gcry_err) - return grub_crypto_gcry_error (gcry_err); + return gcry_err; return grub_cryptodisk_setkey (dev, (grub_uint8_t *) key, - dev->rekey_derived_size); -} - -static inline int -ascii2hex (char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return 0; + dev->rekey_derived_size); } static inline gcry_err_code_t make_uuid (const struct grub_geli_phdr *header, char *uuid) { - grub_uint8_t uuidbin[GRUB_MD_SHA256->mdlen]; + grub_uint8_t uuidbin[GRUB_CRYPTODISK_MAX_UUID_LENGTH]; gcry_err_code_t err; grub_uint8_t *iptr; char *optr; + if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH) + return GPG_ERR_TOO_LARGE; err = grub_crypto_hmac_buffer (GRUB_MD_SHA256, header->salt, sizeof (header->salt), "uuid", sizeof ("uuid") - 1, uuidbin); @@ -187,7 +178,7 @@ make_uuid (const struct grub_geli_phdr *header, return err; optr = uuid; - for (iptr = uuidbin; iptr < &uuidbin[ARRAY_SIZE (uuidbin)]; iptr++) + for (iptr = uuidbin; iptr < &uuidbin[GRUB_MD_SHA256->mdlen]; iptr++) { grub_snprintf (optr, 3, "%02x", *iptr); optr += 2; @@ -198,57 +189,58 @@ make_uuid (const struct grub_geli_phdr *header, #ifdef GRUB_UTIL -#include -#include -#include -#include #include -#include -#include #include char * grub_util_get_geli_uuid (const char *dev) { - int fd = open (dev, O_RDONLY); + grub_util_fd_t fd; grub_uint64_t s; unsigned log_secsize; grub_uint8_t hdr[512]; struct grub_geli_phdr *header; - char *uuid; + char *uuid; gcry_err_code_t err; - if (fd < 0) + fd = grub_util_fd_open (dev, GRUB_UTIL_FD_O_RDONLY); + + if (!GRUB_UTIL_FD_IS_VALID (fd)) return NULL; s = grub_util_get_fd_size (fd, dev, &log_secsize); s >>= log_secsize; - grub_util_fd_seek (fd, dev, (s << log_secsize) - 512); + if (grub_util_fd_seek (fd, (s << log_secsize) - 512) < 0) + grub_util_error ("%s", _("couldn't read ELI metadata")); uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1); if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0) grub_util_error ("%s", _("couldn't read ELI metadata")); - + + grub_util_fd_close (fd); + COMPILE_TIME_ASSERT (sizeof (header) <= 512); header = (void *) &hdr; /* Look for GELI magic sequence. */ if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC)) - || grub_le_to_cpu32 (header->version) > 5 + || grub_le_to_cpu32 (header->version) > 7 || grub_le_to_cpu32 (header->version) < 1) grub_util_error ("%s", _("wrong ELI magic or version")); err = make_uuid ((void *) &hdr, uuid); if (err) - return NULL; + { + grub_free (uuid); + return NULL; + } return uuid; } #endif static grub_cryptodisk_t -configure_ciphers (grub_disk_t disk, const char *check_uuid, - int boot_only) +geli_scan (grub_disk_t disk, grub_cryptomount_args_t cargs) { grub_cryptodisk_t newdev; struct grub_geli_phdr header; @@ -256,11 +248,18 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, const struct gcry_cipher_spec *ciph; const char *ciphername = NULL; gcry_err_code_t gcry_err; - char uuid[GRUB_MD_SHA256->mdlen * 2 + 1]; + char uuid[GRUB_CRYPTODISK_MAX_UUID_LENGTH]; grub_disk_addr_t sector; grub_err_t err; - sector = grub_disk_get_size (disk); + /* Detached headers are not implemented yet */ + if (cargs->hdr_file != NULL) + return NULL; + + if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH) + return NULL; + + sector = grub_disk_native_sectors (disk); if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0) return NULL; @@ -271,7 +270,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, /* Look for GELI magic sequence. */ if (grub_memcmp (header.magic, GELI_MAGIC, sizeof (GELI_MAGIC)) - || grub_le_to_cpu32 (header.version) > 5 + || grub_le_to_cpu32 (header.version) > 7 || grub_le_to_cpu32 (header.version) < 1) { grub_dprintf ("geli", "wrong magic %02x\n", header.magic[0]); @@ -293,11 +292,11 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, return NULL; } - if (boot_only && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT)) + if (cargs->check_boot && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT)) { grub_dprintf ("geli", "not a boot volume\n"); return NULL; - } + } gcry_err = make_uuid (&header, uuid); if (gcry_err) @@ -306,9 +305,9 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, return NULL; } - if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0) + if (cargs->search_uuid != NULL && grub_uuidcasecmp (cargs->search_uuid, uuid, sizeof (uuid)) != 0) { - grub_dprintf ("geli", "%s != %s\n", uuid, check_uuid); + grub_dprintf ("geli", "%s != %s\n", uuid, cargs->search_uuid); return NULL; } @@ -338,22 +337,32 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, { secondary_cipher = grub_crypto_cipher_open (ciph); if (!secondary_cipher) - return NULL; + { + grub_crypto_cipher_close (cipher); + return NULL; + } + } if (grub_le_to_cpu16 (header.keylen) > 1024) { grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d", grub_le_to_cpu16 (header.keylen)); + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (secondary_cipher); return NULL; } newdev = grub_zalloc (sizeof (struct grub_cryptodisk)); if (!newdev) - return NULL; + { + grub_crypto_cipher_close (cipher); + grub_crypto_cipher_close (secondary_cipher); + return NULL; + } newdev->cipher = cipher; newdev->secondary_cipher = secondary_cipher; - newdev->offset = 0; + newdev->offset_sectors = 0; newdev->source_disk = NULL; newdev->benbi_log = 0; if (grub_le_to_cpu16 (header.alg) == 0x16) @@ -371,9 +380,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, newdev->hash = GRUB_MD_SHA512; newdev->iv_hash = GRUB_MD_SHA256; - for (newdev->log_sector_size = 0; - (1U << newdev->log_sector_size) < grub_le_to_cpu32 (header.sector_size); - newdev->log_sector_size++); + newdev->log_sector_size = grub_log2ull (grub_le_to_cpu32 (header.sector_size)); if (grub_le_to_cpu32 (header.version) >= 5) { @@ -381,33 +388,39 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, newdev->rekey_shift = 20; } -#ifdef GRUB_UTIL newdev->modname = "geli"; -#endif - newdev->total_length = grub_disk_get_size (disk) - 1; + newdev->total_sectors = grub_disk_native_sectors (disk) - 1; grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= 32 * 2 + 1); return newdev; } static grub_err_t -recover_key (grub_disk_t source, grub_cryptodisk_t dev) +geli_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs) { grub_size_t keysize; - grub_uint8_t digest[dev->hash->mdlen]; - grub_uint8_t geomkey[dev->hash->mdlen]; - grub_uint8_t verify_key[dev->hash->mdlen]; - grub_uint8_t zero[dev->cipher->cipher->blocksize]; - char passphrase[MAX_PASSPHRASE] = ""; + grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t geomkey[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t verify_key[GRUB_CRYPTO_MAX_MDLEN]; + grub_uint8_t zero[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; + grub_uint8_t geli_cipher_key[64]; unsigned i; gcry_err_code_t gcry_err; struct grub_geli_phdr header; - char *tmp; grub_disk_addr_t sector; grub_err_t err; - sector = grub_disk_get_size (source); + if (cargs->key_data == NULL || cargs->key_len == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data"); + + if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) + return grub_error (GRUB_ERR_BUG, "cipher block is too long"); + + if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return grub_error (GRUB_ERR_BUG, "mdlen is too long"); + + sector = grub_disk_native_sectors (source); if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0) return grub_error (GRUB_ERR_BUG, "not a geli"); @@ -416,28 +429,17 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) if (err) return err; - keysize = grub_le_to_cpu16 (header.keylen) / 8; + keysize = grub_le_to_cpu16 (header.keylen) / GRUB_CHAR_BIT; grub_memset (zero, 0, sizeof (zero)); grub_puts_ (N_("Attempting to decrypt master key...")); - /* Get the passphrase from the user. */ - tmp = NULL; - if (source->partition) - tmp = grub_partition_get_name (source->partition); - grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, - source->partition ? "," : "", tmp ? : "", - dev->uuid); - grub_free (tmp); - if (!grub_password_get (passphrase, MAX_PASSPHRASE)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); - /* Calculate the PBKDF2 of the user supplied passphrase. */ if (grub_le_to_cpu32 (header.niter) != 0) { grub_uint8_t pbkdf_key[64]; - gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase, - grub_strlen (passphrase), + gcry_err = grub_crypto_pbkdf2 (dev->hash, cargs->key_data, + cargs->key_len, header.salt, sizeof (header.salt), grub_le_to_cpu32 (header.niter), @@ -460,7 +462,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY); grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt)); - grub_crypto_hmac_write (hnd, passphrase, grub_strlen (passphrase)); + grub_crypto_hmac_write (hnd, cargs->key_data, cargs->key_len); gcry_err = grub_crypto_hmac_fini (hnd, geomkey); if (gcry_err) @@ -468,12 +470,12 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) } gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey, - sizeof (geomkey), "\1", 1, digest); + dev->hash->mdlen, "\1", 1, digest); if (gcry_err) return grub_crypto_gcry_error (gcry_err); gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey, - sizeof (geomkey), "\0", 1, verify_key); + dev->hash->mdlen, "\0", 1, verify_key); if (gcry_err) return grub_crypto_gcry_error (gcry_err); @@ -483,7 +485,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) for (i = 0; i < ARRAY_SIZE (header.keys); i++) { struct grub_geli_key candidate_key; - grub_uint8_t key_hmac[dev->hash->mdlen]; + grub_uint8_t key_hmac[GRUB_CRYPTO_MAX_MDLEN]; /* Check if keyslot is enabled. */ if (! (header.keys_used & (1 << i))) @@ -504,7 +506,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) return grub_crypto_gcry_error (gcry_err); gcry_err = grub_crypto_hmac_buffer (dev->hash, verify_key, - sizeof (verify_key), + dev->hash->mdlen, &candidate_key, (sizeof (candidate_key) - sizeof (candidate_key.hmac)), @@ -516,6 +518,19 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) continue; grub_printf_ (N_("Slot %d opened\n"), i); + if (grub_le_to_cpu32 (header.version) >= 7) + { + /* GELI >=7 uses the cipher_key */ + grub_memcpy (geli_cipher_key, candidate_key.cipher_key, + sizeof (candidate_key.cipher_key)); + } + else + { + /* GELI <=6 uses the iv_key */ + grub_memcpy (geli_cipher_key, candidate_key.iv_key, + sizeof (candidate_key.iv_key)); + } + /* Set the master key. */ if (!dev->rekey) { @@ -523,7 +538,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) if (grub_le_to_cpu16 (header.alg) == 0x16) real_keysize *= 2; gcry_err = grub_cryptodisk_setkey (dev, candidate_key.cipher_key, - real_keysize); + real_keysize); if (gcry_err) return grub_crypto_gcry_error (gcry_err); } @@ -532,13 +547,13 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) grub_size_t real_keysize = keysize; if (grub_le_to_cpu16 (header.alg) == 0x16) real_keysize *= 2; - /* For a reason I don't know, the IV key is used in rekeying. */ - grub_memcpy (dev->rekey_key, candidate_key.iv_key, - sizeof (candidate_key.iv_key)); + + grub_memcpy (dev->rekey_key, geli_cipher_key, + sizeof (geli_cipher_key)); dev->rekey_derived_size = real_keysize; dev->last_rekey = -1; COMPILE_TIME_ASSERT (sizeof (dev->rekey_key) - >= sizeof (candidate_key.iv_key)); + >= sizeof (geli_cipher_key)); } dev->iv_prefix_len = sizeof (candidate_key.iv_key); @@ -554,8 +569,8 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) } struct grub_cryptodisk_dev geli_crypto = { - .scan = configure_ciphers, - .recover_key = recover_key + .scan = geli_scan, + .recover_key = geli_recover_key }; GRUB_MOD_INIT (geli) diff --git a/grub-core/disk/host.c b/grub-core/disk/host.c index 5ee0d2e56..f34529f86 100644 --- a/grub-core/disk/host.c +++ b/grub-core/disk/host.c @@ -20,20 +20,24 @@ /* When using the disk, make a reference to this module. Otherwise the user will end up with a useless module :-). */ +#include +#include + #include #include #include +#include int grub_disk_host_i_want_a_reference; static int -grub_host_iterate (int (*hook) (const char *name), +grub_host_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { if (pull != GRUB_DISK_PULL_NONE) return 0; - if (hook ("host")) + if (hook ("host", hook_data)) return 1; return 0; } @@ -45,7 +49,7 @@ grub_host_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a host disk"); disk->total_sectors = 0; - disk->id = (unsigned long) "host"; + disk->id = 0; disk->data = 0; @@ -80,11 +84,11 @@ static struct grub_disk_dev grub_host_dev = /* The only important line in this file :-) */ .name = "host", .id = GRUB_DISK_DEVICE_HOST_ID, - .iterate = grub_host_iterate, - .open = grub_host_open, - .close = grub_host_close, - .read = grub_host_read, - .write = grub_host_write, + .disk_iterate = grub_host_iterate, + .disk_open = grub_host_open, + .disk_close = grub_host_close, + .disk_read = grub_host_read, + .disk_write = grub_host_write, .next = 0 }; diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 7ca89e3f7..1d6788950 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -71,7 +71,7 @@ static int grub_biosdisk_get_num_floppies (void) * non-zero, otherwise zero. */ -static int +static int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap) { struct grub_bios_int_registers regs; @@ -91,7 +91,7 @@ grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap) * NSEC sectors from COFF/HOFF/SOFF into SEGMENT. If an error occurs, * return non-zero, otherwise zero. */ -static int +static int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff, int soff, int nsec, int segment) { @@ -110,7 +110,7 @@ grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff, /* set bits 0-5 of %cl to sector */ regs.ecx |= soff & 0x3f; - /* set %dh to head and %dl to drive */ + /* set %dh to head and %dl to drive */ regs.edx = (drive & 0xff) | ((hoff << 8) & 0xff00); /* set %ah to AH */ regs.eax = (ah << 8) & 0xff00; @@ -153,7 +153,7 @@ grub_biosdisk_check_int13_extensions (int drive) regs.ebx = 0x55aa; regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x13, ®s); - + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) return 0; @@ -171,7 +171,7 @@ grub_biosdisk_check_int13_extensions (int drive) * Return the geometry of DRIVE in CYLINDERS, HEADS and SECTORS. If an * error occurs, then return non-zero, otherwise zero. */ -static int +static int grub_biosdisk_get_diskinfo_standard (int drive, unsigned long *cylinders, unsigned long *heads, @@ -185,12 +185,12 @@ grub_biosdisk_get_diskinfo_standard (int drive, regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x13, ®s); - /* Check if unsuccessful. Ignore return value if carry isn't set to + /* Check if unsuccessful. Ignore return value if carry isn't set to workaround some buggy BIOSes. */ if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) && ((regs.eax & 0xff00) != 0)) return (regs.eax & 0xff00) >> 8; - /* bogus BIOSes may not return an error number */ + /* bogus BIOSes may not return an error number */ /* 0 sectors means no disk */ if (!(regs.ecx & 0x3f)) /* XXX 0x60 is one of the unused error numbers */ @@ -218,7 +218,7 @@ grub_biosdisk_get_diskinfo_real (int drive, void *drp, grub_uint16_t ax) regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x13, ®s); - /* Check if unsuccessful. Ignore return value if carry isn't set to + /* Check if unsuccessful. Ignore return value if carry isn't set to workaround some buggy BIOSes. */ if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) && ((regs.eax & 0xff00) != 0)) return (regs.eax & 0xff00) >> 8; @@ -272,21 +272,22 @@ grub_biosdisk_get_drive (const char *name) } static int -grub_biosdisk_call_hook (int (*hook) (const char *name), int drive) +grub_biosdisk_call_hook (grub_disk_dev_iterate_hook_t hook, void *hook_data, + int drive) { char name[10]; if (cd_drive && drive == cd_drive) - return hook ("cd"); + return hook ("cd", hook_data); grub_snprintf (name, sizeof (name), (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80)); - return hook (name); + return hook (name, hook_data); } static int -grub_biosdisk_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull __attribute__ ((unused))) +grub_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) { int num_floppies; int drive; @@ -304,7 +305,7 @@ grub_biosdisk_iterate (int (*hook) (const char *name), break; } - if (grub_biosdisk_call_hook (hook, drive)) + if (grub_biosdisk_call_hook (hook, hook_data, drive)) return 1; } return 0; @@ -312,14 +313,14 @@ grub_biosdisk_iterate (int (*hook) (const char *name), case GRUB_DISK_PULL_REMOVABLE: if (cd_drive) { - if (grub_biosdisk_call_hook (hook, cd_drive)) + if (grub_biosdisk_call_hook (hook, hook_data, cd_drive)) return 1; } /* For floppy disks, we can get the number safely. */ num_floppies = grub_biosdisk_get_num_floppies (); for (drive = 0; drive < num_floppies; drive++) - if (grub_biosdisk_call_hook (hook, drive)) + if (grub_biosdisk_call_hook (hook, hook_data, drive)) return 1; return 0; default: @@ -366,7 +367,7 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) if (version) { struct grub_biosdisk_drp *drp - = (struct grub_biosdisk_drp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + = (struct grub_biosdisk_drp *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); /* Clear out the DRP. */ grub_memset (drp, 0, sizeof (*drp)); @@ -381,16 +382,13 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) /* Some buggy BIOSes doesn't return the total sectors correctly but returns zero. So if it is zero, compute it by C/H/S returned by the LBA BIOS call. */ - total_sectors = drp->cylinders * drp->heads * drp->sectors; + total_sectors = ((grub_uint64_t) drp->cylinders) + * drp->heads * drp->sectors; if (drp->bytes_per_sector && !(drp->bytes_per_sector & (drp->bytes_per_sector - 1)) && drp->bytes_per_sector >= 512 && drp->bytes_per_sector <= 16384) - { - for (disk->log_sector_size = 0; - (1 << disk->log_sector_size) < drp->bytes_per_sector; - disk->log_sector_size++); - } + disk->log_sector_size = grub_log2ull (drp->bytes_per_sector); } } } @@ -418,11 +416,24 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) } } + if (data->sectors == 0) + data->sectors = 63; + if (data->heads == 0) + data->heads = 255; + if (! total_sectors) - total_sectors = data->cylinders * data->heads * data->sectors; + total_sectors = ((grub_uint64_t) data->cylinders) + * data->heads * data->sectors; } disk->total_sectors = total_sectors; + /* Limit the max to 0x7f because of Phoenix EDD. */ + disk->max_agglomerate = 0x7f >> GRUB_DISK_CACHE_BITS; + COMPILE_TIME_ASSERT ((0x7f >> GRUB_DISK_CACHE_BITS + << (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS)) + + sizeof (struct grub_biosdisk_dap) + < GRUB_MEMORY_MACHINE_SCRATCH_SIZE); + disk->data = data; return GRUB_ERR_NONE; @@ -447,12 +458,20 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, { struct grub_biosdisk_data *data = disk->data; + /* VirtualBox fails with sectors above 2T on CDs. + Since even BD-ROMS are never that big anyway, return error. */ + if ((data->flags & GRUB_BIOSDISK_FLAG_CDROM) + && (sector >> 32)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("attempt to read or write outside of disk `%s'"), + disk->name); + if (data->flags & GRUB_BIOSDISK_FLAG_LBA) { struct grub_biosdisk_dap *dap; dap = (struct grub_biosdisk_dap *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR - + (data->sectors + + (GRUB_DISK_MAX_LBA_SECTORS << disk->log_sector_size)); dap->length = sizeof (*dap); dap->reserved = 0; @@ -542,15 +561,14 @@ get_safe_sectors (grub_disk_t disk, grub_disk_addr_t sector) struct grub_biosdisk_data *data = disk->data; grub_uint32_t sectors = data->sectors; + if (data->flags & GRUB_BIOSDISK_FLAG_LBA) + sectors = GRUB_DISK_MAX_LBA_SECTORS; + /* OFFSET = SECTOR % SECTORS */ grub_divmod64 (sector, sectors, &offset); size = sectors - offset; - /* Limit the max to 0x7f because of Phoenix EDD. */ - if (size > ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size)) - size = ((0x7fU << GRUB_DISK_SECTOR_BITS) >> disk->log_sector_size); - return size; } @@ -618,11 +636,11 @@ static struct grub_disk_dev grub_biosdisk_dev = { .name = "biosdisk", .id = GRUB_DISK_DEVICE_BIOSDISK_ID, - .iterate = grub_biosdisk_iterate, - .open = grub_biosdisk_open, - .close = grub_biosdisk_close, - .read = grub_biosdisk_read, - .write = grub_biosdisk_write, + .disk_iterate = grub_biosdisk_iterate, + .disk_open = grub_biosdisk_open, + .disk_close = grub_biosdisk_close, + .disk_read = grub_biosdisk_read, + .disk_write = grub_biosdisk_write, .next = 0 }; @@ -635,7 +653,7 @@ grub_disk_biosdisk_fini (void) GRUB_MOD_INIT(biosdisk) { struct grub_biosdisk_cdrp *cdrp - = (struct grub_biosdisk_cdrp *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + = (struct grub_biosdisk_cdrp *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); grub_uint8_t boot_drive; if (grub_disk_firmware_is_tainted) diff --git a/grub-core/disk/ieee1275/nand.c b/grub-core/disk/ieee1275/nand.c index ad30852ec..bcf3a06f4 100644 --- a/grub-core/disk/ieee1275/nand.c +++ b/grub-core/disk/ieee1275/nand.c @@ -33,25 +33,32 @@ struct grub_nand_data }; static int -grub_nand_iterate (int (*hook) (const char *name), +grub_nand_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { - auto int dev_iterate (struct grub_ieee1275_devalias *alias); - int dev_iterate (struct grub_ieee1275_devalias *alias) - { - if (grub_strcmp (alias->name, "nand") == 0) - { - hook (alias->name); - return 1; - } - - return 0; - } + static int have_nand = -1; if (pull != GRUB_DISK_PULL_NONE) return 0; - return grub_devalias_iterate (dev_iterate); + if (have_nand == -1) + { + struct grub_ieee1275_devalias alias; + + have_nand = 0; + FOR_IEEE1275_DEVALIASES(alias) + if (grub_strcmp (alias.name, "nand") == 0) + { + have_nand = 1; + break; + } + grub_ieee1275_devalias_free (&alias); + } + + if (have_nand) + return hook ("nand", hook_data); + + return 0; } static grub_err_t @@ -106,6 +113,11 @@ grub_nand_open (const char *name, grub_disk_t disk) } data->block_size = (args.size1 >> GRUB_DISK_SECTOR_BITS); + if (!data->block_size) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "invalid block size"); + goto fail; + } INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3); args.method = (grub_ieee1275_cell_t) "size"; @@ -203,18 +215,19 @@ grub_nand_write (grub_disk_t disk __attribute ((unused)), grub_size_t size __attribute ((unused)), const char *buf __attribute ((unused))) { - return GRUB_ERR_NOT_IMPLEMENTED_YET; + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "nand write is not supported"); } static struct grub_disk_dev grub_nand_dev = { .name = "nand", .id = GRUB_DISK_DEVICE_NAND_ID, - .iterate = grub_nand_iterate, - .open = grub_nand_open, - .close = grub_nand_close, - .read = grub_nand_read, - .write = grub_nand_write, + .disk_iterate = grub_nand_iterate, + .disk_open = grub_nand_open, + .disk_close = grub_nand_close, + .disk_read = grub_nand_read, + .disk_write = grub_nand_write, .next = 0 }; diff --git a/grub-core/disk/ieee1275/obdisk.c b/grub-core/disk/ieee1275/obdisk.c new file mode 100644 index 000000000..fcc39e0a2 --- /dev/null +++ b/grub-core/disk/ieee1275/obdisk.c @@ -0,0 +1,1109 @@ +/* obdisk.c - Open Boot disk access. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2019 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IEEE1275_DEV "ieee1275/" +#define IEEE1275_DISK_ALIAS "/disk@" + +struct disk_dev +{ + struct disk_dev *next; + struct disk_dev **prev; + char *name; + char *raw_name; + char *grub_devpath; + char *grub_alias_devpath; + grub_ieee1275_ihandle_t ihandle; + grub_uint32_t block_size; + grub_uint64_t num_blocks; + unsigned int log_sector_size; + grub_uint32_t opened; + grub_uint32_t valid; + grub_uint32_t boot_dev; +}; + +struct parent_dev +{ + struct parent_dev *next; + struct parent_dev **prev; + char *name; + char *type; + grub_ieee1275_ihandle_t ihandle; + grub_uint32_t address_cells; +}; + +static struct grub_scsi_test_unit_ready tur = +{ + .opcode = grub_scsi_cmd_test_unit_ready, + .lun = 0, + .reserved1 = 0, + .reserved2 = 0, + .reserved3 = 0, + .control = 0, +}; + +static int disks_enumerated; +static struct disk_dev *disk_devs; +static struct parent_dev *parent_devs; + +static const char *block_blacklist[] = { + /* Requires additional work in grub before being able to be used. */ + "/iscsi-hba", + /* This block device should never be used by grub. */ + "/reboot-memory@0", + 0 +}; + +#define STRCMP(a, b) ((a) && (b) && (grub_strcmp (a, b) == 0)) + +static char * +strip_ob_partition (char *path) +{ + char *sptr; + + sptr = grub_strstr (path, ":"); + + if (sptr != NULL) + *sptr = '\0'; + + return path; +} + +static void +escape_commas (const char *src, char *dest) +{ + const char *iptr; + + for (iptr = src; *iptr; ) + { + if (*iptr == ',') + *dest++ ='\\'; + + *dest++ = *iptr++; + } + + *dest = '\0'; +} + +static int +count_commas (const char *src) +{ + int count = 0; + + for ( ; *src; src++) + if (*src == ',') + count++; + + return count; +} + + +static char * +decode_grub_devname (const char *name) +{ + char *devpath; + char *p, c; + grub_size_t sz; + + if (grub_add (grub_strlen (name), 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of device name")); + return NULL; + } + + devpath = grub_malloc (sz); + if (devpath == NULL) + return NULL; + + /* Un-escape commas. */ + p = devpath; + while ((c = *name++) != '\0') + { + if (c == '\\' && *name == ',') + { + *p++ = ','; + name++; + } + else + *p++ = c; + } + + *p++ = '\0'; + + return devpath; +} + +static char * +encode_grub_devname (const char *path) +{ + char *encoding, *optr; + grub_size_t sz; + + if (path == NULL) + return NULL; + + if (grub_add (sizeof (IEEE1275_DEV) + 1, count_commas (path), &sz) || + grub_add (sz, grub_strlen (path), &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining encoding size")); + grub_print_error (); + return NULL; + } + + encoding = grub_malloc (sz); + + if (encoding == NULL) + { + grub_print_error (); + return NULL; + } + + optr = grub_stpcpy (encoding, IEEE1275_DEV); + escape_commas (path, optr); + return encoding; +} + +static char * +get_parent_devname (const char *devname) +{ + char *parent, *pptr; + + parent = grub_strdup (devname); + + if (parent == NULL) + { + grub_print_error (); + return NULL; + } + + pptr = grub_strstr (parent, IEEE1275_DISK_ALIAS); + + if (pptr != NULL) + *pptr = '\0'; + + return parent; +} + +static void +free_parent_dev (struct parent_dev *parent) +{ + if (parent != NULL) + { + grub_free (parent->name); + grub_free (parent->type); + grub_free (parent); + } +} + +static struct parent_dev * +init_parent (const char *parent) +{ + struct parent_dev *op; + + op = grub_zalloc (sizeof (struct parent_dev)); + + if (op == NULL) + { + grub_print_error (); + return NULL; + } + + op->name = grub_strdup (parent); + op->type = grub_malloc (IEEE1275_MAX_PROP_LEN); + + if ((op->name == NULL) || (op->type == NULL)) + { + grub_print_error (); + free_parent_dev (op); + return NULL; + } + + return op; +} + +static struct parent_dev * +open_new_parent (const char *parent) +{ + struct parent_dev *op = init_parent(parent); + grub_ieee1275_ihandle_t ihandle; + grub_ieee1275_phandle_t phandle; + grub_uint32_t address_cells = 2; + + if (op == NULL) + return NULL; + + grub_ieee1275_open (parent, &ihandle); + + if (ihandle == 0) + { + grub_error (GRUB_ERR_BAD_DEVICE, "unable to open %s", parent); + grub_print_error (); + free_parent_dev (op); + return NULL; + } + + if (grub_ieee1275_instance_to_package (ihandle, &phandle)) + { + grub_error (GRUB_ERR_BAD_DEVICE, "unable to get parent %s", parent); + grub_print_error (); + free_parent_dev (op); + return NULL; + } + + /* + * IEEE Std 1275-1994 page 110: A missing "address-cells" property + * signifies that the number of address cells is two. So ignore on error. + */ + if (grub_ieee1275_get_integer_property (phandle, "#address-cells", + &address_cells, + sizeof (address_cells), 0) != 0) + address_cells = 2; + + grub_ieee1275_get_property (phandle, "device_type", op->type, + IEEE1275_MAX_PROP_LEN, NULL); + + op->ihandle = ihandle; + op->address_cells = address_cells; + return op; +} + +static struct parent_dev * +open_parent (const char *parent) +{ + struct parent_dev *op; + + op = grub_named_list_find (GRUB_AS_NAMED_LIST (parent_devs), parent); + + if (op == NULL) + { + op = open_new_parent (parent); + + if (op != NULL) + grub_list_push (GRUB_AS_LIST_P (&parent_devs), GRUB_AS_LIST (op)); + } + + return op; +} + +static void +display_parents (void) +{ + struct parent_dev *parent; + + grub_printf ("-------------------- PARENTS --------------------\n"); + + FOR_LIST_ELEMENTS (parent, parent_devs) + { + grub_printf ("name: %s\n", parent->name); + grub_printf ("type: %s\n", parent->type); + grub_printf ("address_cells %x\n", parent->address_cells); + } + + grub_printf ("-------------------------------------------------\n"); +} + +static char * +canonicalise_4cell_ua (grub_ieee1275_ihandle_t ihandle, char *unit_address) +{ + grub_uint32_t phy_lo, phy_hi, lun_lo, lun_hi; + int valid_phy = 0; + grub_size_t size; + char *canon = NULL; + + valid_phy = grub_ieee1275_decode_unit4 (ihandle, unit_address, + grub_strlen (unit_address), &phy_lo, + &phy_hi, &lun_lo, &lun_hi); + + if ((valid_phy == 0) && (phy_hi != 0xffffffff)) + canon = grub_ieee1275_encode_uint4 (ihandle, phy_lo, phy_hi, + lun_lo, lun_hi, &size); + + return canon; +} + +static char * +canonicalise_disk (const char *devname) +{ + char *canon, *parent; + struct parent_dev *op; + + canon = grub_ieee1275_canonicalise_devname (devname); + + if (canon == NULL) + { + /* This should not happen. */ + grub_error (GRUB_ERR_BAD_DEVICE, "canonicalise devname failed"); + grub_print_error (); + return NULL; + } + + /* Don't try to open the parent of a virtual device. */ + if (grub_strstr (canon, "virtual-devices")) + return canon; + + parent = get_parent_devname (canon); + + if (parent == NULL) + return NULL; + + op = open_parent (parent); + + /* + * Devices with 4 address cells can have many different types of addressing + * (phy, wwn, and target lun). Use the parents encode-unit / decode-unit + * to find the true canonical name. + */ + if ((op) && (op->address_cells == 4)) + { + char *unit_address, *real_unit_address, *real_canon; + grub_size_t real_unit_str_len; + + unit_address = grub_strstr (canon, IEEE1275_DISK_ALIAS); + unit_address += grub_strlen (IEEE1275_DISK_ALIAS); + + if (unit_address == NULL) + { + /* + * This should not be possible, but return the canonical name for + * the non-disk block device. + */ + grub_free (parent); + return (canon); + } + + real_unit_address = canonicalise_4cell_ua (op->ihandle, unit_address); + + if (real_unit_address == NULL) + { + /* + * This is not an error, since this function could be called with a devalias + * containing a drive that isn't installed in the system. + */ + grub_free (parent); + return NULL; + } + + real_unit_str_len = grub_strlen (op->name) + sizeof (IEEE1275_DISK_ALIAS) + + grub_strlen (real_unit_address); + if (grub_add (grub_strlen (op->name), sizeof (IEEE1275_DISK_ALIAS), &real_unit_str_len) || + grub_add (real_unit_str_len, grub_strlen (real_unit_address), &real_unit_str_len)) + { + grub_free (parent); + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of canonical name")); + grub_print_error (); + return NULL; + } + + real_canon = grub_malloc (real_unit_str_len); + if (real_canon == NULL) + { + grub_free (parent); + grub_print_error (); + return NULL; + } + + grub_snprintf (real_canon, real_unit_str_len, "%s/disk@%s", + op->name, real_unit_address); + + grub_free (canon); + canon = real_canon; + } + + grub_free (parent); + return (canon); +} + +static struct disk_dev * +add_canon_disk (const char *cname) +{ + grub_size_t sz; + struct disk_dev *dev; + + dev = grub_zalloc (sizeof (struct disk_dev)); + + if (dev == NULL) + goto failed; + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_RAW_DEVNAMES)) + { + /* + * Append :nolabel to the end of all SPARC disks. + * nolabel is mutually exclusive with all other + * arguments and allows a client program to open + * the entire (raw) disk. Any disk label is ignored. + */ + if (grub_add (grub_strlen (cname), sizeof (":nolabel"), &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while appending :nolabel to end of canonical name"); + goto failed; + } + + dev->raw_name = grub_malloc (sz); + + if (dev->raw_name == NULL) + goto failed; + + grub_snprintf (dev->raw_name, sz, "%s:nolabel", cname); + } + + /* + * Don't use grub_ieee1275_encode_devname here, the devpath in grub.cfg doesn't + * understand device aliases, which the layer above sometimes sends us. + */ + dev->grub_devpath = encode_grub_devname(cname); + + if (dev->grub_devpath == NULL) + goto failed; + + dev->name = grub_strdup (cname); + + if (dev->name == NULL) + goto failed; + + dev->valid = 1; + grub_list_push (GRUB_AS_LIST_P (&disk_devs), GRUB_AS_LIST (dev)); + return dev; + + failed: + grub_print_error (); + + if (dev != NULL) + { + grub_free (dev->name); + grub_free (dev->grub_devpath); + grub_free (dev->raw_name); + } + + grub_free (dev); + return NULL; +} + +static grub_err_t +add_disk (const char *path) +{ + grub_err_t ret = GRUB_ERR_NONE; + struct disk_dev *dev; + char *canon; + + canon = canonicalise_disk (path); + dev = grub_named_list_find (GRUB_AS_NAMED_LIST (disk_devs), canon); + + if ((canon != NULL) && (dev == NULL)) + { + struct disk_dev *ob_device; + + ob_device = add_canon_disk (canon); + + if (ob_device == NULL) + ret = grub_error (GRUB_ERR_OUT_OF_MEMORY, "failure to add disk"); + } + else if (dev != NULL) + dev->valid = 1; + + grub_free (canon); + return (ret); +} + +static grub_err_t +grub_obdisk_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *dest) +{ + grub_err_t ret = GRUB_ERR_NONE; + struct disk_dev *dev; + unsigned long long pos; + grub_ssize_t result = 0; + + if (disk->data == NULL) + return grub_error (GRUB_ERR_BAD_DEVICE, "invalid disk data"); + + dev = (struct disk_dev *)disk->data; + pos = sector << disk->log_sector_size; + grub_ieee1275_seek (dev->ihandle, pos, &result); + + if (result < 0) + { + dev->opened = 0; + return grub_error (GRUB_ERR_READ_ERROR, "seek error, can't seek block %llu", + (long long) sector); + } + + grub_ieee1275_read (dev->ihandle, dest, size << disk->log_sector_size, + &result); + + if (result != (grub_ssize_t) (size << disk->log_sector_size)) + { + dev->opened = 0; + return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " + "from `%s'"), + (unsigned long long) sector, + disk->name); + } + return ret; +} + +static void +grub_obdisk_close (grub_disk_t disk) +{ + grub_memset (disk, 0, sizeof (*disk)); +} + +static void +scan_usb_disk (const char *parent) +{ + struct parent_dev *op; + grub_ssize_t result; + + op = open_parent (parent); + + if (op == NULL) + { + grub_error (GRUB_ERR_BAD_DEVICE, "unable to open %s", parent); + grub_print_error (); + return; + } + + if ((grub_ieee1275_set_address (op->ihandle, 0, 0) == 0) && + (grub_ieee1275_no_data_command (op->ihandle, &tur, &result) == 0) && + (result == 0)) + { + char *buf; + + buf = grub_malloc (IEEE1275_MAX_PATH_LEN); + + if (buf == NULL) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "disk scan failure"); + grub_print_error (); + return; + } + + grub_snprintf (buf, IEEE1275_MAX_PATH_LEN, "%s/disk@0", parent); + add_disk (buf); + grub_free (buf); + } +} + +static void +scan_nvme_disk (const char *path) +{ + char *buf; + + buf = grub_malloc (IEEE1275_MAX_PATH_LEN); + + if (buf == NULL) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "disk scan failure"); + grub_print_error (); + return; + } + + grub_snprintf (buf, IEEE1275_MAX_PATH_LEN, "%s/disk@1", path); + add_disk (buf); + grub_free (buf); +} + +static void +scan_sparc_sas_2cell (struct parent_dev *op) +{ + grub_ssize_t result; + grub_uint8_t tgt; + char *buf; + + buf = grub_malloc (IEEE1275_MAX_PATH_LEN); + + if (buf == NULL) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "disk scan failure"); + grub_print_error (); + return; + } + + for (tgt = 0; tgt < 0xf; tgt++) + { + + if ((grub_ieee1275_set_address(op->ihandle, tgt, 0) == 0) && + (grub_ieee1275_no_data_command (op->ihandle, &tur, &result) == 0) && + (result == 0)) + { + + grub_snprintf (buf, IEEE1275_MAX_PATH_LEN, "%s/disk@%" + PRIxGRUB_UINT32_T, op->name, tgt); + + add_disk (buf); + } + } +} + +static void +scan_sparc_sas_4cell (struct parent_dev *op) +{ + grub_uint16_t exp; + grub_uint8_t phy; + char *buf; + + buf = grub_malloc (IEEE1275_MAX_PATH_LEN); + + if (buf == NULL) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "disk scan failure"); + grub_print_error (); + return; + } + + /* + * Cycle thru the potential for dual ported SAS disks + * behind a SAS expander. + */ + for (exp = 0; exp <= 0x100; exp+=0x100) + + /* The current limit is 32 disks on a phy. */ + for (phy = 0; phy < 0x20; phy++) + { + char *canon = NULL; + + grub_snprintf (buf, IEEE1275_MAX_PATH_LEN, "p%" PRIxGRUB_UINT32_T ",0", + exp | phy); + + canon = canonicalise_4cell_ua (op->ihandle, buf); + + if (canon != NULL) + { + grub_snprintf (buf, IEEE1275_MAX_PATH_LEN, "%s/disk@%s", + op->name, canon); + + add_disk (buf); + grub_free (canon); + } + } + + grub_free (buf); +} + +static void +scan_sparc_sas_disk (const char *parent) +{ + struct parent_dev *op; + + op = open_parent (parent); + + if ((op != NULL) && (op->address_cells == 4)) + scan_sparc_sas_4cell (op); + else if ((op != NULL) && (op->address_cells == 2)) + scan_sparc_sas_2cell (op); +} + +static void +iterate_devtree (const struct grub_ieee1275_devalias *alias) +{ + struct grub_ieee1275_devalias child; + + if ((grub_strcmp (alias->type, "scsi-2") == 0) || + (grub_strcmp (alias->type, "scsi-sas") == 0)) + return scan_sparc_sas_disk (alias->path); + + else if (grub_strcmp (alias->type, "nvme") == 0) + return scan_nvme_disk (alias->path); + + else if (grub_strcmp (alias->type, "scsi-usb") == 0) + return scan_usb_disk (alias->path); + + else if (grub_strcmp (alias->type, "block") == 0) + { + const char **bl = block_blacklist; + + while (*bl != NULL) + { + if (grub_strstr (alias->path, *bl)) + return; + bl++; + } + + add_disk (alias->path); + return; + } + + FOR_IEEE1275_DEVCHILDREN (alias->path, child) + iterate_devtree (&child); +} + +static void +enumerate_disks (void) +{ + struct grub_ieee1275_devalias alias; + + FOR_IEEE1275_DEVCHILDREN("/", alias) + iterate_devtree (&alias); +} + +static grub_err_t +add_bootpath (void) +{ + struct disk_dev *ob_device; + grub_err_t ret = GRUB_ERR_NONE; + char *dev, *alias; + char *type; + + dev = grub_ieee1275_get_boot_dev (); + + if (dev == NULL) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "failure adding boot device"); + + type = grub_ieee1275_get_device_type (dev); + + if (type == NULL) + { + grub_free (dev); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "failure adding boot device"); + } + + alias = NULL; + + if (grub_strcmp (type, "network") != 0) + { + dev = strip_ob_partition (dev); + ob_device = add_canon_disk (dev); + + if (ob_device == NULL) + ret = grub_error (GRUB_ERR_OUT_OF_MEMORY, "failure adding boot device"); + + ob_device->valid = 1; + + alias = grub_ieee1275_get_devname (dev); + + if (alias && grub_strcmp (alias, dev) != 0) + ob_device->grub_alias_devpath = grub_ieee1275_encode_devname (dev); + + ob_device->boot_dev = 1; + } + + grub_free (type); + grub_free (dev); + grub_free (alias); + return ret; +} + +static void +enumerate_aliases (void) +{ + struct grub_ieee1275_devalias alias; + + /* + * Some block device aliases are not in canonical form + * + * For example: + * + * disk3 /pci@301/pci@1/scsi@0/disk@p3 + * disk2 /pci@301/pci@1/scsi@0/disk@p2 + * disk1 /pci@301/pci@1/scsi@0/disk@p1 + * disk /pci@301/pci@1/scsi@0/disk@p0 + * disk0 /pci@301/pci@1/scsi@0/disk@p0 + * + * None of these devices are in canonical form. + * + * Also, just because there is a devalias, doesn't mean there is a disk + * at that location. And a valid boot block device doesn't have to have + * a devalias at all. + * + * At this point, all valid disks have been found in the system + * and devaliases that point to canonical names are stored in the + * disk_devs list already. + */ + FOR_IEEE1275_DEVALIASES (alias) + { + struct disk_dev *dev; + char *canon; + + if (grub_strcmp (alias.type, "block") != 0) + continue; + + canon = canonicalise_disk (alias.name); + + if (canon == NULL) + /* This is not an error, a devalias could point to a nonexistent disk. */ + continue; + + dev = grub_named_list_find (GRUB_AS_NAMED_LIST (disk_devs), canon); + + if (dev != NULL) + { + /* + * If more than one alias points to the same device, + * remove the previous one unless it is the boot dev, + * since the upper level will use the first one. The reason + * all the others are redone is in the case of hot-plugging + * a disk. If the boot disk gets hot-plugged, it will come + * thru here with a different name without the boot_dev flag + * set. + */ + if ((dev->boot_dev) && (dev->grub_alias_devpath)) + continue; + + grub_free (dev->grub_alias_devpath); + dev->grub_alias_devpath = grub_ieee1275_encode_devname (alias.path); + } + grub_free (canon); + } +} + +static void +display_disks (void) +{ + struct disk_dev *dev; + + grub_printf ("--------------------- DISKS ---------------------\n"); + + FOR_LIST_ELEMENTS (dev, disk_devs) + { + grub_printf ("name: %s\n", dev->name); + grub_printf ("grub_devpath: %s\n", dev->grub_devpath); + grub_printf ("grub_alias_devpath: %s\n", dev->grub_alias_devpath); + grub_printf ("valid: %s\n", (dev->valid) ? "yes" : "no"); + grub_printf ("boot_dev: %s\n", (dev->boot_dev) ? "yes" : "no"); + grub_printf ("opened: %s\n", (dev->ihandle) ? "yes" : "no"); + grub_printf ("block size: %" PRIuGRUB_UINT32_T "\n", + dev->block_size); + grub_printf ("num blocks: %" PRIuGRUB_UINT64_T "\n", + dev->num_blocks); + grub_printf ("log sector size: %" PRIuGRUB_UINT32_T "\n", + dev->log_sector_size); + grub_printf ("\n"); + } + + grub_printf ("-------------------------------------------------\n"); +} + +static void +display_stats (void) +{ + const char *debug = grub_env_get ("debug"); + + if (debug == NULL) + return; + + if (grub_strword (debug, "all") || grub_strword (debug, "obdisk")) + { + display_parents (); + display_disks (); + } +} + +static void +invalidate_all_disks (void) +{ + struct disk_dev *dev = NULL; + + if (disks_enumerated != 0) + FOR_LIST_ELEMENTS (dev, disk_devs) + dev->valid = 0; +} + +static struct disk_dev * +find_legacy_grub_devpath (const char *name) +{ + struct disk_dev *dev = NULL; + char *canon, *devpath = NULL; + + devpath = decode_grub_devname (name + sizeof ("ieee1275")); + canon = canonicalise_disk (devpath); + + if (canon != NULL) + dev = grub_named_list_find (GRUB_AS_NAMED_LIST (disk_devs), canon); + + grub_free (devpath); + grub_free (canon); + return dev; +} + +static void +enumerate_devices (void) +{ + invalidate_all_disks (); + enumerate_disks (); + enumerate_aliases (); + disks_enumerated = 1; + display_stats (); +} + +static struct disk_dev * +find_grub_devpath_real (const char *name) +{ + struct disk_dev *dev = NULL; + + FOR_LIST_ELEMENTS (dev, disk_devs) + { + if ((STRCMP (dev->grub_devpath, name)) + || (STRCMP (dev->grub_alias_devpath, name))) + break; + } + + return dev; +} + +static struct disk_dev * +find_grub_devpath (const char *name) +{ + struct disk_dev *dev = NULL; + int enumerated; + + do { + enumerated = disks_enumerated; + dev = find_grub_devpath_real (name); + + if (dev != NULL) + break; + + dev = find_legacy_grub_devpath (name); + + if (dev != NULL) + break; + + enumerate_devices (); + } while (enumerated == 0); + + return dev; +} + +static int +grub_obdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +{ + struct disk_dev *dev; + const char *name; + + if (pull != GRUB_DISK_PULL_NONE) + return 0; + + enumerate_devices (); + + FOR_LIST_ELEMENTS (dev, disk_devs) + { + if (dev->valid == 1) + { + if (dev->grub_alias_devpath) + name = dev->grub_alias_devpath; + else + name = dev->grub_devpath; + + if (hook (name, hook_data)) + return 1; + } + } + + return 0; +} + +static grub_err_t +grub_obdisk_open (const char *name, grub_disk_t disk) +{ + grub_ieee1275_ihandle_t ihandle = 0; + struct disk_dev *dev = NULL; + + if (grub_strncmp (name, IEEE1275_DEV, sizeof (IEEE1275_DEV) - 1) != 0) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not IEEE1275 device"); + + dev = find_grub_devpath (name); + + if (dev == NULL) + { + grub_printf ("UNKNOWN DEVICE: %s\n", name); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "%s", name); + } + + if (dev->opened == 0) + { + if (dev->raw_name != NULL) + grub_ieee1275_open (dev->raw_name, &ihandle); + else + grub_ieee1275_open (dev->name, &ihandle); + + if (ihandle == 0) + { + grub_printf ("Can't open device %s\n", name); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device %s", name); + } + + dev->block_size = grub_ieee1275_get_block_size (ihandle); + dev->num_blocks = grub_ieee1275_num_blocks (ihandle); + + if (dev->num_blocks == 0) + dev->num_blocks = grub_ieee1275_num_blocks64 (ihandle); + + if (dev->num_blocks == 0) + dev->num_blocks = GRUB_DISK_SIZE_UNKNOWN; + + if (dev->block_size != 0) + dev->log_sector_size = grub_log2ull (dev->block_size); + else + dev->log_sector_size = 9; + + dev->ihandle = ihandle; + dev->opened = 1; + } + + disk->total_sectors = dev->num_blocks; + disk->id = dev->ihandle; + disk->data = dev; + disk->log_sector_size = dev->log_sector_size; + return GRUB_ERR_NONE; +} + + +static struct grub_disk_dev grub_obdisk_dev = + { + .name = "obdisk", + .id = GRUB_DISK_DEVICE_OBDISK_ID, + .disk_iterate = grub_obdisk_iterate, + .disk_open = grub_obdisk_open, + .disk_close = grub_obdisk_close, + .disk_read = grub_obdisk_read, + }; + +void +grub_obdisk_init (void) +{ + grub_disk_firmware_fini = grub_obdisk_fini; + add_bootpath (); + grub_disk_dev_register (&grub_obdisk_dev); +} + +void +grub_obdisk_fini (void) +{ + struct disk_dev *dev; + + FOR_LIST_ELEMENTS (dev, disk_devs) + { + if (dev->opened != 0) + grub_ieee1275_close (dev->ihandle); + } + + grub_disk_dev_unregister (&grub_obdisk_dev); +} diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c index b0aa7ec7b..dbc0f1aba 100644 --- a/grub-core/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -24,6 +24,7 @@ #include #include #include +#include static char *last_devpath; static grub_ieee1275_ihandle_t last_ihandle; @@ -31,12 +32,22 @@ static grub_ieee1275_ihandle_t last_ihandle; struct ofdisk_hash_ent { char *devpath; + char *open_path; + char *grub_devpath; + int is_boot; + int is_removable; + int block_size_fails; /* Pointer to shortest available name on nodes representing canonical names, otherwise NULL. */ const char *shortest; + const char *grub_shortest; struct ofdisk_hash_ent *next; }; +static grub_err_t +grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size, + struct ofdisk_hash_ent *op); + #define OFDISK_HASH_SZ 8 static struct ofdisk_hash_ent *ofdisk_hash[OFDISK_HASH_SZ]; @@ -68,18 +79,80 @@ ofdisk_hash_add_real (char *devpath) { struct ofdisk_hash_ent *p; struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)]; + const char *iptr; + char *optr; + grub_size_t sz; - p = grub_malloc(sizeof (*p)); + p = grub_zalloc (sizeof (*p)); if (!p) return NULL; p->devpath = devpath; + + if (grub_mul (grub_strlen (p->devpath), 2, &sz) || + grub_add (sz, sizeof ("ieee1275/"), &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of device path")); + return NULL; + } + + p->grub_devpath = grub_malloc (sz); + + if (!p->grub_devpath) + { + grub_free (p); + return NULL; + } + + if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) + { + if (grub_add (grub_strlen (p->devpath), 3, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of an open path")); + return NULL; + } + + p->open_path = grub_malloc (sz); + if (!p->open_path) + { + grub_free (p->grub_devpath); + grub_free (p); + return NULL; + } + optr = grub_stpcpy (p->open_path, p->devpath); + *optr++ = ':'; + *optr++ = '0'; + *optr = '\0'; + } + else + p->open_path = p->devpath; + + optr = grub_stpcpy (p->grub_devpath, "ieee1275/"); + for (iptr = p->devpath; *iptr; ) + { + if (*iptr == ',') + *optr++ = '\\'; + *optr++ = *iptr++; + } + *optr = 0; + p->next = *head; - p->shortest = 0; *head = p; return p; } +static int +check_string_removable (const char *str) +{ + const char *ptr = grub_strrchr (str, '/'); + + if (ptr) + ptr++; + else + ptr = str; + return (grub_strncmp (ptr, "cdrom", 5) == 0 || grub_strncmp (ptr, "fd", 2) == 0); +} + static struct ofdisk_hash_ent * ofdisk_hash_add (char *devpath, char *curcan) { @@ -91,7 +164,10 @@ ofdisk_hash_add (char *devpath, char *curcan) if (!curcan) { - p->shortest = devpath; + p->shortest = p->devpath; + p->grub_shortest = p->grub_devpath; + if (check_string_removable (devpath)) + p->is_removable = 1; return p; } @@ -101,124 +177,232 @@ ofdisk_hash_add (char *devpath, char *curcan) else grub_free (curcan); + if (check_string_removable (devpath) || check_string_removable (curcan)) + pcan->is_removable = 1; + if (!pcan) grub_errno = GRUB_ERR_NONE; else { if (!pcan->shortest || grub_strlen (pcan->shortest) > grub_strlen (devpath)) - pcan->shortest = devpath; + { + pcan->shortest = p->devpath; + pcan->grub_shortest = p->grub_devpath; + } } return p; } static void -scan (void) +dev_iterate_real (const char *name, const char *path) { - auto int dev_iterate_real (const char *name, const char *path); + struct ofdisk_hash_ent *op; - int dev_iterate_real (const char *name, const char *path) + grub_dprintf ("disk", "disk name = %s, path = %s\n", name, + path); + + op = ofdisk_hash_find (path); + if (!op) { - struct ofdisk_hash_ent *op; - - grub_dprintf ("disk", "disk name = %s, path = %s\n", name, - path); - - op = ofdisk_hash_find (path); - if (!op) + char *name_dup = grub_strdup (name); + char *can = grub_strdup (path); + if (!name_dup || !can) { - char *name_dup = grub_strdup (name); - char *can = grub_strdup (path); - if (!name_dup || !can) - { - grub_errno = GRUB_ERR_NONE; - grub_free (name_dup); - grub_free (can); - return 0; - } - op = ofdisk_hash_add (name_dup, can); + grub_errno = GRUB_ERR_NONE; + grub_free (name_dup); + grub_free (can); + return; } - return 0; + op = ofdisk_hash_add (name_dup, can); + } + return; +} + +static void +dev_iterate (const struct grub_ieee1275_devalias *alias) +{ + if (grub_strcmp (alias->type, "vscsi") == 0) + { + static grub_ieee1275_ihandle_t ihandle; + struct set_color_args + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t catch_result; + grub_ieee1275_cell_t nentries; + grub_ieee1275_cell_t table; + } + args; + char *buf, *bufptr; + unsigned i; + grub_size_t sz; + + if (grub_ieee1275_open (alias->path, &ihandle)) + return; + + /* This method doesn't need memory allocation for the table. Open + firmware takes care of all memory management and the result table + stays in memory and is never freed. */ + INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3); + args.method = (grub_ieee1275_cell_t) "vscsi-report-luns"; + args.ihandle = ihandle; + args.table = 0; + args.nentries = 0; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1 || args.catch_result) + { + grub_ieee1275_close (ihandle); + return; + } + + if (grub_add (grub_strlen (alias->path), 32, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while creating buffer for vscsi"); + grub_ieee1275_close (ihandle); + return; + } + + buf = grub_malloc (sz); + if (!buf) + { + grub_ieee1275_close (ihandle); + return; + } + bufptr = grub_stpcpy (buf, alias->path); + + for (i = 0; i < args.nentries; i++) + { + grub_uint64_t *ptr; + + ptr = *(grub_uint64_t **) (args.table + 4 + 8 * i); + while (*ptr) + { + grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T, *ptr++); + dev_iterate_real (buf, buf); + } + } + grub_ieee1275_close (ihandle); + grub_free (buf); + return; + } + else if (grub_strcmp (alias->type, "sas_ioa") == 0) + { + /* The method returns the number of disks and a table where + * each ID is 64-bit long. Example of sas paths: + * /pci@80000002000001f/pci1014,034A@0/sas/disk@c05db70800 + * /pci@80000002000001f/pci1014,034A@0/sas/disk@a05db70800 + * /pci@80000002000001f/pci1014,034A@0/sas/disk@805db70800 */ + + struct sas_children + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t max; + grub_ieee1275_cell_t table; + grub_ieee1275_cell_t catch_result; + grub_ieee1275_cell_t nentries; + } + args; + char *buf, *bufptr; + unsigned i; + grub_uint64_t *table; + grub_uint16_t table_size; + grub_ieee1275_ihandle_t ihandle; + grub_size_t sz; + + if (grub_add (grub_strlen (alias->path), sizeof ("/disk@7766554433221100"), &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected while creating buffer for sas_ioa"); + return; + } + + buf = grub_malloc (sz); + if (!buf) + return; + bufptr = grub_stpcpy (buf, alias->path); + + /* Power machines documentation specify 672 as maximum SAS disks in + one system. Using a slightly larger value to be safe. */ + table_size = 768; + table = grub_calloc (table_size, sizeof (grub_uint64_t)); + + if (!table) + { + grub_free (buf); + return; + } + + if (grub_ieee1275_open (alias->path, &ihandle)) + { + grub_free (buf); + grub_free (table); + return; + } + + INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 2); + args.method = (grub_ieee1275_cell_t) "get-sas-children"; + args.ihandle = ihandle; + args.max = table_size; + args.table = (grub_ieee1275_cell_t) table; + args.catch_result = 0; + args.nentries = 0; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + { + grub_ieee1275_close (ihandle); + grub_free (table); + grub_free (buf); + return; + } + + for (i = 0; i < args.nentries; i++) + { + grub_snprintf (bufptr, sizeof ("/disk@7766554433221100"), + "/disk@%" PRIxGRUB_UINT64_T, table[i]); + dev_iterate_real (buf, buf); + } + + grub_ieee1275_close (ihandle); + grub_free (table); + grub_free (buf); + } + + if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS) + && grub_strcmp (alias->type, "block") == 0) + { + dev_iterate_real (alias->path, alias->path); + return; } - auto int dev_iterate_alias (struct grub_ieee1275_devalias *alias); - int dev_iterate_alias (struct grub_ieee1275_devalias *alias) { - if (grub_strcmp (alias->type, "block") != 0) - return 0; - return dev_iterate_real (alias->name, alias->path); + struct grub_ieee1275_devalias child; + + FOR_IEEE1275_DEVCHILDREN(alias->path, child) + dev_iterate (&child); } +} - auto int dev_iterate (struct grub_ieee1275_devalias *alias); - int dev_iterate (struct grub_ieee1275_devalias *alias) - { - if (grub_strcmp (alias->type, "vscsi") == 0) - { - static grub_ieee1275_ihandle_t ihandle; - struct set_color_args - { - struct grub_ieee1275_common_hdr common; - grub_ieee1275_cell_t method; - grub_ieee1275_cell_t ihandle; - grub_ieee1275_cell_t catch_result; - grub_ieee1275_cell_t nentries; - grub_ieee1275_cell_t table; - } - args; - char *buf, *bufptr; - unsigned i; +static void +scan (void) +{ + struct grub_ieee1275_devalias alias; + FOR_IEEE1275_DEVALIASES(alias) + { + if (grub_strcmp (alias.type, "block") != 0) + continue; + dev_iterate_real (alias.name, alias.path); + } - if (grub_ieee1275_open (alias->path, &ihandle)) - return 0; - - INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3); - args.method = (grub_ieee1275_cell_t) "vscsi-report-luns"; - args.ihandle = ihandle; - args.table = 0; - args.nentries = 0; - - if (IEEE1275_CALL_ENTRY_FN (&args) == -1) - { - grub_ieee1275_close (ihandle); - return 0; - } - - buf = grub_malloc (grub_strlen (alias->path) + 32); - if (!buf) - return 0; - bufptr = grub_stpcpy (buf, alias->path); - - for (i = 0; i < args.nentries; i++) - { - grub_uint64_t *ptr; - - ptr = *(grub_uint64_t **) (args.table + 4 + 8 * i); - while (*ptr) - { - grub_snprintf (bufptr, 32, "/disk@%" PRIxGRUB_UINT64_T, *ptr++); - if (dev_iterate_real (buf, buf)) - return 1; - } - } - grub_ieee1275_close (ihandle); - grub_free (buf); - return 0; - } - - if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS) - && grub_strcmp (alias->type, "block") == 0) - return dev_iterate_real (alias->path, alias->path); - - return grub_children_iterate (alias->path, dev_iterate); - } - - grub_devalias_iterate (dev_iterate_alias); - grub_children_iterate ("/", dev_iterate); + FOR_IEEE1275_DEVCHILDREN("/", alias) + dev_iterate (&alias); } static int -grub_ofdisk_iterate (int (*hook) (const char *name), +grub_ofdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { unsigned i; @@ -227,7 +411,7 @@ grub_ofdisk_iterate (int (*hook) (const char *name), return 0; scan (); - + for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++) { static struct ofdisk_hash_ent *ent; @@ -261,35 +445,30 @@ grub_ofdisk_iterate (int (*hook) (const char *name), } } - if (grub_strncmp (ent->shortest, "cdrom", 5) == 0) + if (!ent->is_boot && ent->is_removable) continue; - { - char buffer[sizeof ("ieee1275/") + 2 * grub_strlen (ent->shortest)]; - const char *iptr; - char *optr; - optr = grub_stpcpy (buffer, "ieee1275/"); - for (iptr = ent->shortest; *iptr; ) - { - if (*iptr == ',') - *optr++ = '\\'; - *optr++ = *iptr++; - } - *optr = 0; - if (hook (buffer)) - return 1; - } + if (hook (ent->grub_shortest, hook_data)) + return 1; } - } + } return 0; } static char * compute_dev_path (const char *name) { - char *devpath = grub_malloc (grub_strlen (name) + 3); + char *devpath; char *p, c; + grub_size_t sz; + if (grub_add (grub_strlen (name), 3, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining size of device path")); + return NULL; + } + + devpath = grub_malloc (sz); if (!devpath) return NULL; @@ -319,6 +498,8 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) /* XXX: This should be large enough for any possible case. */ char prop[64]; grub_ssize_t actual; + grub_uint32_t block_size = 0; + grub_err_t err; if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, @@ -359,14 +540,27 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) op = ofdisk_hash_find (devpath); if (!op) op = ofdisk_hash_add (devpath, NULL); - else - grub_free (devpath); if (!op) - return grub_errno; + { + grub_free (devpath); + return grub_errno; + } disk->id = (unsigned long) op; - disk->data = op->devpath; + disk->data = op->open_path; + + err = grub_ofdisk_get_block_size (devpath, &block_size, op); + if (err) + { + grub_free (devpath); + return err; + } + if (block_size != 0) + disk->log_sector_size = grub_log2ull (block_size); + else + disk->log_sector_size = 9; } + grub_free (devpath); return 0; } @@ -396,26 +590,13 @@ grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector) last_ihandle = 0; last_devpath = NULL; - if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) - { - char name2[grub_strlen (disk->data) + 3]; - char *p; - - grub_strcpy (name2, disk->data); - p = name2 + grub_strlen (name2); - *p++ = ':'; - *p++ = '0'; - *p = 0; - grub_ieee1275_open (name2, &last_ihandle); - } - else - grub_ieee1275_open (disk->data, &last_ihandle); + grub_ieee1275_open (disk->data, &last_ihandle); if (! last_ihandle) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); - last_devpath = disk->data; + last_devpath = disk->data; } - pos = sector << GRUB_DISK_SECTOR_BITS; + pos = sector << disk->log_sector_size; grub_ieee1275_seek (last_ihandle, pos, &status); if (status < 0) @@ -434,9 +615,9 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, err = grub_ofdisk_prepare (disk, sector); if (err) return err; - grub_ieee1275_read (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, + grub_ieee1275_read (last_ihandle, buf, size << disk->log_sector_size, &actual); - if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (actual != (grub_ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " "from `%s'"), (unsigned long long) sector, @@ -454,9 +635,9 @@ grub_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector, err = grub_ofdisk_prepare (disk, sector); if (err) return err; - grub_ieee1275_write (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, + grub_ieee1275_write (last_ihandle, buf, size << disk->log_sector_size, &actual); - if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + if (actual != (grub_ssize_t) (size << disk->log_sector_size)) return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx " "to `%s'"), (unsigned long long) sector, @@ -469,18 +650,59 @@ static struct grub_disk_dev grub_ofdisk_dev = { .name = "ofdisk", .id = GRUB_DISK_DEVICE_OFDISK_ID, - .iterate = grub_ofdisk_iterate, - .open = grub_ofdisk_open, - .close = grub_ofdisk_close, - .read = grub_ofdisk_read, - .write = grub_ofdisk_write, + .disk_iterate = grub_ofdisk_iterate, + .disk_open = grub_ofdisk_open, + .disk_close = grub_ofdisk_close, + .disk_read = grub_ofdisk_read, + .disk_write = grub_ofdisk_write, .next = 0 }; -void -grub_ofdisk_init (void) +static void +insert_bootpath (void) { - grub_disk_dev_register (&grub_ofdisk_dev); + char *bootpath; + grub_ssize_t bootpath_size; + char *type; + grub_size_t sz; + + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath", + &bootpath_size) + || bootpath_size <= 0) + { + /* Should never happen. */ + grub_printf ("/chosen/bootpath property missing!\n"); + return; + } + + if (grub_add (bootpath_size, 64, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while obtaining bootpath size")); + return; + } + + bootpath = (char *) grub_malloc (sz); + if (! bootpath) + { + grub_print_error (); + return; + } + grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath, + (grub_size_t) bootpath_size + 1, 0); + bootpath[bootpath_size] = '\0'; + + /* Transform an OF device path to a GRUB path. */ + + type = grub_ieee1275_get_device_type (bootpath); + if (!(type && grub_strcmp (type, "network") == 0)) + { + struct ofdisk_hash_ent *op; + char *device = grub_ieee1275_get_devname (bootpath); + op = ofdisk_hash_add (device, NULL); + op->is_boot = 1; + } + grub_free (type); + grub_free (bootpath); } void @@ -493,3 +715,69 @@ grub_ofdisk_fini (void) grub_disk_dev_unregister (&grub_ofdisk_dev); } + +void +grub_ofdisk_init (void) +{ + grub_disk_firmware_fini = grub_ofdisk_fini; + + insert_bootpath (); + + grub_disk_dev_register (&grub_ofdisk_dev); +} + +static grub_err_t +grub_ofdisk_get_block_size (const char *device, grub_uint32_t *block_size, + struct ofdisk_hash_ent *op) +{ + struct size_args_ieee1275 + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t result; + grub_ieee1275_cell_t size1; + grub_ieee1275_cell_t size2; + } args_ieee1275; + + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + + last_ihandle = 0; + last_devpath = NULL; + + grub_ieee1275_open (device, &last_ihandle); + if (! last_ihandle) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + + *block_size = 0; + + if (op->block_size_fails >= 2) + return GRUB_ERR_NONE; + + INIT_IEEE1275_COMMON (&args_ieee1275.common, "call-method", 2, 2); + args_ieee1275.method = (grub_ieee1275_cell_t) "block-size"; + args_ieee1275.ihandle = last_ihandle; + args_ieee1275.result = 1; + + if (IEEE1275_CALL_ENTRY_FN (&args_ieee1275) == -1) + { + grub_dprintf ("disk", "can't get block size: failed call-method\n"); + op->block_size_fails++; + } + else if (args_ieee1275.result) + { + grub_dprintf ("disk", "can't get block size: %lld\n", + (long long) args_ieee1275.result); + op->block_size_fails++; + } + else if (args_ieee1275.size1 + && !(args_ieee1275.size1 & (args_ieee1275.size1 - 1)) + && args_ieee1275.size1 >= 512 && args_ieee1275.size1 <= 16384) + { + op->block_size_fails = 0; + *block_size = args_ieee1275.size1; + } + + return 0; +} diff --git a/grub-core/disk/key_protector.c b/grub-core/disk/key_protector.c new file mode 100644 index 000000000..0d146c1c0 --- /dev/null +++ b/grub-core/disk/key_protector.c @@ -0,0 +1,73 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Microsoft Corporation + * Copyright (C) 2024 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_key_protector *grub_key_protectors = NULL; + +grub_err_t +grub_key_protector_register (struct grub_key_protector *protector) +{ + if (protector == NULL || protector->name == NULL || protector->name[0] == '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid key protector for registration"); + + if (grub_key_protectors != NULL && + grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors), protector->name) != NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Key protector '%s' already registered", protector->name); + + grub_list_push (GRUB_AS_LIST_P (&grub_key_protectors), GRUB_AS_LIST (protector)); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_key_protector_unregister (struct grub_key_protector *protector) +{ + if (protector == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid key protector for unregistration"); + + grub_list_remove (GRUB_AS_LIST (protector)); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_key_protector_recover_key (const char *protector, grub_uint8_t **key, + grub_size_t *key_size) +{ + struct grub_key_protector *kp = NULL; + + if (grub_key_protectors == NULL) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "No key protector registered"); + + if (protector == NULL || protector[0] == '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid key protector"); + + kp = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_key_protectors), protector); + if (kp == NULL) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "Key protector '%s' not found", protector); + + return kp->recover_key (key, key_size); +} diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c index 0e4761b5a..0f4f22aaa 100644 --- a/grub-core/disk/ldm.c +++ b/grub-core/disk/ldm.c @@ -22,8 +22,10 @@ #include #include #include +#include #include #include +#include #ifdef GRUB_UTIL #include @@ -48,7 +50,7 @@ struct grub_ldm_vblk { grub_uint8_t type; grub_uint32_t unused2; grub_uint8_t dynamic[104]; -} __attribute__ ((packed)); +} GRUB_PACKED; #define LDM_VBLK_MAGIC "VBLK" enum @@ -82,7 +84,7 @@ struct grub_ldm_label grub_uint64_t pv_size; grub_uint64_t config_start; grub_uint64_t config_size; -} __attribute__ ((packed)); +} GRUB_PACKED; #define LDM_MAGIC "PRIVHEAD" @@ -103,37 +105,72 @@ read_int (grub_uint8_t *in, grub_size_t s) return ret; } -static const grub_gpt_part_type_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM; +static int +check_ldm_partition (grub_disk_t disk __attribute__ ((unused)), const grub_partition_t p, void *data) +{ + int *has_ldm = data; + + if (p->number >= 4) + return 1; + if (p->msdostype == GRUB_PC_PARTITION_TYPE_LDM) + { + *has_ldm = 1; + return 1; + } + return 0; +} + +static int +msdos_has_ldm_partition (grub_disk_t dsk) +{ + grub_err_t err; + int has_ldm = 0; + + err = grub_partition_msdos_iterate (dsk, check_ldm_partition, &has_ldm); + if (err) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + + return has_ldm; +} + +static const grub_guid_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM; + +/* Helper for gpt_ldm_sector. */ +static int +gpt_ldm_sector_iter (grub_disk_t disk, const grub_partition_t p, void *data) +{ + grub_disk_addr_t *sector = data; + struct grub_gpt_partentry gptdata; + grub_partition_t p2; + + p2 = disk->partition; + disk->partition = p->parent; + if (grub_disk_read (disk, p->offset, p->index, + sizeof (gptdata), &gptdata)) + { + disk->partition = p2; + return 0; + } + disk->partition = p2; + + if (! grub_memcmp (&gptdata.type, &ldm_type, 16)) + { + *sector = p->start + p->len - 1; + return 1; + } + return 0; +} static grub_disk_addr_t gpt_ldm_sector (grub_disk_t dsk) { grub_disk_addr_t sector = 0; grub_err_t err; - auto int hook (grub_disk_t disk, const grub_partition_t p); - int hook (grub_disk_t disk, const grub_partition_t p) - { - struct grub_gpt_partentry gptdata; - grub_partition_t p2; - p2 = disk->partition; - disk->partition = p->parent; - if (grub_disk_read (disk, p->offset, p->index, - sizeof (gptdata), &gptdata)) - { - disk->partition = p2; - return 0; - } - disk->partition = p2; - - if (! grub_memcmp (&gptdata.type, &ldm_type, 16)) - { - sector = p->start + p->len - 1; - return 1; - } - return 0; - } - err = grub_gpt_partition_map_iterate (dsk, hook); + err = grub_gpt_partition_map_iterate (dsk, gpt_ldm_sector_iter, §or); if (err) { grub_errno = GRUB_ERR_NONE; @@ -142,6 +179,36 @@ gpt_ldm_sector (grub_disk_t dsk) return sector; } +static void +free_pv (struct grub_diskfilter_pv *pv) +{ + if (pv == NULL) + return; + + grub_free (pv->internal_id); + grub_free (pv->id.uuid); + grub_free (pv); +} + +static void +free_lv (struct grub_diskfilter_lv *lv) +{ + if (lv == NULL) + return; + + grub_free (lv->internal_id); + grub_free (lv->name); + grub_free (lv->fullname); + if (lv->segments) + { + unsigned int i; + for (i = 0; i < lv->segment_count; i++) + grub_free (lv->segments[i].nodes); + grub_free (lv->segments); + } + grub_free (lv); +} + static struct grub_diskfilter_vg * make_vg (grub_disk_t disk, const struct grub_ldm_label *label) @@ -159,11 +226,8 @@ make_vg (grub_disk_t disk, vg->name = grub_malloc (LDM_NAME_STRLEN + 1); vg->uuid = grub_malloc (LDM_GUID_STRLEN + 1); if (! vg->uuid || !vg->name) - { - grub_free (vg->uuid); - grub_free (vg->name); - return NULL; - } + goto fail1; + grub_memcpy (vg->uuid, label->group_guid, LDM_GUID_STRLEN); grub_memcpy (vg->name, label->group_name, LDM_NAME_STRLEN); vg->name[LDM_NAME_STRLEN] = 0; @@ -182,6 +246,7 @@ make_vg (grub_disk_t disk, struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_ldm_vblk)]; unsigned i; + grub_size_t sz; err = grub_disk_read (disk, cursec, 0, sizeof(vblk), &vblk); if (err) @@ -213,20 +278,26 @@ make_vg (grub_disk_t disk, grub_free (pv); goto fail2; } - pv->internal_id = grub_malloc (ptr[0] + 2); - if (!pv->internal_id) + if (grub_add (ptr[0], 2, &sz)) { grub_free (pv); goto fail2; } + + pv->internal_id = grub_malloc (sz); + if (!pv->internal_id) + { + free_pv (pv); + goto fail2; + } grub_memcpy (pv->internal_id, ptr, (grub_size_t) ptr[0] + 1); pv->internal_id[(grub_size_t) ptr[0] + 1] = 0; - + ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (pv); + free_pv (pv); goto fail2; } /* ptr = name. */ @@ -234,11 +305,23 @@ make_vg (grub_disk_t disk, if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (pv); + free_pv (pv); goto fail2; } pv->id.uuidlen = *ptr; - pv->id.uuid = grub_malloc (pv->id.uuidlen + 1); + + if (grub_add (pv->id.uuidlen, 1, &sz)) + { + free_pv (pv); + goto fail2; + } + + pv->id.uuid = grub_malloc (sz); + if (pv->id.uuid == NULL) + { + free_pv (pv); + goto fail2; + } grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen); pv->id.uuid[pv->id.uuidlen] = 0; @@ -253,6 +336,7 @@ make_vg (grub_disk_t disk, struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_ldm_vblk)]; unsigned i; + grub_size_t sz; err = grub_disk_read (disk, cursec, 0, sizeof(vblk), &vblk); if (err) @@ -282,26 +366,37 @@ make_vg (grub_disk_t disk, lv->visible = 1; lv->segments = grub_zalloc (sizeof (*lv->segments)); if (!lv->segments) - goto fail2; + { + free_lv (lv); + goto fail2; + } lv->segments->start_extent = 0; lv->segments->type = GRUB_DISKFILTER_MIRROR; lv->segments->node_count = 0; lv->segments->node_alloc = 8; - lv->segments->nodes = grub_zalloc (sizeof (*lv->segments->nodes) - * lv->segments->node_alloc); + lv->segments->nodes = grub_calloc (lv->segments->node_alloc, + sizeof (*lv->segments->nodes)); if (!lv->segments->nodes) - goto fail2; + { + free_lv (lv); + goto fail2; + } ptr = vblk[i].dynamic; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (lv); + free_lv (lv); goto fail2; } - lv->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2); + if (grub_add (ptr[0], 2, &sz)) + { + free_lv (lv); + goto fail2; + } + lv->internal_id = grub_malloc (sz); if (!lv->internal_id) { - grub_free (lv); + free_lv (lv); goto fail2; } grub_memcpy (lv->internal_id, ptr, ptr[0] + 1); @@ -311,14 +406,18 @@ make_vg (grub_disk_t disk, if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (lv); + free_lv (lv); goto fail2; } - lv->name = grub_malloc (*ptr + 1); + if (grub_add (*ptr, 1, &sz)) + { + free_lv (lv); + goto fail2; + } + lv->name = grub_malloc (sz); if (!lv->name) { - grub_free (lv->internal_id); - grub_free (lv); + free_lv (lv); goto fail2; } grub_memcpy (lv->name, ptr + 1, *ptr); @@ -327,36 +426,28 @@ make_vg (grub_disk_t disk, vg->uuid, lv->name); if (!lv->fullname) { - grub_free (lv->internal_id); - grub_free (lv->name); - grub_free (lv); + free_lv (lv); goto fail2; } ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (lv->internal_id); - grub_free (lv->name); - grub_free (lv); + free_lv (lv); goto fail2; } /* ptr = volume type. */ ptr += *ptr + 1; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (lv->internal_id); - grub_free (lv->name); - grub_free (lv); + free_lv (lv); goto fail2; } /* ptr = flags. */ ptr += *ptr + 1; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (lv->internal_id); - grub_free (lv->name); - grub_free (lv); + free_lv (lv); goto fail2; } @@ -365,17 +456,13 @@ make_vg (grub_disk_t disk, /* ptr = number of children. */ if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (lv->internal_id); - grub_free (lv->name); - grub_free (lv); + free_lv (lv); goto fail2; } ptr += *ptr + 1; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (lv->internal_id); - grub_free (lv->name); - grub_free (lv); + free_lv (lv); goto fail2; } @@ -385,9 +472,7 @@ make_vg (grub_disk_t disk, || ptr + *ptr + 1>= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (lv->internal_id); - grub_free (lv->name); - grub_free (lv); + free_lv (lv); goto fail2; } lv->size = read_int (ptr + 1, *ptr); @@ -404,6 +489,7 @@ make_vg (grub_disk_t disk, struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_ldm_vblk)]; unsigned i; + grub_size_t sz; err = grub_disk_read (disk, cursec, 0, sizeof(vblk), &vblk); if (err) @@ -436,12 +522,18 @@ make_vg (grub_disk_t disk, ptr = vblk[i].dynamic; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { + free_lv (comp); goto fail2; } - comp->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2); + if (grub_add (ptr[0], 2, &sz)) + { + free_lv (comp); + goto fail2; + } + comp->internal_id = grub_malloc (sz); if (!comp->internal_id) { - grub_free (comp); + free_lv (comp); goto fail2; } grub_memcpy (comp->internal_id, ptr, ptr[0] + 1); @@ -450,16 +542,14 @@ make_vg (grub_disk_t disk, ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (comp->internal_id); - grub_free (comp); + free_lv (comp); goto fail2; } /* ptr = name. */ ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (comp->internal_id); - grub_free (comp); + free_lv (comp); goto fail2; } /* ptr = state. */ @@ -469,8 +559,7 @@ make_vg (grub_disk_t disk, ptr += 4; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (comp->internal_id); - grub_free (comp); + free_lv (comp); goto fail2; } @@ -478,16 +567,14 @@ make_vg (grub_disk_t disk, ptr += *ptr + 1; if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (comp->internal_id); - grub_free (comp); + free_lv (comp); goto fail2; } ptr += 8 + 8; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (comp->internal_id); - grub_free (comp); + free_lv (comp); goto fail2; } for (lv = vg->lvs; lv; lv = lv->next) @@ -498,8 +585,7 @@ make_vg (grub_disk_t disk, } if (!lv) { - grub_free (comp->internal_id); - grub_free (comp); + free_lv (comp); continue; } comp->size = lv->size; @@ -507,10 +593,13 @@ make_vg (grub_disk_t disk, { comp->segment_alloc = 8; comp->segment_count = 0; - comp->segments = grub_malloc (sizeof (*comp->segments) - * comp->segment_alloc); + comp->segments = grub_calloc (comp->segment_alloc, + sizeof (*comp->segments)); if (!comp->segments) - goto fail2; + { + free_lv (comp); + goto fail2; + } } else { @@ -518,7 +607,10 @@ make_vg (grub_disk_t disk, comp->segment_count = 1; comp->segments = grub_malloc (sizeof (*comp->segments)); if (!comp->segments) - goto fail2; + { + free_lv (comp); + goto fail2; + } comp->segments->start_extent = 0; comp->segments->extent_count = lv->size; comp->segments->layout = 0; @@ -530,17 +622,22 @@ make_vg (grub_disk_t disk, comp->segments->layout = GRUB_RAID_LAYOUT_SYMMETRIC_MASK; } else - goto fail2; + { + free_lv (comp); + goto fail2; + } ptr += *ptr + 1; ptr++; if (!(vblk[i].flags & 0x10)) - goto fail2; + { + free_lv (comp); + goto fail2; + } if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic) || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (comp->internal_id); - grub_free (comp); + free_lv (comp); goto fail2; } comp->segments->stripe_size = read_int (ptr + 1, *ptr); @@ -548,27 +645,37 @@ make_vg (grub_disk_t disk, if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { - grub_free (comp->internal_id); - grub_free (comp); + free_lv (comp); goto fail2; } comp->segments->node_count = read_int (ptr + 1, *ptr); comp->segments->node_alloc = comp->segments->node_count; - comp->segments->nodes = grub_zalloc (sizeof (*comp->segments->nodes) - * comp->segments->node_alloc); - if (!lv->segments->nodes) - goto fail2; + comp->segments->nodes = grub_calloc (comp->segments->node_alloc, + sizeof (*comp->segments->nodes)); + if (comp->segments->nodes == NULL) + { + free_lv (comp); + goto fail2; + } } if (lv->segments->node_alloc == lv->segments->node_count) { void *t; - lv->segments->node_alloc *= 2; - t = grub_realloc (lv->segments->nodes, - sizeof (*lv->segments->nodes) - * lv->segments->node_alloc); + + if (grub_mul (lv->segments->node_alloc, 2, &lv->segments->node_alloc) || + grub_mul (lv->segments->node_alloc, sizeof (*lv->segments->nodes), &sz)) + { + free_lv (comp); + goto fail2; + } + + t = grub_realloc (lv->segments->nodes, sz); if (!t) - goto fail2; + { + free_lv (comp); + goto fail2; + } lv->segments->nodes = t; } lv->segments->nodes[lv->segments->node_count].pv = 0; @@ -671,26 +778,29 @@ make_vg (grub_disk_t disk, if (comp->segment_alloc == 1) { - unsigned index; + unsigned node_index; ptr += *ptr + 1; if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) { goto fail2; } - index = read_int (ptr + 1, *ptr); - if (index < comp->segments->node_count) - comp->segments->nodes[index] = part; + node_index = read_int (ptr + 1, *ptr); + if (node_index < comp->segments->node_count) + comp->segments->nodes[node_index] = part; } else { if (comp->segment_alloc == comp->segment_count) { void *t; - comp->segment_alloc *= 2; - t = grub_realloc (comp->segments, - comp->segment_alloc - * sizeof (*comp->segments)); + grub_size_t sz; + + if (grub_mul (comp->segment_alloc, 2, &comp->segment_alloc) || + grub_mul (comp->segment_alloc, sizeof (*comp->segments), &sz)) + goto fail2; + + t = grub_realloc (comp->segments, sz); if (!t) goto fail2; comp->segments = t; @@ -703,7 +813,10 @@ make_vg (grub_disk_t disk, comp->segments[comp->segment_count].nodes = grub_malloc (sizeof (*comp->segments[comp->segment_count].nodes)); if (!comp->segments[comp->segment_count].nodes) - goto fail2; + { + grub_free (comp->segments); + goto fail2; + } comp->segments[comp->segment_count].nodes[0] = part; comp->segment_count++; } @@ -718,30 +831,24 @@ make_vg (grub_disk_t disk, struct grub_diskfilter_pv *pv, *next_pv; for (lv = vg->lvs; lv; lv = next_lv) { - unsigned i; - for (i = 0; i < lv->segment_count; i++) - grub_free (lv->segments[i].nodes); - next_lv = lv->next; - grub_free (lv->segments); - grub_free (lv->internal_id); - grub_free (lv->name); - grub_free (lv->fullname); - grub_free (lv); + free_lv (lv); + } for (pv = vg->pvs; pv; pv = next_pv) { next_pv = pv->next; - grub_free (pv->id.uuid); - grub_free (pv); + free_pv (pv); } } + fail1: grub_free (vg->uuid); + grub_free (vg->name); grub_free (vg); return NULL; } -static struct grub_diskfilter_vg * +static struct grub_diskfilter_vg * grub_ldm_detect (grub_disk_t disk, struct grub_diskfilter_pv_id *id, grub_disk_addr_t *start_sector) @@ -756,19 +863,22 @@ grub_ldm_detect (grub_disk_t disk, { int i; + int has_ldm = msdos_has_ldm_partition (disk); for (i = 0; i < 3; i++) { grub_disk_addr_t sector = LDM_LABEL_SECTOR; switch (i) { case 0: + if (!has_ldm) + continue; sector = LDM_LABEL_SECTOR; break; case 1: /* LDM is never inside a partition. */ - if (disk->partition) + if (!has_ldm || disk->partition) continue; - sector = grub_disk_get_size (disk); + sector = grub_disk_native_sectors (disk); if (sector == GRUB_DISK_SIZE_UNKNOWN) continue; sector--; @@ -867,6 +977,7 @@ int grub_util_is_ldm (grub_disk_t disk) { int i; + int has_ldm = msdos_has_ldm_partition (disk); for (i = 0; i < 3; i++) { grub_disk_addr_t sector = LDM_LABEL_SECTOR; @@ -876,13 +987,15 @@ grub_util_is_ldm (grub_disk_t disk) switch (i) { case 0: + if (!has_ldm) + continue; sector = LDM_LABEL_SECTOR; break; case 1: /* LDM is never inside a partition. */ - if (disk->partition) + if (!has_ldm || disk->partition) continue; - sector = grub_disk_get_size (disk); + sector = grub_disk_native_sectors (disk); if (sector == GRUB_DISK_SIZE_UNKNOWN) continue; sector--; @@ -921,7 +1034,7 @@ grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors, if (embed_type != GRUB_EMBED_PCBIOS) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "LDM curently supports only PC-BIOS embedding"); + "LDM currently supports only PC-BIOS embedding"); if (disk->partition) return grub_error (GRUB_ERR_BUG, "disk isn't LDM"); pv = grub_diskfilter_get_pv_from_disk (disk, &vg); @@ -970,12 +1083,12 @@ grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors, usable for bootloaders (called generically "embedding zone") and this operation is called "embedding". */ - N_("your LDM embedding Partition is too small;" + N_("your LDM Embedding Partition is too small;" " embedding won't be possible")); *nsectors = lv->size; if (*nsectors > max_nsectors) *nsectors = max_nsectors; - *sectors = grub_malloc (*nsectors * sizeof (**sectors)); + *sectors = grub_calloc (*nsectors, sizeof (**sectors)); if (!*sectors) return grub_errno; for (i = 0; i < *nsectors; i++) diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c index f3b19eff7..2bea4e922 100644 --- a/grub-core/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -24,6 +24,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -32,15 +33,19 @@ struct grub_loopback char *devname; grub_file_t file; struct grub_loopback *next; + unsigned long id; + grub_uint64_t refcnt; }; static struct grub_loopback *loopback_list; +static unsigned long last_id = 0; static const struct grub_arg_option options[] = { /* TRANSLATORS: The disk is simply removed from the list of available ones, not wiped, avoid to scare user. */ {"delete", 'd', 0, N_("Delete the specified loopback drive."), 0, 0}, + {"decompress", 'D', 0, N_("Transparently decompress backing file."), 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -61,6 +66,8 @@ delete_loopback (const char *name) if (! dev) return grub_error (GRUB_ERR_BAD_DEVICE, "device not found"); + if (dev->refcnt > 0) + return grub_error (GRUB_ERR_STILL_REFERENCED, "device still referenced"); /* Remove the device from the list. */ *prev = dev->next; @@ -77,6 +84,7 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; grub_file_t file; + enum grub_file_type type = GRUB_FILE_TYPE_LOOPBACK; struct grub_loopback *newdev; grub_err_t ret; @@ -85,27 +93,22 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) /* Check if `-d' was used. */ if (state[0].set) - return delete_loopback (args[0]); + return delete_loopback (args[0]); + + if (!state[1].set) + type |= GRUB_FILE_TYPE_NO_DECOMPRESS; if (argc < 2) return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); - file = grub_file_open (args[1]); - if (! file) - return grub_errno; - - /* First try to replace the old device. */ + /* Check that a device with requested name does not already exist. */ for (newdev = loopback_list; newdev; newdev = newdev->next) if (grub_strcmp (newdev->devname, args[0]) == 0) - break; + return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name already exists"); - if (newdev) - { - grub_file_close (newdev->file); - newdev->file = file; - - return 0; - } + file = grub_file_open (args[1], type); + if (! file) + return grub_errno; /* Unable to replace it, make a new entry. */ newdev = grub_malloc (sizeof (struct grub_loopback)); @@ -120,6 +123,8 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) } newdev->file = file; + newdev->id = last_id++; + newdev->refcnt = 0; /* Add the new entry to the list. */ newdev->next = loopback_list; @@ -135,15 +140,15 @@ fail: static int -grub_loopback_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull) +grub_loopback_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) { struct grub_loopback *d; if (pull != GRUB_DISK_PULL_NONE) return 0; for (d = loopback_list; d; d = d->next) { - if (hook (d->devname)) + if (hook (d->devname, hook_data)) return 1; } return 0; @@ -161,19 +166,35 @@ grub_loopback_open (const char *name, grub_disk_t disk) if (! dev) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + if (grub_add (dev->refcnt, 1, &dev->refcnt)) + grub_fatal ("Reference count overflow"); + /* Use the filesize for the disk size, round up to a complete sector. */ if (dev->file->size != GRUB_FILE_SIZE_UNKNOWN) disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1) / GRUB_DISK_SECTOR_SIZE); else disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; - disk->id = (unsigned long) dev; + /* Avoid reading more than 512M. */ + disk->max_agglomerate = 1 << (29 - GRUB_DISK_SECTOR_BITS + - GRUB_DISK_CACHE_BITS); + + disk->id = dev->id; disk->data = dev; return 0; } +static void +grub_loopback_close (grub_disk_t disk) +{ + struct grub_loopback *dev = disk->data; + + if (grub_sub (dev->refcnt, 1, &dev->refcnt)) + grub_fatal ("Reference count underflow"); +} + static grub_err_t grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf) @@ -206,17 +227,19 @@ grub_loopback_write (grub_disk_t disk __attribute ((unused)), grub_size_t size __attribute ((unused)), const char *buf __attribute ((unused))) { - return GRUB_ERR_NOT_IMPLEMENTED_YET; + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "loopback write is not supported"); } static struct grub_disk_dev grub_loopback_dev = { .name = "loopback", .id = GRUB_DISK_DEVICE_LOOPBACK_ID, - .iterate = grub_loopback_iterate, - .open = grub_loopback_open, - .read = grub_loopback_read, - .write = grub_loopback_write, + .disk_iterate = grub_loopback_iterate, + .disk_open = grub_loopback_open, + .disk_close = grub_loopback_close, + .disk_read = grub_loopback_read, + .disk_write = grub_loopback_write, .next = 0 }; @@ -225,7 +248,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(loopback) { cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, 0, - N_("[-d] DEVICENAME FILE."), + N_("[-d] [-D] DEVICENAME FILE."), /* TRANSLATORS: The file itself is not destroyed or transformed into drive. */ N_("Make a virtual drive from a file."), options); diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 44f3cacb7..9e1e6a5d9 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003,2007,2010,2011 Free Software Foundation, Inc. + * Copyright (C) 2003,2007,2010,2011,2019 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,8 +29,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); -#define MAX_PASSPHRASE 256 - #define LUKS_KEY_ENABLED 0x00AC71F3 /* On disk LUKS header */ @@ -56,7 +54,7 @@ struct grub_luks_phdr grub_uint32_t keyMaterialOffset; grub_uint32_t stripes; } keyblock[8]; -} __attribute__ ((packed)); +} GRUB_PACKED; typedef struct grub_luks_phdr *grub_luks_phdr_t; @@ -65,28 +63,16 @@ gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, grub_size_t blocknumbers); static grub_cryptodisk_t -configure_ciphers (grub_disk_t disk, const char *check_uuid, - int check_boot) +luks_scan (grub_disk_t disk, grub_cryptomount_args_t cargs) { grub_cryptodisk_t newdev; - const char *iptr; struct grub_luks_phdr header; - char *optr; - char uuid[sizeof (header.uuid) + 1]; char ciphername[sizeof (header.cipherName) + 1]; char ciphermode[sizeof (header.cipherMode) + 1]; - char *cipheriv = NULL; char hashspec[sizeof (header.hashSpec) + 1]; - grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL; - grub_crypto_cipher_handle_t essiv_cipher = NULL; - const gcry_md_spec_t *hash = NULL, *essiv_hash = NULL; - const struct gcry_cipher_spec *ciph; - grub_cryptodisk_mode_t mode; - grub_cryptodisk_mode_iv_t mode_iv; - int benbi_log = 0; grub_err_t err; - if (check_boot) + if (cargs->check_boot) return NULL; /* Read the LUKS header. */ @@ -103,18 +89,9 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, || grub_be_to_cpu16 (header.version) != 1) return NULL; - optr = uuid; - for (iptr = header.uuid; iptr < &header.uuid[ARRAY_SIZE (header.uuid)]; - iptr++) + if (cargs->search_uuid != NULL && grub_uuidcasecmp (cargs->search_uuid, header.uuid, sizeof (header.uuid)) != 0) { - if (*iptr != '-') - *optr++ = *iptr; - } - *optr = 0; - - if (check_uuid && grub_strcasecmp (check_uuid, uuid) != 0) - { - grub_dprintf ("luks", "%s != %s\n", uuid, check_uuid); + grub_dprintf ("luks", "%s != %s\n", header.uuid, cargs->search_uuid); return NULL; } @@ -126,191 +103,53 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, grub_memcpy (hashspec, header.hashSpec, sizeof (header.hashSpec)); hashspec[sizeof (header.hashSpec)] = 0; - ciph = grub_crypto_lookup_cipher_by_name (ciphername); - if (!ciph) - { - grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available", - ciphername); + newdev = grub_zalloc (sizeof (struct grub_cryptodisk)); + if (!newdev) return NULL; - } - - /* Configure the cipher used for the bulk data. */ - cipher = grub_crypto_cipher_open (ciph); - if (!cipher) - return NULL; - - if (grub_be_to_cpu32 (header.keyBytes) > 1024) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d", - grub_be_to_cpu32 (header.keyBytes)); - return NULL; - } - - /* Configure the cipher mode. */ - if (grub_strcmp (ciphermode, "ecb") == 0) - { - mode = GRUB_CRYPTODISK_MODE_ECB; - mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN; - cipheriv = NULL; - } - else if (grub_strcmp (ciphermode, "plain") == 0) - { - mode = GRUB_CRYPTODISK_MODE_CBC; - mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN; - cipheriv = NULL; - } - else if (grub_memcmp (ciphermode, "cbc-", sizeof ("cbc-") - 1) == 0) - { - mode = GRUB_CRYPTODISK_MODE_CBC; - cipheriv = ciphermode + sizeof ("cbc-") - 1; - } - else if (grub_memcmp (ciphermode, "pcbc-", sizeof ("pcbc-") - 1) == 0) - { - mode = GRUB_CRYPTODISK_MODE_PCBC; - cipheriv = ciphermode + sizeof ("pcbc-") - 1; - } - else if (grub_memcmp (ciphermode, "xts-", sizeof ("xts-") - 1) == 0) - { - mode = GRUB_CRYPTODISK_MODE_XTS; - cipheriv = ciphermode + sizeof ("xts-") - 1; - secondary_cipher = grub_crypto_cipher_open (ciph); - if (!secondary_cipher) - { - grub_crypto_cipher_close (cipher); - return NULL; - } - if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) - { - grub_crypto_cipher_close (cipher); - grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", - cipher->cipher->blocksize); - return NULL; - } - if (secondary_cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) - { - grub_crypto_cipher_close (cipher); - grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported XTS block size: %d", - secondary_cipher->cipher->blocksize); - return NULL; - } - } - else if (grub_memcmp (ciphermode, "lrw-", sizeof ("lrw-") - 1) == 0) - { - mode = GRUB_CRYPTODISK_MODE_LRW; - cipheriv = ciphermode + sizeof ("lrw-") - 1; - if (cipher->cipher->blocksize != GRUB_CRYPTODISK_GF_BYTES) - { - grub_crypto_cipher_close (cipher); - grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported LRW block size: %d", - cipher->cipher->blocksize); - return NULL; - } - } - else - { - grub_crypto_cipher_close (cipher); - grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown cipher mode: %s", - ciphermode); - return NULL; - } - - if (cipheriv == NULL); - else if (grub_memcmp (cipheriv, "plain", sizeof ("plain") - 1) == 0) - mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN; - else if (grub_memcmp (cipheriv, "plain64", sizeof ("plain64") - 1) == 0) - mode_iv = GRUB_CRYPTODISK_MODE_IV_PLAIN64; - else if (grub_memcmp (cipheriv, "benbi", sizeof ("benbi") - 1) == 0) - { - if (cipher->cipher->blocksize & (cipher->cipher->blocksize - 1) - || cipher->cipher->blocksize == 0) - grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported benbi blocksize: %d", - cipher->cipher->blocksize); - for (benbi_log = 0; - (cipher->cipher->blocksize << benbi_log) < GRUB_DISK_SECTOR_SIZE; - benbi_log++); - mode_iv = GRUB_CRYPTODISK_MODE_IV_BENBI; - } - else if (grub_memcmp (cipheriv, "null", sizeof ("null") - 1) == 0) - mode_iv = GRUB_CRYPTODISK_MODE_IV_NULL; - else if (grub_memcmp (cipheriv, "essiv:", sizeof ("essiv:") - 1) == 0) - { - char *hash_str = cipheriv + 6; - - mode_iv = GRUB_CRYPTODISK_MODE_IV_ESSIV; - - /* Configure the hash and cipher used for ESSIV. */ - essiv_hash = grub_crypto_lookup_md_by_name (hash_str); - if (!essiv_hash) - { - grub_crypto_cipher_close (cipher); - grub_error (GRUB_ERR_FILE_NOT_FOUND, - "Couldn't load %s hash", hash_str); - return NULL; - } - essiv_cipher = grub_crypto_cipher_open (ciph); - if (!essiv_cipher) - { - grub_crypto_cipher_close (cipher); - return NULL; - } - } - else - { - grub_crypto_cipher_close (cipher); - grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown IV mode: %s", - cipheriv); - return NULL; - } + newdev->offset_sectors = grub_be_to_cpu32 (header.payloadOffset); + newdev->source_disk = NULL; + newdev->log_sector_size = GRUB_LUKS1_LOG_SECTOR_SIZE; + newdev->total_sectors = grub_disk_native_sectors (disk) - newdev->offset_sectors; + grub_memcpy (newdev->uuid, header.uuid, sizeof (header.uuid)); + newdev->modname = "luks"; /* Configure the hash used for the AF splitter and HMAC. */ - hash = grub_crypto_lookup_md_by_name (hashspec); - if (!hash) + newdev->hash = grub_crypto_lookup_md_by_name (hashspec); + if (!newdev->hash) { - grub_crypto_cipher_close (cipher); - grub_crypto_cipher_close (essiv_cipher); - grub_crypto_cipher_close (secondary_cipher); + grub_free (newdev); grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", hashspec); return NULL; } - newdev = grub_zalloc (sizeof (struct grub_cryptodisk)); - if (!newdev) - return NULL; - newdev->cipher = cipher; - newdev->offset = grub_be_to_cpu32 (header.payloadOffset); - newdev->source_disk = NULL; - newdev->benbi_log = benbi_log; - newdev->mode = mode; - newdev->mode_iv = mode_iv; - newdev->secondary_cipher = secondary_cipher; - newdev->essiv_cipher = essiv_cipher; - newdev->essiv_hash = essiv_hash; - newdev->hash = hash; - newdev->log_sector_size = 9; - newdev->total_length = grub_disk_get_size (disk) - newdev->offset; - grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid)); -#ifdef GRUB_UTIL - newdev->modname = "luks"; -#endif - COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (uuid)); + err = grub_cryptodisk_setcipher (newdev, ciphername, ciphermode); + if (err) + { + grub_free (newdev); + return NULL; + } + + COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= sizeof (header.uuid)); return newdev; } static grub_err_t luks_recover_key (grub_disk_t source, - grub_cryptodisk_t dev) + grub_cryptodisk_t dev, + grub_cryptomount_args_t cargs) { struct grub_luks_phdr header; grub_size_t keysize; grub_uint8_t *split_key = NULL; - char passphrase[MAX_PASSPHRASE] = ""; grub_uint8_t candidate_digest[sizeof (header.mkDigest)]; unsigned i; grub_size_t length; grub_err_t err; grub_size_t max_stripes = 1; - char *tmp; + + if (cargs->key_data == NULL || cargs->key_len == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data"); err = grub_disk_read (source, 0, 0, sizeof (header), &header); if (err) @@ -318,36 +157,24 @@ luks_recover_key (grub_disk_t source, grub_puts_ (N_("Attempting to decrypt master key...")); keysize = grub_be_to_cpu32 (header.keyBytes); + if (keysize > GRUB_CRYPTODISK_MAX_KEYLEN) + return grub_error (GRUB_ERR_BAD_FS, "key is too long"); for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) if (grub_be_to_cpu32 (header.keyblock[i].active) == LUKS_KEY_ENABLED && grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes) max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes); - split_key = grub_malloc (keysize * max_stripes); + split_key = grub_calloc (keysize, max_stripes); if (!split_key) return grub_errno; - /* Get the passphrase from the user. */ - tmp = NULL; - if (source->partition) - tmp = grub_partition_get_name (source->partition); - grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name, - source->partition ? "," : "", tmp ? : "", - dev->uuid); - grub_free (tmp); - if (!grub_password_get (passphrase, MAX_PASSPHRASE)) - { - grub_free (split_key); - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied"); - } - /* Try to recover master key from each active keyslot. */ for (i = 0; i < ARRAY_SIZE (header.keyblock); i++) { gcry_err_code_t gcry_err; - grub_uint8_t candidate_key[keysize]; - grub_uint8_t digest[keysize]; + grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN]; /* Check if keyslot is enabled. */ if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED) @@ -356,8 +183,8 @@ luks_recover_key (grub_disk_t source, grub_dprintf ("luks", "Trying keyslot %d\n", i); /* Calculate the PBKDF2 of the user supplied passphrase. */ - gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase, - grub_strlen (passphrase), + gcry_err = grub_crypto_pbkdf2 (dev->hash, cargs->key_data, + cargs->key_len, header.keyblock[i].passwordSalt, sizeof (header.keyblock[i].passwordSalt), grub_be_to_cpu32 (header.keyblock[i]. @@ -372,7 +199,7 @@ luks_recover_key (grub_disk_t source, grub_dprintf ("luks", "PBKDF2 done\n"); - gcry_err = grub_cryptodisk_setkey (dev, digest, keysize); + gcry_err = grub_cryptodisk_setkey (dev, digest, keysize); if (gcry_err) { grub_free (split_key); @@ -392,7 +219,8 @@ luks_recover_key (grub_disk_t source, return err; } - gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0); + gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0, + GRUB_LUKS1_LOG_SECTOR_SIZE); if (gcry_err) { grub_free (split_key); @@ -439,7 +267,7 @@ luks_recover_key (grub_disk_t source, grub_printf_ (N_("Slot %d opened\n"), i); /* Set the master key. */ - gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize); + gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize); if (gcry_err) { grub_free (split_key); @@ -451,11 +279,12 @@ luks_recover_key (grub_disk_t source, return GRUB_ERR_NONE; } + grub_free (split_key); return GRUB_ACCESS_DENIED; } struct grub_cryptodisk_dev luks_crypto = { - .scan = configure_ciphers, + .scan = luks_scan, .recover_key = luks_recover_key }; diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c new file mode 100644 index 000000000..8036d76ff --- /dev/null +++ b/grub-core/disk/luks2.c @@ -0,0 +1,808 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2019 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define LUKS_MAGIC_1ST "LUKS\xBA\xBE" +#define LUKS_MAGIC_2ND "SKUL\xBA\xBE" + +enum grub_luks2_kdf_type +{ + LUKS2_KDF_TYPE_ARGON2I, + LUKS2_KDF_TYPE_PBKDF2 +}; +typedef enum grub_luks2_kdf_type grub_luks2_kdf_type_t; + +/* On disk LUKS header */ +struct grub_luks2_header +{ + char magic[6]; + grub_uint16_t version; + grub_uint64_t hdr_size; + grub_uint64_t seqid; + char label[48]; + char csum_alg[32]; + grub_uint8_t salt[64]; + char uuid[40]; + char subsystem[48]; + grub_uint64_t hdr_offset; + char _padding[184]; + grub_uint8_t csum[64]; + char _padding4096[7*512]; +} GRUB_PACKED; +typedef struct grub_luks2_header grub_luks2_header_t; + +struct grub_luks2_keyslot +{ + /* The integer key to the associative array of keyslots. */ + grub_uint64_t idx; + grub_int64_t key_size; + grub_int64_t priority; + struct + { + const char *encryption; + grub_uint64_t offset; + grub_uint64_t size; + grub_int64_t key_size; + } area; + struct + { + const char *hash; + grub_int64_t stripes; + } af; + struct + { + grub_luks2_kdf_type_t type; + const char *salt; + union + { + struct + { + grub_int64_t time; + grub_int64_t memory; + grub_int64_t cpus; + } argon2i; + struct + { + const char *hash; + grub_int64_t iterations; + } pbkdf2; + } u; + } kdf; +}; +typedef struct grub_luks2_keyslot grub_luks2_keyslot_t; + +struct grub_luks2_segment +{ + grub_uint64_t idx; + grub_uint64_t offset; + const char *size; + const char *encryption; + grub_int64_t sector_size; +}; +typedef struct grub_luks2_segment grub_luks2_segment_t; + +struct grub_luks2_digest +{ + grub_uint64_t idx; + /* Both keyslots and segments are interpreted as bitfields here */ + grub_uint64_t keyslots; + grub_uint64_t segments; + const char *salt; + const char *digest; + const char *hash; + grub_int64_t iterations; +}; +typedef struct grub_luks2_digest grub_luks2_digest_t; + +gcry_err_code_t AF_merge (const gcry_md_spec_t * hash, grub_uint8_t * src, + grub_uint8_t * dst, grub_size_t blocksize, + grub_size_t blocknumbers); + +static grub_err_t +luks2_parse_keyslot (grub_luks2_keyslot_t *out, const grub_json_t *keyslot) +{ + grub_json_t area, af, kdf; + const char *type; + + if (grub_json_getstring (&type, keyslot, "type")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing or invalid keyslot"); + else if (grub_strcmp (type, "luks2")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported keyslot type %s", type); + else if (grub_json_getint64 (&out->key_size, keyslot, "key_size")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing keyslot information"); + if (grub_json_getint64 (&out->priority, keyslot, "priority")) + out->priority = 1; + + if (grub_json_getvalue (&area, keyslot, "area") || + grub_json_getstring (&type, &area, "type")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing or invalid key area"); + else if (grub_strcmp (type, "raw")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported key area type: %s", type); + else if (grub_json_getuint64 (&out->area.offset, &area, "offset") || + grub_json_getuint64 (&out->area.size, &area, "size") || + grub_json_getstring (&out->area.encryption, &area, "encryption") || + grub_json_getint64 (&out->area.key_size, &area, "key_size")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing key area information"); + + if (grub_json_getvalue (&kdf, keyslot, "kdf") || + grub_json_getstring (&type, &kdf, "type") || + grub_json_getstring (&out->kdf.salt, &kdf, "salt")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing or invalid KDF"); + else if (!grub_strcmp (type, "argon2i") || !grub_strcmp (type, "argon2id")) + { + out->kdf.type = LUKS2_KDF_TYPE_ARGON2I; + if (grub_json_getint64 (&out->kdf.u.argon2i.time, &kdf, "time") || + grub_json_getint64 (&out->kdf.u.argon2i.memory, &kdf, "memory") || + grub_json_getint64 (&out->kdf.u.argon2i.cpus, &kdf, "cpus")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing Argon2i parameters"); + } + else if (!grub_strcmp (type, "pbkdf2")) + { + out->kdf.type = LUKS2_KDF_TYPE_PBKDF2; + if (grub_json_getstring (&out->kdf.u.pbkdf2.hash, &kdf, "hash") || + grub_json_getint64 (&out->kdf.u.pbkdf2.iterations, &kdf, "iterations")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing PBKDF2 parameters"); + } + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported KDF type %s", type); + + if (grub_json_getvalue (&af, keyslot, "af") || + grub_json_getstring (&type, &af, "type")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing or invalid area"); + if (grub_strcmp (type, "luks1")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported AF type %s", type); + if (grub_json_getint64 (&out->af.stripes, &af, "stripes") || + grub_json_getstring (&out->af.hash, &af, "hash")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing AF parameters"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +luks2_parse_segment (grub_luks2_segment_t *out, const grub_json_t *segment) +{ + const char *type; + + if (grub_json_getstring (&type, segment, "type")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid segment type"); + else if (grub_strcmp (type, "crypt")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported segment type %s", type); + + if (grub_json_getuint64 (&out->offset, segment, "offset") || + grub_json_getstring (&out->size, segment, "size") || + grub_json_getstring (&out->encryption, segment, "encryption") || + grub_json_getint64 (&out->sector_size, segment, "sector_size")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing segment parameters"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +luks2_parse_digest (grub_luks2_digest_t *out, const grub_json_t *digest) +{ + grub_json_t segments, keyslots, o; + grub_size_t i, size; + grub_uint64_t bit; + const char *type; + + if (grub_json_getstring (&type, digest, "type")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid digest type"); + else if (grub_strcmp (type, "pbkdf2")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported digest type %s", type); + + if (grub_json_getvalue (&segments, digest, "segments") || + grub_json_getvalue (&keyslots, digest, "keyslots") || + grub_json_getstring (&out->salt, digest, "salt") || + grub_json_getstring (&out->digest, digest, "digest") || + grub_json_getstring (&out->hash, digest, "hash") || + grub_json_getint64 (&out->iterations, digest, "iterations")) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Missing digest parameters"); + + if (grub_json_getsize (&size, &segments)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Digest references no segments"); + + out->segments = 0; + for (i = 0; i < size; i++) + { + if (grub_json_getchild (&o, &segments, i) || + grub_json_getuint64 (&bit, &o, NULL)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid segment"); + out->segments |= (1 << bit); + } + + if (grub_json_getsize (&size, &keyslots)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Digest references no keyslots"); + + out->keyslots = 0; + for (i = 0; i < size; i++) + { + if (grub_json_getchild (&o, &keyslots, i) || + grub_json_getuint64 (&bit, &o, NULL)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid keyslot"); + out->keyslots |= (1 << bit); + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +luks2_get_keyslot (grub_luks2_keyslot_t *k, grub_luks2_digest_t *d, grub_luks2_segment_t *s, + const grub_json_t *root, grub_size_t keyslot_json_idx) +{ + grub_json_t keyslots, keyslot, digests, digest, segments, segment; + grub_size_t json_idx, size; + + /* Get nth keyslot */ + if (grub_json_getvalue (&keyslots, root, "keyslots") || + grub_json_getchild (&keyslot, &keyslots, keyslot_json_idx) || + grub_json_getuint64 (&k->idx, &keyslot, NULL) || + grub_json_getchild (&keyslot, &keyslot, 0) || + luks2_parse_keyslot (k, &keyslot)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse keyslot index %" PRIuGRUB_SIZE, keyslot_json_idx); + + /* Get digest that matches the keyslot. */ + if (grub_json_getvalue (&digests, root, "digests") || + grub_json_getsize (&size, &digests)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get digests"); + for (json_idx = 0; json_idx < size; json_idx++) + { + if (grub_json_getchild (&digest, &digests, json_idx) || + grub_json_getuint64 (&d->idx, &digest, NULL) || + grub_json_getchild (&digest, &digest, 0) || + luks2_parse_digest (d, &digest)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse digest index %" PRIuGRUB_SIZE, json_idx); + + if ((d->keyslots & (1 << k->idx))) + break; + } + if (json_idx == size) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No digest for keyslot \"%" PRIuGRUB_UINT64_T "\"", k->idx); + + /* Get segment that matches the digest. */ + if (grub_json_getvalue (&segments, root, "segments") || + grub_json_getsize (&size, &segments)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get segments"); + for (json_idx = 0; json_idx < size; json_idx++) + { + if (grub_json_getchild (&segment, &segments, json_idx) || + grub_json_getuint64 (&s->idx, &segment, NULL) || + grub_json_getchild (&segment, &segment, 0) || + luks2_parse_segment (s, &segment)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not parse segment index %" PRIuGRUB_SIZE, json_idx); + + if ((d->segments & (1 << s->idx))) + break; + } + if (json_idx == size) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "No segment for digest \"%" PRIuGRUB_UINT64_T "\"", d->idx); + + return GRUB_ERR_NONE; +} + +/* Determine whether to use primary or secondary header */ +static grub_err_t +luks2_read_header (grub_disk_t disk, grub_luks2_header_t *outhdr) +{ + grub_luks2_header_t primary, secondary, *header = &primary; + grub_err_t ret; + + /* Read the primary LUKS header. */ + ret = grub_disk_read (disk, 0, 0, sizeof (primary), &primary); + if (ret) + return ret; + + /* Look for LUKS magic sequence. */ + if (grub_memcmp (primary.magic, LUKS_MAGIC_1ST, sizeof (primary.magic)) || + grub_be_to_cpu16 (primary.version) != 2) + return GRUB_ERR_BAD_SIGNATURE; + + /* Read the secondary header. */ + ret = grub_disk_read (disk, 0, grub_be_to_cpu64 (primary.hdr_size), sizeof (secondary), &secondary); + if (ret) + return ret; + + /* Look for LUKS magic sequence. */ + if (grub_memcmp (secondary.magic, LUKS_MAGIC_2ND, sizeof (secondary.magic)) || + grub_be_to_cpu16 (secondary.version) != 2) + return GRUB_ERR_BAD_SIGNATURE; + + if (grub_be_to_cpu64 (primary.seqid) < grub_be_to_cpu64 (secondary.seqid)) + header = &secondary; + grub_memcpy (outhdr, header, sizeof (*header)); + + return GRUB_ERR_NONE; +} + +static grub_cryptodisk_t +luks2_scan (grub_disk_t disk, grub_cryptomount_args_t cargs) +{ + grub_cryptodisk_t cryptodisk; + grub_luks2_header_t header; + + if (cargs->check_boot) + return NULL; + + if (luks2_read_header (disk, &header)) + { + grub_errno = GRUB_ERR_NONE; + return NULL; + } + + if (cargs->search_uuid != NULL && grub_uuidcasecmp (cargs->search_uuid, header.uuid, sizeof (header.uuid)) != 0) + { + grub_dprintf ("luks2", "%s != %s\n", header.uuid, cargs->search_uuid); + return NULL; + } + + cryptodisk = grub_zalloc (sizeof (*cryptodisk)); + if (!cryptodisk) + return NULL; + + COMPILE_TIME_ASSERT (sizeof (cryptodisk->uuid) >= sizeof (header.uuid)); + grub_memcpy (cryptodisk->uuid, header.uuid, sizeof (header.uuid)); + + cryptodisk->modname = "luks2"; + return cryptodisk; +} + +static grub_err_t +luks2_base64_decode (const char *in, grub_size_t inlen, grub_uint8_t *decoded, idx_t *decodedlen) +{ + grub_size_t unescaped_len = 0; + char *unescaped = NULL; + bool successful; + + if (grub_json_unescape (&unescaped, &unescaped_len, in, inlen) != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("could not unescape Base64 string")); + + successful = base64_decode (unescaped, unescaped_len, (char *) decoded, decodedlen); + grub_free (unescaped); + if (!successful) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("could not decode Base64 string")); + + return GRUB_ERR_NONE; +} + +static grub_err_t +luks2_verify_key (grub_luks2_digest_t *d, grub_uint8_t *candidate_key, + grub_size_t candidate_key_len) +{ + grub_uint8_t candidate_digest[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN], salt[GRUB_CRYPTODISK_MAX_KEYLEN]; + idx_t saltlen = sizeof (salt), digestlen = sizeof (digest); + const gcry_md_spec_t *hash; + gcry_err_code_t gcry_ret; + + /* Decode both digest and salt */ + if (luks2_base64_decode (d->digest, grub_strlen (d->digest), + digest, &digestlen) != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid digest"); + if (luks2_base64_decode (d->salt, grub_strlen (d->salt), + salt, &saltlen) != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid digest salt"); + + /* Configure the hash used for the digest. */ + hash = grub_crypto_lookup_md_by_name (d->hash); + if (!hash) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", d->hash); + + /* Calculate the candidate key's digest */ + gcry_ret = grub_crypto_pbkdf2 (hash, + candidate_key, candidate_key_len, + salt, saltlen, + d->iterations, + candidate_digest, digestlen); + if (gcry_ret) + return grub_crypto_gcry_error (gcry_ret); + + if (grub_memcmp (candidate_digest, digest, digestlen) != 0) + return grub_error (GRUB_ERR_ACCESS_DENIED, "Mismatching digests"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +luks2_decrypt_key (grub_uint8_t *out_key, + grub_disk_t source, grub_cryptodisk_t crypt, + grub_luks2_keyslot_t *k, + const grub_uint8_t *passphrase, grub_size_t passphraselen) +{ + grub_uint8_t area_key[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t salt[GRUB_CRYPTODISK_MAX_KEYLEN]; + grub_uint8_t *split_key = NULL; + idx_t saltlen = sizeof (salt); + char cipher[32], *p; + const gcry_md_spec_t *hash; + gcry_err_code_t gcry_ret; + grub_err_t ret; + + if (luks2_base64_decode (k->kdf.salt, grub_strlen (k->kdf.salt), + salt, &saltlen) != GRUB_ERR_NONE) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid keyslot salt"); + goto err; + } + + /* Calculate the binary area key of the user supplied passphrase. */ + switch (k->kdf.type) + { + case LUKS2_KDF_TYPE_ARGON2I: + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Argon2 not supported"); + goto err; + case LUKS2_KDF_TYPE_PBKDF2: + hash = grub_crypto_lookup_md_by_name (k->kdf.u.pbkdf2.hash); + if (!hash) + { + ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", + k->kdf.u.pbkdf2.hash); + goto err; + } + + gcry_ret = grub_crypto_pbkdf2 (hash, (grub_uint8_t *) passphrase, + passphraselen, + salt, saltlen, + k->kdf.u.pbkdf2.iterations, + area_key, k->area.key_size); + if (gcry_ret) + { + ret = grub_crypto_gcry_error (gcry_ret); + goto err; + } + + break; + } + + /* Set up disk encryption parameters for the key area */ + grub_strncpy (cipher, k->area.encryption, sizeof (cipher)); + p = grub_memchr (cipher, '-', grub_strlen (cipher)); + if (!p) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid encryption"); + *p = '\0'; + + ret = grub_cryptodisk_setcipher (crypt, cipher, p + 1); + if (ret) + return ret; + + gcry_ret = grub_cryptodisk_setkey (crypt, area_key, k->area.key_size); + if (gcry_ret) + { + ret = grub_crypto_gcry_error (gcry_ret); + goto err; + } + + /* Read and decrypt the binary key area with the area key. */ + split_key = grub_malloc (k->area.size); + if (!split_key) + { + ret = grub_errno; + goto err; + } + + grub_errno = GRUB_ERR_NONE; + ret = grub_disk_read (source, 0, k->area.offset, k->area.size, split_key); + if (ret) + { + grub_error (GRUB_ERR_IO, "Read error: %s\n", grub_errmsg); + goto err; + } + + /* + * The key slots area is always encrypted in 512-byte sectors, + * regardless of encrypted data sector size. + */ + gcry_ret = grub_cryptodisk_decrypt (crypt, split_key, k->area.size, 0, + GRUB_LUKS1_LOG_SECTOR_SIZE); + if (gcry_ret) + { + ret = grub_crypto_gcry_error (gcry_ret); + goto err; + } + + /* Configure the hash used for anti-forensic merging. */ + hash = grub_crypto_lookup_md_by_name (k->af.hash); + if (!hash) + { + ret = grub_error (GRUB_ERR_FILE_NOT_FOUND, "Couldn't load %s hash", + k->af.hash); + goto err; + } + + /* Merge the decrypted key material to get the candidate master key. */ + gcry_ret = AF_merge (hash, split_key, out_key, k->key_size, k->af.stripes); + if (gcry_ret) + { + ret = grub_crypto_gcry_error (gcry_ret); + goto err; + } + + grub_dprintf ("luks2", "Candidate key recovered\n"); + + err: + grub_free (split_key); + return ret; +} + +static grub_err_t +luks2_recover_key (grub_disk_t source, + grub_cryptodisk_t crypt, + grub_cryptomount_args_t cargs) +{ + grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN]; + char cipher[32], *json_header = NULL, *ptr; + grub_size_t candidate_key_len = 0, json_idx, size; + grub_luks2_header_t header; + grub_luks2_keyslot_t keyslot; + grub_luks2_digest_t digest; + grub_luks2_segment_t segment; + gcry_err_code_t gcry_ret; + grub_json_t *json = NULL, keyslots; + grub_err_t ret; + grub_size_t sz; + + if (cargs->key_data == NULL || cargs->key_len == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data"); + + ret = luks2_read_header (source, &header); + if (ret) + return ret; + + if (grub_sub (grub_be_to_cpu64 (header.hdr_size), sizeof (header), &sz)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "underflow detected while calculating json header size"); + + json_header = grub_zalloc (sz); + if (!json_header) + return GRUB_ERR_OUT_OF_MEMORY; + + /* Read the JSON area. */ + ret = grub_disk_read (source, 0, grub_be_to_cpu64 (header.hdr_offset) + sizeof (header), + grub_be_to_cpu64 (header.hdr_size) - sizeof (header), json_header); + if (ret) + goto err; + + ptr = grub_memchr (json_header, 0, grub_be_to_cpu64 (header.hdr_size) - sizeof (header)); + if (!ptr) + goto err; + + ret = grub_json_parse (&json, json_header, grub_be_to_cpu64 (header.hdr_size)); + if (ret) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid LUKS2 JSON header"); + goto err; + } + + if (grub_json_getvalue (&keyslots, json, "keyslots") || + grub_json_getsize (&size, &keyslots)) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Could not get keyslots"); + goto err; + } + + if (grub_disk_native_sectors (source) == GRUB_DISK_SIZE_UNKNOWN) + { + /* FIXME: Allow use of source disk, and maybe cause errors in read. */ + grub_dprintf ("luks2", "Source disk %s has an unknown size, " + "conservatively returning error\n", source->name); + ret = grub_error (GRUB_ERR_BUG, "Unknown size of luks2 source device"); + goto err; + } + + /* Try all keyslot */ + for (json_idx = 0; json_idx < size; json_idx++) + { + char indexstr[21]; /* log10(2^64) ~ 20, plus NUL character. */ + typeof (source->total_sectors) max_crypt_sectors = 0; + + grub_errno = GRUB_ERR_NONE; + ret = luks2_get_keyslot (&keyslot, &digest, &segment, json, json_idx); + if (ret) + { + /* + * luks2_get_keyslot() can fail for a variety of reasons that do not + * necessarily mean the next keyslot should not be tried (e.g. a new + * kdf type). So always try the next slot. + */ + grub_dprintf ("luks2", "Failed to get keyslot %" PRIuGRUB_UINT64_T "\n", keyslot.idx); + continue; + } + if (grub_errno != GRUB_ERR_NONE) + grub_dprintf ("luks2", "Ignoring unhandled error %d from luks2_get_keyslot\n", grub_errno); + + if (keyslot.priority == 0) + { + grub_dprintf ("luks2", "Ignoring keyslot \"%" PRIuGRUB_UINT64_T "\" due to priority\n", keyslot.idx); + continue; + } + + grub_dprintf ("luks2", "Trying keyslot \"%" PRIuGRUB_UINT64_T "\"\n", keyslot.idx); + + /* Sector size should be one of 512, 1024, 2048, or 4096. */ + if (!(segment.sector_size == 512 || segment.sector_size == 1024 || + segment.sector_size == 2048 || segment.sector_size == 4096)) + { + grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" sector" + " size %" PRIuGRUB_UINT64_T " is not one of" + " 512, 1024, 2048, or 4096\n", + segment.idx, segment.sector_size); + continue; + } + + /* Set up disk according to keyslot's segment. */ + crypt->offset_sectors = grub_divmod64 (segment.offset, segment.sector_size, NULL); + crypt->log_sector_size = grub_log2ull (segment.sector_size); + /* Set to the source disk/partition size, which is the maximum we allow. */ + max_crypt_sectors = grub_disk_native_sectors (source); + max_crypt_sectors = grub_convert_sector (max_crypt_sectors, GRUB_DISK_SECTOR_BITS, + crypt->log_sector_size); + + if (max_crypt_sectors < crypt->offset_sectors) + { + grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" has offset" + " %" PRIuGRUB_UINT64_T " which is greater than" + " source disk size %" PRIuGRUB_UINT64_T "," + " skipping\n", segment.idx, crypt->offset_sectors, + max_crypt_sectors); + continue; + } + + if (grub_strcmp (segment.size, "dynamic") == 0) + crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors; + else + { + grub_errno = GRUB_ERR_NONE; + + /* Convert segment.size to sectors, rounding up to nearest sector */ + crypt->total_sectors = grub_strtoull (segment.size, NULL, 10); + + if (grub_errno == GRUB_ERR_NONE) + { + crypt->total_sectors = ALIGN_UP (crypt->total_sectors, + 1 << crypt->log_sector_size); + crypt->total_sectors >>= crypt->log_sector_size; + } + else if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" size" + " \"%s\" is not a parsable number," + " skipping keyslot\n", + segment.idx, segment.size); + continue; + } + else if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + { + /* + * There was an overflow in parsing segment.size, so disk must + * be very large or the string is incorrect. + * + * TODO: Allow reading of at least up max_crypt_sectors. Really, + * its very unlikely one would be booting from such a large drive + * anyway. Use another smaller LUKS2 boot device. + */ + grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" size" + " %s overflowed 64-bit unsigned integer," + " skipping keyslot\n", segment.idx, segment.size); + continue; + } + } + + if (crypt->total_sectors == 0) + { + grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" has zero" + " sectors, skipping\n", segment.idx); + continue; + } + else if (max_crypt_sectors < (crypt->offset_sectors + crypt->total_sectors)) + { + grub_dprintf ("luks2", "Segment \"%" PRIuGRUB_UINT64_T "\" has last" + " data position greater than source disk size," + " the end of the crypto device will be" + " inaccessible\n", segment.idx); + + /* Allow decryption up to the end of the source disk. */ + crypt->total_sectors = max_crypt_sectors - crypt->offset_sectors; + } + + ret = luks2_decrypt_key (candidate_key, source, crypt, &keyslot, + cargs->key_data, cargs->key_len); + if (ret) + { + grub_dprintf ("luks2", "Decryption with keyslot \"%" PRIuGRUB_UINT64_T "\" failed: %s\n", + keyslot.idx, grub_errmsg); + continue; + } + + ret = luks2_verify_key (&digest, candidate_key, keyslot.key_size); + if (ret) + { + grub_dprintf ("luks2", "Could not open keyslot \"%" PRIuGRUB_UINT64_T "\": %s\n", + keyslot.idx, grub_errmsg); + continue; + } + + grub_snprintf (indexstr, sizeof (indexstr) - 1, "%" PRIuGRUB_UINT64_T, keyslot.idx); + /* + * TRANSLATORS: It's a cryptographic key slot: one element of an array + * where each element is either empty or holds a key. + */ + grub_printf_ (N_("Slot \"%s\" opened\n"), indexstr); + + candidate_key_len = keyslot.key_size; + break; + } + if (candidate_key_len == 0) + { + ret = grub_error (GRUB_ERR_ACCESS_DENIED, "Invalid passphrase"); + goto err; + } + + /* Set up disk cipher. */ + grub_strncpy (cipher, segment.encryption, sizeof (cipher)); + ptr = grub_memchr (cipher, '-', grub_strlen (cipher)); + if (!ptr) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid encryption"); + *ptr = '\0'; + + ret = grub_cryptodisk_setcipher (crypt, cipher, ptr + 1); + if (ret) + goto err; + + /* Set the master key. */ + gcry_ret = grub_cryptodisk_setkey (crypt, candidate_key, candidate_key_len); + if (gcry_ret) + { + ret = grub_crypto_gcry_error (gcry_ret); + goto err; + } + + err: + grub_free (json_header); + grub_json_free (json); + return ret; +} + +static struct grub_cryptodisk_dev luks2_crypto = { + .scan = luks2_scan, + .recover_key = luks2_recover_key +}; + +GRUB_MOD_INIT (luks2) +{ + grub_cryptodisk_dev_register (&luks2_crypto); +} + +GRUB_MOD_FINI (luks2) +{ + grub_cryptodisk_dev_unregister (&luks2_crypto); +} diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 508e94af0..af6a8e93c 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef GRUB_UTIL #include @@ -33,12 +34,19 @@ GRUB_MOD_LICENSE ("GPLv3+"); +struct ignored_feature_lv +{ + struct grub_diskfilter_lv *lv; + char *origin; + struct ignored_feature_lv *next; +}; + /* Go the string STR and return the number after STR. *P will point at the number. In case STR is not found, *P will be NULL and the return value will be 0. */ static grub_uint64_t -grub_lvm_getvalue (char **p, const char *str) +grub_lvm_getvalue (const char ** const p, const char *str) { *p = grub_strstr (*p, str); if (! *p) @@ -63,12 +71,12 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl) #endif static int -grub_lvm_check_flag (char *p, const char *str, const char *flag) +grub_lvm_check_flag (const char *p, const char *str, const char *flag) { - int len_str = grub_strlen (str), len_flag = grub_strlen (flag); + grub_size_t len_str = grub_strlen (str), len_flag = grub_strlen (flag); while (1) { - char *q; + const char *q; p = grub_strstr (p, str); if (! p) return 0; @@ -95,23 +103,53 @@ grub_lvm_check_flag (char *p, const char *str, const char *flag) } } -static struct grub_diskfilter_vg * +static void +grub_lvm_free_ignored_feature_lvs (struct ignored_feature_lv *ignored_feature_lvs) +{ + struct ignored_feature_lv *ignored_feature; + + while ((ignored_feature = ignored_feature_lvs)) + { + ignored_feature_lvs = ignored_feature_lvs->next; + + if (ignored_feature->lv) + { + unsigned int i; + + for (i = 0; i < ignored_feature->lv->segment_count; ++i) + if (ignored_feature->lv->segments) + grub_free (ignored_feature->lv->segments[i].nodes); + grub_free (ignored_feature->lv->segments); + grub_free (ignored_feature->lv->fullname); + grub_free (ignored_feature->lv->idname); + grub_free (ignored_feature->lv->name); + } + grub_free (ignored_feature->lv); + grub_free (ignored_feature->origin); + grub_free (ignored_feature); + } +} + +static struct grub_diskfilter_vg * grub_lvm_detect (grub_disk_t disk, struct grub_diskfilter_pv_id *id, grub_disk_addr_t *start_sector) { grub_err_t err; grub_uint64_t mda_offset, mda_size; + grub_size_t ptr; char buf[GRUB_LVM_LABEL_SIZE]; char vg_id[GRUB_LVM_ID_STRLEN+1]; char pv_id[GRUB_LVM_ID_STRLEN+1]; - char *metadatabuf, *p, *q, *vgname; + char *metadatabuf, *mda_end, *vgname; + const char *p, *q; struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf; struct grub_lvm_pv_header *pvh; struct grub_lvm_disk_locn *dlocn; struct grub_lvm_mda_header *mdah; struct grub_lvm_raw_locn *rlocn; - unsigned int i, j, vgname_len; + unsigned int i, j; + grub_size_t vgname_len; struct grub_diskfilter_vg *vg; struct grub_diskfilter_pv *pv; @@ -138,6 +176,20 @@ grub_lvm_detect (grub_disk_t disk, goto fail; } + /* + * We read a grub_lvm_pv_header and then 2 grub_lvm_disk_locns that + * immediately follow the PV header. Make sure we have space for both. + */ + if (grub_le_to_cpu32 (lh->offset_xl) >= + GRUB_LVM_LABEL_SIZE - sizeof (struct grub_lvm_pv_header) - + 2 * sizeof (struct grub_lvm_disk_locn)) + { +#ifdef GRUB_UTIL + grub_util_info ("LVM PV header/disk locations are beyond the end of the block"); +#endif + goto fail; + } + pvh = (struct grub_lvm_pv_header *) (buf + grub_le_to_cpu32(lh->offset_xl)); for (i = 0, j = 0; i < GRUB_LVM_ID_LEN; i++) @@ -159,7 +211,7 @@ grub_lvm_detect (grub_disk_t disk, "we don't support multiple LVM data areas"); #ifdef GRUB_UTIL - grub_util_info ("we don't support multiple LVM data areas\n"); + grub_util_info ("we don't support multiple LVM data areas"); #endif goto fail; } @@ -172,7 +224,7 @@ grub_lvm_detect (grub_disk_t disk, first one. */ /* Allocate buffer space for the circular worst-case scenario. */ - metadatabuf = grub_malloc (2 * mda_size); + metadatabuf = grub_calloc (2, mda_size); if (! metadatabuf) goto fail; @@ -188,15 +240,33 @@ grub_lvm_detect (grub_disk_t disk, grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unknown LVM metadata header"); #ifdef GRUB_UTIL - grub_util_info ("unknown LVM metadata header\n"); + grub_util_info ("unknown LVM metadata header"); #endif goto fail2; } rlocn = mdah->raw_locns; + if (grub_le_to_cpu64 (rlocn->offset) >= grub_le_to_cpu64 (mda_size)) + { +#ifdef GRUB_UTIL + grub_util_info ("metadata offset is beyond end of metadata area"); +#endif + goto fail2; + } + if (grub_le_to_cpu64 (rlocn->offset) + grub_le_to_cpu64 (rlocn->size) > grub_le_to_cpu64 (mdah->size)) { + if (2 * mda_size < GRUB_LVM_MDA_HEADER_SIZE || + (grub_le_to_cpu64 (rlocn->offset) + grub_le_to_cpu64 (rlocn->size) - + grub_le_to_cpu64 (mdah->size) > mda_size - GRUB_LVM_MDA_HEADER_SIZE)) + { +#ifdef GRUB_UTIL + grub_util_info ("cannot copy metadata wrap in circular buffer"); +#endif + goto fail2; + } + /* Metadata is circular. Copy the wrap in place. */ grub_memcpy (metadatabuf + mda_size, metadatabuf + GRUB_LVM_MDA_HEADER_SIZE, @@ -204,19 +274,31 @@ grub_lvm_detect (grub_disk_t disk, grub_le_to_cpu64 (rlocn->size) - grub_le_to_cpu64 (mdah->size)); } - p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset); - while (*q != ' ' && q < metadatabuf + mda_size) - q++; - - if (q == metadatabuf + mda_size) + if (grub_add ((grub_size_t)metadatabuf, + (grub_size_t)grub_le_to_cpu64 (rlocn->offset), + &ptr)) { + error_parsing_metadata: #ifdef GRUB_UTIL - grub_util_info ("error parsing metadata\n"); + grub_util_info ("error parsing metadata"); #endif goto fail2; } + p = q = (char *)ptr; + + if (grub_add (ptr, (grub_size_t) grub_le_to_cpu64 (rlocn->size), &ptr)) + goto error_parsing_metadata; + + mda_end = (char *)ptr; + + while (*q != ' ' && q < mda_end) + q++; + + if (q == mda_end) + goto error_parsing_metadata; + vgname_len = q - p; vgname = grub_malloc (vgname_len + 1); if (!vgname) @@ -229,7 +311,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("couldn't find ID\n"); + grub_util_info ("couldn't find ID"); #endif goto fail3; } @@ -241,6 +323,8 @@ grub_lvm_detect (grub_disk_t disk, if (! vg) { + struct ignored_feature_lv *ignored_feature_lvs = NULL; + /* First time we see this volume group. We've to create the whole volume group structure. */ vg = grub_malloc (sizeof (*vg)); @@ -257,7 +341,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown extent size\n"); + grub_util_info ("unknown extent size"); #endif goto fail4; } @@ -273,20 +357,30 @@ grub_lvm_detect (grub_disk_t disk, /* Add all the pvs to the volume group. */ while (1) { - int s; - while (grub_isspace (*p)) + grub_ssize_t s; + while (grub_isspace (*p) && p < mda_end) p++; + if (p == mda_end) + goto fail4; + if (*p == '}') break; pv = grub_zalloc (sizeof (*pv)); + if (pv == NULL) + goto fail4; q = p; - while (*q != ' ') + while (*q != ' ' && q < mda_end) q++; + if (q == mda_end) + goto pvs_fail_noname; + s = q - p; pv->name = grub_malloc (s + 1); + if (pv->name == NULL) + goto pvs_fail_noname; grub_memcpy (pv->name, p, s); pv->name[s] = '\0'; @@ -305,7 +399,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown pe_start\n"); + grub_util_info ("unknown pe_start"); #endif goto pvs_fail; } @@ -314,7 +408,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("error parsing pe_start\n"); + grub_util_info ("error parsing pe_start"); #endif goto pvs_fail; } @@ -327,37 +421,48 @@ grub_lvm_detect (grub_disk_t disk, continue; pvs_fail: grub_free (pv->name); + pvs_fail_noname: grub_free (pv); goto fail4; } } + else + goto fail4; - p = grub_strstr (p, "logical_volumes"); + p = grub_strstr (p, "logical_volumes {"); if (p) { - p += sizeof ("logical_volumes = ") - 1; + p += sizeof ("logical_volumes {") - 1; /* And add all the lvs to the volume group. */ while (1) { - int s; + grub_ssize_t s; int skip_lv = 0; struct grub_diskfilter_lv *lv; struct grub_diskfilter_segment *seg; int is_pvmove; - while (grub_isspace (*p)) + while (grub_isspace (*p) && p < mda_end) p++; + if (p == mda_end) + goto fail4; + if (*p == '}') break; lv = grub_zalloc (sizeof (*lv)); + if (lv == NULL) + goto fail4; q = p; - while (*q != ' ') + while (*q != ' ' && q < mda_end) q++; + if (q == mda_end) + goto lvs_fail; + s = q - p; lv->name = grub_strndup (p, s); if (!lv->name) @@ -366,8 +471,26 @@ grub_lvm_detect (grub_disk_t disk, { const char *iptr; char *optr; - lv->fullname = grub_malloc (sizeof ("lvm/") - 1 + 2 * vgname_len - + 1 + 2 * s + 1); + + /* + * This is kind of hard to read with our safe (but rather + * baroque) math primatives, but it boils down to: + * + * sz0 = vgname_len * 2 + 1 + + * s * 2 + 1 + + * sizeof ("lvm/") - 1; + */ + grub_size_t sz0 = vgname_len, sz1 = s; + + if (grub_mul (sz0, 2, &sz0) || + grub_add (sz0, 1, &sz0) || + grub_mul (sz1, 2, &sz1) || + grub_add (sz1, 1, &sz1) || + grub_add (sz0, sz1, &sz0) || + grub_add (sz0, sizeof ("lvm/") - 1, &sz0)) + goto lvs_fail; + + lv->fullname = grub_malloc (sz0); if (!lv->fullname) goto lvs_fail; @@ -387,6 +510,29 @@ grub_lvm_detect (grub_disk_t disk, *optr++ = '-'; } *optr++ = 0; + lv->idname = grub_malloc (sizeof ("lvmid/") + + 2 * GRUB_LVM_ID_STRLEN + 1); + if (!lv->idname) + goto lvs_fail; + grub_memcpy (lv->idname, "lvmid/", + sizeof ("lvmid/") - 1); + grub_memcpy (lv->idname + sizeof ("lvmid/") - 1, + vg_id, GRUB_LVM_ID_STRLEN); + lv->idname[sizeof ("lvmid/") - 1 + GRUB_LVM_ID_STRLEN] = '/'; + + p = grub_strstr (q, "id = \""); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("couldn't find ID"); +#endif + goto lvs_fail; + } + p += sizeof ("id = \"") - 1; + grub_memcpy (lv->idname + sizeof ("lvmid/") - 1 + + GRUB_LVM_ID_STRLEN + 1, + p, GRUB_LVM_ID_STRLEN); + lv->idname[sizeof ("lvmid/") - 1 + 2 * GRUB_LVM_ID_STRLEN + 1] = '\0'; } lv->size = 0; @@ -398,11 +544,13 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown segment_count\n"); + grub_util_info ("unknown segment_count"); #endif goto lvs_fail; } - lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count); + lv->segments = grub_calloc (lv->segment_count, sizeof (*seg)); + if (lv->segments == NULL) + goto lvs_fail; seg = lv->segments; for (i = 0; i < lv->segment_count; i++) @@ -412,7 +560,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown segment\n"); + grub_util_info ("unknown segment"); #endif goto lvs_segment_fail; } @@ -421,7 +569,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown start_extent\n"); + grub_util_info ("unknown start_extent"); #endif goto lvs_segment_fail; } @@ -429,7 +577,7 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown extent_count\n"); + grub_util_info ("unknown extent_count"); #endif goto lvs_segment_fail; } @@ -451,23 +599,34 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown stripe_count\n"); + grub_util_info ("unknown stripe_count"); #endif goto lvs_segment_fail; } if (seg->node_count != 1) - seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); + { + seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown stripe_size"); +#endif + goto lvs_segment_fail; + } + } - seg->nodes = grub_zalloc (sizeof (*stripe) - * seg->node_count); + seg->nodes = grub_calloc (seg->node_count, + sizeof (*stripe)); + if (seg->nodes == NULL) + goto lvs_segment_fail; stripe = seg->nodes; p = grub_strstr (p, "stripes = ["); if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown stripes\n"); + grub_util_info ("unknown stripes"); #endif goto lvs_segment_fail2; } @@ -477,11 +636,14 @@ grub_lvm_detect (grub_disk_t disk, { p = grub_strchr (p, '"'); if (p == NULL) - continue; + goto lvs_segment_fail2; q = ++p; - while (*q != '"') + while (q < mda_end && *q != '"') q++; + if (q == mda_end) + goto lvs_segment_fail2; + s = q - p; stripe->name = grub_malloc (s + 1); @@ -496,7 +658,10 @@ grub_lvm_detect (grub_disk_t disk, stripe->start = grub_lvm_getvalue (&p, ",") * vg->extent_size; if (p == NULL) - continue; + { + grub_free (stripe->name); + goto lvs_segment_fail2; + } stripe++; } @@ -509,19 +674,20 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown mirror_count\n"); + grub_util_info ("unknown mirror_count"); #endif goto lvs_segment_fail; } - seg->nodes = grub_zalloc (sizeof (seg->nodes[0]) - * seg->node_count); + seg->nodes = grub_calloc (seg->node_count, sizeof (seg->nodes[0])); + if (seg->nodes == NULL) + goto lvs_segment_fail; p = grub_strstr (p, "mirrors = ["); if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown mirrors\n"); + grub_util_info ("unknown mirrors"); #endif goto lvs_segment_fail2; } @@ -533,11 +699,14 @@ grub_lvm_detect (grub_disk_t disk, p = grub_strchr (p, '"'); if (p == NULL) - continue; + goto lvs_segment_fail2; q = ++p; - while (*q != '"') + while (q < mda_end && *q != '"') q++; + if (q == mda_end) + goto lvs_segment_fail2; + s = q - p; lvname = grub_malloc (s + 1); @@ -553,13 +722,17 @@ grub_lvm_detect (grub_disk_t disk, if (is_pvmove) seg->node_count = 1; } - else if (grub_memcmp (p, "raid", sizeof ("raid") - 1) - == 0 && (p[sizeof ("raid") - 1] >= '4' - && p[sizeof ("raid") - 1] <= '6') + else if (grub_memcmp (p, "raid", sizeof ("raid") - 1) == 0 + && ((p[sizeof ("raid") - 1] >= '4' + && p[sizeof ("raid") - 1] <= '6') + || p[sizeof ("raid") - 1] == '1') && p[sizeof ("raidX") - 1] == '"') { switch (p[sizeof ("raid") - 1]) { + case '1': + seg->type = GRUB_DISKFILTER_MIRROR; + break; case '4': seg->type = GRUB_DISKFILTER_RAID4; seg->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC; @@ -579,29 +752,32 @@ grub_lvm_detect (grub_disk_t disk, if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown device_count\n"); + grub_util_info ("unknown device_count"); #endif goto lvs_segment_fail; } - seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); - if (p == NULL) + if (seg->type != GRUB_DISKFILTER_MIRROR) { + seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); + if (p == NULL) + { #ifdef GRUB_UTIL - grub_util_info ("unknown stripe_size\n"); + grub_util_info ("unknown stripe_size"); #endif - goto lvs_segment_fail; + goto lvs_segment_fail; + } } - - seg->nodes = grub_zalloc (sizeof (seg->nodes[0]) - * seg->node_count); + seg->nodes = grub_calloc (seg->node_count, sizeof (seg->nodes[0])); + if (seg->nodes == NULL) + goto lvs_segment_fail; p = grub_strstr (p, "raids = ["); if (p == NULL) { #ifdef GRUB_UTIL - grub_util_info ("unknown mirrors\n"); + grub_util_info ("unknown raids"); #endif goto lvs_segment_fail2; } @@ -615,7 +791,7 @@ grub_lvm_detect (grub_disk_t disk, p = p ? grub_strchr (p + 1, '"') : 0; p = p ? grub_strchr (p + 1, '"') : 0; if (p == NULL) - continue; + goto lvs_segment_fail2; q = ++p; while (*q != '"') q++; @@ -641,14 +817,108 @@ grub_lvm_detect (grub_disk_t disk, seg->nodes[seg->node_count - 1].name = tmp; } } + /* + * Cache and integrity LVs have extra parts that + * we can ignore for our read-only access. + */ + else if (grub_strncmp (p, "cache\"", sizeof ("cache\"") - 1) == 0 || + grub_strncmp (p, "cache+CACHE_USES_CACHEVOL\"", sizeof ("cache+CACHE_USES_CACHEVOL\"") - 1) == 0 || + grub_strncmp (p, "integrity\"", sizeof ("integrity\"") - 1) == 0) + { + struct ignored_feature_lv *ignored_feature = NULL; + + char *p2, *p3; + grub_size_t sz; +#ifdef GRUB_UTIL + p2 = grub_strchr (p, '"'); + if (p2) + *p2 = '\0'; + grub_util_info ("Ignoring extra metadata type '%s' for %s", p, lv->name); + if (p2) + *p2 ='"'; +#endif + + ignored_feature = grub_zalloc (sizeof (*ignored_feature)); + if (!ignored_feature) + goto ignored_feature_lv_fail; + ignored_feature->lv = grub_zalloc (sizeof (*ignored_feature->lv)); + if (!ignored_feature->lv) + goto ignored_feature_lv_fail; + grub_memcpy (ignored_feature->lv, lv, sizeof (*ignored_feature->lv)); + + if (lv->fullname) + { + ignored_feature->lv->fullname = grub_strdup (lv->fullname); + if (!ignored_feature->lv->fullname) + goto ignored_feature_lv_fail; + } + if (lv->idname) + { + ignored_feature->lv->idname = grub_strdup (lv->idname); + if (!ignored_feature->lv->idname) + goto ignored_feature_lv_fail; + } + if (lv->name) + { + ignored_feature->lv->name = grub_strdup (lv->name); + if (!ignored_feature->lv->name) + goto ignored_feature_lv_fail; + } + + skip_lv = 1; + + + p2 = grub_strstr (p, "origin = \""); + if (!p2) + goto ignored_feature_lv_fail; + + p2 = grub_strchr (p2, '"'); + if (!p2) + goto ignored_feature_lv_fail; + + p3 = ++p2; + if (p3 == mda_end) + goto ignored_feature_lv_fail; + p3 = grub_strchr (p3, '"'); + if (!p3) + goto ignored_feature_lv_fail; + + sz = p3 - p2; + + ignored_feature->origin = grub_malloc (sz + 1); + if (!ignored_feature->origin) + goto ignored_feature_lv_fail; + grub_memcpy (ignored_feature->origin, p2, sz); + ignored_feature->origin[sz] = '\0'; + + ignored_feature->next = ignored_feature_lvs; + ignored_feature_lvs = ignored_feature; + break; + + ignored_feature_lv_fail: + if (ignored_feature) + { + grub_free (ignored_feature->origin); + if (ignored_feature->lv) + { + grub_free (ignored_feature->lv->fullname); + grub_free (ignored_feature->lv->idname); + grub_free (ignored_feature->lv->name); + } + grub_free (ignored_feature->lv); + grub_free (ignored_feature); + } + grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs); + goto fail4; + } else { #ifdef GRUB_UTIL char *p2; p2 = grub_strchr (p, '"'); if (p2) - *p2 = 0; - grub_util_info ("unknown LVM type %s\n", p); + *p2 = '\0'; + grub_util_info ("unknown LVM type %s", p); if (p2) *p2 ='"'; #endif @@ -691,10 +961,68 @@ grub_lvm_detect (grub_disk_t disk, } } - /* Match lvs. */ + + { + struct ignored_feature_lv *ignored_feature; + + for (ignored_feature = ignored_feature_lvs; ignored_feature; ignored_feature = ignored_feature->next) + { + struct grub_diskfilter_lv *lv; + + for (lv = vg->lvs; lv; lv = lv->next) + if (grub_strcmp (lv->name, ignored_feature->origin) == 0) + break; + if (lv) + { + ignored_feature->lv->segments = grub_calloc (lv->segment_count, sizeof (*lv->segments)); + if (!ignored_feature->lv->segments) + { + grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs); + goto fail4; + } + grub_memcpy (ignored_feature->lv->segments, lv->segments, lv->segment_count * sizeof (*lv->segments)); + + for (i = 0; i < lv->segment_count; ++i) + { + struct grub_diskfilter_node *nodes = lv->segments[i].nodes; + grub_size_t node_count = lv->segments[i].node_count; + + ignored_feature->lv->segments[i].nodes = grub_calloc (node_count, sizeof (*nodes)); + if (!ignored_feature->lv->segments[i].nodes) + { + for (j = 0; j < i; ++j) + grub_free (ignored_feature->lv->segments[j].nodes); + grub_free (ignored_feature->lv->segments); + ignored_feature->lv->segments = NULL; + grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs); + goto fail4; + } + grub_memcpy (ignored_feature->lv->segments[i].nodes, nodes, node_count * sizeof (*nodes)); + } + + if (ignored_feature->lv->segments) + { + ignored_feature->lv->segment_count = lv->segment_count; + ignored_feature->lv->vg = vg; + ignored_feature->lv->next = vg->lvs; + vg->lvs = ignored_feature->lv; + ignored_feature->lv = NULL; + } + } + else + { +#ifdef GRUB_UTIL + grub_util_info ("Couldn't find LVM part of ignored feature on %s", ignored_feature->origin); +#endif + } + } + } + + /* Match LVs. Must be done after cache and integrity are found. */ { struct grub_diskfilter_lv *lv1; struct grub_diskfilter_lv *lv2; + for (lv1 = vg->lvs; lv1; lv1 = lv1->next) for (i = 0; i < lv1->segment_count; i++) for (j = 0; j < lv1->segments[i].node_count; j++) @@ -711,12 +1039,17 @@ grub_lvm_detect (grub_disk_t disk, } if (lv1->segments[i].nodes[j].pv == NULL) for (lv2 = vg->lvs; lv2; lv2 = lv2->next) - if (grub_strcmp (lv2->name, - lv1->segments[i].nodes[j].name) == 0) - lv1->segments[i].nodes[j].lv = lv2; + { + if (lv1 == lv2) + continue; + if (grub_strcmp (lv2->name, + lv1->segments[i].nodes[j].name) == 0) + lv1->segments[i].nodes[j].lv = lv2; + } } - } + + grub_lvm_free_ignored_feature_lvs (ignored_feature_lvs); if (grub_diskfilter_vg_register (vg)) goto fail4; } diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c index a0e65a8cc..dd5d440a3 100644 --- a/grub-core/disk/mdraid1x_linux.c +++ b/grub-core/disk/mdraid1x_linux.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -97,12 +98,15 @@ struct grub_raid_super_1x */ grub_uint16_t dev_roles[0]; /* Role in array, or 0xffff for a spare, or 0xfffe for faulty. */ }; -/* Could be __attribute__ ((packed)), but since all members in this struct +/* Could be GRUB_PACKED, but since all members in this struct are already appropriately aligned, we can omit this and avoid suboptimal assembly in some cases. */ #define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */ +#define GRUB_MD_SECTOR_SHIFT 9 /* Follow Linux kernel v6.8. */ +#define GRUB_MD_SECTOR_SIZE (1 << GRUB_MD_SECTOR_SHIFT) + static struct grub_diskfilter_vg * grub_mdraid_detect (grub_disk_t disk, struct grub_diskfilter_pv_id *id, @@ -111,7 +115,7 @@ grub_mdraid_detect (grub_disk_t disk, grub_uint64_t size; grub_uint8_t minor_version; - size = grub_disk_get_size (disk); + size = grub_disk_native_sectors (disk); /* Check for an 1.x superblock. * It's always aligned to a 4K boundary @@ -129,10 +133,11 @@ grub_mdraid_detect (grub_disk_t disk, grub_uint32_t level; struct grub_diskfilter_vg *array; char *uuid; - + grub_uint64_t sb_sz, data_end, sb_end; + if (size == GRUB_DISK_SIZE_UNKNOWN && minor_version == 0) continue; - + switch (minor_version) { case 0: @@ -154,6 +159,79 @@ grub_mdraid_detect (grub_disk_t disk, || grub_le_to_cpu64 (sb.super_offset) != sector) continue; + /* + * The first check follows the Linux kernel's data_size + * validation from v6.8-rc5. + */ + if (grub_le_to_cpu64 (sb.data_size) < 10 || + grub_le_to_cpu64 (sb.raid_disks) > GRUB_MDRAID_MAX_DISKS) + { + grub_dprintf ("mdraid1x", "Corrupted superblock\n"); + return NULL; + } + + /* + * Total size of superblock: 256 bytes plus 2 bytes per device + * in the array. + */ + sb_sz = sizeof (struct grub_raid_super_1x) + grub_le_to_cpu64 (sb.raid_disks) * 2; + + if (grub_add (grub_le_to_cpu64 (sb.super_offset), + (ALIGN_UP(sb_sz, GRUB_MD_SECTOR_SIZE) >> GRUB_MD_SECTOR_SHIFT), &sb_end)) + { + grub_dprintf ("mdraid1x", "Invalid superblock end.\n"); + return NULL; + } + + if (grub_add (grub_le_to_cpu64 (sb.data_offset), + grub_le_to_cpu64 (sb.data_size), &data_end)) + { + grub_dprintf ("mdraid1x", "Invalid data end.\n"); + return NULL; + } + + /* In minor versions 1 and 2, superblock is positioned before data. */ + if (minor_version) + { + if (grub_le_to_cpu64 (sb.data_offset) < sb_end) + { + grub_dprintf ("mdraid1x", + "The superblock either overlaps with the data " + "or is behind it.\n"); + return NULL; + } + + if (data_end > size) + { + grub_dprintf ("mdraid1x", + "The data region ends at %" PRIuGRUB_UINT64_T ", " + "past the end of the disk (%" PRIuGRUB_UINT64_T ")\n", + data_end, size); + return NULL; + } + } + else + { + /* In minor version 0, superblock is at the end of the device. */ + if (grub_le_to_cpu64 (sb.super_offset) < data_end) + { + grub_dprintf ("mdraid1x", + "The data either overlaps with the superblock " + "or is behind it.\n"); + return NULL; + } + + if (sb_end > size) + { + grub_dprintf ("mdraid1x", + "The superblock region ends at " + "%" PRIuGRUB_UINT64_T ", past the end of " + "the disk (%" PRIuGRUB_UINT64_T ")\n", + sb_end, size); + return NULL; + } + } + if (sb.major_version != grub_cpu_to_le32_compile_time (1)) /* Unsupported version. */ return NULL; @@ -177,8 +255,8 @@ grub_mdraid_detect (grub_disk_t disk, /* Spares aren't implemented. */ return NULL; - if (grub_disk_read (disk, sector, - (char *) &sb.dev_roles[grub_le_to_cpu32 (sb.dev_number)] + if (grub_disk_read (disk, sector, + (char *) (sb.dev_roles + grub_le_to_cpu32 (sb.dev_number)) - (char *) &sb, sizeof (role), &role)) return NULL; @@ -203,7 +281,7 @@ grub_mdraid_detect (grub_disk_t disk, grub_le_to_cpu32 (sb.raid_disks), sb.set_name, (sb.size) - ? grub_le_to_cpu64 (sb.size) + ? grub_le_to_cpu64 (sb.size) : grub_le_to_cpu64 (sb.data_size), grub_le_to_cpu32 (sb.chunksize), grub_le_to_cpu32 (sb.layout), diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c index f408fd37e..e40216f51 100644 --- a/grub-core/disk/mdraid_linux.c +++ b/grub-core/disk/mdraid_linux.c @@ -33,16 +33,16 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define grub_md_to_cpu64 grub_be_to_cpu64 #define grub_md_to_cpu32 grub_be_to_cpu32 #define grub_md_to_cpu16 grub_be_to_cpu16 -#define grub_cpu_to_md64_compile_time grub_cpu_to_be64 -#define grub_cpu_to_md32_compile_time grub_cpu_to_be32 -#define grub_cpu_to_md16_compile_time grub_cpu_to_be16 +#define grub_cpu_to_md64_compile_time grub_cpu_to_be64_compile_time +#define grub_cpu_to_md32_compile_time grub_cpu_to_be32_compile_time +#define grub_cpu_to_md16_compile_time grub_cpu_to_be16_compile_time #else #define grub_md_to_cpu64 grub_le_to_cpu64 #define grub_md_to_cpu32 grub_le_to_cpu32 #define grub_md_to_cpu16 grub_le_to_cpu16 -#define grub_cpu_to_md64_compile_time grub_cpu_to_le64 -#define grub_cpu_to_md32_compile_time grub_cpu_to_le32 -#define grub_cpu_to_md16_compile_time grub_cpu_to_le16 +#define grub_cpu_to_md64_compile_time grub_cpu_to_le64_compile_time +#define grub_cpu_to_md32_compile_time grub_cpu_to_le32_compile_time +#define grub_cpu_to_md16_compile_time grub_cpu_to_le16_compile_time #endif #define RESERVED_BYTES (64 * 1024) @@ -175,7 +175,7 @@ struct grub_raid_super_09 * Active descriptor */ struct grub_raid_disk_09 this_disk; -} __attribute__ ((packed)); +} GRUB_PACKED; static struct grub_diskfilter_vg * grub_mdraid_detect (grub_disk_t disk, @@ -184,38 +184,43 @@ grub_mdraid_detect (grub_disk_t disk, { grub_disk_addr_t sector; grub_uint64_t size; - struct grub_raid_super_09 sb; + struct grub_raid_super_09 *sb = NULL; grub_uint32_t *uuid; grub_uint32_t level; + struct grub_diskfilter_vg *ret; /* The sector where the mdraid 0.90 superblock is stored, if available. */ - size = grub_disk_get_size (disk); + size = grub_disk_native_sectors (disk); if (size == GRUB_DISK_SIZE_UNKNOWN) /* not 0.9x raid. */ return NULL; sector = NEW_SIZE_SECTORS (size); - if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb)) + sb = grub_malloc (sizeof (*sb)); + if (!sb) return NULL; + if (grub_disk_read (disk, sector, 0, SB_BYTES, sb)) + goto fail; + /* Look whether there is a mdraid 0.90 superblock. */ - if (sb.md_magic != grub_cpu_to_md32_compile_time (SB_MAGIC)) + if (sb->md_magic != grub_cpu_to_md32_compile_time (SB_MAGIC)) /* not 0.9x raid. */ - return NULL; + goto fail; - if (sb.major_version != grub_cpu_to_md32_compile_time (0) - || sb.minor_version != grub_cpu_to_md32_compile_time (90)) + if (sb->major_version != grub_cpu_to_md32_compile_time (0) + || sb->minor_version != grub_cpu_to_md32_compile_time (90)) /* Unsupported version. */ - return NULL; + goto fail; - /* No need for explicit check that sb.size is 0 (unspecified) since + /* No need for explicit check that sb->size is 0 (unspecified) since 0 >= non-0 is false. */ - if (((grub_disk_addr_t) grub_md_to_cpu32 (sb.size)) * 2 >= size) - return NULL; + if (((grub_disk_addr_t) grub_md_to_cpu32 (sb->size)) * 2 >= size) + goto fail; /* FIXME: Check the checksum. */ - level = grub_md_to_cpu32 (sb.level); + level = grub_md_to_cpu32 (sb->level); /* Multipath. */ if ((int) level == -4) level = 1; @@ -225,37 +230,43 @@ grub_mdraid_detect (grub_disk_t disk, { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unsupported RAID level: %d", level); - return NULL; + goto fail; } - if (grub_md_to_cpu32 (sb.this_disk.number) == 0xffff - || grub_md_to_cpu32 (sb.this_disk.number) == 0xfffe) + if (grub_md_to_cpu32 (sb->this_disk.number) == 0xffff + || grub_md_to_cpu32 (sb->this_disk.number) == 0xfffe) /* Spares aren't implemented. */ - return NULL; + goto fail; uuid = grub_malloc (16); if (!uuid) - return NULL; + goto fail; - uuid[0] = grub_swap_bytes32 (sb.set_uuid0); - uuid[1] = grub_swap_bytes32 (sb.set_uuid1); - uuid[2] = grub_swap_bytes32 (sb.set_uuid2); - uuid[3] = grub_swap_bytes32 (sb.set_uuid3); + uuid[0] = grub_swap_bytes32 (sb->set_uuid0); + uuid[1] = grub_swap_bytes32 (sb->set_uuid1); + uuid[2] = grub_swap_bytes32 (sb->set_uuid2); + uuid[3] = grub_swap_bytes32 (sb->set_uuid3); *start_sector = 0; id->uuidlen = 0; - id->id = grub_md_to_cpu32 (sb.this_disk.number); + id->id = grub_md_to_cpu32 (sb->this_disk.number); char buf[32]; - grub_snprintf (buf, sizeof (buf), "md%d", grub_md_to_cpu32 (sb.md_minor)); - return grub_diskfilter_make_raid (16, (char *) uuid, - grub_md_to_cpu32 (sb.raid_disks), buf, - (sb.size) ? ((grub_disk_addr_t) - grub_md_to_cpu32 (sb.size)) * 2 - : sector, - grub_md_to_cpu32 (sb.chunk_size) >> 9, - grub_md_to_cpu32 (sb.layout), - level); + grub_snprintf (buf, sizeof (buf), "md%d", grub_md_to_cpu32 (sb->md_minor)); + ret = grub_diskfilter_make_raid (16, (char *) uuid, + grub_md_to_cpu32 (sb->raid_disks), buf, + (sb->size) ? ((grub_disk_addr_t) + grub_md_to_cpu32 (sb->size)) * 2 + : sector, + grub_md_to_cpu32 (sb->chunk_size) >> 9, + grub_md_to_cpu32 (sb->layout), + level); + grub_free (sb); + return ret; + + fail: + grub_free (sb); + return NULL; } static struct grub_diskfilter grub_mdraid_dev = { diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c index 4de0971ae..2d7afaea3 100644 --- a/grub-core/disk/memdisk.c +++ b/grub-core/disk/memdisk.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -30,13 +31,13 @@ static char *memdisk_addr; static grub_off_t memdisk_size = 0; static int -grub_memdisk_iterate (int (*hook) (const char *name), +grub_memdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { if (pull != GRUB_DISK_PULL_NONE) return 0; - return hook ("memdisk"); + return hook ("memdisk", hook_data); } static grub_err_t @@ -46,7 +47,8 @@ grub_memdisk_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a memdisk"); disk->total_sectors = memdisk_size / GRUB_DISK_SECTOR_SIZE; - disk->id = (unsigned long) "mdsk"; + disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; + disk->id = 0; return GRUB_ERR_NONE; } @@ -76,11 +78,11 @@ static struct grub_disk_dev grub_memdisk_dev = { .name = "memdisk", .id = GRUB_DISK_DEVICE_MEMDISK_ID, - .iterate = grub_memdisk_iterate, - .open = grub_memdisk_open, - .close = grub_memdisk_close, - .read = grub_memdisk_read, - .write = grub_memdisk_write, + .disk_iterate = grub_memdisk_iterate, + .disk_open = grub_memdisk_open, + .disk_close = grub_memdisk_close, + .disk_read = grub_memdisk_read, + .disk_write = grub_memdisk_write, .next = 0 }; @@ -95,8 +97,14 @@ GRUB_MOD_INIT(memdisk) grub_dprintf ("memdisk", "Found memdisk image at %p\n", memdisk_orig_addr); - memdisk_size = header->size - sizeof (struct grub_module_header); + if (grub_sub (header->size, sizeof (struct grub_module_header), &memdisk_size)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "underflow detected while obtaining memdisk size"); + return; + } memdisk_addr = grub_malloc (memdisk_size); + if (memdisk_addr == NULL) + return; grub_dprintf ("memdisk", "Copying memdisk image to dynamic memory\n"); grub_memmove (memdisk_addr, memdisk_orig_addr, memdisk_size); diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index 00b04e2d4..0578a93e1 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -123,7 +123,7 @@ grub_pata_wait (void) static void grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size) -{ +{ unsigned int i; /* Read in the data, word by word. */ @@ -331,6 +331,12 @@ grub_pata_device_initialize (int port, int device, int addr) *devp = dev; err = check_device (dev); + if (err == GRUB_ERR_UNKNOWN_DEVICE) + { + grub_dprintf ("pata", "%s\n", grub_errmsg); + grub_error_pop (); + } + if (err) grub_print_error (); @@ -338,9 +344,10 @@ grub_pata_device_initialize (int port, int device, int addr) } #ifndef GRUB_MACHINE_MIPS_QEMU_MIPS -static int NESTED_FUNC_ATTR +static int grub_pata_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid) + grub_pci_id_t pciid, + void *data __attribute__ ((unused))) { static int compat_use[2] = { 0 }; grub_pci_address_t addr; @@ -401,9 +408,15 @@ grub_pata_pciinit (grub_pci_device_t dev, bar2 = grub_pci_read (addr); /* Check if the BARs describe an IO region. */ - if ((bar1 & 1) && (bar2 & 1)) + if ((bar1 & 1) && (bar2 & 1) && (bar1 & ~3)) { rega = bar1 & ~3; + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, grub_pci_read_word (addr) + | GRUB_PCI_COMMAND_IO_ENABLED + | GRUB_PCI_COMMAND_MEM_ENABLED + | GRUB_PCI_COMMAND_BUS_MASTER); + } } @@ -446,7 +459,7 @@ grub_pata_pciinit (grub_pci_device_t dev, static grub_err_t grub_pata_initialize (void) { - grub_pci_iterate (grub_pata_pciinit); + grub_pci_iterate (grub_pata_pciinit, NULL); return 0; } #else @@ -500,7 +513,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata) } static int -grub_pata_iterate (int (*hook) (int id, int bus), +grub_pata_iterate (grub_ata_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { struct grub_pata_device *dev; @@ -509,7 +522,8 @@ grub_pata_iterate (int (*hook) (int id, int bus), return 0; for (dev = grub_pata_devices; dev; dev = dev->next) - if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device)) + if (hook (GRUB_SCSI_SUBSYSTEM_PATA, dev->port * 2 + dev->device, + hook_data)) return 1; return 0; @@ -528,13 +542,7 @@ static struct grub_ata_dev grub_pata_dev = GRUB_MOD_INIT(ata_pthru) { - /* To prevent two drivers operating on the same disks. */ - grub_disk_firmware_is_tainted = 1; - if (grub_disk_firmware_fini) - { - grub_disk_firmware_fini (); - grub_disk_firmware_fini = NULL; - } + grub_stop_disk_firmware (); /* ATA initialization. */ grub_pata_initialize (); diff --git a/grub-core/disk/plainmount.c b/grub-core/disk/plainmount.c new file mode 100644 index 000000000..21ec4072c --- /dev/null +++ b/grub-core/disk/plainmount.c @@ -0,0 +1,463 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +/* plaimount.c - Open device encrypted in plain mode. */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define PLAINMOUNT_DEFAULT_SECTOR_SIZE 512 +#define PLAINMOUNT_DEFAULT_UUID "109fea84-a6b7-34a8-4bd1-1c506305a400" + + +enum PLAINMOUNT_OPTION + { + OPTION_HASH, + OPTION_CIPHER, + OPTION_KEY_SIZE, + OPTION_SECTOR_SIZE, + OPTION_PASSWORD, + OPTION_KEYFILE, + OPTION_KEYFILE_OFFSET, + OPTION_UUID + }; + +static const struct grub_arg_option options[] = + { + /* TRANSLATORS: It's still restricted to this module only. */ + {"hash", 'h', 0, N_("Password hash"), 0, ARG_TYPE_STRING}, + {"cipher", 'c', 0, N_("Password cipher"), 0, ARG_TYPE_STRING}, + {"key-size", 's', 0, N_("Key size (in bits)"), 0, ARG_TYPE_INT}, + {"sector-size", 'S', 0, N_("Device sector size"), 0, ARG_TYPE_INT}, + {"password", 'p', 0, N_("Password (key)"), 0, ARG_TYPE_STRING}, + {"keyfile", 'd', 0, N_("Keyfile path"), 0, ARG_TYPE_STRING}, + {"keyfile-offset", 'O', 0, N_("Keyfile offset"), 0, ARG_TYPE_INT}, + {"uuid", 'u', 0, N_("Set device UUID"), 0, ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} + }; + +/* Cryptodisk setkey() function wrapper */ +static grub_err_t +plainmount_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, + grub_size_t size) +{ + gcry_err_code_t code = grub_cryptodisk_setkey (dev, key, size); + if (code != GPG_ERR_NO_ERROR) + { + grub_dprintf ("plainmount", "failed to set cipher key with code: %d\n", code); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("cannot set specified key")); + } + return GRUB_ERR_NONE; +} + +/* Configure cryptodisk uuid */ +static void plainmount_set_uuid (grub_cryptodisk_t dev, const char *user_uuid) +{ + grub_size_t pos = 0; + + /* Size of user_uuid is checked in main func */ + if (user_uuid != NULL) + grub_strcpy (dev->uuid, user_uuid); + else + { + /* + * Set default UUID. Last digits start from 1 and are incremented for + * each new plainmount device by snprintf(). + */ + grub_snprintf (dev->uuid, sizeof (dev->uuid) - 1, "%36lx", dev->id + 1); + while (dev->uuid[++pos] == ' '); + grub_memcpy (dev->uuid, PLAINMOUNT_DEFAULT_UUID, pos); + } + COMPILE_TIME_ASSERT (sizeof (dev->uuid) >= sizeof (PLAINMOUNT_DEFAULT_UUID)); +} + +/* Configure cryptodevice sector size (-S option) */ +static grub_err_t +plainmount_configure_sectors (grub_cryptodisk_t dev, grub_disk_t disk, + grub_size_t sector_size) +{ + dev->total_sectors = grub_disk_native_sectors (disk); + if (dev->total_sectors == GRUB_DISK_SIZE_UNKNOWN) + return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot determine disk %s size"), + disk->name); + + /* Convert size to sectors */ + dev->log_sector_size = grub_log2ull (sector_size); + dev->total_sectors = grub_convert_sector (dev->total_sectors, + GRUB_DISK_SECTOR_BITS, + dev->log_sector_size); + if (dev->total_sectors == 0) + return grub_error (GRUB_ERR_BAD_DEVICE, + N_("cannot set specified sector size on disk %s"), + disk->name); + + grub_dprintf ("plainmount", "log_sector_size=%d, total_sectors=%" + PRIuGRUB_UINT64_T"\n", dev->log_sector_size, dev->total_sectors); + return GRUB_ERR_NONE; +} + +/* Hashes a password into a key and stores it with the cipher. */ +static grub_err_t +plainmount_configure_password (grub_cryptodisk_t dev, const char *hash, + grub_uint8_t *key_data, grub_size_t key_size, + grub_size_t password_size) +{ + grub_uint8_t *derived_hash, *dh; + char *p; + unsigned int round, i, len, size; + grub_size_t alloc_size, sz; + grub_err_t err = GRUB_ERR_NONE; + + /* Support none (plain) hash */ + if (grub_strcmp (hash, "plain") == 0) + { + dev->hash = NULL; + return err; + } + + /* Hash argument was checked at main func */ + dev->hash = grub_crypto_lookup_md_by_name (hash); + len = dev->hash->mdlen; + + alloc_size = grub_max (password_size, key_size); + /* + * Allocate buffer for the password and for an added prefix character + * for each hash round ('alloc_size' may not be a multiple of 'len'). + */ + if (grub_add (alloc_size, (alloc_size / len), &sz) || + grub_add (sz, 1, &sz)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow detected while allocating size of password buffer")); + + p = grub_zalloc (sz); + derived_hash = grub_zalloc (GRUB_CRYPTODISK_MAX_KEYLEN * 2); + if (p == NULL || derived_hash == NULL) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + goto fail; + } + dh = derived_hash; + + /* + * Hash password. Adapted from cryptsetup. + * https://gitlab.com/cryptsetup/cryptsetup/-/blob/main/lib/crypt_plain.c + */ + for (round = 0, size = alloc_size; size; round++, dh += len, size -= len) + { + for (i = 0; i < round; i++) + p[i] = 'A'; + + grub_memcpy (p + i, (char*) key_data, password_size); + + if (len > size) + len = size; + + grub_crypto_hash (dev->hash, dh, p, password_size + round); + } + grub_memcpy (key_data, derived_hash, key_size); + + fail: + grub_free (p); + grub_free (derived_hash); + return err; +} + +/* Read key material from keyfile */ +static grub_err_t +plainmount_configure_keyfile (char *keyfile, grub_uint8_t *key_data, + grub_size_t key_size, grub_size_t keyfile_offset) +{ + grub_file_t g_keyfile = grub_file_open (keyfile, GRUB_FILE_TYPE_NONE); + if (g_keyfile == NULL) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("cannot open keyfile %s"), + keyfile); + + if (grub_file_seek (g_keyfile, keyfile_offset) == (grub_off_t) - 1) + return grub_error (GRUB_ERR_FILE_READ_ERROR, + N_("cannot seek keyfile at offset %"PRIuGRUB_SIZE), + keyfile_offset); + + if (key_size > (g_keyfile->size - keyfile_offset)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Specified key size (%" + PRIuGRUB_SIZE") is too small for keyfile size (%" + PRIuGRUB_UINT64_T") and offset (%"PRIuGRUB_SIZE")"), + key_size, g_keyfile->size, keyfile_offset); + + if (grub_file_read (g_keyfile, key_data, key_size) != (grub_ssize_t) key_size) + return grub_error (GRUB_ERR_FILE_READ_ERROR, N_("error reading key file")); + return GRUB_ERR_NONE; +} + +/* Plainmount command entry point */ +static grub_err_t +grub_cmd_plainmount (grub_extcmd_context_t ctxt, int argc, char **args) +{ + struct grub_arg_list *state = ctxt->state; + grub_cryptodisk_t dev = NULL; + grub_disk_t disk = NULL; + const gcry_md_spec_t *gcry_hash; + char *diskname, *disklast = NULL, *cipher, *mode, *hash, *keyfile, *uuid; + grub_size_t len, key_size, sector_size, keyfile_offset = 0, password_size = 0; + grub_err_t err; + const char *p; + grub_uint8_t *key_data; + + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("device name required")); + + /* Check whether required arguments are specified */ + if (!state[OPTION_CIPHER].set || !state[OPTION_KEY_SIZE].set) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "cipher and key size must be set"); + if (!state[OPTION_HASH].set && !state[OPTION_KEYFILE].set) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "hash algorithm must be set"); + + /* Check hash */ + if (!state[OPTION_KEYFILE].set) + { + gcry_hash = grub_crypto_lookup_md_by_name (state[OPTION_HASH].arg); + if (!gcry_hash) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("couldn't load hash %s"), + state[OPTION_HASH].arg); + + if (gcry_hash->mdlen > GRUB_CRYPTODISK_MAX_KEYLEN) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("hash length %"PRIuGRUB_SIZE" exceeds maximum %d bits"), + gcry_hash->mdlen * GRUB_CHAR_BIT, + GRUB_CRYPTODISK_MAX_KEYLEN * GRUB_CHAR_BIT); + } + + /* Check cipher mode */ + if (!grub_strchr (state[OPTION_CIPHER].arg,'-')) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("invalid cipher mode, must be of format cipher-mode")); + + /* Check password size */ + if (state[OPTION_PASSWORD].set && grub_strlen (state[OPTION_PASSWORD].arg) > + GRUB_CRYPTODISK_MAX_PASSPHRASE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("password exceeds maximium size")); + + /* Check uuid length */ + if (state[OPTION_UUID].set && grub_strlen (state[OPTION_UUID].arg) > + GRUB_CRYPTODISK_MAX_UUID_LENGTH - 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("specified UUID exceeds maximum size")); + if (state[OPTION_UUID].set && grub_strlen (state[OPTION_UUID].arg) == 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("specified UUID too short")); + + /* Parse plainmount arguments */ + grub_errno = GRUB_ERR_NONE; + keyfile_offset = state[OPTION_KEYFILE_OFFSET].set ? + grub_strtoull (state[OPTION_KEYFILE_OFFSET].arg, &p, 0) : 0; + if (state[OPTION_KEYFILE_OFFSET].set && + (state[OPTION_KEYFILE_OFFSET].arg[0] == '\0' || *p != '\0' || + grub_errno != GRUB_ERR_NONE)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized keyfile offset")); + + sector_size = state[OPTION_SECTOR_SIZE].set ? + grub_strtoull (state[OPTION_SECTOR_SIZE].arg, &p, 0) : + PLAINMOUNT_DEFAULT_SECTOR_SIZE; + if (state[OPTION_SECTOR_SIZE].set && (state[OPTION_SECTOR_SIZE].arg[0] == '\0' || + *p != '\0' || grub_errno != GRUB_ERR_NONE)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized sector size")); + + /* Check key size */ + key_size = grub_strtoull (state[OPTION_KEY_SIZE].arg, &p, 0); + if (state[OPTION_KEY_SIZE].arg[0] == '\0' || *p != '\0' || + grub_errno != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized key size")); + if ((key_size % GRUB_CHAR_BIT) != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("key size is not multiple of %d bits"), GRUB_CHAR_BIT); + key_size = key_size / GRUB_CHAR_BIT; + if (key_size > GRUB_CRYPTODISK_MAX_KEYLEN) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("key size %"PRIuGRUB_SIZE" exceeds maximum %d bits"), + key_size * GRUB_CHAR_BIT, + GRUB_CRYPTODISK_MAX_KEYLEN * GRUB_CHAR_BIT); + + /* Check disk sector size */ + if (sector_size < GRUB_DISK_SECTOR_SIZE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("sector size -S must be at least %d"), + GRUB_DISK_SECTOR_SIZE); + if ((sector_size & (sector_size - 1)) != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("sector size -S %"PRIuGRUB_SIZE" is not power of 2"), + sector_size); + + /* Allocate all stuff here */ + hash = state[OPTION_HASH].set ? grub_strdup (state[OPTION_HASH].arg) : NULL; + cipher = grub_strdup (state[OPTION_CIPHER].arg); + keyfile = state[OPTION_KEYFILE].set ? + grub_strdup (state[OPTION_KEYFILE].arg) : NULL; + dev = grub_zalloc (sizeof *dev); + key_data = grub_zalloc (GRUB_CRYPTODISK_MAX_PASSPHRASE); + uuid = state[OPTION_UUID].set ? grub_strdup (state[OPTION_UUID].arg) : NULL; + if ((state[OPTION_HASH].set && hash == NULL) || cipher == NULL || dev == NULL || + (state[OPTION_KEYFILE].set && keyfile == NULL) || key_data == NULL || + (state[OPTION_UUID].set && uuid == NULL)) + { + err = grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + goto fail; + } + + /* Copy user password from -p option */ + if (state[OPTION_PASSWORD].set) + { + /* + * Password from the '-p' option is limited to C-string. + * Arbitrary data keys are supported via keyfiles. + */ + password_size = grub_strlen (state[OPTION_PASSWORD].arg); + grub_strcpy ((char*) key_data, state[OPTION_PASSWORD].arg); + } + + /* Set cipher mode (tested above) */ + mode = grub_strchr (cipher,'-'); + *mode++ = '\0'; + + /* Check cipher */ + err = grub_cryptodisk_setcipher (dev, cipher, mode); + if (err != GRUB_ERR_NONE) + { + if (err == GRUB_ERR_FILE_NOT_FOUND) + err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid cipher %s"), cipher); + else if (err == GRUB_ERR_BAD_ARGUMENT) + err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid mode %s"), mode); + else + err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid cipher %s or mode %s"), + cipher, mode); + goto fail; + } + + /* Open SOURCE disk */ + diskname = args[0]; + len = grub_strlen (diskname); + if (len && diskname[0] == '(' && diskname[len - 1] == ')') + { + disklast = &diskname[len - 1]; + *disklast = '\0'; + diskname++; + } + disk = grub_disk_open (diskname); + if (disk == NULL) + { + if (disklast) + *disklast = ')'; + err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("cannot open disk %s"), diskname); + goto fail; + } + + /* Get password from console */ + if (!state[OPTION_KEYFILE].set && key_data[0] == '\0') + { + char *part = grub_partition_get_name (disk->partition); + grub_printf_ (N_("Enter passphrase for %s%s%s: "), disk->name, + disk->partition != NULL ? "," : "", + part != NULL ? part : N_("UNKNOWN")); + grub_free (part); + + if (!grub_password_get ((char*) key_data, GRUB_CRYPTODISK_MAX_PASSPHRASE - 1)) + { + err = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("error reading password")); + goto fail; + } + /* + * Password from interactive console is limited to C-string. + * Arbitrary data keys are supported via keyfiles. + */ + password_size = grub_strlen ((char*) key_data); + } + + /* Warn if hash and keyfile are both provided */ + if (state[OPTION_KEYFILE].set && state[OPTION_HASH].arg) + grub_printf_ (N_("warning: hash is ignored if keyfile is specified\n")); + + /* Warn if -p option is specified with keyfile */ + if (state[OPTION_PASSWORD].set && state[OPTION_KEYFILE].set) + grub_printf_ (N_("warning: password specified with -p option " + "is ignored if keyfile is provided\n")); + + /* Warn of -O is provided without keyfile */ + if (state[OPTION_KEYFILE_OFFSET].set && !state[OPTION_KEYFILE].set) + grub_printf_ (N_("warning: keyfile offset option -O " + "specified without keyfile option -d\n")); + + grub_dprintf ("plainmount", "parameters: cipher=%s, hash=%s, key_size=%" + PRIuGRUB_SIZE ", keyfile=%s, keyfile offset=%" PRIuGRUB_SIZE "\n", + cipher, hash, key_size, keyfile, keyfile_offset); + + err = plainmount_configure_sectors (dev, disk, sector_size); + if (err != GRUB_ERR_NONE) + goto fail; + + /* Configure keyfile or password */ + if (state[OPTION_KEYFILE].set) + err = plainmount_configure_keyfile (keyfile, key_data, key_size, keyfile_offset); + else + err = plainmount_configure_password (dev, hash, key_data, key_size, password_size); + if (err != GRUB_ERR_NONE) + goto fail; + + err = plainmount_setkey (dev, key_data, key_size); + if (err != GRUB_ERR_NONE) + goto fail; + + err = grub_cryptodisk_insert (dev, diskname, disk); + if (err != GRUB_ERR_NONE) + goto fail; + + dev->modname = "plainmount"; + dev->source_disk = disk; + plainmount_set_uuid (dev, uuid); + + fail: + grub_free (hash); + grub_free (cipher); + grub_free (keyfile); + grub_free (key_data); + grub_free (uuid); + if (err != GRUB_ERR_NONE && disk != NULL) + grub_disk_close (disk); + if (err != GRUB_ERR_NONE) + grub_free (dev); + return err; +} + +static grub_extcmd_t cmd; +GRUB_MOD_INIT (plainmount) +{ + cmd = grub_register_extcmd ("plainmount", grub_cmd_plainmount, 0, + N_("-c cipher -s key-size [-h hash] [-S sector-size]" + " [-o offset] [-p password] [-u uuid] " + " [[-d keyfile] [-O keyfile offset]] "), + N_("Open partition encrypted in plain mode."), + options); +} + +GRUB_MOD_FINI (plainmount) +{ + grub_unregister_extcmd (cmd); +} diff --git a/grub-core/disk/raid6_recover.c b/grub-core/disk/raid6_recover.c index ba889ba3d..75fe464a4 100644 --- a/grub-core/disk/raid6_recover.c +++ b/grub-core/disk/raid6_recover.c @@ -30,13 +30,13 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* x**y. */ static grub_uint8_t powx[255 * 2]; /* Such an s that x**s = y */ -static int powx_inv[256]; +static unsigned powx_inv[256]; static const grub_uint8_t poly = 0x1d; static void -grub_raid_block_mulx (int mul, char *buf, int size) +grub_raid_block_mulx (unsigned mul, char *buf, grub_size_t size) { - int i; + grub_size_t i; grub_uint8_t *p; p = (grub_uint8_t *) buf; @@ -48,7 +48,7 @@ grub_raid_block_mulx (int mul, char *buf, int size) static void grub_raid6_init_table (void) { - int i; + unsigned i; grub_uint8_t cur = 1; for (i = 0; i < 255; i++) @@ -63,15 +63,37 @@ grub_raid6_init_table (void) } } +static unsigned +mod_255 (unsigned x) +{ + while (x > 0xff) + x = (x >> 8) + (x & 0xff); + if (x == 0xff) + return 0; + return x; +} + static grub_err_t -grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p, - char *buf, grub_disk_addr_t sector, grub_size_t size) +raid6_recover_read_node (void *data, int disknr, + grub_uint64_t sector, + void *buf, grub_size_t size) +{ + struct grub_diskfilter_segment *array = data; + + return grub_diskfilter_read_node (&array->nodes[disknr], + (grub_disk_addr_t)sector, + size >> GRUB_DISK_SECTOR_BITS, buf); +} + +grub_err_t +grub_raid6_recover_gen (void *data, grub_uint64_t nstripes, int disknr, int p, + char *buf, grub_uint64_t sector, grub_size_t size, + int layout, raid_recover_read_t read_func) { int i, q, pos; int bad1 = -1, bad2 = -1; char *pbuf = 0, *qbuf = 0; - size <<= GRUB_DISK_SECTOR_BITS; pbuf = grub_zalloc (size); if (!pbuf) goto quit; @@ -81,17 +103,17 @@ grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p, goto quit; q = p + 1; - if (q == (int) array->node_count) + if (q == (int) nstripes) q = 0; pos = q + 1; - if (pos == (int) array->node_count) + if (pos == (int) nstripes) pos = 0; - for (i = 0; i < (int) array->node_count - 2; i++) + for (i = 0; i < (int) nstripes - 2; i++) { int c; - if (array->layout & GRUB_RAID_LAYOUT_MUL_FROM_POS) + if (layout & GRUB_RAID_LAYOUT_MUL_FROM_POS) c = pos; else c = i; @@ -99,8 +121,7 @@ grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p, bad1 = c; else { - if (! grub_diskfilter_read_node (&array->nodes[pos], sector, - size >> GRUB_DISK_SECTOR_BITS, buf)) + if (!read_func (data, pos, sector, buf, size)) { grub_crypto_xor (pbuf, pbuf, buf, size); grub_raid_block_mulx (c, buf, size); @@ -118,7 +139,7 @@ grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p, } pos++; - if (pos == (int) array->node_count) + if (pos == (int) nstripes) pos = 0; } @@ -129,16 +150,14 @@ grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p, if (bad2 < 0) { /* One bad device */ - if ((! grub_diskfilter_read_node (&array->nodes[p], sector, - size >> GRUB_DISK_SECTOR_BITS, buf))) + if (!read_func (data, p, sector, buf, size)) { grub_crypto_xor (buf, buf, pbuf, size); goto quit; } grub_errno = GRUB_ERR_NONE; - if (grub_diskfilter_read_node (&array->nodes[q], sector, - size >> GRUB_DISK_SECTOR_BITS, buf)) + if (read_func (data, q, sector, buf, size)) goto quit; grub_crypto_xor (buf, buf, qbuf, size); @@ -148,24 +167,23 @@ grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p, else { /* Two bad devices */ - int c; + unsigned c; - if (grub_diskfilter_read_node (&array->nodes[p], sector, - size >> GRUB_DISK_SECTOR_BITS, buf)) + if (read_func (data, p, sector, buf, size)) goto quit; grub_crypto_xor (pbuf, pbuf, buf, size); - if (grub_diskfilter_read_node (&array->nodes[q], sector, - size >> GRUB_DISK_SECTOR_BITS, buf)) + if (read_func (data, q, sector, buf, size)) goto quit; grub_crypto_xor (qbuf, qbuf, buf, size); - c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255; + c = mod_255((255 ^ bad1) + + (255 ^ powx_inv[(powx[bad2 + (bad1 ^ 255)] ^ 1)])); grub_raid_block_mulx (c, qbuf, size); - c = (bad2 + c) % 255; + c = mod_255((unsigned) bad2 + c); grub_raid_block_mulx (c, pbuf, size); grub_crypto_xor (pbuf, pbuf, qbuf, size); @@ -179,6 +197,15 @@ quit: return grub_errno; } +static grub_err_t +grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p, + char *buf, grub_disk_addr_t sector, grub_size_t size) +{ + return grub_raid6_recover_gen (array, array->node_count, disknr, p, buf, + sector, size << GRUB_DISK_SECTOR_BITS, + array->layout, raid6_recover_read_node); +} + GRUB_MOD_INIT(raid6rec) { grub_raid6_init_table (); diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 29dd0d3b8..1c3865fd2 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -90,7 +90,7 @@ grub_scsi_test_unit_ready (grub_scsi_t scsi) struct grub_scsi_test_unit_ready tur; grub_err_t err; grub_err_t err_sense; - + tur.opcode = grub_scsi_cmd_test_unit_ready; tur.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; tur.reserved1 = 0; @@ -108,7 +108,7 @@ grub_scsi_test_unit_ready (grub_scsi_t scsi) if (err_sense != GRUB_ERR_NONE) grub_errno = err; /* err_sense is ignored for now and Request Sense Data also... */ - + if (err) return err; @@ -169,7 +169,7 @@ grub_scsi_read_capacity10 (grub_scsi_t scsi) rc.PMI = 0; rc.control = 0; rc.pad = 0; - + err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc, sizeof (rcd), (char *) &rcd); @@ -201,10 +201,10 @@ grub_scsi_read_capacity16 (grub_scsi_t scsi) rc.opcode = grub_scsi_cmd_read_capacity16; rc.lun = (scsi->lun << GRUB_SCSI_LUN_SHIFT) | 0x10; rc.logical_block_addr = 0; - rc.alloc_len = grub_cpu_to_be32 (sizeof (rcd)); + rc.alloc_len = grub_cpu_to_be32_compile_time (sizeof (rcd)); rc.PMI = 0; rc.control = 0; - + err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc, sizeof (rcd), (char *) &rcd); @@ -423,50 +423,59 @@ grub_scsi_write16 (grub_disk_t disk, grub_disk_addr_t sector, -static int -grub_scsi_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull) +/* Context for grub_scsi_iterate. */ +struct grub_scsi_iterate_ctx { - grub_scsi_dev_t p; + grub_disk_dev_iterate_hook_t hook; + void *hook_data; +}; - auto int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns); +/* Helper for grub_scsi_iterate. */ +static int +scsi_iterate (int id, int bus, int luns, void *data) +{ + struct grub_scsi_iterate_ctx *ctx = data; + int i; - int NESTED_FUNC_ATTR scsi_iterate (int id, int bus, int luns) + /* In case of a single LUN, just return `usbX'. */ + if (luns == 1) { - int i; - - /* In case of a single LUN, just return `usbX'. */ - if (luns == 1) - { - char *sname; - int ret; - sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus); - if (!sname) - return 1; - ret = hook (sname); - grub_free (sname); - return ret; - } - - /* In case of multiple LUNs, every LUN will get a prefix to - distinguish it. */ - for (i = 0; i < luns; i++) - { - char *sname; - int ret; - sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i); - if (!sname) - return 1; - ret = hook (sname); - grub_free (sname); - if (ret) - return 1; - } - return 0; + char *sname; + int ret; + sname = grub_xasprintf ("%s%d", grub_scsi_names[id], bus); + if (!sname) + return 1; + ret = ctx->hook (sname, ctx->hook_data); + grub_free (sname); + return ret; } + /* In case of multiple LUNs, every LUN will get a prefix to + distinguish it. */ + for (i = 0; i < luns; i++) + { + char *sname; + int ret; + sname = grub_xasprintf ("%s%d%c", grub_scsi_names[id], bus, 'a' + i); + if (!sname) + return 1; + ret = ctx->hook (sname, ctx->hook_data); + grub_free (sname); + if (ret) + return 1; + } + return 0; +} + +static int +grub_scsi_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +{ + struct grub_scsi_iterate_ctx ctx = { hook, hook_data }; + grub_scsi_dev_t p; + for (p = grub_scsi_dev_list; p; p = p->next) - if (p->iterate && (p->iterate) (scsi_iterate, pull)) + if (p->iterate && (p->iterate) (scsi_iterate, &ctx, pull)) return 1; return 0; @@ -597,15 +606,21 @@ grub_scsi_open (const char *name, grub_disk_t disk) } disk->total_sectors = scsi->last_block + 1; + /* PATA doesn't support more than 32K reads. + Not sure about AHCI and USB. If it's confirmed that either of + them can do bigger reads reliably this value can be moved to 'scsi' + structure. */ + disk->max_agglomerate = 32768 >> (GRUB_DISK_SECTOR_BITS + + GRUB_DISK_CACHE_BITS); + if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize) { + grub_error (GRUB_ERR_IO, "invalid sector size %d", + scsi->blocksize); grub_free (scsi); - return grub_error (GRUB_ERR_IO, "invalid sector size %d", - scsi->blocksize); + return grub_errno; } - for (disk->log_sector_size = 0; - (1U << disk->log_sector_size) < scsi->blocksize; - disk->log_sector_size++); + disk->log_sector_size = grub_log2ull (scsi->blocksize); grub_dprintf ("scsi", "last_block=%" PRIuGRUB_UINT64_T ", blocksize=%u\n", scsi->last_block, scsi->blocksize); @@ -638,40 +653,27 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, scsi = disk->data; - while (size) + grub_err_t err; + /* Depending on the type, select a read function. */ + switch (scsi->devtype) { - /* PATA doesn't support more than 32K reads. - Not sure about AHCI and USB. If it's confirmed that either of - them can do bigger reads reliably this value can be moved to 'scsi' - structure. */ - grub_size_t len = 32768 >> disk->log_sector_size; - grub_err_t err; - if (len > size) - len = size; - /* Depending on the type, select a read function. */ - switch (scsi->devtype) - { - case grub_scsi_devtype_direct: - if (sector >> 32) - err = grub_scsi_read16 (disk, sector, len, buf); - else - err = grub_scsi_read10 (disk, sector, len, buf); - if (err) - return err; - break; + case grub_scsi_devtype_direct: + if (sector >> 32) + err = grub_scsi_read16 (disk, sector, size, buf); + else + err = grub_scsi_read10 (disk, sector, size, buf); + if (err) + return err; + break; - case grub_scsi_devtype_cdrom: - if (sector >> 32) - err = grub_scsi_read16 (disk, sector, len, buf); - else - err = grub_scsi_read12 (disk, sector, len, buf); - if (err) - return err; - break; - } - size -= len; - sector += len; - buf += len << disk->log_sector_size; + case grub_scsi_devtype_cdrom: + if (sector >> 32) + err = grub_scsi_read16 (disk, sector, size, buf); + else + err = grub_scsi_read12 (disk, sector, size, buf); + if (err) + return err; + break; } return GRUB_ERR_NONE; @@ -709,10 +711,10 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, } static grub_err_t -grub_scsi_write (grub_disk_t disk __attribute((unused)), - grub_disk_addr_t sector __attribute((unused)), - grub_size_t size __attribute((unused)), - const char *buf __attribute((unused))) +grub_scsi_write (grub_disk_t disk, + grub_disk_addr_t sector, + grub_size_t size, + const char *buf) { grub_scsi_t scsi; @@ -721,31 +723,18 @@ grub_scsi_write (grub_disk_t disk __attribute((unused)), if (scsi->devtype == grub_scsi_devtype_cdrom) return grub_error (GRUB_ERR_IO, N_("cannot write to CD-ROM")); - while (size) + grub_err_t err; + /* Depending on the type, select a read function. */ + switch (scsi->devtype) { - /* PATA doesn't support more than 32K reads. - Not sure about AHCI and USB. If it's confirmed that either of - them can do bigger reads reliably this value can be moved to 'scsi' - structure. */ - grub_size_t len = 32768 >> disk->log_sector_size; - grub_err_t err; - if (len > size) - len = size; - /* Depending on the type, select a read function. */ - switch (scsi->devtype) - { - case grub_scsi_devtype_direct: - if (sector >> 32) - err = grub_scsi_write16 (disk, sector, len, buf); - else - err = grub_scsi_write10 (disk, sector, len, buf); - if (err) - return err; - break; - } - size -= len; - sector += len; - buf += len << disk->log_sector_size; + case grub_scsi_devtype_direct: + if (sector >> 32) + err = grub_scsi_write16 (disk, sector, size, buf); + else + err = grub_scsi_write10 (disk, sector, size, buf); + if (err) + return err; + break; } return GRUB_ERR_NONE; @@ -756,11 +745,11 @@ static struct grub_disk_dev grub_scsi_dev = { .name = "scsi", .id = GRUB_DISK_DEVICE_SCSI_ID, - .iterate = grub_scsi_iterate, - .open = grub_scsi_open, - .close = grub_scsi_close, - .read = grub_scsi_read, - .write = grub_scsi_write, + .disk_iterate = grub_scsi_iterate, + .disk_open = grub_scsi_open, + .disk_close = grub_scsi_close, + .disk_read = grub_scsi_read, + .disk_write = grub_scsi_write, .next = 0 }; diff --git a/grub-core/disk/uboot/ubootdisk.c b/grub-core/disk/uboot/ubootdisk.c new file mode 100644 index 000000000..0e918d4d1 --- /dev/null +++ b/grub-core/disk/uboot/ubootdisk.c @@ -0,0 +1,305 @@ +/* ubootdisk.c - disk subsystem support for U-Boot platforms */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct ubootdisk_data *hd_devices; +static int hd_num; +static int hd_max; + +/* + * grub_ubootdisk_register(): + * Called for each disk device enumerated as part of U-Boot initialization + * code. + */ +grub_err_t +grub_ubootdisk_register (struct device_info *newdev) +{ + struct ubootdisk_data *d; + +#define STOR_TYPE(x) ((x) & 0x0ff0) + switch (STOR_TYPE (newdev->type)) + { + case DT_STOR_IDE: + case DT_STOR_SATA: + case DT_STOR_SCSI: + case DT_STOR_MMC: + case DT_STOR_USB: + /* hd */ + if (hd_num == hd_max) + { + int new_num; + new_num = (hd_max ? hd_max * 2 : 1); + d = grub_realloc(hd_devices, + sizeof (struct ubootdisk_data) * new_num); + if (!d) + return grub_errno; + hd_devices = d; + hd_max = new_num; + } + + d = &hd_devices[hd_num]; + hd_num++; + break; + default: + return GRUB_ERR_BAD_DEVICE; + break; + } + + d->dev = newdev; + d->cookie = newdev->cookie; + d->opencount = 0; + + return 0; +} + +/* + * uboot_disk_iterate(): + * Iterator over enumerated disk devices. + */ +static int +uboot_disk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +{ + char buf[16]; + int count; + + switch (pull) + { + case GRUB_DISK_PULL_NONE: + /* "hd" - built-in mass-storage */ + for (count = 0 ; count < hd_num; count++) + { + grub_snprintf (buf, sizeof (buf) - 1, "hd%d", count); + grub_dprintf ("ubootdisk", "iterating %s\n", buf); + if (hook (buf, hook_data)) + return 1; + } + break; + default: + return 0; + } + + return 0; +} + +/* Helper function for uboot_disk_open. */ +static struct ubootdisk_data * +get_hd_device (int num) +{ + if (num < hd_num) + return &hd_devices[num]; + + return NULL; +} + +/* + * uboot_disk_open(): + * Opens a disk device already enumerated. + */ +static grub_err_t +uboot_disk_open (const char *name, struct grub_disk *disk) +{ + struct ubootdisk_data *d; + struct device_info *devinfo; + int num; + int retval; + + grub_dprintf ("ubootdisk", "Opening '%s'\n", name); + + num = grub_strtoul (name + 2, 0, 10); + if (grub_errno != GRUB_ERR_NONE) + { + grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid number\n", + name); + goto fail; + } + + if (name[1] != 'd') + { + grub_dprintf ("ubootdisk", "Opening '%s' failed, invalid name\n", name); + goto fail; + } + + switch (name[0]) + { + case 'h': + d = get_hd_device (num); + break; + default: + goto fail; + } + + if (!d) + goto fail; + + /* + * Subsystems may call open on the same device recursively - but U-Boot + * does not deal with this. So simply keep track of number of calls and + * return success if already open. + */ + if (d->opencount > 0) + { + grub_dprintf ("ubootdisk", "(%s) already open\n", disk->name); + d->opencount++; + retval = 0; + } + else + { + retval = grub_uboot_dev_open (d->dev); + if (retval != 0) + goto fail; + d->opencount = 1; + } + + grub_dprintf ("ubootdisk", "cookie: 0x%08x\n", (grub_addr_t) d->cookie); + disk->id = (grub_addr_t) d->cookie; + + devinfo = d->dev; + + d->block_size = devinfo->di_stor.block_size; + if (d->block_size == 0) + return grub_error (GRUB_ERR_IO, "no block size"); + + disk->log_sector_size = grub_log2ull (d->block_size); + + grub_dprintf ("ubootdisk", "(%s) blocksize=%d, log_sector_size=%d\n", + disk->name, d->block_size, disk->log_sector_size); + + if (devinfo->di_stor.block_count) + disk->total_sectors = devinfo->di_stor.block_count; + else + disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; + + disk->data = d; + + return GRUB_ERR_NONE; + +fail: + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device"); +} + +static void +uboot_disk_close (struct grub_disk *disk) +{ + struct ubootdisk_data *d; + int retval; + + d = disk->data; + + /* + * In mirror of open function, keep track of number of calls to close and + * send on to U-Boot only when opencount would decrease to 0. + */ + if (d->opencount > 1) + { + grub_dprintf ("ubootdisk", "Closed (%s)\n", disk->name); + + d->opencount--; + } + else if (d->opencount == 1) + { + retval = grub_uboot_dev_close (d->dev); + d->opencount--; + grub_dprintf ("ubootdisk", "closed %s (%d)\n", disk->name, retval); + } + else + { + grub_dprintf ("ubootdisk", "device %s not open!\n", disk->name); + } +} + +/* + * uboot_disk_read(): + * Called from within disk subsystem to read a sequence of blocks into the + * disk cache. Maps directly on top of U-Boot API, only wrap in some error + * handling. + */ +static grub_err_t +uboot_disk_read (struct grub_disk *disk, + grub_disk_addr_t offset, grub_size_t numblocks, char *buf) +{ + struct ubootdisk_data *d; + grub_size_t real_size; + int retval; + + d = disk->data; + + retval = grub_uboot_dev_read (d->dev, buf, numblocks, offset, &real_size); + grub_dprintf ("ubootdisk", + "retval=%d, numblocks=%d, real_size=%llu, sector=%llu\n", + retval, numblocks, (grub_uint64_t) real_size, + (grub_uint64_t) offset); + if (retval != 0) + return grub_error (GRUB_ERR_IO, "U-Boot disk read error"); + + return GRUB_ERR_NONE; +} + +static grub_err_t +uboot_disk_write (struct grub_disk *disk, + grub_disk_addr_t offset, grub_size_t numblocks, const char *buf) +{ + struct ubootdisk_data *d; + int retval; + + d = disk->data; + + retval = grub_uboot_dev_write (d->dev, buf, numblocks, offset); + grub_dprintf ("ubootdisk", + "retval=%d, numblocks=%d, sector=%llu\n", + retval, numblocks, (grub_uint64_t) offset); + + if (retval != 0) + return grub_error (GRUB_ERR_IO, "U-Boot disk write error"); + + return GRUB_ERR_NONE; +} + +static struct grub_disk_dev grub_ubootdisk_dev = { + .name = "ubootdisk", + .id = GRUB_DISK_DEVICE_UBOOTDISK_ID, + .disk_iterate = uboot_disk_iterate, + .disk_open = uboot_disk_open, + .disk_close = uboot_disk_close, + .disk_read = uboot_disk_read, + .disk_write = uboot_disk_write, + .next = 0 +}; + +void +grub_ubootdisk_init (void) +{ + grub_disk_dev_register (&grub_ubootdisk_dev); +} + +void +grub_ubootdisk_fini (void) +{ + grub_disk_dev_unregister (&grub_ubootdisk_dev); +} diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c index 52cc33e93..b81e3ad9d 100644 --- a/grub-core/disk/usbms.c +++ b/grub-core/disk/usbms.c @@ -44,7 +44,7 @@ struct grub_usbms_cbw grub_uint8_t lun; grub_uint8_t length; grub_uint8_t cbwcb[16]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_usbms_csw { @@ -52,7 +52,7 @@ struct grub_usbms_csw grub_uint32_t tag; grub_uint32_t residue; grub_uint8_t status; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_usbms_dev { @@ -76,7 +76,7 @@ typedef struct grub_usbms_dev *grub_usbms_dev_t; static grub_usbms_dev_t grub_usbms_devices[MAX_USBMS_DEVICES]; static int first_available_slot = 0; -static grub_err_t +static grub_usb_err_t grub_usbms_cbi_cmd (grub_usb_device_t dev, int interface, grub_uint8_t *cbicb) { @@ -86,7 +86,7 @@ grub_usbms_cbi_cmd (grub_usb_device_t dev, int interface, GRUB_USBMS_CBI_CMD_SIZE, (char*)cbicb); } -static grub_err_t +static grub_usb_err_t grub_usbms_cbi_reset (grub_usb_device_t dev, int interface) { /* Prepare array with Command Block Reset (=CBR) */ @@ -104,21 +104,17 @@ grub_usbms_cbi_reset (grub_usb_device_t dev, int interface) { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } }; - + return grub_usbms_cbi_cmd (dev, interface, (grub_uint8_t *)&cbicb); } -static grub_err_t +static grub_usb_err_t grub_usbms_bo_reset (grub_usb_device_t dev, int interface) { - grub_usb_err_t u; - u = grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0); - if (u) - return grub_error (GRUB_ERR_IO, "USB error %d", u); - return GRUB_ERR_NONE; + return grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0); } -static grub_err_t +static grub_usb_err_t grub_usbms_reset (grub_usbms_dev_t dev) { if (dev->protocol == GRUB_USBMS_PROTOCOL_BULK) @@ -149,7 +145,9 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) int j; grub_uint8_t luns = 0; unsigned curnum; - grub_usb_err_t err = GRUB_ERR_NONE; + grub_usb_err_t err = GRUB_USB_ERR_NONE; + + grub_boot_time ("Attaching USB mass storage"); if (first_available_slot == ARRAY_SIZE (grub_usbms_devices)) return 0; @@ -163,7 +161,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) /* Experimental support of RBC, MMC-2, UFI, SFF-8070i devices */ && interf->subclass != GRUB_USBMS_SUBCLASS_RBC && interf->subclass != GRUB_USBMS_SUBCLASS_MMC2 - && interf->subclass != GRUB_USBMS_SUBCLASS_UFI + && interf->subclass != GRUB_USBMS_SUBCLASS_UFI && interf->subclass != GRUB_USBMS_SUBCLASS_SFF8070 ) || (interf->protocol != GRUB_USBMS_PROTOCOL_BULK && interf->protocol != GRUB_USBMS_PROTOCOL_CBI @@ -217,7 +215,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) if (grub_usbms_devices[curnum]->protocol == GRUB_USBMS_PROTOCOL_BULK) { /* Only Bulk only devices support Get Max LUN command */ err = grub_usb_control_msg (usbdev, 0xA1, 254, 0, interfno, 1, (char *) &luns); - + if (err) { /* In case of a stall, clear the stall. */ @@ -233,7 +231,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) else /* luns = 0 means one LUN with ID 0 present ! */ /* We get from device not number of LUNs but highest - * LUN number. LUNs are numbered from 0, + * LUN number. LUNs are numbered from 0, * i.e. number of LUNs is luns+1 ! */ grub_usbms_devices[curnum]->luns = luns + 1; } @@ -241,11 +239,13 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) /* XXX: Does CBI devices support multiple LUNs ? * I.e., should we detect number of device's LUNs ? (How?) */ grub_usbms_devices[curnum]->luns = 1; - + grub_dprintf ("usbms", "alive\n"); usbdev->config[configno].interf[interfno].detach_hook = grub_usbms_detach; + grub_boot_time ("Attached USB mass storage"); + #if 0 /* All this part should be probably deleted. * This make trouble on some devices if they are not in * Phase Error state - and there they should be not in such state... @@ -265,7 +265,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) static int -grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns), +grub_usbms_iterate (grub_scsi_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { unsigned i; @@ -273,12 +273,13 @@ grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns), if (pull != GRUB_DISK_PULL_NONE) return 0; - grub_usb_poll_devices (); + grub_usb_poll_devices (1); for (i = 0; i < ARRAY_SIZE (grub_usbms_devices); i++) if (grub_usbms_devices[i]) { - if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns)) + if (hook (GRUB_SCSI_SUBSYSTEM_USBMS, i, grub_usbms_devices[i]->luns, + hook_data)) return 1; } @@ -296,7 +297,9 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, grub_usb_err_t err = GRUB_USB_ERR_NONE; grub_usb_err_t errCSW = GRUB_USB_ERR_NONE; int retrycnt = 3 + 1; - + + tag++; + retry: retrycnt--; if (retrycnt == 0) @@ -304,14 +307,14 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Setup the request. */ grub_memset (&cbw, 0, sizeof (cbw)); - cbw.signature = grub_cpu_to_le32 (0x43425355); - cbw.tag = tag++; + cbw.signature = grub_cpu_to_le32_compile_time (0x43425355); + cbw.tag = tag; cbw.transfer_length = grub_cpu_to_le32 (size); cbw.flags = (!read_write) << GRUB_USBMS_DIRECTION_BIT; cbw.lun = scsi->lun; /* In USB MS CBW are LUN bits on another place than in SCSI CDB, both should be set correctly. */ cbw.length = cmdsize; grub_memcpy (cbw.cbwcb, cmd, cmdsize); - + /* Debug print of CBW content. */ grub_dprintf ("usb", "CBW: sign=0x%08x tag=0x%08x len=0x%08x\n", cbw.signature, cbw.tag, cbw.transfer_length); @@ -325,7 +328,7 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Write the request. * XXX: Error recovery is maybe still not fully correct. */ - err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, + err = grub_usb_bulk_write (dev->dev, dev->out, sizeof (cbw), (char *) &cbw); if (err) { @@ -334,14 +337,14 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, grub_usb_clear_halt (dev->dev, dev->out->endp_addr); goto CheckCSW; } - return grub_error (GRUB_ERR_IO, "USB Mass Storage request failed"); + goto retry; } /* Read/write the data, (maybe) according to specification. */ if (size && (read_write == 0)) { - err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf); - grub_dprintf ("usb", "read: %d %d\n", err, GRUB_USB_ERR_STALL); + err = grub_usb_bulk_read (dev->dev, dev->in, size, buf); + grub_dprintf ("usb", "read: %d %d\n", err, GRUB_USB_ERR_STALL); if (err) { if (err == GRUB_USB_ERR_STALL) @@ -361,7 +364,7 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, } else if (size) { - err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf); + err = grub_usb_bulk_write (dev->dev, dev->out, size, buf); grub_dprintf ("usb", "write: %d %d\n", err, GRUB_USB_ERR_STALL); grub_dprintf ("usb", "First 16 bytes of sent data:\n %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", buf[ 0], buf[ 1], buf[ 2], buf[ 3], @@ -387,12 +390,12 @@ grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Read the status - (maybe) according to specification. */ CheckCSW: - errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, + errCSW = grub_usb_bulk_read (dev->dev, dev->in, sizeof (status), (char *) &status); if (errCSW) { grub_usb_clear_halt (dev->dev, dev->in->endp_addr); - errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, + errCSW = grub_usb_bulk_read (dev->dev, dev->in, sizeof (status), (char *) &status); if (errCSW) { /* Bulk-only reset device. */ @@ -408,10 +411,10 @@ CheckCSW: grub_dprintf ("usb", "CSW: sign=0x%08x tag=0x%08x resid=0x%08x\n", status.signature, status.tag, status.residue); grub_dprintf ("usb", "CSW: status=0x%02x\n", status.status); - + /* If phase error or not valid signature, do bulk-only reset device. */ if ((status.status == 2) || - (status.signature != grub_cpu_to_le32(0x53425355))) + (status.signature != grub_cpu_to_le32_compile_time(0x53425355))) { /* Bulk-only reset device. */ grub_dprintf ("usb", "Bulk-only reset device - bad status\n"); grub_usbms_reset (dev); @@ -441,7 +444,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, grub_usb_err_t err = GRUB_USB_ERR_NONE; grub_uint8_t cbicb[GRUB_USBMS_CBI_CMD_SIZE]; grub_uint16_t status; - + retry: retrycnt--; if (retrycnt == 0) @@ -453,7 +456,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, cmdsize >= GRUB_USBMS_CBI_CMD_SIZE ? GRUB_USBMS_CBI_CMD_SIZE : cmdsize); - + /* Debug print of CBIcb content. */ grub_dprintf ("usb", "cbicb:\n %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", cbicb[ 0], cbicb[ 1], cbicb[ 2], cbicb[ 3], @@ -475,7 +478,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, else if (dev->protocol == GRUB_USBMS_PROTOCOL_CBI) { /* Try to get status from interrupt pipe */ - err = grub_usb_bulk_read (dev->dev, dev->intrpt->endp_addr, + err = grub_usb_bulk_read (dev->dev, dev->intrpt, 2, (char*)&status); grub_dprintf ("usb", "CBI cmdcb setup status: err=%d, status=0x%x\n", err, status); } @@ -486,8 +489,8 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, /* Read/write the data, (maybe) according to specification. */ if (size && (read_write == 0)) { - err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf); - grub_dprintf ("usb", "read: %d\n", err); + err = grub_usb_bulk_read (dev->dev, dev->in, size, buf); + grub_dprintf ("usb", "read: %d\n", err); if (err) { if (err == GRUB_USB_ERR_STALL) @@ -497,7 +500,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, } else if (size) { - err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf); + err = grub_usb_bulk_write (dev->dev, dev->out, size, buf); grub_dprintf ("usb", "write: %d\n", err); if (err) { @@ -516,7 +519,7 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, * (we do not it yet) - ? */ if (dev->protocol == GRUB_USBMS_PROTOCOL_CBI) { /* Check status in interrupt pipe */ - err = grub_usb_bulk_read (dev->dev, dev->intrpt->endp_addr, + err = grub_usb_bulk_read (dev->dev, dev->intrpt, 2, (char*)&status); grub_dprintf ("usb", "read status: %d\n", err); if (err) @@ -566,8 +569,11 @@ grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, } } } - - return err; + + if (err) + return grub_error (GRUB_ERR_IO, "USB error %d", err); + + return GRUB_ERR_NONE; } @@ -606,7 +612,8 @@ grub_usbms_open (int id, int devnum, struct grub_scsi *scsi) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not USB Mass Storage device"); - grub_usb_poll_devices (); + if (!grub_usbms_devices[devnum]) + grub_usb_poll_devices (1); if (!grub_usbms_devices[devnum]) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, diff --git a/grub-core/disk/xen/xendisk.c b/grub-core/disk/xen/xendisk.c new file mode 100644 index 000000000..496f1ea7b --- /dev/null +++ b/grub-core/disk/xen/xendisk.c @@ -0,0 +1,483 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct virtdisk +{ + int handle; + char *fullname; + char *backend_dir; + char *frontend_dir; + struct blkif_sring *shared_page; + struct blkif_front_ring ring; + grub_xen_grant_t grant; + grub_xen_evtchn_t evtchn; + void *dma_page; + grub_xen_grant_t dma_grant; + struct virtdisk *compat_next; +}; + +#define xen_wmb() mb() +#define xen_mb() mb() + +static struct virtdisk *virtdisks; +static grub_size_t vdiskcnt; +struct virtdisk *compat_head; + +static int +grub_virtdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +{ + grub_size_t i; + + if (pull != GRUB_DISK_PULL_NONE) + return 0; + + for (i = 0; i < vdiskcnt; i++) + if (hook (virtdisks[i].fullname, hook_data)) + return 1; + return 0; +} + +static grub_err_t +grub_virtdisk_open (const char *name, grub_disk_t disk) +{ + int i; + grub_uint32_t secsize; + char fdir[200]; + char *buf; + int num = -1; + struct virtdisk *vd; + + /* For compatibility with pv-grub legacy menu.lst accept hdX as disk name */ + if (name[0] == 'h' && name[1] == 'd' && name[2]) + { + num = grub_strtoul (name + 2, 0, 10); + if (grub_errno) + { + grub_errno = 0; + num = -1; + } + } + for (i = 0, vd = compat_head; vd; vd = vd->compat_next, i++) + if (i == num || grub_strcmp (name, vd->fullname) == 0) + break; + if (!vd) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a virtdisk"); + disk->data = vd; + disk->id = vd - virtdisks; + + grub_snprintf (fdir, sizeof (fdir), "%s/sectors", vd->backend_dir); + buf = grub_xenstore_get_file (fdir, NULL); + if (!buf) + return grub_errno; + disk->total_sectors = grub_strtoull (buf, 0, 10); + if (grub_errno) + return grub_errno; + + grub_snprintf (fdir, sizeof (fdir), "%s/sector-size", vd->backend_dir); + buf = grub_xenstore_get_file (fdir, NULL); + if (!buf) + return grub_errno; + secsize = grub_strtoull (buf, 0, 10); + if (grub_errno) + return grub_errno; + + if ((secsize & (secsize - 1)) || !secsize || secsize < 512 + || secsize > GRUB_XEN_PAGE_SIZE) + return grub_error (GRUB_ERR_IO, "unsupported sector size %d", secsize); + + disk->log_sector_size = grub_log2ull (secsize); + disk->total_sectors >>= disk->log_sector_size - 9; + + return GRUB_ERR_NONE; +} + +static void +grub_virtdisk_close (grub_disk_t disk __attribute__ ((unused))) +{ +} + +static grub_err_t +grub_virtdisk_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + struct virtdisk *data = disk->data; + + while (size) + { + grub_size_t cur; + struct blkif_request *req; + struct blkif_response *resp; + int sta = 0; + struct evtchn_send send; + cur = size; + if (cur > (unsigned) (GRUB_XEN_PAGE_SIZE >> disk->log_sector_size)) + cur = GRUB_XEN_PAGE_SIZE >> disk->log_sector_size; + while (RING_FULL (&data->ring)) + grub_xen_sched_op (SCHEDOP_yield, 0); + req = RING_GET_REQUEST (&data->ring, data->ring.req_prod_pvt); + req->operation = BLKIF_OP_READ; + req->nr_segments = 1; + req->handle = data->handle; + req->id = 0; + req->sector_number = sector << (disk->log_sector_size - 9); + req->seg[0].gref = data->dma_grant; + req->seg[0].first_sect = 0; + req->seg[0].last_sect = (cur << (disk->log_sector_size - 9)) - 1; + data->ring.req_prod_pvt++; + RING_PUSH_REQUESTS (&data->ring); + mb (); + send.port = data->evtchn; + grub_xen_event_channel_op (EVTCHNOP_send, &send); + + while (!RING_HAS_UNCONSUMED_RESPONSES (&data->ring)) + { + grub_xen_sched_op (SCHEDOP_yield, 0); + mb (); + } + while (1) + { + int wtd; + RING_FINAL_CHECK_FOR_RESPONSES (&data->ring, wtd); + if (!wtd) + break; + resp = RING_GET_RESPONSE (&data->ring, data->ring.rsp_cons); + data->ring.rsp_cons++; + if (resp->status) + sta = resp->status; + } + if (sta) + return grub_error (GRUB_ERR_IO, "read failed"); + grub_memcpy (buf, data->dma_page, cur << disk->log_sector_size); + size -= cur; + sector += cur; + buf += cur << disk->log_sector_size; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_virtdisk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf) +{ + struct virtdisk *data = disk->data; + + while (size) + { + grub_size_t cur; + struct blkif_request *req; + struct blkif_response *resp; + int sta = 0; + struct evtchn_send send; + cur = size; + if (cur > (unsigned) (GRUB_XEN_PAGE_SIZE >> disk->log_sector_size)) + cur = GRUB_XEN_PAGE_SIZE >> disk->log_sector_size; + + grub_memcpy (data->dma_page, buf, cur << disk->log_sector_size); + + while (RING_FULL (&data->ring)) + grub_xen_sched_op (SCHEDOP_yield, 0); + req = RING_GET_REQUEST (&data->ring, data->ring.req_prod_pvt); + req->operation = BLKIF_OP_WRITE; + req->nr_segments = 1; + req->handle = data->handle; + req->id = 0; + req->sector_number = sector << (disk->log_sector_size - 9); + req->seg[0].gref = data->dma_grant; + req->seg[0].first_sect = 0; + req->seg[0].last_sect = (cur << (disk->log_sector_size - 9)) - 1; + data->ring.req_prod_pvt++; + RING_PUSH_REQUESTS (&data->ring); + mb (); + send.port = data->evtchn; + grub_xen_event_channel_op (EVTCHNOP_send, &send); + + while (!RING_HAS_UNCONSUMED_RESPONSES (&data->ring)) + { + grub_xen_sched_op (SCHEDOP_yield, 0); + mb (); + } + while (1) + { + int wtd; + RING_FINAL_CHECK_FOR_RESPONSES (&data->ring, wtd); + if (!wtd) + break; + resp = RING_GET_RESPONSE (&data->ring, data->ring.rsp_cons); + data->ring.rsp_cons++; + if (resp->status) + sta = resp->status; + } + if (sta) + return grub_error (GRUB_ERR_IO, "write failed"); + size -= cur; + sector += cur; + buf += cur << disk->log_sector_size; + } + return GRUB_ERR_NONE; +} + +static struct grub_disk_dev grub_virtdisk_dev = { + .name = "xen", + .id = GRUB_DISK_DEVICE_XEN, + .disk_iterate = grub_virtdisk_iterate, + .disk_open = grub_virtdisk_open, + .disk_close = grub_virtdisk_close, + .disk_read = grub_virtdisk_read, + .disk_write = grub_virtdisk_write, + .next = 0 +}; + +static int +count (const char *dir __attribute__ ((unused)), void *data) +{ + grub_size_t *ctr = data; + (*ctr)++; + + return 0; +} + +static int +fill (const char *dir, void *data) +{ + grub_size_t *ctr = data; + domid_t dom; + /* "dir" is just a number, at most 19 characters. */ + char fdir[200]; + char num[20]; + grub_err_t err; + void *buf; + struct evtchn_alloc_unbound alloc_unbound; + struct virtdisk **prev = &compat_head, *vd = compat_head; + + /* Shouldn't happen unles some hotplug happened. */ + if (vdiskcnt >= *ctr) + return 1; + virtdisks[vdiskcnt].handle = grub_strtoul (dir, 0, 10); + if (grub_errno) + { + grub_errno = 0; + return 0; + } + virtdisks[vdiskcnt].fullname = 0; + virtdisks[vdiskcnt].backend_dir = 0; + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/backend", dir); + virtdisks[vdiskcnt].backend_dir = grub_xenstore_get_file (fdir, NULL); + if (!virtdisks[vdiskcnt].backend_dir) + goto out_fail_1; + + grub_snprintf (fdir, sizeof (fdir), "%s/dev", + virtdisks[vdiskcnt].backend_dir); + buf = grub_xenstore_get_file (fdir, NULL); + if (!buf) + { + grub_errno = 0; + virtdisks[vdiskcnt].fullname = grub_xasprintf ("xenid/%s", dir); + } + else + { + virtdisks[vdiskcnt].fullname = grub_xasprintf ("xen/%s", (char *) buf); + grub_free (buf); + } + if (!virtdisks[vdiskcnt].fullname) + goto out_fail_1; + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/backend-id", dir); + buf = grub_xenstore_get_file (fdir, NULL); + if (!buf) + goto out_fail_1; + + dom = grub_strtoul (buf, 0, 10); + grub_free (buf); + if (grub_errno) + goto out_fail_1; + + virtdisks[vdiskcnt].shared_page = + grub_xen_alloc_shared_page (dom, &virtdisks[vdiskcnt].grant); + if (!virtdisks[vdiskcnt].shared_page) + goto out_fail_1; + + virtdisks[vdiskcnt].dma_page = + grub_xen_alloc_shared_page (dom, &virtdisks[vdiskcnt].dma_grant); + if (!virtdisks[vdiskcnt].dma_page) + goto out_fail_2; + + alloc_unbound.dom = DOMID_SELF; + alloc_unbound.remote_dom = dom; + + grub_xen_event_channel_op (EVTCHNOP_alloc_unbound, &alloc_unbound); + virtdisks[vdiskcnt].evtchn = alloc_unbound.port; + + SHARED_RING_INIT (virtdisks[vdiskcnt].shared_page); + FRONT_RING_INIT (&virtdisks[vdiskcnt].ring, virtdisks[vdiskcnt].shared_page, + GRUB_XEN_PAGE_SIZE); + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/ring-ref", dir); + grub_snprintf (num, sizeof (num), "%u", virtdisks[vdiskcnt].grant); + err = grub_xenstore_write_file (fdir, num, grub_strlen (num)); + if (err) + goto out_fail_3; + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/event-channel", dir); + grub_snprintf (num, sizeof (num), "%u", virtdisks[vdiskcnt].evtchn); + err = grub_xenstore_write_file (fdir, num, grub_strlen (num)); + if (err) + goto out_fail_3; + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/protocol", dir); + err = grub_xenstore_write_file (fdir, XEN_IO_PROTO_ABI_NATIVE, + grub_strlen (XEN_IO_PROTO_ABI_NATIVE)); + if (err) + goto out_fail_3; + + struct gnttab_dump_table dt; + dt.dom = DOMID_SELF; + grub_xen_grant_table_op (GNTTABOP_dump_table, (void *) &dt, 1); + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s/state", dir); + err = grub_xenstore_write_file (fdir, "3", 1); + if (err) + goto out_fail_3; + + while (1) + { + grub_snprintf (fdir, sizeof (fdir), "%s/state", + virtdisks[vdiskcnt].backend_dir); + buf = grub_xenstore_get_file (fdir, NULL); + if (!buf) + goto out_fail_3; + if (grub_strcmp (buf, "2") != 0) + break; + grub_free (buf); + grub_xen_sched_op (SCHEDOP_yield, 0); + } + grub_dprintf ("xen", "state=%s\n", (char *) buf); + grub_free (buf); + + grub_snprintf (fdir, sizeof (fdir), "device/vbd/%s", dir); + + virtdisks[vdiskcnt].frontend_dir = grub_strdup (fdir); + + /* For compatibility with pv-grub maintain linked list sorted by handle + value in increasing order. This allows mapping of (hdX) disk names + from legacy menu.lst */ + while (vd) + { + if (vd->handle > virtdisks[vdiskcnt].handle) + break; + prev = &vd->compat_next; + vd = vd->compat_next; + } + virtdisks[vdiskcnt].compat_next = vd; + *prev = &virtdisks[vdiskcnt]; + + vdiskcnt++; + return 0; + +out_fail_3: + grub_xen_free_shared_page (virtdisks[vdiskcnt].dma_page); +out_fail_2: + grub_xen_free_shared_page (virtdisks[vdiskcnt].shared_page); +out_fail_1: + grub_free (virtdisks[vdiskcnt].backend_dir); + grub_free (virtdisks[vdiskcnt].fullname); + + grub_errno = 0; + return 0; +} + +void +grub_xendisk_init (void) +{ + grub_size_t ctr = 0; + if (grub_xenstore_dir ("device/vbd", count, &ctr)) + grub_errno = 0; + + if (!ctr) + return; + + virtdisks = grub_calloc (ctr, sizeof (virtdisks[0])); + if (!virtdisks) + return; + if (grub_xenstore_dir ("device/vbd", fill, &ctr)) + grub_errno = 0; + + grub_disk_dev_register (&grub_virtdisk_dev); +} + +void +grub_xendisk_fini (void) +{ + char fdir[200]; + unsigned i; + + for (i = 0; i < vdiskcnt; i++) + { + char *buf; + struct evtchn_close close_op = {.port = virtdisks[i].evtchn }; + + grub_snprintf (fdir, sizeof (fdir), "%s/state", + virtdisks[i].frontend_dir); + grub_xenstore_write_file (fdir, "6", 1); + + while (1) + { + grub_snprintf (fdir, sizeof (fdir), "%s/state", + virtdisks[i].backend_dir); + buf = grub_xenstore_get_file (fdir, NULL); + grub_dprintf ("xen", "state=%s\n", (char *) buf); + + if (!buf || grub_strcmp (buf, "6") == 0) + break; + grub_free (buf); + grub_xen_sched_op (SCHEDOP_yield, 0); + } + grub_free (buf); + + grub_snprintf (fdir, sizeof (fdir), "%s/ring-ref", + virtdisks[i].frontend_dir); + grub_xenstore_write_file (fdir, NULL, 0); + + grub_snprintf (fdir, sizeof (fdir), "%s/event-channel", + virtdisks[i].frontend_dir); + grub_xenstore_write_file (fdir, NULL, 0); + + grub_xen_free_shared_page (virtdisks[i].dma_page); + grub_xen_free_shared_page (virtdisks[i].shared_page); + + grub_xen_event_channel_op (EVTCHNOP_close, &close_op); + + /* Prepare for handoff. */ + grub_snprintf (fdir, sizeof (fdir), "%s/state", + virtdisks[i].frontend_dir); + grub_xenstore_write_file (fdir, "1", 1); + } +} diff --git a/grub-core/efiemu/i386/coredetect.c b/grub-core/efiemu/i386/coredetect.c index c3782fda9..a262b5328 100644 --- a/grub-core/efiemu/i386/coredetect.c +++ b/grub-core/efiemu/i386/coredetect.c @@ -18,42 +18,10 @@ #include #include - -#define cpuid(num,a,b,c,d) \ - asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ - : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ - : "0" (num)) - -#define bit_LM (1 << 29) +#include const char * grub_efiemu_get_default_core_name (void) { - - unsigned int eax, ebx, ecx, edx; - unsigned int max_level; - unsigned int ext_level; - - /* See if we can use cpuid. */ - asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;" - "pushl %0; popfl; pushfl; popl %0; popfl" - : "=&r" (eax), "=&r" (ebx) - : "i" (0x00200000)); - if (((eax ^ ebx) & 0x00200000) == 0) - return "efiemu32.o"; - - /* Check the highest input value for eax. */ - cpuid (0, eax, ebx, ecx, edx); - /* We only look at the first four characters. */ - max_level = eax; - if (max_level == 0) - return "efiemu32.o"; - - cpuid (0x80000000, eax, ebx, ecx, edx); - ext_level = eax; - if (ext_level < 0x80000000) - return "efiemu32.o"; - - cpuid (0x80000001, eax, ebx, ecx, edx); - return (edx & bit_LM) ? "efiemu64.o" : "efiemu32.o"; + return grub_cpuid_has_longmode ? "efiemu64.o" : "efiemu32.o"; } diff --git a/grub-core/efiemu/i386/loadcore64.c b/grub-core/efiemu/i386/loadcore64.c index e49d0b6ff..ae476ef2c 100644 --- a/grub-core/efiemu/i386/loadcore64.c +++ b/grub-core/efiemu/i386/loadcore64.c @@ -98,6 +98,7 @@ grub_arch_efiemu_relocate_symbols64 (grub_efiemu_segment_t segs, break; case R_X86_64_PC32: + case R_X86_64_PLT32: err = grub_efiemu_write_value (addr, *addr32 + rel->r_addend + sym.off @@ -120,9 +121,14 @@ grub_arch_efiemu_relocate_symbols64 (grub_efiemu_segment_t segs, return err; break; default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("relocation 0x%x is not implemented yet"), - ELF_R_TYPE (rel->r_info)); + { + char rel_info[17]; /* log16(2^64) = 16, plus NUL. */ + + grub_snprintf (rel_info, sizeof (rel_info) - 1, "%" PRIxGRUB_UINT64_T, + ELF_R_TYPE (rel->r_info)); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%s is not implemented yet"), rel_info); + } } } } diff --git a/grub-core/efiemu/i386/pc/cfgtables.c b/grub-core/efiemu/i386/pc/cfgtables.c index 492c07c46..056ec0bc9 100644 --- a/grub-core/efiemu/i386/pc/cfgtables.c +++ b/grub-core/efiemu/i386/pc/cfgtables.c @@ -22,16 +22,16 @@ #include #include #include +#include grub_err_t grub_machine_efiemu_init_tables (void) { - grub_uint8_t *ptr; void *table; grub_err_t err; - grub_efi_guid_t smbios = GRUB_EFI_SMBIOS_TABLE_GUID; - grub_efi_guid_t acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID; - grub_efi_guid_t acpi = GRUB_EFI_ACPI_TABLE_GUID; + static grub_guid_t smbios = GRUB_EFI_SMBIOS_TABLE_GUID; + static grub_guid_t acpi20 = GRUB_EFI_ACPI_20_TABLE_GUID; + static grub_guid_t acpi = GRUB_EFI_ACPI_TABLE_GUID; err = grub_efiemu_unregister_configuration_table (smbios); if (err) @@ -57,17 +57,10 @@ grub_machine_efiemu_init_tables (void) if (err) return err; } - - for (ptr = (grub_uint8_t *) 0xf0000; ptr < (grub_uint8_t *) 0x100000; - ptr += 16) - if (grub_memcmp (ptr, "_SM_", 4) == 0 - && grub_byte_checksum (ptr, *(ptr + 5)) == 0) - break; - - if (ptr < (grub_uint8_t *) 0x100000) + table = grub_smbios_get_eps (); + if (table) { - grub_dprintf ("efiemu", "Registering SMBIOS\n"); - err = grub_efiemu_register_configuration_table (smbios, 0, 0, ptr); + err = grub_efiemu_register_configuration_table (smbios, 0, 0, table); if (err) return err; } diff --git a/grub-core/efiemu/loadcore.c b/grub-core/efiemu/loadcore.c index 6968b3719..2b924623f 100644 --- a/grub-core/efiemu/loadcore.c +++ b/grub-core/efiemu/loadcore.c @@ -154,7 +154,10 @@ grub_efiemu_init_segments (grub_efiemu_segment_t *segs, const Elf_Ehdr *e) s->sh_flags & SHF_EXECINSTR ? GRUB_EFI_RUNTIME_SERVICES_CODE : GRUB_EFI_RUNTIME_SERVICES_DATA); if (seg->handle < 0) - return grub_errno; + { + grub_free (seg); + return grub_errno; + } seg->off = 0; } @@ -198,7 +201,7 @@ grub_efiemu_count_symbols (const Elf_Ehdr *e) grub_efiemu_nelfsyms = (unsigned) s->sh_size / (unsigned) s->sh_entsize; grub_efiemu_elfsyms = (struct grub_efiemu_elf_sym *) - grub_malloc (sizeof (struct grub_efiemu_elf_sym) * grub_efiemu_nelfsyms); + grub_calloc (grub_efiemu_nelfsyms, sizeof (struct grub_efiemu_elf_sym)); /* Relocators */ for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); @@ -343,7 +346,7 @@ SUFFIX (grub_efiemu_loadcore_init) (void *core, const char *filename, return grub_error (GRUB_ERR_BAD_MODULE, N_("this ELF file is not of the right type")); /* Make sure that every section is within the core. */ - if ((grub_size_t) core_size < e->e_shoff + e->e_shentsize * e->e_shnum) + if ((grub_size_t) core_size < e->e_shoff + (grub_uint32_t) e->e_shentsize * e->e_shnum) return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), filename); diff --git a/grub-core/efiemu/main.c b/grub-core/efiemu/main.c index f2140ad29..e7037f4ed 100644 --- a/grub-core/efiemu/main.c +++ b/grub-core/efiemu/main.c @@ -80,7 +80,7 @@ grub_efiemu_unload (void) /* Remove previously registered table from the list */ grub_err_t -grub_efiemu_unregister_configuration_table (grub_efi_guid_t guid) +grub_efiemu_unregister_configuration_table (grub_guid_t guid) { struct grub_efiemu_configuration_table *cur, *prev; @@ -136,7 +136,7 @@ grub_efiemu_register_prepare_hook (grub_err_t (*hook) (void *data), or with a hook */ grub_err_t -grub_efiemu_register_configuration_table (grub_efi_guid_t guid, +grub_efiemu_register_configuration_table (grub_guid_t guid, void * (*get_table) (void *data), void (*unload) (void *data), void *data) @@ -187,7 +187,7 @@ grub_efiemu_load_file (const char *filename) grub_file_t file; grub_err_t err; - file = grub_file_open (filename); + file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE); if (! file) return grub_errno; @@ -196,7 +196,7 @@ grub_efiemu_load_file (const char *filename) { grub_file_close (file); grub_efiemu_unload (); - return grub_errno; + return err; } grub_dprintf ("efiemu", "mm initialized\n"); diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c index 10cbc68cc..9b8e0d0ad 100644 --- a/grub-core/efiemu/mm.c +++ b/grub-core/efiemu/mm.c @@ -99,7 +99,8 @@ grub_efiemu_request_memalign (grub_size_t align, grub_size_t size, grub_size_t align_overhead; struct grub_efiemu_memrequest *ret, *cur, *prev; /* Check that the request is correct */ - if (type >= GRUB_EFI_MAX_MEMORY_TYPE || type <= GRUB_EFI_LOADER_CODE) + if (type <= GRUB_EFI_LOADER_CODE || type == GRUB_EFI_PERSISTENT_MEMORY || + type >= GRUB_EFI_MAX_MEMORY_TYPE) return -2; /* Add new size to requested size */ @@ -166,6 +167,13 @@ efiemu_alloc_requests (void) GRUB_EFI_MEMORY_MAPPED_IO, GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE, GRUB_EFI_PAL_CODE + + /* + * These are not allocatable: + * GRUB_EFI_RESERVED_MEMORY_TYPE + * GRUB_EFI_PERSISTENT_MEMORY + * >= GRUB_EFI_MAX_MEMORY_TYPE + */ }; /* Compute total memory needed */ @@ -268,26 +276,26 @@ grub_efiemu_mm_return_request (int handle) } } +/* Helper for grub_efiemu_mmap_init. */ +static int +bounds_hook (grub_uint64_t addr __attribute__ ((unused)), + grub_uint64_t size __attribute__ ((unused)), + grub_memory_type_t type __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + mmap_reserved_size++; + return 0; +} + /* Reserve space for memory map */ static grub_err_t grub_efiemu_mmap_init (void) { - auto int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t, grub_uint64_t, - grub_memory_type_t); - int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t addr __attribute__ ((unused)), - grub_uint64_t size __attribute__ ((unused)), - grub_memory_type_t type - __attribute__ ((unused))) - { - mmap_reserved_size++; - return 0; - } - // the place for memory used by efiemu itself mmap_reserved_size = GRUB_EFI_MAX_MEMORY_TYPE + 1; #ifndef GRUB_MACHINE_EMU - grub_machine_mmap_iterate (bounds_hook); + grub_machine_mmap_iterate (bounds_hook, NULL); #endif return GRUB_ERR_NONE; @@ -383,48 +391,52 @@ grub_efiemu_mm_init (void) return GRUB_ERR_NONE; } +/* Helper for grub_efiemu_mmap_fill. */ +static int +fill_hook (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + void *data __attribute__ ((unused))) + { + switch (type) + { + case GRUB_MEMORY_AVAILABLE: + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_CONVENTIONAL_MEMORY); + + case GRUB_MEMORY_ACPI: + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_ACPI_RECLAIM_MEMORY); + + case GRUB_MEMORY_NVS: + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_ACPI_MEMORY_NVS); + + case GRUB_MEMORY_PERSISTENT: + case GRUB_MEMORY_PERSISTENT_LEGACY: + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_PERSISTENT_MEMORY); + default: + grub_dprintf ("efiemu", + "Unknown memory type %d. Assuming unusable\n", type); + /* FALLTHROUGH */ + case GRUB_MEMORY_RESERVED: + return grub_efiemu_add_to_mmap (addr, size, + GRUB_EFI_UNUSABLE_MEMORY); + } + } + /* Copy host memory map */ static grub_err_t grub_efiemu_mmap_fill (void) { - auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, - grub_memory_type_t); - int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, - grub_uint64_t size, - grub_memory_type_t type) - { - switch (type) - { - case GRUB_MEMORY_AVAILABLE: - return grub_efiemu_add_to_mmap (addr, size, - GRUB_EFI_CONVENTIONAL_MEMORY); - - case GRUB_MEMORY_ACPI: - return grub_efiemu_add_to_mmap (addr, size, - GRUB_EFI_ACPI_RECLAIM_MEMORY); - - case GRUB_MEMORY_NVS: - return grub_efiemu_add_to_mmap (addr, size, - GRUB_EFI_ACPI_MEMORY_NVS); - - default: - grub_dprintf ("efiemu", - "Unknown memory type %d. Assuming unusable\n", type); - case GRUB_MEMORY_RESERVED: - return grub_efiemu_add_to_mmap (addr, size, - GRUB_EFI_UNUSABLE_MEMORY); - } - } - #ifndef GRUB_MACHINE_EMU - grub_machine_mmap_iterate (fill_hook); + grub_machine_mmap_iterate (fill_hook, NULL); #endif return GRUB_ERR_NONE; } grub_err_t -grub_efiemu_mmap_iterate (grub_memory_hook_t hook) +grub_efiemu_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { unsigned i; @@ -433,12 +445,12 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook) { case GRUB_EFI_RUNTIME_SERVICES_CODE: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_CODE); + GRUB_MEMORY_CODE, hook_data); break; case GRUB_EFI_UNUSABLE_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_BADRAM); + GRUB_MEMORY_BADRAM, hook_data); break; case GRUB_EFI_RESERVED_MEMORY_TYPE: @@ -446,9 +458,9 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook) case GRUB_EFI_MEMORY_MAPPED_IO: case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE: case GRUB_EFI_PAL_CODE: - case GRUB_EFI_MAX_MEMORY_TYPE: + default: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_RESERVED); + GRUB_MEMORY_RESERVED, hook_data); break; case GRUB_EFI_LOADER_CODE: @@ -457,18 +469,24 @@ grub_efiemu_mmap_iterate (grub_memory_hook_t hook) case GRUB_EFI_BOOT_SERVICES_DATA: case GRUB_EFI_CONVENTIONAL_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE, hook_data); break; case GRUB_EFI_ACPI_RECLAIM_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_ACPI); + GRUB_MEMORY_ACPI, hook_data); break; case GRUB_EFI_ACPI_MEMORY_NVS: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_MEMORY_NVS); + GRUB_MEMORY_NVS, hook_data); break; + + case GRUB_EFI_PERSISTENT_MEMORY: + hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, + GRUB_MEMORY_PERSISTENT, hook_data); + break; + } return 0; @@ -504,7 +522,8 @@ grub_efiemu_mmap_sort_and_uniq (void) [GRUB_EFI_ACPI_MEMORY_NVS] = 3, [GRUB_EFI_MEMORY_MAPPED_IO] = 4, [GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE] = 4, - [GRUB_EFI_PAL_CODE] = 4 + [GRUB_EFI_PAL_CODE] = 4, + [GRUB_EFI_PERSISTENT_MEMORY] = 4 }; int i, j, k, done; @@ -535,11 +554,11 @@ grub_efiemu_mmap_sort_and_uniq (void) /* Initialize variables*/ grub_memset (present, 0, sizeof (int) * GRUB_EFI_MAX_MEMORY_TYPE); scanline_events = (struct grub_efiemu_mmap_scan *) - grub_malloc (sizeof (struct grub_efiemu_mmap_scan) * 2 * mmap_num); + grub_calloc (mmap_num, sizeof (struct grub_efiemu_mmap_scan) * 2); /* Number of chunks can't increase more than by factor of 2 */ result = (grub_efi_memory_descriptor_t *) - grub_malloc (sizeof (grub_efi_memory_descriptor_t) * 2 * mmap_num); + grub_calloc (mmap_num, sizeof (grub_efi_memory_descriptor_t) * 2); if (!result || !scanline_events) { grub_free (result); @@ -641,7 +660,7 @@ grub_efiemu_mm_do_alloc (void) /* Preallocate mmap */ efiemu_mmap = (grub_efi_memory_descriptor_t *) - grub_malloc (mmap_reserved_size * sizeof (grub_efi_memory_descriptor_t)); + grub_calloc (mmap_reserved_size, sizeof (grub_efi_memory_descriptor_t)); if (!efiemu_mmap) { grub_efiemu_unload (); diff --git a/grub-core/efiemu/pnvram.c b/grub-core/efiemu/pnvram.c index 28d005044..dd42bc691 100644 --- a/grub-core/efiemu/pnvram.c +++ b/grub-core/efiemu/pnvram.c @@ -39,7 +39,7 @@ static grub_size_t nvramsize; /* Parse signed value */ static int -grub_strtosl (const char *arg, char **end, int base) +grub_strtosl (const char *arg, const char ** const end, int base) { if (arg[0] == '-') return -grub_strtoul (arg + 1, end, base); @@ -102,92 +102,7 @@ nvram_set (void * data __attribute__ ((unused))) grub_uint32_t *accuracy = grub_efiemu_mm_obtain_request (accuracy_handle); char *nvramptr; - - auto int iterate_env (struct grub_env_var *var); - int iterate_env (struct grub_env_var *var) - { - char *guid, *attr, *name, *varname; - struct efi_variable *efivar; - int len = 0; - int i; - grub_uint64_t guidcomp; - - if (grub_memcmp (var->name, "EfiEmu.pnvram.", - sizeof ("EfiEmu.pnvram.") - 1) != 0) - return 0; - - guid = var->name + sizeof ("EfiEmu.pnvram.") - 1; - - attr = grub_strchr (guid, '.'); - if (!attr) - return 0; - attr++; - - name = grub_strchr (attr, '.'); - if (!name) - return 0; - name++; - - efivar = (struct efi_variable *) nvramptr; - if (nvramptr - nvram + sizeof (struct efi_variable) > nvramsize) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, - "too many NVRAM variables for reserved variable space." - " Try increasing EfiEmu.pnvram.size"); - return 1; - } - - nvramptr += sizeof (struct efi_variable); - - efivar->guid.data1 = grub_cpu_to_le32 (grub_strtoul (guid, &guid, 16)); - if (*guid != '-') - return 0; - guid++; - - efivar->guid.data2 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16)); - if (*guid != '-') - return 0; - guid++; - - efivar->guid.data3 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16)); - if (*guid != '-') - return 0; - guid++; - - guidcomp = grub_strtoull (guid, 0, 16); - for (i = 0; i < 8; i++) - efivar->guid.data4[i] = (guidcomp >> (56 - 8 * i)) & 0xff; - - efivar->attributes = grub_strtoull (attr, 0, 16); - - varname = grub_malloc (grub_strlen (name) + 1); - if (! varname) - return 1; - - if (unescape (name, varname, varname + grub_strlen (name) + 1, &len)) - return 1; - - len = grub_utf8_to_utf16 ((grub_uint16_t *) nvramptr, - (nvramsize - (nvramptr - nvram)) / 2, - (grub_uint8_t *) varname, len, NULL); - - nvramptr += 2 * len; - *((grub_uint16_t *) nvramptr) = 0; - nvramptr += 2; - efivar->namelen = 2 * len + 2; - - if (unescape (var->value, nvramptr, nvram + nvramsize, &len)) - { - efivar->namelen = 0; - return 1; - } - - nvramptr += len; - - efivar->size = len; - - return 0; - } + struct grub_env_var *var; /* Copy to definitive loaction */ grub_dprintf ("efiemu", "preparing pnvram\n"); @@ -203,9 +118,89 @@ nvram_set (void * data __attribute__ ((unused))) nvramptr = nvram; grub_memset (nvram, 0, nvramsize); - grub_env_iterate (iterate_env); + FOR_SORTED_ENV (var) + { + const char *guid; + char *attr, *name, *varname; + struct efi_variable *efivar; + int len = 0; + int i; + grub_uint64_t guidcomp; + + if (grub_memcmp (var->name, "EfiEmu.pnvram.", + sizeof ("EfiEmu.pnvram.") - 1) != 0) + continue; + + guid = var->name + sizeof ("EfiEmu.pnvram.") - 1; + + attr = grub_strchr (guid, '.'); + if (!attr) + continue; + attr++; + + name = grub_strchr (attr, '.'); + if (!name) + continue; + name++; + + efivar = (struct efi_variable *) nvramptr; + if (nvramptr - nvram + sizeof (struct efi_variable) > nvramsize) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "too many NVRAM variables for reserved variable space." + " Try increasing EfiEmu.pnvram.size"); + + nvramptr += sizeof (struct efi_variable); + + efivar->guid.data1 = grub_cpu_to_le32 (grub_strtoul (guid, &guid, 16)); + if (*guid != '-') + continue; + guid++; + + efivar->guid.data2 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16)); + if (*guid != '-') + continue; + guid++; + + efivar->guid.data3 = grub_cpu_to_le16 (grub_strtoul (guid, &guid, 16)); + if (*guid != '-') + continue; + guid++; + + guidcomp = grub_strtoull (guid, 0, 16); + for (i = 0; i < 8; i++) + efivar->guid.data4[i] = (guidcomp >> (56 - 8 * i)) & 0xff; + + efivar->attributes = grub_strtoull (attr, 0, 16); + + varname = grub_malloc (grub_strlen (name) + 1); + if (! varname) + return grub_errno; + + if (unescape (name, varname, varname + grub_strlen (name) + 1, &len)) + break; + + len = grub_utf8_to_utf16 ((grub_uint16_t *) nvramptr, + (nvramsize - (nvramptr - nvram)) / 2, + (grub_uint8_t *) varname, len, NULL); + + nvramptr += 2 * len; + *((grub_uint16_t *) nvramptr) = 0; + nvramptr += 2; + efivar->namelen = 2 * len + 2; + + if (unescape (var->value, nvramptr, nvram + nvramsize, &len)) + { + efivar->namelen = 0; + break; + } + + nvramptr += len; + + efivar->size = len; + } if (grub_errno) return grub_errno; + *nvramsize_def = nvramsize; /* Register symbols */ diff --git a/grub-core/efiemu/prepare.c b/grub-core/efiemu/prepare.c index 2aef8634d..99ddb5abb 100644 --- a/grub-core/efiemu/prepare.c +++ b/grub-core/efiemu/prepare.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -82,10 +83,16 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks, ((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off); /* Put pointer to the list of configuration tables in system table */ - grub_efiemu_write_value - (&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0, - conftable_handle, 0, 1, - sizeof (SUFFIX (grub_efiemu_system_table)->configuration_table)); + err = grub_efiemu_write_value + (&(SUFFIX (grub_efiemu_system_table)->configuration_table), 0, + conftable_handle, 0, 1, + sizeof (SUFFIX (grub_efiemu_system_table)->configuration_table)); + if (err) + { + grub_efiemu_unload (); + return err; + } + SUFFIX(grub_efiemu_system_table)->num_table_entries = cntconftables; /* Fill the list of configuration tables */ @@ -122,7 +129,10 @@ SUFFIX (grub_efiemu_crc) (void) int handle; grub_off_t off; struct SUFFIX (grub_efiemu_runtime_services) *runtime_services; - grub_uint8_t crc32_context[GRUB_MD_CRC32->contextsize]; + grub_uint32_t crc32_val; + + if (GRUB_MD_CRC32->mdlen != 4) + return grub_error (GRUB_ERR_BUG, "incorrect mdlen"); /* compute CRC32 of runtime_services */ err = grub_efiemu_resolve_symbol ("efiemu_runtime_services", @@ -134,12 +144,11 @@ SUFFIX (grub_efiemu_crc) (void) ((grub_uint8_t *) grub_efiemu_mm_obtain_request (handle) + off); runtime_services->hdr.crc32 = 0; - GRUB_MD_CRC32->init(crc32_context); - GRUB_MD_CRC32->write(crc32_context, runtime_services, runtime_services->hdr.header_size); - GRUB_MD_CRC32->final(crc32_context); + grub_crypto_hash (GRUB_MD_CRC32, &crc32_val, + runtime_services, runtime_services->hdr.header_size); runtime_services->hdr.crc32 = - grub_be_to_cpu32(*(grub_uint32_t*)GRUB_MD_CRC32->read(crc32_context)); + grub_be_to_cpu32(crc32_val); err = grub_efiemu_resolve_symbol ("efiemu_system_table", &handle, &off); if (err) @@ -147,12 +156,11 @@ SUFFIX (grub_efiemu_crc) (void) /* compute CRC32 of system table */ SUFFIX (grub_efiemu_system_table)->hdr.crc32 = 0; - GRUB_MD_CRC32->init(crc32_context); - GRUB_MD_CRC32->write(crc32_context, SUFFIX (grub_efiemu_system_table), - SUFFIX (grub_efiemu_system_table)->hdr.header_size); - GRUB_MD_CRC32->final(crc32_context); + grub_crypto_hash (GRUB_MD_CRC32, &crc32_val, + SUFFIX (grub_efiemu_system_table), + SUFFIX (grub_efiemu_system_table)->hdr.header_size); SUFFIX (grub_efiemu_system_table)->hdr.crc32 = - grub_be_to_cpu32(*(grub_uint32_t*)GRUB_MD_CRC32->read(crc32_context)); + grub_be_to_cpu32(crc32_val); grub_dprintf ("efiemu","system_table = %p, runtime_services = %p\n", SUFFIX (grub_efiemu_system_table), runtime_services); diff --git a/grub-core/efiemu/runtime/config.h b/grub-core/efiemu/runtime/config.h index 26fb2ff08..c9fe02716 100644 --- a/grub-core/efiemu/runtime/config.h +++ b/grub-core/efiemu/runtime/config.h @@ -19,16 +19,18 @@ #define GRUB_TYPES_CPU_HEADER 1 -#ifdef ELF32 +#ifdef __i386__ # define SIZEOF_VOID_P 4 # define SIZEOF_LONG 4 # define GRUB_TARGET_SIZEOF_VOID_P 4 # define GRUB_TARGET_SIZEOF_LONG 4 # define EFI_FUNC(x) x -#else +#elif defined (__x86_64__) # define SIZEOF_VOID_P 8 # define SIZEOF_LONG 8 # define GRUB_TARGET_SIZEOF_VOID_P 8 # define GRUB_TARGET_SIZEOF_LONG 8 # define EFI_FUNC(x) x ## _real +#else +#error "Unknown architecture" #endif diff --git a/grub-core/efiemu/runtime/efiemu.c b/grub-core/efiemu/runtime/efiemu.c index 84b02cb20..51dc02114 100644 --- a/grub-core/efiemu/runtime/efiemu.c +++ b/grub-core/efiemu/runtime/efiemu.c @@ -32,17 +32,17 @@ #include #include -grub_efi_status_t +grub_efi_status_t __grub_efi_api efiemu_get_time (grub_efi_time_t *time, grub_efi_time_capabilities_t *capabilities); -grub_efi_status_t +grub_efi_status_t __grub_efi_api efiemu_set_time (grub_efi_time_t *time); -grub_efi_status_t +grub_efi_status_t __grub_efi_api efiemu_get_wakeup_time (grub_efi_boolean_t *enabled, grub_efi_boolean_t *pending, grub_efi_time_t *time); -grub_efi_status_t +grub_efi_status_t __grub_efi_api efiemu_set_wakeup_time (grub_efi_boolean_t enabled, grub_efi_time_t *time); @@ -52,51 +52,51 @@ efiemu_set_wakeup_time (grub_efi_boolean_t enabled, #define PHYSICAL_ATTRIBUTE __attribute__ ((section(".text-physical"))); #endif -grub_efi_status_t +grub_efi_status_t __grub_efi_api efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size, grub_efi_uintn_t descriptor_size, grub_efi_uint32_t descriptor_version, grub_efi_memory_descriptor_t *virtual_map) PHYSICAL_ATTRIBUTE; -grub_efi_status_t +grub_efi_status_t __grub_efi_api efiemu_convert_pointer (grub_efi_uintn_t debug_disposition, void **address) PHYSICAL_ATTRIBUTE; -grub_efi_status_t +grub_efi_status_t __grub_efi_api efiemu_get_variable (grub_efi_char16_t *variable_name, - const grub_efi_guid_t *vendor_guid, + const grub_packed_guid_t *vendor_guid, grub_efi_uint32_t *attributes, grub_efi_uintn_t *data_size, void *data); -grub_efi_status_t +grub_efi_status_t __grub_efi_api efiemu_get_next_variable_name (grub_efi_uintn_t *variable_name_size, grub_efi_char16_t *variable_name, - grub_efi_guid_t *vendor_guid); + grub_packed_guid_t *vendor_guid); -grub_efi_status_t +grub_efi_status_t __grub_efi_api efiemu_set_variable (grub_efi_char16_t *variable_name, - grub_efi_guid_t *vendor_guid, + const grub_packed_guid_t *vendor_guid, grub_efi_uint32_t attributes, grub_efi_uintn_t data_size, void *data); -grub_efi_status_t +grub_efi_status_t __grub_efi_api efiemu_get_next_high_monotonic_count (grub_efi_uint32_t *high_count); -void +void __grub_efi_api efiemu_reset_system (grub_efi_reset_type_t reset_type, grub_efi_status_t reset_status, grub_efi_uintn_t data_size, grub_efi_char16_t *reset_data); -grub_efi_status_t +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_set_virtual_address_map) (grub_efi_uintn_t, grub_efi_uintn_t, grub_efi_uint32_t, grub_efi_memory_descriptor_t *) PHYSICAL_ATTRIBUTE; -grub_efi_status_t +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_convert_pointer) (grub_efi_uintn_t debug_disposition, void **address) PHYSICAL_ATTRIBUTE; @@ -131,11 +131,11 @@ extern grub_uint32_t efiemu_time_accuracy; /* Some standard functions because we need to be standalone */ static void -efiemu_memcpy (void *to, void *from, int count) +efiemu_memcpy (void *to, const void *from, int count) { int i; for (i = 0; i < count; i++) - ((grub_uint8_t *) to)[i] = ((grub_uint8_t *) from)[i]; + ((grub_uint8_t *) to)[i] = ((const grub_uint8_t *) from)[i]; } static int @@ -174,17 +174,17 @@ efiemu_memset (grub_uint8_t *a, grub_uint8_t b, grub_size_t n) static inline void write_cmos (grub_uint8_t addr, grub_uint8_t val) { - __asm__ __volatile__ ("outb %%al,$0x70\n" - "mov %%cl, %%al\n" - "outb %%al,$0x71": :"a" (addr), "c" (val)); + asm volatile ("outb %%al,$0x70\n" + "mov %%cl, %%al\n" + "outb %%al,$0x71": :"a" (addr), "c" (val)); } static inline grub_uint8_t read_cmos (grub_uint8_t addr) { grub_uint8_t ret; - __asm__ __volatile__ ("outb %%al, $0x70\n" - "inb $0x71, %%al": "=a"(ret) :"a" (addr)); + asm volatile ("outb %%al, $0x70\n" + "inb $0x71, %%al": "=a"(ret) :"a" (addr)); return ret; } @@ -202,7 +202,7 @@ bcd_to_hex (grub_uint8_t in) return 10 * ((in & 0xf0) >> 4) + (in & 0x0f); } -grub_efi_status_t +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_get_time) (grub_efi_time_t *time, grub_efi_time_capabilities_t *capabilities) { @@ -246,7 +246,7 @@ EFI_FUNC (efiemu_get_time) (grub_efi_time_t *time, return GRUB_EFI_SUCCESS; } -grub_efi_status_t +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_set_time) (grub_efi_time_t *time) { LOG ('b'); @@ -265,7 +265,7 @@ EFI_FUNC (efiemu_set_time) (grub_efi_time_t *time) } /* Following 2 functions are vendor specific. So announce it as unsupported */ -grub_efi_status_t +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_get_wakeup_time) (grub_efi_boolean_t *enabled, grub_efi_boolean_t *pending, grub_efi_time_t *time) @@ -274,7 +274,7 @@ EFI_FUNC (efiemu_get_wakeup_time) (grub_efi_boolean_t *enabled, return GRUB_EFI_UNSUPPORTED; } -grub_efi_status_t +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_set_wakeup_time) (grub_efi_boolean_t enabled, grub_efi_time_t *time) { @@ -337,7 +337,7 @@ efiemu_getcrc32 (grub_uint32_t crc, void *buf, int size) } -grub_efi_status_t EFI_FUNC +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_set_virtual_address_map) (grub_efi_uintn_t memory_map_size, grub_efi_uintn_t descriptor_size, grub_efi_uint32_t descriptor_version, @@ -403,7 +403,7 @@ grub_efi_status_t EFI_FUNC /* since efiemu_set_virtual_address_map corrects all the pointers we don't need efiemu_convert_pointer */ -grub_efi_status_t +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_convert_pointer) (grub_efi_uintn_t debug_disposition, void **address) { @@ -416,7 +416,7 @@ EFI_FUNC (efiemu_convert_pointer) (grub_efi_uintn_t debug_disposition, /* Find variable by name and GUID. */ static struct efi_variable * -find_variable (const grub_efi_guid_t *vendor_guid, +find_variable (const grub_packed_guid_t *vendor_guid, grub_efi_char16_t *variable_name) { grub_uint8_t *ptr; @@ -436,9 +436,9 @@ find_variable (const grub_efi_guid_t *vendor_guid, return 0; } -grub_efi_status_t +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_get_variable) (grub_efi_char16_t *variable_name, - const grub_efi_guid_t *vendor_guid, + const grub_packed_guid_t *vendor_guid, grub_efi_uint32_t *attributes, grub_efi_uintn_t *data_size, void *data) @@ -461,10 +461,10 @@ EFI_FUNC (efiemu_get_variable) (grub_efi_char16_t *variable_name, return GRUB_EFI_SUCCESS; } -grub_efi_status_t EFI_FUNC +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_get_next_variable_name) (grub_efi_uintn_t *variable_name_size, grub_efi_char16_t *variable_name, - grub_efi_guid_t *vendor_guid) + grub_packed_guid_t *vendor_guid) { struct efi_variable *efivar; LOG ('l'); @@ -501,12 +501,12 @@ grub_efi_status_t EFI_FUNC return GRUB_EFI_SUCCESS; } -grub_efi_status_t +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_set_variable) (grub_efi_char16_t *variable_name, - grub_efi_guid_t *vendor_guid, - grub_efi_uint32_t attributes, - grub_efi_uintn_t data_size, - void *data) + const grub_packed_guid_t *vendor_guid, + grub_efi_uint32_t attributes, + grub_efi_uintn_t data_size, + void *data) { struct efi_variable *efivar; grub_uint8_t *ptr; @@ -556,7 +556,7 @@ EFI_FUNC (efiemu_set_variable) (grub_efi_char16_t *variable_name, return GRUB_EFI_SUCCESS; } -grub_efi_status_t EFI_FUNC +grub_efi_status_t __grub_efi_api EFI_FUNC (efiemu_get_next_high_monotonic_count) (grub_efi_uint32_t *high_count) { LOG ('j'); @@ -570,7 +570,7 @@ grub_efi_status_t EFI_FUNC Besides EFI specification says that this function shouldn't be used on systems supporting ACPI */ -void +void __grub_efi_api EFI_FUNC (efiemu_reset_system) (grub_efi_reset_type_t reset_type, grub_efi_status_t reset_status, grub_efi_uintn_t data_size, @@ -597,9 +597,30 @@ struct grub_efi_runtime_services efiemu_runtime_services = .set_virtual_address_map = efiemu_set_virtual_address_map, .convert_pointer = efiemu_convert_pointer, - .get_variable = efiemu_get_variable, - .get_next_variable_name = efiemu_get_next_variable_name, - .set_variable = efiemu_set_variable, + /* + The code is structured in a way to accept unaligned inputs + in most cases and supply 4-byte aligned outputs. + + Efiemu case is a bit ugly because there inputs and outputs are + reversed and so we need careful casts to account for this + inversion. + */ + .get_variable = (grub_efi_status_t + (__grub_efi_api *) (grub_efi_char16_t *variable_name, + const grub_guid_t *vendor_guid, + grub_efi_uint32_t *attributes, + grub_efi_uintn_t *data_size, + void *data)) efiemu_get_variable, + .get_next_variable_name = (grub_efi_status_t + (__grub_efi_api *) (grub_efi_uintn_t *variable_name_size, + grub_efi_char16_t *variable_name, + grub_guid_t *vendor_guid)) efiemu_get_next_variable_name, + .set_variable = (grub_efi_status_t + (__grub_efi_api *) (grub_efi_char16_t *variable_name, + const grub_guid_t *vendor_guid, + grub_efi_uint32_t attributes, + grub_efi_uintn_t data_size, + void *data)) efiemu_set_variable, .get_next_high_monotonic_count = efiemu_get_next_high_monotonic_count, .reset_system = efiemu_reset_system diff --git a/grub-core/font/font.c b/grub-core/font/font.c index fca8c8d00..18de52562 100644 --- a/grub-core/font/font.c +++ b/grub-core/font/font.c @@ -30,10 +30,11 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); -#ifdef USE_ASCII_FAILBACK +#if HAVE_FONT_SOURCE #include "ascii.h" #endif @@ -55,23 +56,6 @@ struct char_index_entry #define FONT_WEIGHT_BOLD 200 #define ASCII_BITMAP_SIZE 16 -struct grub_font -{ - char *name; - grub_file_t file; - char *family; - short point_size; - short weight; - short max_char_width; - short max_char_height; - short ascent; - short descent; - short leading; - grub_uint32_t num_chars; - struct char_index_entry *char_index; - grub_uint16_t *bmp_idx; -}; - /* Definition of font registry. */ struct grub_font_node *grub_font_list; @@ -127,14 +111,14 @@ static struct grub_font null_font; /* Flag to ensure module is initialized only once. */ static grub_uint8_t font_loader_initialized; -#ifdef USE_ASCII_FAILBACK +#if HAVE_FONT_SOURCE static struct grub_font_glyph *ascii_font_glyph[0x80]; #endif static struct grub_font_glyph * ascii_glyph_lookup (grub_uint32_t code) { -#ifdef USE_ASCII_FAILBACK +#if HAVE_FONT_SOURCE static int ascii_failback_initialized = 0; if (code >= 0x80) @@ -147,13 +131,18 @@ ascii_glyph_lookup (grub_uint32_t code) { ascii_font_glyph[current] = grub_malloc (sizeof (struct grub_font_glyph) + ASCII_BITMAP_SIZE); + if (ascii_font_glyph[current] == NULL) + { + ascii_font_glyph[current] = unknown_glyph; + continue; + } ascii_font_glyph[current]->width = 8; ascii_font_glyph[current]->height = 16; ascii_font_glyph[current]->offset_x = 0; ascii_font_glyph[current]->offset_y = -2; ascii_font_glyph[current]->device_width = 8; - ascii_font_glyph[current]->font = NULL; + ascii_font_glyph[current]->font = &null_font; grub_memcpy (ascii_font_glyph[current]->bitmap, &ascii_bitmaps[current * ASCII_BITMAP_SIZE], @@ -188,6 +177,7 @@ grub_font_loader_init (void) unknown_glyph->offset_x = 0; unknown_glyph->offset_y = -3; unknown_glyph->device_width = 8; + unknown_glyph->font = &null_font; grub_memcpy (unknown_glyph->bitmap, unknown_glyph_bitmap, sizeof (unknown_glyph_bitmap)); @@ -293,7 +283,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct grub_uint32_t last_code; #if FONT_DEBUG >= 2 - grub_printf ("load_font_index(sect_length=%d)\n", sect_length); + grub_dprintf ("font", "load_font_index(sect_length=%d)\n", sect_length); #endif /* Sanity check: ensure section length is divisible by the entry size. */ @@ -310,18 +300,19 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct font->num_chars = sect_length / FONT_CHAR_INDEX_ENTRY_SIZE; /* Allocate the character index array. */ - font->char_index = grub_malloc (font->num_chars - * sizeof (struct char_index_entry)); + font->char_index = grub_calloc (font->num_chars, sizeof (struct char_index_entry)); if (!font->char_index) return 1; font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t)); if (!font->bmp_idx) return 1; + + /* Init the BMP index array to 0xffff. */ grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t)); #if FONT_DEBUG >= 2 - grub_printf ("num_chars=%d)\n", font->num_chars); + grub_dprintf ("font", "num_chars=%d)\n", font->num_chars); #endif last_code = 0; @@ -345,7 +336,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct return 1; } - if (entry->code < 0x10000) + if (entry->code < 0x10000 && i < 0xffff) font->bmp_idx[entry->code] = i; last_code = entry->code; @@ -365,7 +356,7 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct #if FONT_DEBUG >= 5 /* Print the 1st 10 characters. */ if (i < 10) - grub_printf ("c=%d o=%d\n", entry->code, entry->offset); + grub_dprintf ("font", "c=%d o=%d\n", entry->code, entry->offset); #endif } @@ -378,9 +369,13 @@ static char * read_section_as_string (struct font_file_section *section) { char *str; + grub_size_t sz; grub_ssize_t ret; - str = grub_malloc (section->length + 1); + if (grub_add (section->length, 1, &sz)) + return NULL; + + str = grub_malloc (sz); if (!str) return 0; @@ -420,9 +415,30 @@ read_section_as_short (struct font_file_section *section, return 0; } +static grub_file_t +try_open_from_prefix (const char *prefix, const char *filename) +{ + grub_file_t file; + char *fullname, *ptr; + + fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1 + + sizeof ("/fonts/") + sizeof (".pf2")); + if (!fullname) + return NULL; + ptr = grub_stpcpy (fullname, prefix); + ptr = grub_stpcpy (ptr, "/fonts/"); + ptr = grub_stpcpy (ptr, filename); + ptr = grub_stpcpy (ptr, ".pf2"); + *ptr = '\0'; + + file = grub_buffile_open (fullname, GRUB_FILE_TYPE_FONT, 1024); + grub_free (fullname); + return file; +} + /* Load a font and add it to the beginning of the global font list. Returns 0 upon success, nonzero upon failure. */ -int +grub_font_t grub_font_load (const char *filename) { grub_file_t file = 0; @@ -431,38 +447,31 @@ grub_font_load (const char *filename) grub_font_t font = 0; #if FONT_DEBUG >= 1 - grub_printf ("add_font(%s)\n", filename); + grub_dprintf ("font", "add_font(%s)\n", filename); #endif if (filename[0] == '(' || filename[0] == '/' || filename[0] == '+') - file = grub_buffile_open (filename, 1024); + file = grub_buffile_open (filename, GRUB_FILE_TYPE_FONT, 1024); else { - const char *prefix = grub_env_get ("prefix"); - char *fullname, *ptr; - if (!prefix) + file = try_open_from_prefix ("(memdisk)", filename); + if (!file) { - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), - "prefix"); - goto fail; + const char *prefix = grub_env_get ("prefix"); + + if (!prefix) + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); + goto fail; + } + file = try_open_from_prefix (prefix, filename); } - fullname = grub_malloc (grub_strlen (prefix) + grub_strlen (filename) + 1 - + sizeof ("/fonts/") + sizeof (".pf2")); - if (!fullname) - goto fail; - ptr = grub_stpcpy (fullname, prefix); - ptr = grub_stpcpy (ptr, "/fonts/"); - ptr = grub_stpcpy (ptr, filename); - ptr = grub_stpcpy (ptr, ".pf2"); - *ptr = 0; - file = grub_buffile_open (fullname, 1024); - grub_free (fullname); } if (!file) goto fail; #if FONT_DEBUG >= 3 - grub_printf ("file opened\n"); + grub_dprintf ("font", "file opened\n"); #endif /* Read the FILE section. It indicates the file format. */ @@ -470,7 +479,7 @@ grub_font_load (const char *filename) goto fail; #if FONT_DEBUG >= 3 - grub_printf ("opened FILE section\n"); + grub_dprintf ("font", "opened FILE section\n"); #endif if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FILE, sizeof (FONT_FORMAT_SECTION_NAMES_FILE) - 1) != 0) @@ -481,7 +490,7 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 3 - grub_printf ("section name ok\n"); + grub_dprintf ("font", "section name ok\n"); #endif if (section.length != 4) { @@ -492,14 +501,14 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 3 - grub_printf ("section length ok\n"); + grub_dprintf ("font", "section length ok\n"); #endif /* Check the file format type code. */ if (grub_file_read (file, magic, 4) != 4) goto fail; #if FONT_DEBUG >= 3 - grub_printf ("read magic ok\n"); + grub_dprintf ("font", "read magic ok\n"); #endif if (grub_memcmp (magic, FONT_FORMAT_PFF2_MAGIC, 4) != 0) @@ -510,7 +519,7 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 3 - grub_printf ("compare magic ok\n"); + grub_dprintf ("font", "compare magic ok\n"); #endif /* Allocate the font object. */ @@ -522,7 +531,7 @@ grub_font_load (const char *filename) font->file = file; #if FONT_DEBUG >= 3 - grub_printf ("allocate font ok; loading font info\n"); + grub_dprintf ("font", "allocate font ok; loading font info\n"); #endif /* Load the font information. */ @@ -537,7 +546,7 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 2 - grub_printf ("opened section %c%c%c%c ok\n", + grub_dprintf ("font", "opened section %c%c%c%c ok\n", section.name[0], section.name[1], section.name[2], section.name[3]); #endif @@ -545,6 +554,12 @@ grub_font_load (const char *filename) if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FONT_NAME, sizeof (FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0) { + if (font->name != NULL) + { + grub_error (GRUB_ERR_BAD_FONT, "invalid font file: too many NAME sections"); + goto fail; + } + font->name = read_section_as_string (§ion); if (!font->name) goto fail; @@ -621,7 +636,7 @@ grub_font_load (const char *filename) { /* Unhandled section type, simply skip past it. */ #if FONT_DEBUG >= 3 - grub_printf ("Unhandled section type, skipping.\n"); + grub_dprintf ("font", "Unhandled section type, skipping.\n"); #endif grub_off_t section_end = grub_file_tell (file) + section.length; if ((int) grub_file_seek (file, section_end) == -1) @@ -636,15 +651,15 @@ grub_font_load (const char *filename) } #if FONT_DEBUG >= 1 - grub_printf ("Loaded font `%s'.\n" + grub_dprintf ("font", "Loaded font `%s'.\n" "Ascent=%d Descent=%d MaxW=%d MaxH=%d Number of characters=%d.\n", font->name, font->ascent, font->descent, font->max_char_width, font->max_char_height, font->num_chars); #endif - if (font->max_char_width == 0 - || font->max_char_height == 0 + if (font->max_char_width <= 0 + || font->max_char_height <= 0 || font->num_chars == 0 || font->char_index == 0 || font->ascent == 0 || font->descent == 0) { @@ -657,7 +672,7 @@ grub_font_load (const char *filename) if (register_font (font) != 0) goto fail; - return 0; + return font; fail: if (file) @@ -666,7 +681,7 @@ fail: font->file = 0; free_font (font); - return 1; + return 0; } /* Read a 16-bit big-endian integer from FILE, convert it to native byte @@ -693,40 +708,47 @@ read_be_int16 (grub_file_t file, grub_int16_t * value) static inline struct char_index_entry * find_glyph (const grub_font_t font, grub_uint32_t code) { - struct char_index_entry *table; - grub_size_t lo; - grub_size_t hi; - grub_size_t mid; + struct char_index_entry *table, *first, *end; + grub_size_t len; table = font->char_index; + if (table == NULL) + return NULL; /* Use BMP index if possible. */ if (code < 0x10000 && font->bmp_idx) { - if (font->bmp_idx[code] == 0xffff) - return 0; - return &table[font->bmp_idx[code]]; + if (font->bmp_idx[code] < 0xffff) + return &table[font->bmp_idx[code]]; + /* + * When we are here then lookup in BMP index result in miss, + * fallthough to binary-search. + */ } - /* Do a binary search in `char_index', which is ordered by code point. */ - lo = 0; - hi = font->num_chars - 1; + /* + * Do a binary search in char_index which is ordered by code point. + * The code below is the same as libstdc++'s std::lower_bound(). + */ + first = table; + len = font->num_chars; + end = first + len; - if (!table) - return 0; - - while (lo <= hi) + while (len > 0) { - mid = lo + (hi - lo) / 2; - if (code < table[mid].code) - hi = mid - 1; - else if (code > table[mid].code) - lo = mid + 1; + grub_size_t half = len >> 1; + struct char_index_entry *middle = first + half; + + if (middle->code < code) + { + first = middle + 1; + len = len - half - 1; + } else - return &table[mid]; + len = half; } - return 0; + return (first < end && first->code == code) ? first : NULL; } /* Get a glyph for the Unicode character CODE in FONT. The glyph is loaded @@ -746,7 +768,8 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) grub_int16_t xoff; grub_int16_t yoff; grub_int16_t dwidth; - int len; + grub_ssize_t len; + grub_size_t sz; if (index_entry->glyph) /* Return cached glyph. */ @@ -767,15 +790,25 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) || read_be_uint16 (font->file, &height) != 0 || read_be_int16 (font->file, &xoff) != 0 || read_be_int16 (font->file, &yoff) != 0 - || read_be_int16 (font->file, &dwidth) != 0) + || read_be_int16 (font->file, &dwidth) != 0 + || width > font->max_char_width + || height > font->max_char_height) { remove_font (font); return 0; } - len = (width * height + 7) / 8; - glyph = grub_malloc (sizeof (struct grub_font_glyph) + len); - if (!glyph) + /* Calculate real struct size of current glyph. */ + if (grub_video_bitmap_calc_1bpp_bufsz (width, height, &len) || + grub_add (sizeof (struct grub_font_glyph), len, &sz)) + { + remove_font (font); + return 0; + } + + /* Allocate and initialize the glyph struct. */ + glyph = grub_malloc (sz); + if (glyph == NULL) { remove_font (font); return 0; @@ -794,6 +827,7 @@ grub_font_get_glyph_internal (grub_font_t font, grub_uint32_t code) if (grub_file_read (font->file, glyph->bitmap, len) != len) { remove_font (font); + grub_free (glyph); return 0; } } @@ -909,20 +943,6 @@ grub_font_get_max_char_width (grub_font_t font) return font->max_char_width; } -/* Get the maximum height of any character in the font in pixels. */ -int -grub_font_get_max_char_height (grub_font_t font) -{ - return font->max_char_height; -} - -/* Get the distance in pixels from the top of characters to the baseline. */ -int -grub_font_get_ascent (grub_font_t font) -{ - return font->ascent; -} - /* Get the distance in pixels from the baseline to the lowest descenders (for instance, in a lowercase 'y', 'g', etc.). */ int @@ -956,7 +976,7 @@ grub_font_get_height (grub_font_t font) } /* Get the glyph for FONT corresponding to the Unicode code point CODE. - Returns the ASCII glyph for the code if no other fonts are available. + Returns the ASCII glyph for the code if no other fonts are available. The glyphs are cached once loaded. */ struct grub_font_glyph * grub_font_get_glyph (grub_font_t font, grub_uint32_t code) @@ -1064,25 +1084,20 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code) return best_glyph; } -static struct grub_font_glyph * -grub_font_dup_glyph (struct grub_font_glyph *glyph) -{ - static struct grub_font_glyph *ret; - ret = grub_malloc (sizeof (*ret) + (glyph->width * glyph->height + 7) / 8); - if (!ret) - return NULL; - grub_memcpy (ret, glyph, sizeof (*ret) - + (glyph->width * glyph->height + 7) / 8); - return ret; -} - /* FIXME: suboptimal. */ static void grub_font_blit_glyph (struct grub_font_glyph *target, struct grub_font_glyph *src, unsigned dx, unsigned dy) { + grub_uint16_t max_x, max_y; unsigned src_bit, tgt_bit, src_byte, tgt_byte; unsigned i, j; + + /* Harden against out-of-bound writes. */ + if ((grub_add (dx, src->width, &max_x) || max_x > target->width) || + (grub_add (dy, src->height, &max_y) || max_y > target->height)) + return; + for (i = 0; i < src->height; i++) { src_bit = (src->width * i) % 8; @@ -1114,9 +1129,16 @@ grub_font_blit_glyph_mirror (struct grub_font_glyph *target, struct grub_font_glyph *src, unsigned dx, unsigned dy) { + grub_uint16_t max_x, max_y; unsigned tgt_bit, src_byte, tgt_byte; signed src_bit; unsigned i, j; + + /* Harden against out-of-bound writes. */ + if ((grub_add (dx, src->width, &max_x) || max_x > target->width) || + (grub_add (dy, src->height, &max_y) || max_y > target->height)) + return; + for (i = 0; i < src->height; i++) { src_bit = (src->width * i + src->width - 1) % 8; @@ -1143,6 +1165,49 @@ grub_font_blit_glyph_mirror (struct grub_font_glyph *target, } } +/* Context for blit_comb. */ +struct blit_comb_ctx +{ + struct grub_font_glyph *glyph; + int *device_width; + struct grub_video_signed_rect bounds; +}; + +/* Helper for blit_comb. */ +static void +do_blit (struct grub_font_glyph *src, signed dx, signed dy, + struct blit_comb_ctx *ctx) +{ + if (ctx->glyph) + grub_font_blit_glyph (ctx->glyph, src, dx - ctx->glyph->offset_x, + (ctx->glyph->height + ctx->glyph->offset_y) + dy); + if (dx < ctx->bounds.x) + { + ctx->bounds.width += ctx->bounds.x - dx; + ctx->bounds.x = dx; + } + if (ctx->bounds.y > -src->height - dy) + { + ctx->bounds.height += ctx->bounds.y - (-src->height - dy); + ctx->bounds.y = (-src->height - dy); + } + if (dx + src->width - ctx->bounds.x >= (signed) ctx->bounds.width) + ctx->bounds.width = dx + src->width - ctx->bounds.x + 1; + if ((signed) ctx->bounds.height < src->height + (-src->height - dy) + - ctx->bounds.y) + ctx->bounds.height = src->height + (-src->height - dy) - ctx->bounds.y; +} + +/* Helper for blit_comb. */ +static inline void +add_device_width (int val, struct blit_comb_ctx *ctx) +{ + if (ctx->glyph) + ctx->glyph->device_width += val; + if (ctx->device_width) + *ctx->device_width += val; +} + static void blit_comb (const struct grub_unicode_glyph *glyph_id, struct grub_font_glyph *glyph, @@ -1150,63 +1215,37 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, struct grub_font_glyph *main_glyph, struct grub_font_glyph **combining_glyphs, int *device_width) { - struct grub_video_signed_rect bounds; + struct blit_comb_ctx ctx = { + .glyph = glyph, + .device_width = device_width + }; unsigned i; signed above_rightx, above_righty; signed above_leftx, above_lefty; signed below_rightx, below_righty; signed min_devwidth = 0; - auto void NESTED_FUNC_ATTR do_blit (struct grub_font_glyph *src, - signed dx, signed dy); - void NESTED_FUNC_ATTR do_blit (struct grub_font_glyph *src, - signed dx, signed dy) - { - if (glyph) - grub_font_blit_glyph (glyph, src, dx - glyph->offset_x, - (glyph->height + glyph->offset_y) + dy); - if (dx < bounds.x) - { - bounds.width += bounds.x - dx; - bounds.x = dx; - } - if (bounds.y > -src->height - dy) - { - bounds.height += bounds.y - (-src->height - dy); - bounds.y = (-src->height - dy); - } - if (dx + src->width - bounds.x >= (signed) bounds.width) - bounds.width = dx + src->width - bounds.x + 1; - if ((signed) bounds.height < src->height + (-src->height - dy) - bounds.y) - bounds.height = src->height + (-src->height - dy) - bounds.y; - } - - auto void add_device_width (int val); - void add_device_width (int val) - { - if (glyph) - glyph->device_width += val; - if (device_width) - *device_width += val; - } + const struct grub_unicode_combining *comb; if (glyph) glyph->device_width = main_glyph->device_width; if (device_width) *device_width = main_glyph->device_width; - bounds.x = main_glyph->offset_x; - bounds.y = main_glyph->offset_y; - bounds.width = main_glyph->width; - bounds.height = main_glyph->height; + ctx.bounds.x = main_glyph->offset_x; + ctx.bounds.y = main_glyph->offset_y; + ctx.bounds.width = main_glyph->width; + ctx.bounds.height = main_glyph->height; above_rightx = main_glyph->offset_x + main_glyph->width; - above_righty = bounds.y + bounds.height; + above_righty = ctx.bounds.y + (int) ctx.bounds.height; above_leftx = main_glyph->offset_x; - above_lefty = bounds.y + bounds.height; + above_lefty = ctx.bounds.y + (int) ctx.bounds.height; - below_rightx = bounds.x + bounds.width; - below_righty = bounds.y; + below_rightx = ctx.bounds.x + (int) ctx.bounds.width; + below_righty = ctx.bounds.y; + + comb = grub_unicode_get_comb (glyph_id); for (i = 0; i < glyph_id->ncomb; i++) { @@ -1216,41 +1255,41 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, if (!combining_glyphs[i]) continue; - targetx = (bounds.width - combining_glyphs[i]->width) / 2 + bounds.x; + targetx = ((int) ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; /* CGJ is to avoid diacritics reordering. */ - if (glyph_id->combining[i].code + if (comb[i].code == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER) continue; - switch (glyph_id->combining[i].type) + switch (comb[i].type) { case GRUB_UNICODE_COMB_OVERLAY: do_blit (combining_glyphs[i], targetx, - (bounds.height - combining_glyphs[i]->height) / 2 - - (bounds.height + bounds.y)); + ((int) ctx.bounds.height - combining_glyphs[i]->height) / 2 + - ((int) ctx.bounds.height + ctx.bounds.y), &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; case GRUB_UNICODE_COMB_ATTACHED_ABOVE_RIGHT: - do_blit (combining_glyphs[i], above_rightx, -above_righty); + do_blit (combining_glyphs[i], above_rightx, -above_righty, &ctx); above_rightx += combining_glyphs[i]->width; break; case GRUB_UNICODE_COMB_ABOVE_RIGHT: do_blit (combining_glyphs[i], above_rightx, - -(above_righty + combining_glyphs[i]->height)); + -(above_righty + combining_glyphs[i]->height), &ctx); above_rightx += combining_glyphs[i]->width; break; case GRUB_UNICODE_COMB_ABOVE_LEFT: above_leftx -= combining_glyphs[i]->width; do_blit (combining_glyphs[i], above_leftx, - -(above_lefty + combining_glyphs[i]->height)); + -(above_lefty + combining_glyphs[i]->height), &ctx); break; case GRUB_UNICODE_COMB_BELOW_RIGHT: - do_blit (combining_glyphs[i], below_rightx, below_righty); + do_blit (combining_glyphs[i], below_rightx, below_righty, &ctx); below_rightx += combining_glyphs[i]->width; break; @@ -1276,7 +1315,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, space = 1 + (grub_font_get_xheight (main_glyph->font)) / 8; do_blit (combining_glyphs[i], targetx, -(main_glyph->height + main_glyph->offset_y + space - + combining_glyphs[i]->height)); + + combining_glyphs[i]->height), &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; @@ -1297,19 +1336,19 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, - grub_font_get_xheight (combining_glyphs[i]->font) - 1; if (space <= 0) space = 1 + (grub_font_get_xheight (main_glyph->font)) / 8; - + /* Fallthrough. */ case GRUB_UNICODE_STACK_ATTACHED_ABOVE: do_blit (combining_glyphs[i], targetx, - -(bounds.height + bounds.y + space - + combining_glyphs[i]->height)); + -((int) ctx.bounds.height + ctx.bounds.y + space + + combining_glyphs[i]->height), &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; case GRUB_UNICODE_COMB_HEBREW_DAGESH: do_blit (combining_glyphs[i], targetx, - -(bounds.height / 2 + bounds.y - + combining_glyphs[i]->height / 2)); + -((int) ctx.bounds.height / 2 + ctx.bounds.y + + combining_glyphs[i]->height / 2), &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; @@ -1338,15 +1377,17 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, + combining_glyphs[i]->height); if (space <= 0) space = 1 + (grub_font_get_xheight (main_glyph->font)) / 8; + /* Fallthrough. */ case GRUB_UNICODE_STACK_ATTACHED_BELOW: - do_blit (combining_glyphs[i], targetx, -(bounds.y - space)); + do_blit (combining_glyphs[i], targetx, -(ctx.bounds.y - space), + &ctx); if (min_devwidth < combining_glyphs[i]->width) min_devwidth = combining_glyphs[i]->width; break; case GRUB_UNICODE_COMB_MN: - switch (glyph_id->combining[i].code) + switch (comb[i].code) { case GRUB_UNICODE_THAANA_ABAFILI: case GRUB_UNICODE_THAANA_AABAAFILI: @@ -1373,39 +1414,36 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, main_glyph->device_width + combining_glyphs[i]->offset_x, -(combining_glyphs[i]->height - + combining_glyphs[i]->offset_y)); - add_device_width (combining_glyphs[i]->device_width); + + combining_glyphs[i]->offset_y), &ctx); + add_device_width (combining_glyphs[i]->device_width, &ctx); } } } add_device_width ((above_rightx > below_rightx ? above_rightx : below_rightx) - - (main_glyph->offset_x + main_glyph->width)); - add_device_width (above_leftx - main_glyph->offset_x); + (main_glyph->offset_x + main_glyph->width), &ctx); + add_device_width (above_leftx - main_glyph->offset_x, &ctx); if (glyph && glyph->device_width < min_devwidth) glyph->device_width = min_devwidth; if (device_width && *device_width < min_devwidth) *device_width = min_devwidth; if (bounds_out) - *bounds_out = bounds; + *bounds_out = ctx.bounds; } static struct grub_font_glyph * grub_font_construct_dry_run (grub_font_t hinted_font, const struct grub_unicode_glyph *glyph_id, struct grub_video_signed_rect *bounds, - struct grub_font_glyph ***combining_glyphs_out, + struct grub_font_glyph **combining_glyphs, int *device_width) { struct grub_font_glyph *main_glyph = NULL; - struct grub_font_glyph **combining_glyphs; grub_uint32_t desired_attributes = 0; unsigned i; grub_uint32_t base = glyph_id->base; - - if (combining_glyphs_out) - *combining_glyphs_out = NULL; + const struct grub_unicode_combining *comb; if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED) desired_attributes |= GRUB_FONT_CODE_RIGHT_JOINED; @@ -1413,11 +1451,12 @@ grub_font_construct_dry_run (grub_font_t hinted_font, if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED) desired_attributes |= GRUB_FONT_CODE_LEFT_JOINED; + comb = grub_unicode_get_comb (glyph_id); if (base == 'i' || base == 'j') { for (i = 0; i < glyph_id->ncomb; i++) - if (glyph_id->combining[i].type == GRUB_UNICODE_STACK_ABOVE) + if (comb[i].type == GRUB_UNICODE_STACK_ABOVE) break; if (i < glyph_id->ncomb && base == 'i') base = GRUB_UNICODE_DOTLESS_LOWERCASE_I; @@ -1446,8 +1485,6 @@ grub_font_construct_dry_run (grub_font_t hinted_font, if (!glyph_id->ncomb && !glyph_id->attributes) return main_glyph; - combining_glyphs = grub_malloc (sizeof (combining_glyphs[0]) - * glyph_id->ncomb); if (glyph_id->ncomb && !combining_glyphs) { grub_errno = GRUB_ERR_NONE; @@ -1457,18 +1494,37 @@ grub_font_construct_dry_run (grub_font_t hinted_font, for (i = 0; i < glyph_id->ncomb; i++) combining_glyphs[i] = grub_font_get_glyph_with_fallback (main_glyph->font, - glyph_id->combining[i].code); + comb[i].code); blit_comb (glyph_id, NULL, bounds, main_glyph, combining_glyphs, device_width); - if (combining_glyphs_out) - *combining_glyphs_out = combining_glyphs; - else - grub_free (combining_glyphs); return main_glyph; } +static struct grub_font_glyph **render_combining_glyphs = 0; +static grub_size_t render_max_comb_glyphs = 0; + +static void +ensure_comb_space (const struct grub_unicode_glyph *glyph_id) +{ + if (glyph_id->ncomb <= render_max_comb_glyphs) + return; + + if (grub_mul (glyph_id->ncomb, 2, &render_max_comb_glyphs)) + render_max_comb_glyphs = 0; + if (render_max_comb_glyphs > 0 && render_max_comb_glyphs < 8) + render_max_comb_glyphs = 8; + grub_free (render_combining_glyphs); + render_combining_glyphs = (render_max_comb_glyphs > 0) ? + grub_calloc (render_max_comb_glyphs, sizeof (render_combining_glyphs[0])) : NULL; + if (!render_combining_glyphs) + { + render_max_comb_glyphs = 0; + grub_errno = GRUB_ERR_NONE; + } +} + int grub_font_get_constructed_device_width (grub_font_t hinted_font, const struct grub_unicode_glyph @@ -1476,8 +1532,11 @@ grub_font_get_constructed_device_width (grub_font_t hinted_font, { int ret; struct grub_font_glyph *main_glyph; + + ensure_comb_space (glyph_id); + main_glyph = grub_font_construct_dry_run (hinted_font, glyph_id, NULL, - NULL, &ret); + render_combining_glyphs, &ret); if (!main_glyph) return unknown_glyph->device_width; return ret; @@ -1489,31 +1548,52 @@ grub_font_construct_glyph (grub_font_t hinted_font, { struct grub_font_glyph *main_glyph; struct grub_video_signed_rect bounds; - struct grub_font_glyph *glyph; - struct grub_font_glyph **combining_glyphs; + static struct grub_font_glyph *glyph = 0; + static grub_size_t max_glyph_size = 0; + grub_size_t cur_glyph_size; + + ensure_comb_space (glyph_id); main_glyph = grub_font_construct_dry_run (hinted_font, glyph_id, - &bounds, &combining_glyphs, NULL); + &bounds, render_combining_glyphs, + NULL); if (!main_glyph) - return grub_font_dup_glyph (unknown_glyph); + return unknown_glyph; - if (!combining_glyphs) - return grub_font_dup_glyph (main_glyph); + if (!render_combining_glyphs && glyph_id->ncomb) + return main_glyph; - glyph = - grub_zalloc (sizeof (*glyph) + (bounds.width * bounds.height + 7) / 8); + if (!glyph_id->ncomb && !glyph_id->attributes) + return main_glyph; + + if (grub_video_bitmap_calc_1bpp_bufsz (bounds.width, bounds.height, &cur_glyph_size) || + grub_add (sizeof (*glyph), cur_glyph_size, &cur_glyph_size)) + return main_glyph; + + if (max_glyph_size < cur_glyph_size) + { + grub_free (glyph); + if (grub_mul (cur_glyph_size, 2, &max_glyph_size)) + max_glyph_size = 0; + glyph = max_glyph_size > 0 ? grub_malloc (max_glyph_size) : NULL; + } if (!glyph) { + max_glyph_size = 0; grub_errno = GRUB_ERR_NONE; - return grub_font_dup_glyph (main_glyph); + return main_glyph; } + grub_memset (glyph, 0, cur_glyph_size); + glyph->font = main_glyph->font; - glyph->width = bounds.width; - glyph->height = bounds.height; - glyph->offset_x = bounds.x; - glyph->offset_y = bounds.y; + if (bounds.width == 0 || bounds.height == 0 || + grub_cast (bounds.width, &glyph->width) || + grub_cast (bounds.height, &glyph->height) || + grub_cast (bounds.x, &glyph->offset_x) || + grub_cast (bounds.y, &glyph->offset_y)) + return main_glyph; if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR) grub_font_blit_glyph_mirror (glyph, main_glyph, @@ -1527,7 +1607,7 @@ grub_font_construct_glyph (grub_font_t hinted_font, (glyph->height + glyph->offset_y) - (main_glyph->height + main_glyph->offset_y)); - blit_comb (glyph_id, glyph, NULL, main_glyph, combining_glyphs, NULL); + blit_comb (glyph_id, glyph, NULL, main_glyph, render_combining_glyphs, NULL); return glyph; } diff --git a/grub-core/font/font_cmd.c b/grub-core/font/font_cmd.c index 90f605d2f..f3b36f2d6 100644 --- a/grub-core/font/font_cmd.c +++ b/grub-core/font/font_cmd.c @@ -32,7 +32,7 @@ loadfont_command (grub_command_t cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); while (argc--) - if (grub_font_load (*args++) != 0) + if (grub_font_load (*args++) == 0) { if (!grub_errno) return grub_error (GRUB_ERR_BAD_FONT, "invalid font"); @@ -61,7 +61,7 @@ lsfonts_command (grub_command_t cmd __attribute__ ((unused)), static grub_command_t cmd_loadfont, cmd_lsfonts; -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_COREBOOT) void grub_font_init (void) #else GRUB_MOD_INIT(font) @@ -78,7 +78,7 @@ GRUB_MOD_INIT(font) 0, N_("List the loaded fonts.")); } -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) +#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_COREBOOT) void grub_font_fini (void) #else GRUB_MOD_FINI(font) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index ef654791c..520a001c7 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -26,6 +26,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -36,7 +37,7 @@ struct grub_affs_bblock grub_uint8_t flags; grub_uint32_t checksum; grub_uint32_t rootblock; -} __attribute__ ((packed)); +} GRUB_PACKED; /* Set if the filesystem is a AFFS filesystem. Otherwise this is an OFS filesystem. */ @@ -51,14 +52,14 @@ struct grub_affs_rblock grub_uint32_t unused2; grub_uint32_t checksum; grub_uint32_t hashtable[1]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_affs_time { grub_int32_t day; grub_uint32_t min; grub_uint32_t hz; -} __attribute__ ((packed)); +} GRUB_PACKED; /* The second part of a file header block. */ struct grub_affs_file @@ -76,7 +77,7 @@ struct grub_affs_file grub_uint32_t parent; grub_uint32_t extension; grub_uint32_t type; -} __attribute__ ((packed)); +} GRUB_PACKED; /* The location of `struct grub_affs_file' relative to the end of a file header block. */ @@ -97,6 +98,7 @@ enum }; #define AFFS_MAX_LOG_BLOCK_SIZE 4 +#define AFFS_MAX_SUPERBLOCK 1 @@ -184,94 +186,92 @@ grub_affs_mount (grub_disk_t disk) { struct grub_affs_data *data; grub_uint32_t *rootblock = 0; - struct grub_affs_rblock *rblock; + struct grub_affs_rblock *rblock = 0; int log_blocksize = 0; + int bsnum = 0; data = grub_zalloc (sizeof (struct grub_affs_data)); if (!data) return 0; - /* Read the bootblock. */ - grub_disk_read (disk, 0, 0, sizeof (struct grub_affs_bblock), - &data->bblock); - if (grub_errno) - goto fail; - - /* Make sure this is an affs filesystem. */ - if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3)) + for (bsnum = 0; bsnum < AFFS_MAX_SUPERBLOCK + 1; bsnum++) { - grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem"); - goto fail; - } - - /* Test if the filesystem is a OFS filesystem. */ - if (! (data->bblock.flags & GRUB_AFFS_FLAG_FFS)) - { - grub_error (GRUB_ERR_BAD_FS, "OFS not yet supported"); - goto fail; - } - - /* No sane person uses more than 8KB for a block. At least I hope - for that person because in that case this won't work. */ - rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE << AFFS_MAX_LOG_BLOCK_SIZE); - if (!rootblock) - goto fail; - - rblock = (struct grub_affs_rblock *) rootblock; - - /* The filesystem blocksize is not stored anywhere in the filesystem - itself. One way to determine it is try reading blocks for the - rootblock until the checksum is correct. */ - for (log_blocksize = 0; log_blocksize <= AFFS_MAX_LOG_BLOCK_SIZE; - log_blocksize++) - { - grub_uint32_t *currblock = rootblock; - unsigned int i; - grub_uint32_t checksum = 0; - - /* Read the rootblock. */ - grub_disk_read (disk, - (grub_uint64_t) grub_be_to_cpu32 (data->bblock.rootblock) - << log_blocksize, 0, - GRUB_DISK_SECTOR_SIZE << log_blocksize, rootblock); + /* Read the bootblock. */ + grub_disk_read (disk, bsnum, 0, sizeof (struct grub_affs_bblock), + &data->bblock); if (grub_errno) goto fail; - if (rblock->type != grub_cpu_to_be32_compile_time (2) - || rblock->htsize == 0 - || currblock[(GRUB_DISK_SECTOR_SIZE << log_blocksize) - / sizeof (*currblock) - 1] - != grub_cpu_to_be32_compile_time (1)) + /* Make sure this is an affs filesystem. */ + if (grub_strncmp ((char *) (data->bblock.type), "DOS", 3) != 0 + /* Test if the filesystem is a OFS filesystem. */ + || !(data->bblock.flags & GRUB_AFFS_FLAG_FFS)) continue; - for (i = 0; i < (GRUB_DISK_SECTOR_SIZE << log_blocksize) - / sizeof (*currblock); - i++) - checksum += grub_be_to_cpu32 (currblock[i]); + /* No sane person uses more than 8KB for a block. At least I hope + for that person because in that case this won't work. */ + if (!rootblock) + rootblock = grub_malloc (GRUB_DISK_SECTOR_SIZE + << AFFS_MAX_LOG_BLOCK_SIZE); + if (!rootblock) + goto fail; - if (checksum == 0) - break; + rblock = (struct grub_affs_rblock *) rootblock; + + /* The filesystem blocksize is not stored anywhere in the filesystem + itself. One way to determine it is try reading blocks for the + rootblock until the checksum is correct. */ + for (log_blocksize = 0; log_blocksize <= AFFS_MAX_LOG_BLOCK_SIZE; + log_blocksize++) + { + grub_uint32_t *currblock = rootblock; + unsigned int i; + grub_uint32_t checksum = 0; + + /* Read the rootblock. */ + grub_disk_read (disk, + (grub_uint64_t) grub_be_to_cpu32 (data->bblock.rootblock) + << log_blocksize, 0, + GRUB_DISK_SECTOR_SIZE << log_blocksize, rootblock); + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + { + grub_errno = 0; + break; + } + if (grub_errno) + goto fail; + + if (rblock->type != grub_cpu_to_be32_compile_time (2) + || rblock->htsize == 0 + || currblock[(GRUB_DISK_SECTOR_SIZE << log_blocksize) + / sizeof (*currblock) - 1] + != grub_cpu_to_be32_compile_time (1)) + continue; + + for (i = 0; i < (GRUB_DISK_SECTOR_SIZE << log_blocksize) + / sizeof (*currblock); + i++) + checksum += grub_be_to_cpu32 (currblock[i]); + + if (checksum == 0) + { + data->log_blocksize = log_blocksize; + data->disk = disk; + data->htsize = grub_be_to_cpu32 (rblock->htsize); + data->diropen.data = data; + data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock); + data->diropen.parent = NULL; + grub_memcpy (&data->diropen.di, rootblock, + sizeof (data->diropen.di)); + grub_free (rootblock); + + return data; + } + } } - if (log_blocksize > AFFS_MAX_LOG_BLOCK_SIZE) - { - grub_error (GRUB_ERR_BAD_FS, "AFFS blocksize couldn't be determined"); - goto fail; - } - - data->log_blocksize = log_blocksize; - data->disk = disk; - data->htsize = grub_be_to_cpu32 (rblock->htsize); - data->diropen.data = data; - data->diropen.block = grub_be_to_cpu32 (data->bblock.rootblock); - data->diropen.parent = NULL; - grub_memcpy (&data->diropen.di, rootblock, sizeof (data->diropen.di)); - - grub_free (rootblock); - - return data; fail: - if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + if (grub_errno == GRUB_ERR_NONE || grub_errno == GRUB_ERR_OUT_OF_RANGE) grub_error (GRUB_ERR_BAD_FS, "not an AFFS filesystem"); grub_free (data); @@ -302,7 +302,7 @@ grub_affs_read_symlink (grub_fshelp_node_t node) return 0; } latin1[symlink_size] = 0; - utf8 = grub_malloc (symlink_size * GRUB_MAX_UTF8_PER_LATIN1 + 1); + utf8 = grub_calloc (GRUB_MAX_UTF8_PER_LATIN1 + 1, symlink_size); if (!utf8) { grub_free (latin1); @@ -317,113 +317,114 @@ grub_affs_read_symlink (grub_fshelp_node_t node) } +/* Helper for grub_affs_iterate_dir. */ static int -grub_affs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) +grub_affs_create_node (grub_fshelp_node_t dir, + grub_fshelp_iterate_dir_hook_t hook, void *hook_data, + struct grub_fshelp_node **node, + grub_uint32_t block, const struct grub_affs_file *fil) { - unsigned int i; - struct grub_affs_file file; - struct grub_fshelp_node *node = 0; struct grub_affs_data *data = dir->data; - grub_uint32_t *hashtable; + int type = GRUB_FSHELP_REG; + grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1]; + grub_size_t len; + unsigned int nest; - auto int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block, - const struct grub_affs_file *fil); + *node = grub_zalloc (sizeof (**node)); + if (!*node) + return 1; - int NESTED_FUNC_ATTR grub_affs_create_node (grub_uint32_t block, - const struct grub_affs_file *fil) + (*node)->data = data; + (*node)->block = block; + (*node)->parent = dir; + + len = fil->namelen; + if (len > sizeof (fil->name)) + len = sizeof (fil->name); + *grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0'; + + (*node)->di = *fil; + for (nest = 0; nest < 8; nest++) { - int type; - grub_uint8_t name_u8[sizeof (fil->name) * GRUB_MAX_UTF8_PER_LATIN1 + 1]; - grub_size_t len; - unsigned int nest; - - node = grub_zalloc (sizeof (*node)); - if (!node) + switch ((*node)->di.type) { - grub_free (hashtable); - return 1; - } - - node->data = data; - node->block = block; - node->parent = dir; - - len = fil->namelen; - if (len > sizeof (fil->name)) - len = sizeof (fil->name); - *grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0'; - - node->di = *fil; - for (nest = 0; nest < 8; nest++) - { - switch (node->di.type) - { - case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_REG): - type = GRUB_FSHELP_REG; - break; - case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_DIR): - type = GRUB_FSHELP_DIR; - break; - case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_SYMLINK): - type = GRUB_FSHELP_SYMLINK; - break; - case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_HARDLINK): - { - grub_err_t err; - node->block = grub_be_to_cpu32 (node->di.hardlink); - err = grub_disk_read (data->disk, - (((grub_uint64_t) node->block + 1) << data->log_blocksize) - - 1, - GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION, - sizeof (node->di), (char *) &node->di); - if (err) - return 1; - continue; - } - default: - return 0; - } + case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_REG): + type = GRUB_FSHELP_REG; break; + case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_DIR): + type = GRUB_FSHELP_DIR; + break; + case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_SYMLINK): + type = GRUB_FSHELP_SYMLINK; + break; + case grub_cpu_to_be32_compile_time (GRUB_AFFS_FILETYPE_HARDLINK): + { + grub_err_t err; + (*node)->block = grub_be_to_cpu32 ((*node)->di.hardlink); + err = grub_disk_read (data->disk, + (((grub_uint64_t) (*node)->block + 1) << data->log_blocksize) + - 1, + GRUB_DISK_SECTOR_SIZE - GRUB_AFFS_FILE_LOCATION, + sizeof ((*node)->di), (char *) &(*node)->di); + if (err) + { + grub_free (*node); + return 1; + } + continue; + } + default: + { + grub_free (*node); + return 0; + } } + break; + } - if (nest == 8) - return 0; - - type |= GRUB_FSHELP_CASE_INSENSITIVE; - - if (hook ((char *) name_u8, type, node)) - { - grub_free (hashtable); - node = 0; - return 1; - } - node = 0; + if (nest == 8) + { + grub_free (*node); return 0; } + type |= GRUB_FSHELP_CASE_INSENSITIVE; + + if (hook ((char *) name_u8, type, *node, hook_data)) + { + *node = 0; + return 1; + } + *node = 0; + return 0; +} + +static int +grub_affs_iterate_dir (grub_fshelp_node_t dir, + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) +{ + unsigned int i; + struct grub_affs_file file; + struct grub_fshelp_node *node, *orig_node; + struct grub_affs_data *data = dir->data; + grub_uint32_t *hashtable; + /* Create the directory entries for `.' and `..'. */ - node = grub_zalloc (sizeof (*node)); + node = orig_node = grub_zalloc (sizeof (*node)); if (!node) return 1; - + *node = *dir; - if (hook (".", GRUB_FSHELP_DIR, node)) + if (hook (".", GRUB_FSHELP_DIR, node, hook_data)) return 1; if (dir->parent) { - node = grub_zalloc (sizeof (*node)); - if (!node) - return 1; *node = *dir->parent; - if (hook ("..", GRUB_FSHELP_DIR, node)) + if (hook ("..", GRUB_FSHELP_DIR, node, hook_data)) return 1; } - hashtable = grub_zalloc (data->htsize * sizeof (*hashtable)); + hashtable = grub_calloc (data->htsize, sizeof (*hashtable)); if (!hashtable) return 1; @@ -455,18 +456,20 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, if (grub_errno) goto fail; - if (grub_affs_create_node (next, &file)) - return 1; + if (grub_affs_create_node (dir, hook, hook_data, &node, next, &file)) + { + /* Node has been replaced in function. */ + grub_free (orig_node); + grub_free (hashtable); + return 1; + } next = grub_be_to_cpu32 (file.next); } } - grub_free (hashtable); - return 0; - fail: - grub_free (node); + grub_free (orig_node); grub_free (hashtable); return 0; } @@ -531,7 +534,7 @@ grub_affs_read (grub_file_t file, char *buf, grub_size_t len) (struct grub_affs_data *) file->data; return grub_fshelp_read_file (data->diropen.data->disk, &data->diropen, - file->read_hook, + file->read_hook, file->read_hook_data, file->offset, len, buf, grub_affs_read_block, grub_be_to_cpu32 (data->diropen.di.size), data->log_blocksize, 0); @@ -546,31 +549,37 @@ aftime2ctime (const struct grub_affs_time *t) + 8 * 365 * 86400 + 86400 * 2; } +/* Context for grub_affs_dir. */ +struct grub_affs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_affs_dir. */ +static int +grub_affs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_affs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = aftime2ctime (&node->di.mtime); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_affs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_affs_dir_ctx ctx = { hook, hook_data }; struct grub_affs_data *data = 0; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = 1; - info.mtime = aftime2ctime (&node->di.mtime); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_affs_mount (device->disk); @@ -582,7 +591,7 @@ grub_affs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_affs_iterate_dir (fdiro, iterate); + grub_affs_iterate_dir (fdiro, grub_affs_dir_iter, &ctx); fail: if (data && fdiro != &data->diropen) @@ -622,7 +631,7 @@ grub_affs_label (grub_device_t device, char **label) len = file.namelen; if (len > sizeof (file.name)) len = sizeof (file.name); - *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); + *label = grub_calloc (GRUB_MAX_UTF8_PER_LATIN1 + 1, len); if (*label) *grub_latin1_to_utf8 ((grub_uint8_t *) *label, file.name, len) = '\0'; } @@ -637,7 +646,7 @@ grub_affs_label (grub_device_t device, char **label) } static grub_err_t -grub_affs_mtime (grub_device_t device, grub_int32_t *t) +grub_affs_mtime (grub_device_t device, grub_int64_t *t) { struct grub_affs_data *data; grub_disk_t disk = device->disk; @@ -679,12 +688,12 @@ grub_affs_mtime (grub_device_t device, grub_int32_t *t) static struct grub_fs grub_affs_fs = { .name = "affs", - .dir = grub_affs_dir, - .open = grub_affs_open, - .read = grub_affs_read, - .close = grub_affs_close, - .label = grub_affs_label, - .mtime = grub_affs_mtime, + .fs_dir = grub_affs_dir, + .fs_open = grub_affs_open, + .fs_read = grub_affs_read, + .fs_close = grub_affs_close, + .fs_label = grub_affs_label, + .fs_mtime = grub_affs_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 0, @@ -695,11 +704,16 @@ static struct grub_fs grub_affs_fs = GRUB_MOD_INIT(affs) { - grub_fs_register (&grub_affs_fs); + if (!grub_is_lockdown ()) + { + grub_affs_fs.mod = mod; + grub_fs_register (&grub_affs_fs); + } my_mod = mod; } GRUB_MOD_FINI(affs) { - grub_fs_unregister (&grub_affs_fs); + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_affs_fs); } diff --git a/grub-core/fs/archelp.c b/grub-core/fs/archelp.c new file mode 100644 index 000000000..0816b28de --- /dev/null +++ b/grub-core/fs/archelp.c @@ -0,0 +1,316 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static inline void +canonicalize (char *name) +{ + char *iptr, *optr; + for (iptr = name, optr = name; *iptr; ) + { + while (*iptr == '/') + iptr++; + if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0)) + { + iptr++; + continue; + } + if (iptr[0] == '.' && iptr[1] == '.' && (iptr[2] == '/' || iptr[2] == 0)) + { + iptr += 2; + if (optr == name) + continue; + for (optr -= 2; optr >= name && *optr != '/'; optr--); + optr++; + continue; + } + while (*iptr && *iptr != '/') + *optr++ = *iptr++; + if (*iptr) + *optr++ = *iptr++; + } + *optr = 0; +} + +static grub_err_t +handle_symlink (struct grub_archelp_data *data, + struct grub_archelp_ops *arcops, + const char *fn, char **name, + grub_uint32_t mode, int *restart) +{ + grub_size_t flen; + char *target; + char *ptr; + char *lastslash; + grub_size_t prefixlen; + char *rest; + char *linktarget; + grub_size_t linktarget_len; + grub_size_t sz; + + *restart = 0; + + if ((mode & GRUB_ARCHELP_ATTR_TYPE) != GRUB_ARCHELP_ATTR_LNK + || !arcops->get_link_target) + return GRUB_ERR_NONE; + flen = grub_strlen (fn); + if (grub_memcmp (*name, fn, flen) != 0 + || ((*name)[flen] != 0 && (*name)[flen] != '/')) + return GRUB_ERR_NONE; + rest = *name + flen; + lastslash = rest; + if (*rest) + rest++; + while (lastslash >= *name && *lastslash != '/') + lastslash--; + if (lastslash >= *name) + prefixlen = lastslash - *name; + else + prefixlen = 0; + + if (prefixlen) + prefixlen++; + + linktarget = arcops->get_link_target (data); + if (!linktarget) + return grub_errno; + if (linktarget[0] == '\0') + return GRUB_ERR_NONE; + linktarget_len = grub_strlen (linktarget); + + if (grub_add (linktarget_len, grub_strlen (*name), &sz) || + grub_add (sz, 2, &sz)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("link target length overflow")); + + target = grub_malloc (sz); + if (!target) + return grub_errno; + + grub_strcpy (target + prefixlen, linktarget); + grub_free (linktarget); + if (target[prefixlen] == '/') + { + ptr = grub_stpcpy (target, target + prefixlen); + ptr = grub_stpcpy (ptr, rest); + *ptr = 0; + grub_dprintf ("archelp", "symlink redirected %s to %s\n", + *name, target); + grub_free (*name); + + canonicalize (target); + *name = target; + *restart = 1; + return GRUB_ERR_NONE; + } + if (prefixlen) + { + grub_memcpy (target, *name, prefixlen); + target[prefixlen-1] = '/'; + } + grub_strcpy (target + prefixlen + linktarget_len, rest); + grub_dprintf ("archelp", "symlink redirected %s to %s\n", + *name, target); + grub_free (*name); + canonicalize (target); + *name = target; + *restart = 1; + return GRUB_ERR_NONE; +} + +grub_err_t +grub_archelp_dir (struct grub_archelp_data *data, + struct grub_archelp_ops *arcops, + const char *path_in, + grub_fs_dir_hook_t hook, void *hook_data) +{ + char *prev, *name, *path, *ptr; + grub_size_t len; + int symlinknest = 0; + + path = grub_strdup (path_in + 1); + if (!path) + return grub_errno; + canonicalize (path); + for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--) + *ptr = 0; + + prev = 0; + + len = grub_strlen (path); + while (1) + { + grub_int32_t mtime; + grub_uint32_t mode; + grub_err_t err; + + if (arcops->find_file (data, &name, &mtime, &mode)) + goto fail; + + if (mode == GRUB_ARCHELP_ATTR_END) + break; + + canonicalize (name); + + if (grub_memcmp (path, name, len) == 0 + && (name[len] == 0 || name[len] == '/' || len == 0)) + { + char *p, *n; + + n = name + len; + while (*n == '/') + n++; + + p = grub_strchr (n, '/'); + if (p) + *p = 0; + + if ((*n == 0) && ((mode & GRUB_ARCHELP_ATTR_TYPE) + != GRUB_ARCHELP_ATTR_DIR)) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); + grub_free (name); + goto fail; + } + + if (((!prev) || (grub_strcmp (prev, name) != 0)) && *n != 0) + { + struct grub_dirhook_info info; + grub_memset (&info, 0, sizeof (info)); + info.dir = (p != NULL) || ((mode & GRUB_ARCHELP_ATTR_TYPE) + == GRUB_ARCHELP_ATTR_DIR); + if (!(mode & GRUB_ARCHELP_ATTR_NOTIME)) + { + info.mtime = mtime; + info.mtimeset = 1; + } + if (hook (n, &info, hook_data)) + { + grub_free (name); + goto fail; + } + grub_free (prev); + prev = name; + } + else + { + int restart = 0; + err = handle_symlink (data, arcops, name, + &path, mode, &restart); + grub_free (name); + if (err) + goto fail; + if (restart) + { + len = grub_strlen (path); + if (++symlinknest == 8) + { + grub_error (GRUB_ERR_SYMLINK_LOOP, + N_("too deep nesting of symlinks")); + goto fail; + } + arcops->rewind (data); + } + } + } + else + grub_free (name); + } + +fail: + + grub_free (path); + grub_free (prev); + + return grub_errno; +} + +grub_err_t +grub_archelp_open (struct grub_archelp_data *data, + struct grub_archelp_ops *arcops, + const char *name_in) +{ + char *fn; + char *name = grub_strdup (name_in + 1); + int symlinknest = 0; + + if (!name) + return grub_errno; + + canonicalize (name); + + while (1) + { + grub_uint32_t mode; + grub_int32_t mtime; + int restart; + + if (arcops->find_file (data, &fn, &mtime, &mode)) + goto fail; + + if (mode == GRUB_ARCHELP_ATTR_END) + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name_in); + break; + } + + canonicalize (fn); + + if (handle_symlink (data, arcops, fn, &name, mode, &restart)) + { + grub_free (fn); + goto fail; + } + + if (restart) + { + arcops->rewind (data); + if (++symlinknest == 8) + { + grub_error (GRUB_ERR_SYMLINK_LOOP, + N_("too deep nesting of symlinks")); + goto fail; + } + goto no_match; + } + + if (grub_strcmp (name, fn) != 0) + goto no_match; + + grub_free (fn); + grub_free (name); + + return GRUB_ERR_NONE; + + no_match: + + grub_free (fn); + } + +fail: + grub_free (name); + + return grub_errno; +} diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c index 318dc3eec..78aeb051f 100644 --- a/grub-core/fs/bfs.c +++ b/grub-core/fs/bfs.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -73,7 +75,7 @@ struct grub_bfs_extent grub_uint32_t ag; grub_uint16_t start; grub_uint16_t len; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_bfs_superblock { @@ -89,7 +91,7 @@ struct grub_bfs_superblock grub_uint8_t unused3[32]; grub_uint32_t magic3; struct grub_bfs_extent root_dir; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_bfs_inode { @@ -118,11 +120,11 @@ struct grub_bfs_inode grub_uint64_t max_double_indirect_range; grub_uint64_t size; grub_uint32_t pad[4]; - } __attribute__ ((packed)); + } GRUB_PACKED; char inplace_link[144]; - } __attribute__ ((packed)); + } GRUB_PACKED; grub_uint8_t small_data[0]; -} __attribute__ ((packed)); +} GRUB_PACKED; enum { @@ -134,7 +136,7 @@ struct grub_bfs_small_data_element_header grub_uint32_t type; grub_uint16_t name_len; grub_uint16_t value_len; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_bfs_btree_header { @@ -151,7 +153,7 @@ struct grub_bfs_btree_header grub_uint64_t root; #endif grub_uint32_t unused2[2]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_bfs_btree_node { @@ -165,12 +167,21 @@ struct grub_bfs_btree_node grub_uint16_t count_keys; grub_uint16_t total_key_len; #endif -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_bfs_data { struct grub_bfs_superblock sb; - struct grub_bfs_inode ino[0]; + struct grub_bfs_inode ino; +}; + +/* Context for grub_bfs_dir. */ +struct grub_bfs_dir_ctx +{ + grub_device_t device; + grub_fs_dir_hook_t hook; + void *hook_data; + struct grub_bfs_superblock sb; }; static grub_err_t @@ -208,9 +219,7 @@ read_bfs_file (grub_disk_t disk, const struct grub_bfs_superblock *sb, const struct grub_bfs_inode *ino, grub_off_t off, void *buf, grub_size_t len, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length)) + grub_disk_read_hook_t read_hook, void *read_hook_data) { if (len == 0) return GRUB_ERR_NONE; @@ -236,6 +245,7 @@ read_bfs_file (grub_disk_t disk, if (read_size > len) read_size = len; disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; err = read_extent (disk, sb, &ino->direct[i], 0, off - pos, buf, read_size); disk->read_hook = 0; @@ -281,6 +291,7 @@ read_bfs_file (grub_disk_t disk, if (read_size > len) read_size = len; disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; err = read_extent (disk, sb, &entries[i], 0, off - pos, buf, read_size); disk->read_hook = 0; @@ -392,6 +403,7 @@ read_bfs_file (grub_disk_t disk, if (read_size > len) read_size = len; disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; err = read_extent (disk, sb, &l2_entries[l2n], 0, boff, buf, read_size); disk->read_hook = 0; @@ -405,22 +417,83 @@ read_bfs_file (grub_disk_t disk, len -= read_size; buf = (char *) buf + read_size; } + grub_free (l1_entries); + grub_free (l2_entries); return GRUB_ERR_NONE; } } +static grub_err_t +read_b_node (grub_disk_t disk, + const struct grub_bfs_superblock *sb, + const struct grub_bfs_inode *ino, + grub_uint64_t node_off, + struct grub_bfs_btree_node **node, + char **key_data, grub_uint16_t **keylen_idx, + grub_unaligned_uint64_t **key_values) +{ + void *ret; + struct grub_bfs_btree_node node_head; + grub_size_t total_size; + grub_err_t err; + + *node = NULL; + *key_data = NULL; + *keylen_idx = NULL; + *key_values = NULL; + + err = read_bfs_file (disk, sb, ino, node_off, &node_head, sizeof (node_head), + 0, 0); + if (err) + return err; + + total_size = ALIGN_UP (sizeof (node_head) + + grub_bfs_to_cpu_treehead + (node_head.total_key_len), + BTREE_ALIGN) + + grub_bfs_to_cpu_treehead (node_head.count_keys) * + sizeof (grub_uint16_t) + + grub_bfs_to_cpu_treehead (node_head.count_keys) * + sizeof (grub_uint64_t); + + ret = grub_malloc (total_size); + if (!ret) + return grub_errno; + + err = read_bfs_file (disk, sb, ino, node_off, ret, total_size, 0, 0); + if (err) + { + grub_free (ret); + return err; + } + + *node = ret; + *key_data = (char *) ret + sizeof (node_head); + *keylen_idx = (grub_uint16_t *) ret + + ALIGN_UP (sizeof (node_head) + + grub_bfs_to_cpu_treehead (node_head.total_key_len), + BTREE_ALIGN) / 2; + *key_values = (grub_unaligned_uint64_t *) + (*keylen_idx + + grub_bfs_to_cpu_treehead (node_head.count_keys)); + + return GRUB_ERR_NONE; +} + static int iterate_in_b_tree (grub_disk_t disk, const struct grub_bfs_superblock *sb, const struct grub_bfs_inode *ino, - int NESTED_FUNC_ATTR (*hook) (const char *name, grub_uint64_t value)) + int (*hook) (const char *name, grub_uint64_t value, + struct grub_bfs_dir_ctx *ctx), + struct grub_bfs_dir_ctx *ctx) { struct grub_bfs_btree_header head; grub_err_t err; int level; grub_uint64_t node_off; - err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0); + err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0, 0); if (err) return 0; node_off = grub_bfs_to_cpu64 (head.root); @@ -430,7 +503,8 @@ iterate_in_b_tree (grub_disk_t disk, { struct grub_bfs_btree_node node; grub_uint64_t key_value; - err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); + err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), + 0, 0); if (err) return 0; err = read_bfs_file (disk, sb, ino, node_off @@ -440,7 +514,7 @@ iterate_in_b_tree (grub_disk_t disk, BTREE_ALIGN) + grub_bfs_to_cpu_treehead (node.count_keys) * sizeof (grub_uint16_t), &key_value, - sizeof (grub_uint64_t), 0); + sizeof (grub_uint64_t), 0, 0); if (err) return 0; @@ -449,67 +523,51 @@ iterate_in_b_tree (grub_disk_t disk, while (1) { - struct grub_bfs_btree_node node; - err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); + struct grub_bfs_btree_node *node; + char *key_data; + grub_uint16_t *keylen_idx; + grub_unaligned_uint64_t *key_values; + unsigned i; + grub_uint16_t start = 0, end = 0; + + err = read_b_node (disk, sb, ino, + node_off, + &node, + &key_data, + &keylen_idx, + &key_values); + if (err) return 0; - { - char key_data[grub_bfs_to_cpu_treehead (node.total_key_len) + 1]; - grub_uint16_t keylen_idx[grub_bfs_to_cpu_treehead (node.count_keys)]; - grub_uint64_t key_values[grub_bfs_to_cpu_treehead (node.count_keys)]; - unsigned i; - grub_uint16_t start = 0, end = 0; - err = - read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, - grub_bfs_to_cpu_treehead (node.total_key_len), 0); - if (err) - return 0; - key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0; - err = read_bfs_file (disk, sb, ino, node_off - + ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu_treehead - (node.total_key_len), BTREE_ALIGN), - keylen_idx, - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint16_t), 0); - if (err) - return 0; - err = read_bfs_file (disk, sb, ino, node_off - + ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu_treehead - (node.total_key_len), - BTREE_ALIGN) + - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint16_t), key_values, - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint64_t), 0); - if (err) - return 0; - - for (i = 0; i < grub_bfs_to_cpu_treehead (node.count_keys); i++) - { - char c; - start = end; - end = grub_bfs_to_cpu16 (keylen_idx[i]); - if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) - end = grub_bfs_to_cpu_treehead (node.total_key_len); - c = key_data[end]; - key_data[end] = 0; - if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i]))) + for (i = 0; i < grub_bfs_to_cpu_treehead (node->count_keys); i++) + { + char c; + start = end; + end = grub_bfs_to_cpu16 (keylen_idx[i]); + if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) + end = grub_bfs_to_cpu_treehead (node->total_key_len); + c = key_data[end]; + key_data[end] = 0; + if (hook (key_data + start, grub_bfs_to_cpu64 (key_values[i].val), + ctx)) + { + grub_free (node); return 1; + } key_data[end] = c; } - node_off = grub_bfs_to_cpu64 (node.right); + node_off = grub_bfs_to_cpu64 (node->right); + grub_free (node); if (node_off == POINTER_INVALID) return 0; - } } } static int bfs_strcmp (const char *a, const char *b, grub_size_t alen) { + char ac, bc; while (*b && alen) { if (*a != *b) @@ -520,16 +578,13 @@ bfs_strcmp (const char *a, const char *b, grub_size_t alen) alen--; } + ac = alen ? *a : 0; + bc = *b; + #ifdef MODE_AFS - if (!alen) - return - (int) (grub_int8_t) *b; - - return (int) (grub_int8_t) *a - (int) (grub_int8_t) *b; + return (int) (grub_int8_t) ac - (int) (grub_int8_t) bc; #else - if (!alen) - return - (int) (grub_uint8_t) *b; - - return (int) (grub_uint8_t) *a - (int) (grub_uint8_t) *b; + return (int) (grub_uint8_t) ac - (int) (grub_uint8_t) bc; #endif } @@ -544,7 +599,7 @@ find_in_b_tree (grub_disk_t disk, int level; grub_uint64_t node_off; - err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0); + err = read_bfs_file (disk, sb, ino, 0, &head, sizeof (head), 0, 0); if (err) return err; node_off = grub_bfs_to_cpu64 (head.root); @@ -552,264 +607,221 @@ find_in_b_tree (grub_disk_t disk, level = grub_bfs_to_cpu32 (head.level) - 1; while (1) { - struct grub_bfs_btree_node node; - err = read_bfs_file (disk, sb, ino, node_off, &node, sizeof (node), 0); + struct grub_bfs_btree_node *node; + char *key_data; + grub_uint16_t *keylen_idx; + grub_unaligned_uint64_t *key_values; + int lg, j; + unsigned i; + + err = read_b_node (disk, sb, ino, node_off, &node, &key_data, &keylen_idx, &key_values); if (err) return err; - if (node.count_keys == 0) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), - name); - { - char key_data[grub_bfs_to_cpu_treehead (node.total_key_len) + 1]; - grub_uint16_t keylen_idx[grub_bfs_to_cpu_treehead (node.count_keys)]; - grub_uint64_t key_values[grub_bfs_to_cpu_treehead (node.count_keys)]; - unsigned i; - err = - read_bfs_file (disk, sb, ino, node_off + sizeof (node), key_data, - grub_bfs_to_cpu_treehead (node.total_key_len), 0); - if (err) - return err; - key_data[grub_bfs_to_cpu_treehead (node.total_key_len)] = 0; - err = read_bfs_file (disk, sb, ino, node_off - + - ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu_treehead (node. - total_key_len), - BTREE_ALIGN), keylen_idx, - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint16_t), 0); - if (err) - return err; - err = read_bfs_file (disk, sb, ino, node_off - + ALIGN_UP (sizeof (node) + - grub_bfs_to_cpu_treehead - (node.total_key_len), - BTREE_ALIGN) + - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint16_t), key_values, - grub_bfs_to_cpu_treehead (node.count_keys) * - sizeof (grub_uint64_t), 0); - if (err) - return err; - int lg, j; + if (node->count_keys == 0) + { + grub_free (node); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), + name); + } - for (lg = 0; grub_bfs_to_cpu_treehead (node.count_keys) >> lg; lg++); + for (lg = 0; grub_bfs_to_cpu_treehead (node->count_keys) >> lg; lg++); - i = 0; + i = 0; - for (j = lg - 1; j >= 0; j--) - { - int cmp; - grub_uint16_t start = 0, end = 0; - if ((i | (1 << j)) >= grub_bfs_to_cpu_treehead (node.count_keys)) - continue; - start = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j)) - 1]); - end = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j))]); - if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) - end = grub_bfs_to_cpu_treehead (node.total_key_len); - cmp = bfs_strcmp (key_data + start, name, end - start); - if (cmp == 0 && level == 0) - { - *res = grub_bfs_to_cpu64 (key_values[i | (1 << j)]); - return GRUB_ERR_NONE; - } + for (j = lg - 1; j >= 0; j--) + { + int cmp; + grub_uint16_t start = 0, end = 0; + if ((i | (1 << j)) >= grub_bfs_to_cpu_treehead (node->count_keys)) + continue; + start = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j)) - 1]); + end = grub_bfs_to_cpu16 (keylen_idx[(i | (1 << j))]); + if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) + end = grub_bfs_to_cpu_treehead (node->total_key_len); + cmp = bfs_strcmp (key_data + start, name, end - start); + if (cmp == 0 && level == 0) + { + *res = grub_bfs_to_cpu64 (key_values[i | (1 << j)].val); + grub_free (node); + return GRUB_ERR_NONE; + } #ifdef MODE_AFS - if (cmp <= 0) + if (cmp <= 0) #else - if (cmp < 0) + if (cmp < 0) #endif - i |= (1 << j); - } - if (i == 0) - { - grub_uint16_t end = 0; - int cmp; - end = grub_bfs_to_cpu16 (keylen_idx[0]); - if (grub_bfs_to_cpu_treehead (node.total_key_len) <= end) - end = grub_bfs_to_cpu_treehead (node.total_key_len); - cmp = bfs_strcmp (key_data, name, end); - if (cmp == 0 && level == 0) - { - *res = grub_bfs_to_cpu64 (key_values[0]); - return GRUB_ERR_NONE; - } + i |= (1 << j); + } + if (i == 0) + { + grub_uint16_t end = 0; + int cmp; + end = grub_bfs_to_cpu16 (keylen_idx[0]); + if (grub_bfs_to_cpu_treehead (node->total_key_len) <= end) + end = grub_bfs_to_cpu_treehead (node->total_key_len); + cmp = bfs_strcmp (key_data, name, end); + if (cmp == 0 && level == 0) + { + *res = grub_bfs_to_cpu64 (key_values[0].val); + grub_free (node); + return GRUB_ERR_NONE; + } #ifdef MODE_AFS - if (cmp > 0 && level != 0) + if (cmp > 0 && level != 0) #else if (cmp >= 0 && level != 0) #endif { - node_off = grub_bfs_to_cpu64 (key_values[0]); + node_off = grub_bfs_to_cpu64 (key_values[0].val); level--; + grub_free (node); continue; } else if (level != 0 - && grub_bfs_to_cpu_treehead (node.count_keys) >= 2) + && grub_bfs_to_cpu_treehead (node->count_keys) >= 2) { - node_off = grub_bfs_to_cpu64 (key_values[1]); + node_off = grub_bfs_to_cpu64 (key_values[1].val); level--; + grub_free (node); continue; - } + } } else if (level != 0 - && i + 1 < grub_bfs_to_cpu_treehead (node.count_keys)) + && i + 1 < grub_bfs_to_cpu_treehead (node->count_keys)) { - node_off = grub_bfs_to_cpu64 (key_values[i + 1]); + node_off = grub_bfs_to_cpu64 (key_values[i + 1].val); level--; + grub_free (node); continue; } - if (node.overflow != POINTER_INVALID) + if (node->overflow != POINTER_INVALID) { - node_off = grub_bfs_to_cpu64 (node.overflow); + node_off = grub_bfs_to_cpu64 (node->overflow); /* This level-- isn't specified but is needed. */ level--; + grub_free (node); continue; } + grub_free (node); return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name); - } } } +struct grub_fshelp_node +{ + grub_disk_t disk; + const struct grub_bfs_superblock *sb; + struct grub_bfs_inode ino; +}; + static grub_err_t -hop_level (grub_disk_t disk, - const struct grub_bfs_superblock *sb, - struct grub_bfs_inode *ino, const char *name) +lookup_file (grub_fshelp_node_t dir, + const char *name, + grub_fshelp_node_t *foundnode, + enum grub_fshelp_filetype *foundtype) { grub_err_t err; + struct grub_bfs_inode *new_ino; grub_uint64_t res = 0; - if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) != ATTR_DIR)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - - err = find_in_b_tree (disk, sb, ino, name, &res); + err = find_in_b_tree (dir->disk, dir->sb, &dir->ino, name, &res); if (err) return err; - return grub_disk_read (disk, res - << (grub_bfs_to_cpu32 (sb->log2_bsize) - - GRUB_DISK_SECTOR_BITS), 0, - grub_bfs_to_cpu32 (sb->bsize), (char *) ino); + *foundnode = grub_malloc (sizeof (struct grub_fshelp_node)); + if (!*foundnode) + return grub_errno; + + (*foundnode)->disk = dir->disk; + (*foundnode)->sb = dir->sb; + new_ino = &(*foundnode)->ino; + + if (grub_disk_read (dir->disk, res + << (grub_bfs_to_cpu32 (dir->sb->log2_bsize) + - GRUB_DISK_SECTOR_BITS), 0, + sizeof (*new_ino), (char *) new_ino)) + { + grub_free (*foundnode); + return grub_errno; + } + switch (grub_bfs_to_cpu32 (new_ino->mode) & ATTR_TYPE) + { + default: + case ATTR_REG: + *foundtype = GRUB_FSHELP_REG; + break; + case ATTR_DIR: + *foundtype = GRUB_FSHELP_DIR; + break; + case ATTR_LNK: + *foundtype = GRUB_FSHELP_SYMLINK; + break; + } + return GRUB_ERR_NONE; +} + +static char * +read_symlink (grub_fshelp_node_t node) +{ + char *alloc = NULL; + grub_err_t err; + +#ifndef MODE_AFS + if (!(grub_bfs_to_cpu32 (node->ino.flags) & LONG_SYMLINK)) + { + alloc = grub_malloc (sizeof (node->ino.inplace_link) + 1); + if (!alloc) + { + return NULL; + } + grub_memcpy (alloc, node->ino.inplace_link, + sizeof (node->ino.inplace_link)); + alloc[sizeof (node->ino.inplace_link)] = 0; + } + else +#endif + { + grub_size_t symsize = grub_bfs_to_cpu64 (node->ino.size); + alloc = grub_malloc (symsize + 1); + if (!alloc) + return NULL; + err = read_bfs_file (node->disk, node->sb, &node->ino, 0, alloc, symsize, 0, 0); + if (err) + { + grub_free (alloc); + return NULL; + } + alloc[symsize] = 0; + } + + return alloc; } static grub_err_t find_file (const char *path, grub_disk_t disk, - const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino) + const struct grub_bfs_superblock *sb, struct grub_bfs_inode *ino, + enum grub_fshelp_filetype exptype) { - char *ptr, *ptr2; - char *alloc = NULL; grub_err_t err; - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; - } old_ino; - unsigned symlinks_max = 32; + struct grub_fshelp_node root = { + .disk = disk, + .sb = sb, + }; + struct grub_fshelp_node *found = NULL; - err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, - grub_bfs_to_cpu32 (sb->bsize)); + err = read_extent (disk, sb, &sb->root_dir, 0, 0, &root.ino, + sizeof (root.ino)); if (err) return err; + err = grub_fshelp_find_file_lookup (path, &root, &found, lookup_file, read_symlink, exptype); + if (!err) + grub_memcpy (ino, &found->ino, sizeof (*ino)); - ptr = (char *) path; - while (1) - { - while (*ptr == '/') - ptr++; - if (*ptr == 0) - { - grub_free (alloc); - return GRUB_ERR_NONE; - } - ptr2 = grub_strchr (ptr, '/'); - grub_memcpy (&old_ino, ino, grub_bfs_to_cpu32 (sb->bsize)); - if (ptr2) - { - char component[ptr2 - ptr + 1]; - grub_memcpy (component, ptr, ptr2 - ptr); - component[ptr2 - ptr] = 0; - err = hop_level (disk, sb, ino, component); - } - else - err = hop_level (disk, sb, ino, ptr); - if (err) - return err; - - if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) == ATTR_LNK)) - { - char *old_alloc = alloc; - if (--symlinks_max == 0) - { - grub_free (alloc); - return grub_error (GRUB_ERR_SYMLINK_LOOP, - N_("too deep nesting of symlinks")); - } - -#ifndef MODE_AFS - if (grub_bfs_to_cpu32 (ino->flags) & LONG_SYMLINK) -#endif - { - grub_size_t symsize = grub_bfs_to_cpu64 (ino->size); - alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) - + symsize + 1); - if (!alloc) - { - grub_free (alloc); - return grub_errno; - } - grub_free (old_alloc); - err = read_bfs_file (disk, sb, ino, 0, alloc, symsize, 0); - if (err) - { - grub_free (alloc); - return err; - } - alloc[symsize] = 0; - } -#ifndef MODE_AFS - else - { - alloc = grub_malloc ((ptr2 ? grub_strlen (ptr2) : 0) - + sizeof (ino->inplace_link) + 1); - if (!alloc) - { - grub_free (alloc); - return grub_errno; - } - grub_free (old_alloc); - grub_memcpy (alloc, ino->inplace_link, - sizeof (ino->inplace_link)); - alloc[sizeof (ino->inplace_link)] = 0; - } -#endif - if (alloc[0] == '/') - { - err = read_extent (disk, sb, &sb->root_dir, 0, 0, ino, - grub_bfs_to_cpu32 (sb->bsize)); - if (err) - { - grub_free (alloc); - return err; - } - } - else - grub_memcpy (ino, &old_ino, grub_bfs_to_cpu32 (sb->bsize)); - ptr = alloc + grub_strlen (alloc); - if (ptr2) - ptr = grub_stpcpy (ptr, ptr2); - *ptr = 0; - ptr = ptr2 = alloc; - continue; - } - - if (!ptr2) - { - grub_free (alloc); - return GRUB_ERR_NONE; - } - ptr = ptr2 + 1; - } + if (&root != found) + grub_free (found); + return err; } static grub_err_t @@ -818,7 +830,7 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb) grub_err_t err; err = grub_disk_read (disk, SUPERBLOCK, 0, sizeof (*sb), sb); if (err == GRUB_ERR_OUT_OF_RANGE) - return grub_error (GRUB_ERR_BAD_FS, + return grub_error (GRUB_ERR_BAD_FS, #ifdef MODE_AFS "not an AFS filesystem" #else @@ -834,7 +846,7 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb) || (grub_bfs_to_cpu32 (sb->bsize) != (1U << grub_bfs_to_cpu32 (sb->log2_bsize))) || grub_bfs_to_cpu32 (sb->log2_bsize) < GRUB_DISK_SECTOR_BITS) - return grub_error (GRUB_ERR_BAD_FS, + return grub_error (GRUB_ERR_BAD_FS, #ifdef MODE_AFS "not an AFS filesystem" #else @@ -844,61 +856,58 @@ mount (grub_disk_t disk, struct grub_bfs_superblock *sb) return GRUB_ERR_NONE; } +/* Helper for grub_bfs_dir. */ +static int +grub_bfs_dir_iter (const char *name, grub_uint64_t value, + struct grub_bfs_dir_ctx *ctx) +{ + grub_err_t err2; + struct grub_bfs_inode ino; + struct grub_dirhook_info info; + + err2 = grub_disk_read (ctx->device->disk, value + << (grub_bfs_to_cpu32 (ctx->sb.log2_bsize) + - GRUB_DISK_SECTOR_BITS), 0, + sizeof (ino), (char *) &ino); + if (err2) + { + grub_print_error (); + return 0; + } + + info.mtimeset = 1; +#ifdef MODE_AFS + info.mtime = + grub_divmod64 (grub_bfs_to_cpu64 (ino.mtime), 1000000, 0); +#else + info.mtime = grub_bfs_to_cpu64 (ino.mtime) >> 16; +#endif + info.dir = ((grub_bfs_to_cpu32 (ino.mode) & ATTR_TYPE) == ATTR_DIR); + return ctx->hook (name, &info, ctx->hook_data); +} + static grub_err_t grub_bfs_dir (grub_device_t device, const char *path, - int (*hook_in) (const char *filename, - const struct grub_dirhook_info * info)) + grub_fs_dir_hook_t hook, void *hook_data) { - struct grub_bfs_superblock sb; + struct grub_bfs_dir_ctx ctx = { + .device = device, + .hook = hook, + .hook_data = hook_data + }; grub_err_t err; - auto int NESTED_FUNC_ATTR hook (const char *name, grub_uint64_t value); - int NESTED_FUNC_ATTR hook (const char *name, grub_uint64_t value) - { - grub_err_t err2; - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; - } ino; - struct grub_dirhook_info info; - - err2 = grub_disk_read (device->disk, value - << (grub_bfs_to_cpu32 (sb.log2_bsize) - - GRUB_DISK_SECTOR_BITS), 0, - grub_bfs_to_cpu32 (sb.bsize), (char *) ino.raw); - if (err2) - { - grub_print_error (); - return 0; - } - - info.mtimeset = 1; -#ifdef MODE_AFS - info.mtime = - grub_divmod64 (grub_bfs_to_cpu64 (ino.ino.mtime), 1000000, 0); -#else - info.mtime = grub_bfs_to_cpu64 (ino.ino.mtime) >> 16; -#endif - info.dir = ((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) == ATTR_DIR); - return hook_in (name, &info); - } - err = mount (device->disk, &sb); + err = mount (device->disk, &ctx.sb); if (err) return err; { - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; - } ino; - err = find_file (path, device->disk, &sb, &ino.ino); + struct grub_bfs_inode ino; + err = find_file (path, device->disk, &ctx.sb, &ino, GRUB_FSHELP_DIR); if (err) return err; - if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_DIR)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - iterate_in_b_tree (device->disk, &sb, &ino.ino, hook); + iterate_in_b_tree (device->disk, &ctx.sb, &ino, grub_bfs_dir_iter, + &ctx); } return grub_errno; @@ -915,26 +924,19 @@ grub_bfs_open (struct grub_file *file, const char *name) return err; { - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; - } ino; + struct grub_bfs_inode ino; struct grub_bfs_data *data; - err = find_file (name, file->device->disk, &sb, &ino.ino); + err = find_file (name, file->device->disk, &sb, &ino, GRUB_FSHELP_REG); if (err) return err; - if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_REG)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); - data = grub_zalloc (sizeof (struct grub_bfs_data) - + grub_bfs_to_cpu32 (sb.bsize)); + data = grub_zalloc (sizeof (struct grub_bfs_data)); if (!data) return grub_errno; data->sb = sb; - grub_memcpy (&data->ino, &ino, grub_bfs_to_cpu32 (sb.bsize)); + grub_memcpy (&data->ino, &ino, sizeof (data->ino)); file->data = data; - file->size = grub_bfs_to_cpu64 (ino.ino.size); + file->size = grub_bfs_to_cpu64 (ino.size); } return GRUB_ERR_NONE; @@ -955,7 +957,8 @@ grub_bfs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_bfs_data *data = file->data; err = read_bfs_file (file->device->disk, &data->sb, - data->ino, file->offset, buf, len, file->read_hook); + &data->ino, file->offset, buf, len, + file->read_hook, file->read_hook_data); if (err) return -1; return len; @@ -981,7 +984,7 @@ grub_bfs_label (grub_device_t device, char **label) static grub_ssize_t read_bfs_attr (grub_disk_t disk, const struct grub_bfs_superblock *sb, - const struct grub_bfs_inode *ino, + struct grub_bfs_inode *ino, const char *name, void *buf, grub_size_t len) { grub_uint8_t *ptr = (grub_uint8_t *) ino->small_data; @@ -1012,32 +1015,27 @@ read_bfs_attr (grub_disk_t disk, if (ino->attr.len != 0) { - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb->bsize)]; - } ino2; grub_size_t read; grub_err_t err; grub_uint64_t res; - err = read_extent (disk, sb, &ino->attr, 0, 0, ino2.raw, + err = read_extent (disk, sb, &ino->attr, 0, 0, ino, grub_bfs_to_cpu32 (sb->bsize)); if (err) return -1; - err = find_in_b_tree (disk, sb, &ino2.ino, name, &res); + err = find_in_b_tree (disk, sb, ino, name, &res); if (err) return -1; grub_disk_read (disk, res << (grub_bfs_to_cpu32 (sb->log2_bsize) - GRUB_DISK_SECTOR_BITS), 0, - grub_bfs_to_cpu32 (sb->bsize), (char *) &ino2); - read = grub_bfs_to_cpu64 (ino2.ino.size); + grub_bfs_to_cpu32 (sb->bsize), (char *) ino); + read = grub_bfs_to_cpu64 (ino->size); if (read > len) read = len; - err = read_bfs_file (disk, sb, &ino2.ino, 0, buf, read, 0); + err = read_bfs_file (disk, sb, ino, 0, buf, read, 0, 0); if (err) return -1; return read; @@ -1050,6 +1048,8 @@ grub_bfs_uuid (grub_device_t device, char **uuid) { struct grub_bfs_superblock sb; grub_err_t err; + struct grub_bfs_inode *ino; + grub_uint64_t vid; *uuid = 0; @@ -1057,23 +1057,24 @@ grub_bfs_uuid (grub_device_t device, char **uuid) if (err) return err; - { - union - { - struct grub_bfs_inode ino; - grub_uint8_t raw[grub_bfs_to_cpu32 (sb.bsize)]; - } ino; - grub_uint64_t vid; + ino = grub_malloc (grub_bfs_to_cpu32 (sb.bsize)); + if (!ino) + return grub_errno; - err = read_extent (device->disk, &sb, &sb.root_dir, 0, 0, - &ino, grub_bfs_to_cpu32 (sb.bsize)); - if (err) + err = read_extent (device->disk, &sb, &sb.root_dir, 0, 0, + ino, grub_bfs_to_cpu32 (sb.bsize)); + if (err) + { + grub_free (ino); return err; - if (read_bfs_attr (device->disk, &sb, &ino.ino, "be:volume_id", - &vid, sizeof (vid)) == sizeof (vid)) - *uuid = - grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid)); - } + } + if (read_bfs_attr (device->disk, &sb, ino, "be:volume_id", + &vid, sizeof (vid)) == sizeof (vid)) + *uuid = + grub_xasprintf ("%016" PRIxGRUB_UINT64_T, grub_bfs_to_cpu64 (vid)); + + grub_free (ino); + return GRUB_ERR_NONE; } #endif @@ -1084,13 +1085,13 @@ static struct grub_fs grub_bfs_fs = { #else .name = "bfs", #endif - .dir = grub_bfs_dir, - .open = grub_bfs_open, - .read = grub_bfs_read, - .close = grub_bfs_close, - .label = grub_bfs_label, + .fs_dir = grub_bfs_dir, + .fs_open = grub_bfs_open, + .fs_read = grub_bfs_read, + .fs_close = grub_bfs_close, + .fs_label = grub_bfs_label, #ifndef MODE_AFS - .uuid = grub_bfs_uuid, + .fs_uuid = grub_bfs_uuid, #endif #ifdef GRUB_UTIL .reserved_first_sector = 1, @@ -1106,7 +1107,11 @@ GRUB_MOD_INIT (bfs) { COMPILE_TIME_ASSERT (1 << LOG_EXTENT_SIZE == sizeof (struct grub_bfs_extent)); - grub_fs_register (&grub_bfs_fs); + if (!grub_is_lockdown ()) + { + grub_bfs_fs.mod = mod; + grub_fs_register (&grub_bfs_fs); + } } #ifdef MODE_AFS @@ -1115,5 +1120,6 @@ GRUB_MOD_FINI (afs) GRUB_MOD_FINI (bfs) #endif { - grub_fs_unregister (&grub_bfs_fs); + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_bfs_fs); } diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index a993f0747..7bf8d922f 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -1,7 +1,7 @@ /* btrfs.c - B-tree file system. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2010 Free Software Foundation, Inc. + * Copyright (C) 2010,2011,2012,2013 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,6 +17,14 @@ * along with GRUB. If not, see . */ +/* + * Tell zstd to expose functions that aren't part of the stable API, which + * aren't safe to use when linking against a dynamic library. We vendor in a + * specific zstd version, so we know what we're getting. We need these unstable + * functions to provide our own allocator, which uses grub_malloc(), to zstd. + */ +#define ZSTD_STATIC_LINKING_ONLY + #include #include #include @@ -27,7 +35,12 @@ #include #include #include +#include #include +#include +#include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -44,6 +57,9 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE (GRUB_BTRFS_LZO_BLOCK_SIZE + \ (GRUB_BTRFS_LZO_BLOCK_SIZE / 16) + 64 + 3) +#define ZSTD_BTRFS_MAX_WINDOWLOG 17 +#define ZSTD_BTRFS_MAX_INPUT (1 << ZSTD_BTRFS_MAX_WINDOWLOG) + typedef grub_uint8_t grub_btrfs_checksum_t[0x20]; typedef grub_uint16_t grub_btrfs_uuid_t[8]; @@ -52,7 +68,7 @@ struct grub_btrfs_device grub_uint64_t device_id; grub_uint64_t size; grub_uint8_t dummy[0x62 - 0x10]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_btrfs_superblock { @@ -70,16 +86,17 @@ struct grub_btrfs_superblock char label[0x100]; grub_uint8_t dummy4[0x100]; grub_uint8_t bootstrap_mapping[0x800]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct btrfs_header { grub_btrfs_checksum_t checksum; grub_btrfs_uuid_t uuid; - grub_uint8_t dummy[0x30]; + grub_uint64_t bytenr; + grub_uint8_t dummy[0x28]; grub_uint32_t nitems; grub_uint8_t level; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_btrfs_device_desc { @@ -106,24 +123,6 @@ struct grub_btrfs_data struct grub_btrfs_extent_data *extent; }; -enum - { - GRUB_BTRFS_ITEM_TYPE_INODE_ITEM = 0x01, - GRUB_BTRFS_ITEM_TYPE_INODE_REF = 0x0c, - GRUB_BTRFS_ITEM_TYPE_DIR_ITEM = 0x54, - GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM = 0x6c, - GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM = 0x84, - GRUB_BTRFS_ITEM_TYPE_DEVICE = 0xd8, - GRUB_BTRFS_ITEM_TYPE_CHUNK = 0xe4 - }; - -struct grub_btrfs_key -{ - grub_uint64_t object_id; - grub_uint8_t type; - grub_uint64_t offset; -} __attribute__ ((packed)); - struct grub_btrfs_chunk_item { grub_uint64_t size; @@ -136,31 +135,35 @@ struct grub_btrfs_chunk_item #define GRUB_BTRFS_CHUNK_TYPE_RAID1 0x10 #define GRUB_BTRFS_CHUNK_TYPE_DUPLICATED 0x20 #define GRUB_BTRFS_CHUNK_TYPE_RAID10 0x40 +#define GRUB_BTRFS_CHUNK_TYPE_RAID5 0x80 +#define GRUB_BTRFS_CHUNK_TYPE_RAID6 0x100 +#define GRUB_BTRFS_CHUNK_TYPE_RAID1C3 0x200 +#define GRUB_BTRFS_CHUNK_TYPE_RAID1C4 0x400 grub_uint8_t dummy2[0xc]; grub_uint16_t nstripes; grub_uint16_t nsubstripes; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_btrfs_chunk_stripe { grub_uint64_t device_id; grub_uint64_t offset; grub_btrfs_uuid_t device_uuid; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_btrfs_leaf_node { struct grub_btrfs_key key; grub_uint32_t offset; grub_uint32_t size; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_btrfs_internal_node { struct grub_btrfs_key key; grub_uint64_t addr; grub_uint64_t dummy; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_btrfs_dir_item { @@ -173,7 +176,7 @@ struct grub_btrfs_dir_item #define GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK 7 grub_uint8_t type; char name[0]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_btrfs_leaf_descriptor { @@ -188,18 +191,11 @@ struct grub_btrfs_leaf_descriptor } *data; }; -struct grub_btrfs_root_item -{ - grub_uint8_t dummy[0xb0]; - grub_uint64_t tree; - grub_uint64_t inode; -}; - struct grub_btrfs_time { grub_int64_t sec; grub_uint32_t nanosec; -} __attribute__ ((aligned (4))); +} GRUB_PACKED; struct grub_btrfs_inode { @@ -207,7 +203,7 @@ struct grub_btrfs_inode grub_uint64_t size; grub_uint8_t dummy2[0x70]; struct grub_btrfs_time mtime; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_btrfs_extent_data { @@ -228,7 +224,7 @@ struct grub_btrfs_extent_data grub_uint64_t filled; }; }; -} __attribute__ ((packed)); +} GRUB_PACKED; #define GRUB_BTRFS_EXTENT_INLINE 0 #define GRUB_BTRFS_EXTENT_REGULAR 1 @@ -236,6 +232,7 @@ struct grub_btrfs_extent_data #define GRUB_BTRFS_COMPRESSION_NONE 0 #define GRUB_BTRFS_COMPRESSION_ZLIB 1 #define GRUB_BTRFS_COMPRESSION_LZO 2 +#define GRUB_BTRFS_COMPRESSION_ZSTD 3 #define GRUB_BTRFS_OBJECT_ID_CHUNK 0x100 @@ -251,11 +248,11 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, static grub_err_t read_sblock (grub_disk_t disk, struct grub_btrfs_superblock *sb) { + struct grub_btrfs_superblock sblock; unsigned i; grub_err_t err = GRUB_ERR_NONE; for (i = 0; i < ARRAY_SIZE (superblock_sectors); i++) { - struct grub_btrfs_superblock sblock; /* Don't try additional superblocks beyond device size. */ if (i && (grub_le_to_cpu64 (sblock.this_device.size) >> GRUB_DISK_SECTOR_BITS) <= superblock_sectors[i]) @@ -308,6 +305,25 @@ free_iterator (struct grub_btrfs_leaf_descriptor *desc) grub_free (desc->data); } +static grub_err_t +check_btrfs_header (struct grub_btrfs_data *data, struct btrfs_header *header, + grub_disk_addr_t addr) +{ + if (grub_le_to_cpu64 (header->bytenr) != addr) + { + grub_dprintf ("btrfs", "btrfs_header.bytenr is not equal node addr\n"); + return grub_error (GRUB_ERR_BAD_FS, + "header bytenr is not equal node addr"); + } + if (grub_memcmp (data->sblock.uuid, header->uuid, sizeof(grub_btrfs_uuid_t))) + { + grub_dprintf ("btrfs", "btrfs_header.uuid doesn't match sblock uuid\n"); + return grub_error (GRUB_ERR_BAD_FS, + "header uuid doesn't match sblock uuid"); + } + return GRUB_ERR_NONE; +} + static grub_err_t save_ref (struct grub_btrfs_leaf_descriptor *desc, grub_disk_addr_t addr, unsigned i, unsigned m, int l) @@ -316,9 +332,13 @@ save_ref (struct grub_btrfs_leaf_descriptor *desc, if (desc->allocated < desc->depth) { void *newdata; - desc->allocated *= 2; - newdata = grub_realloc (desc->data, sizeof (desc->data[0]) - * desc->allocated); + grub_size_t sz; + + if (grub_mul (desc->allocated, 2, &desc->allocated) || + grub_mul (desc->allocated, sizeof (desc->data[0]), &sz)) + return GRUB_ERR_OUT_OF_RANGE; + + newdata = grub_realloc (desc->data, sz); if (!newdata) return grub_errno; desc->data = newdata; @@ -365,6 +385,7 @@ next (struct grub_btrfs_data *data, &head, sizeof (head), 0); if (err) return -err; + check_btrfs_header (data, &head, grub_le_to_cpu64 (node.addr)); save_ref (desc, grub_le_to_cpu64 (node.addr), 0, grub_le_to_cpu32 (head.nitems), !head.level); @@ -399,7 +420,7 @@ lower_bound (struct grub_btrfs_data *data, { desc->allocated = 16; desc->depth = 0; - desc->data = grub_malloc (sizeof (desc->data[0]) * desc->allocated); + desc->data = grub_calloc (desc->allocated, sizeof (desc->data[0])); if (!desc->data) return grub_errno; } @@ -426,6 +447,7 @@ lower_bound (struct grub_btrfs_data *data, recursion_depth + 1); if (err) return err; + check_btrfs_header (data, &head, addr); addr += sizeof (head); if (head.level) { @@ -538,81 +560,301 @@ lower_bound (struct grub_btrfs_data *data, } } -static grub_device_t -find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan) +/* Context for find_device. */ +struct find_device_ctx { - grub_device_t dev_found = NULL; - auto int hook (const char *name); - int hook (const char *name) - { - grub_device_t dev; - grub_err_t err; - struct grub_btrfs_superblock sb; - dev = grub_device_open (name); - if (!dev) + struct grub_btrfs_data *data; + grub_uint64_t id; + grub_device_t dev_found; +}; + +/* Helper for find_device. */ +static int +find_device_iter (const char *name, void *data) +{ + struct find_device_ctx *ctx = data; + grub_device_t dev; + grub_err_t err; + struct grub_btrfs_superblock sb; + + dev = grub_device_open (name); + if (!dev) + return 0; + if (!dev->disk) + { + grub_device_close (dev); return 0; - if (!dev->disk) - { - grub_device_close (dev); - return 0; - } - err = read_sblock (dev->disk, &sb); - if (err == GRUB_ERR_BAD_FS) - { - grub_device_close (dev); - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (err) - { - grub_device_close (dev); - grub_print_error (); - return 0; - } - if (grub_memcmp (data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0 - || sb.this_device.device_id != id) - { - grub_device_close (dev); - return 0; - } + } + err = read_sblock (dev->disk, &sb); + if (err == GRUB_ERR_BAD_FS) + { + grub_device_close (dev); + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (err) + { + grub_device_close (dev); + grub_print_error (); + return 0; + } + if (grub_memcmp (ctx->data->sblock.uuid, sb.uuid, sizeof (sb.uuid)) != 0 + || sb.this_device.device_id != ctx->id) + { + grub_device_close (dev); + return 0; + } - dev_found = dev; - return 1; - } + ctx->dev_found = dev; + return 1; +} +static grub_device_t +find_device (struct grub_btrfs_data *data, grub_uint64_t id) +{ + struct find_device_ctx ctx = { + .data = data, + .id = id, + .dev_found = NULL + }; unsigned i; for (i = 0; i < data->n_devices_attached; i++) if (id == data->devices_attached[i].id) return data->devices_attached[i].dev; - if (do_rescan) - grub_device_iterate (hook); - if (!dev_found) - { - grub_error (GRUB_ERR_BAD_FS, - N_("couldn't find a necessary member device " - "of multi-device filesystem")); - return NULL; - } + + grub_device_iterate (find_device_iter, &ctx); + data->n_devices_attached++; if (data->n_devices_attached > data->n_devices_allocated) { void *tmp; - data->n_devices_allocated = 2 * data->n_devices_attached + 1; - data->devices_attached - = grub_realloc (tmp = data->devices_attached, - data->n_devices_allocated - * sizeof (data->devices_attached[0])); + grub_size_t sz; + + if (grub_mul (data->n_devices_attached, 2, &data->n_devices_allocated) || + grub_add (data->n_devices_allocated, 1, &data->n_devices_allocated) || + grub_mul (data->n_devices_allocated, sizeof (data->devices_attached[0]), &sz)) + goto fail; + + data->devices_attached = grub_realloc (tmp = data->devices_attached, sz); if (!data->devices_attached) { - grub_device_close (dev_found); data->devices_attached = tmp; + + fail: + if (ctx.dev_found) + grub_device_close (ctx.dev_found); return NULL; } } data->devices_attached[data->n_devices_attached - 1].id = id; - data->devices_attached[data->n_devices_attached - 1].dev = dev_found; - return dev_found; + data->devices_attached[data->n_devices_attached - 1].dev = ctx.dev_found; + return ctx.dev_found; +} + +static grub_err_t +btrfs_read_from_chunk (struct grub_btrfs_data *data, + struct grub_btrfs_chunk_item *chunk, + grub_uint64_t stripen, grub_uint64_t stripe_offset, + int redundancy, grub_uint64_t csize, + void *buf) +{ + struct grub_btrfs_chunk_stripe *stripe; + grub_disk_addr_t paddr; + grub_device_t dev; + grub_err_t err; + + stripe = (struct grub_btrfs_chunk_stripe *) (chunk + 1); + /* Right now the redundancy handling is easy. + With RAID5-like it will be more difficult. */ + stripe += stripen + redundancy; + + paddr = grub_le_to_cpu64 (stripe->offset) + stripe_offset; + + grub_dprintf ("btrfs", "stripe %" PRIxGRUB_UINT64_T + " maps to 0x%" PRIxGRUB_UINT64_T "\n" + "reading paddr 0x%" PRIxGRUB_UINT64_T "\n", + stripen, stripe->offset, paddr); + + dev = find_device (data, stripe->device_id); + if (!dev) + { + grub_dprintf ("btrfs", + "couldn't find a necessary member device " + "of multi-device filesystem\n"); + grub_errno = GRUB_ERR_NONE; + return GRUB_ERR_READ_ERROR; + } + + err = grub_disk_read (dev->disk, paddr >> GRUB_DISK_SECTOR_BITS, + paddr & (GRUB_DISK_SECTOR_SIZE - 1), + csize, buf); + return err; +} + +struct raid56_buffer { + void *buf; + int data_is_valid; +}; + +static void +rebuild_raid5 (char *dest, struct raid56_buffer *buffers, + grub_uint64_t nstripes, grub_uint64_t csize) +{ + grub_uint64_t i; + int first; + + for(i = 0; buffers[i].data_is_valid && i < nstripes; i++); + + if (i == nstripes) + { + grub_dprintf ("btrfs", "called rebuild_raid5(), but all disks are OK\n"); + return; + } + + grub_dprintf ("btrfs", "rebuilding RAID 5 stripe #%" PRIuGRUB_UINT64_T "\n", i); + + for (i = 0, first = 1; i < nstripes; i++) + { + if (!buffers[i].data_is_valid) + continue; + + if (first) { + grub_memcpy(dest, buffers[i].buf, csize); + first = 0; + } else + grub_crypto_xor (dest, dest, buffers[i].buf, csize); + } +} + +static grub_err_t +raid6_recover_read_buffer (void *data, int disk_nr, + grub_uint64_t addr __attribute__ ((unused)), + void *dest, grub_size_t size) +{ + struct raid56_buffer *buffers = data; + + if (!buffers[disk_nr].data_is_valid) + return grub_errno = GRUB_ERR_READ_ERROR; + + grub_memcpy(dest, buffers[disk_nr].buf, size); + + return grub_errno = GRUB_ERR_NONE; +} + +static void +rebuild_raid6 (struct raid56_buffer *buffers, grub_uint64_t nstripes, + grub_uint64_t csize, grub_uint64_t parities_pos, void *dest, + grub_uint64_t stripen) + +{ + grub_raid6_recover_gen (buffers, nstripes, stripen, parities_pos, + dest, 0, csize, 0, raid6_recover_read_buffer); +} + +static grub_err_t +raid56_read_retry (struct grub_btrfs_data *data, + struct grub_btrfs_chunk_item *chunk, + grub_uint64_t stripe_offset, grub_uint64_t stripen, + grub_uint64_t csize, void *buf, grub_uint64_t parities_pos) +{ + struct raid56_buffer *buffers; + grub_uint64_t nstripes = grub_le_to_cpu16 (chunk->nstripes); + grub_uint64_t chunk_type = grub_le_to_cpu64 (chunk->type); + grub_err_t ret = GRUB_ERR_OUT_OF_MEMORY; + grub_uint64_t i, failed_devices; + + buffers = grub_calloc (nstripes, sizeof (*buffers)); + if (!buffers) + goto cleanup; + + for (i = 0; i < nstripes; i++) + { + buffers[i].buf = grub_zalloc (csize); + if (!buffers[i].buf) + goto cleanup; + } + + for (failed_devices = 0, i = 0; i < nstripes; i++) + { + struct grub_btrfs_chunk_stripe *stripe; + grub_disk_addr_t paddr; + grub_device_t dev; + grub_err_t err; + + /* + * The struct grub_btrfs_chunk_stripe array lives + * behind struct grub_btrfs_chunk_item. + */ + stripe = (struct grub_btrfs_chunk_stripe *) (chunk + 1) + i; + + paddr = grub_le_to_cpu64 (stripe->offset) + stripe_offset; + grub_dprintf ("btrfs", "reading paddr %" PRIxGRUB_UINT64_T + " from stripe ID %" PRIxGRUB_UINT64_T "\n", + paddr, stripe->device_id); + + dev = find_device (data, stripe->device_id); + if (!dev) + { + grub_dprintf ("btrfs", "stripe %" PRIuGRUB_UINT64_T " FAILED (dev ID %" + PRIxGRUB_UINT64_T ")\n", i, stripe->device_id); + failed_devices++; + continue; + } + + err = grub_disk_read (dev->disk, paddr >> GRUB_DISK_SECTOR_BITS, + paddr & (GRUB_DISK_SECTOR_SIZE - 1), + csize, buffers[i].buf); + if (err == GRUB_ERR_NONE) + { + buffers[i].data_is_valid = 1; + grub_dprintf ("btrfs", "stripe %" PRIuGRUB_UINT64_T " OK (dev ID %" + PRIxGRUB_UINT64_T ")\n", i, stripe->device_id); + } + else + { + grub_dprintf ("btrfs", "stripe %" PRIuGRUB_UINT64_T + " READ FAILED (dev ID %" PRIxGRUB_UINT64_T ")\n", + i, stripe->device_id); + failed_devices++; + } + } + + if (failed_devices > 1 && (chunk_type & GRUB_BTRFS_CHUNK_TYPE_RAID5)) + { + grub_dprintf ("btrfs", "not enough disks for RAID 5: total %" PRIuGRUB_UINT64_T + ", missing %" PRIuGRUB_UINT64_T "\n", + nstripes, failed_devices); + ret = GRUB_ERR_READ_ERROR; + goto cleanup; + } + else if (failed_devices > 2 && (chunk_type & GRUB_BTRFS_CHUNK_TYPE_RAID6)) + { + grub_dprintf ("btrfs", "not enough disks for RAID 6: total %" PRIuGRUB_UINT64_T + ", missing %" PRIuGRUB_UINT64_T "\n", + nstripes, failed_devices); + ret = GRUB_ERR_READ_ERROR; + goto cleanup; + } + else + grub_dprintf ("btrfs", "enough disks for RAID 5: total %" + PRIuGRUB_UINT64_T ", missing %" PRIuGRUB_UINT64_T "\n", + nstripes, failed_devices); + + /* We have enough disks. So, rebuild the data. */ + if (chunk_type & GRUB_BTRFS_CHUNK_TYPE_RAID5) + rebuild_raid5 (buf, buffers, nstripes, csize); + else + rebuild_raid6 (buffers, nstripes, csize, parities_pos, buf, stripen); + + ret = GRUB_ERR_NONE; + cleanup: + if (buffers) + for (i = 0; i < nstripes; i++) + grub_free (buffers[i].buf); + grub_free (buffers); + + return ret; } static grub_err_t @@ -628,7 +870,6 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, grub_err_t err = 0; struct grub_btrfs_key key_out; int challoc = 0; - grub_device_t dev; struct grub_btrfs_key key_in; grub_size_t chsize; grub_disk_addr_t chaddr; @@ -671,6 +912,23 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, return grub_error (GRUB_ERR_BAD_FS, "couldn't find the chunk descriptor"); + if (!chsize) + { + grub_dprintf ("btrfs", "zero-size chunk\n"); + return grub_error (GRUB_ERR_BAD_FS, + "got an invalid zero-size chunk"); + } + + /* + * The space being allocated for a chunk should at least be able to + * contain one chunk item. + */ + if (chsize < sizeof (struct grub_btrfs_chunk_item)) + { + grub_dprintf ("btrfs", "chunk-size too small\n"); + return grub_error (GRUB_ERR_BAD_FS, + "got an invalid chunk size"); + } chunk = grub_malloc (chsize); if (!chunk) return grub_errno; @@ -689,8 +947,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, grub_uint64_t stripen; grub_uint64_t stripe_offset; grub_uint64_t off = addr - grub_le_to_cpu64 (key->offset); + grub_uint64_t chunk_stripe_length; + grub_uint16_t nstripes; unsigned redundancy = 1; unsigned i, j; + int is_raid56; + grub_uint64_t parities_pos = 0; + + is_raid56 = !!(grub_le_to_cpu64 (chunk->type) & + (GRUB_BTRFS_CHUNK_TYPE_RAID5 | + GRUB_BTRFS_CHUNK_TYPE_RAID6)); if (grub_le_to_cpu64 (chunk->size) <= off) { @@ -699,15 +965,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, "couldn't find the chunk descriptor"); } + nstripes = grub_le_to_cpu16 (chunk->nstripes) ? : 1; + chunk_stripe_length = grub_le_to_cpu64 (chunk->stripe_length) ? : 512; grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T "+0x%" PRIxGRUB_UINT64_T " (%d stripes (%d substripes) of %" PRIxGRUB_UINT64_T ")\n", grub_le_to_cpu64 (key->offset), grub_le_to_cpu64 (chunk->size), - grub_le_to_cpu16 (chunk->nstripes), + nstripes, grub_le_to_cpu16 (chunk->nsubstripes), - grub_le_to_cpu64 (chunk->stripe_length)); + chunk_stripe_length); switch (grub_le_to_cpu64 (chunk->type) & ~GRUB_BTRFS_CHUNK_TYPE_BITS_DONTCARE) @@ -717,20 +985,50 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, grub_uint64_t stripe_length; grub_dprintf ("btrfs", "single\n"); stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size), - grub_le_to_cpu16 (chunk->nstripes), + nstripes, NULL); + + /* For single, there should be exactly 1 stripe. */ + if (grub_le_to_cpu16 (chunk->nstripes) != 1) + { + grub_dprintf ("btrfs", "invalid RAID_SINGLE: nstripes != 1 (%u)\n", + grub_le_to_cpu16 (chunk->nstripes)); + return grub_error (GRUB_ERR_BAD_FS, + "invalid RAID_SINGLE: nstripes != 1 (%u)", + grub_le_to_cpu16 (chunk->nstripes)); + } + if (stripe_length == 0) + stripe_length = 512; stripen = grub_divmod64 (off, stripe_length, &stripe_offset); csize = (stripen + 1) * stripe_length - off; break; } + case GRUB_BTRFS_CHUNK_TYPE_RAID1C4: + redundancy++; + /* fall through */ + case GRUB_BTRFS_CHUNK_TYPE_RAID1C3: + redundancy++; + /* fall through */ case GRUB_BTRFS_CHUNK_TYPE_DUPLICATED: case GRUB_BTRFS_CHUNK_TYPE_RAID1: { - grub_dprintf ("btrfs", "RAID1\n"); + grub_dprintf ("btrfs", "RAID1 (copies: %d)\n", ++redundancy); stripen = 0; stripe_offset = off; csize = grub_le_to_cpu64 (chunk->size) - off; - redundancy = 2; + + /* + * Redundancy, and substripes only apply to RAID10, and there + * should be exactly 2 sub-stripes. + */ + if (grub_le_to_cpu16 (chunk->nstripes) != redundancy) + { + grub_dprintf ("btrfs", "invalid RAID1: nstripes != %u (%u)\n", + redundancy, grub_le_to_cpu16 (chunk->nstripes)); + return grub_error (GRUB_ERR_BAD_FS, + "invalid RAID1: nstripes != %u (%u)", + redundancy, grub_le_to_cpu16 (chunk->nstripes)); + } break; } case GRUB_BTRFS_CHUNK_TYPE_RAID0: @@ -739,33 +1037,131 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, grub_uint64_t low; grub_dprintf ("btrfs", "RAID0\n"); middle = grub_divmod64 (off, - grub_le_to_cpu64 (chunk->stripe_length), + chunk_stripe_length, &low); - high = grub_divmod64 (middle, grub_le_to_cpu16 (chunk->nstripes), + high = grub_divmod64 (middle, nstripes, &stripen); stripe_offset = - low + grub_le_to_cpu64 (chunk->stripe_length) * high; - csize = grub_le_to_cpu64 (chunk->stripe_length) - low; + low + chunk_stripe_length * high; + csize = chunk_stripe_length - low; break; } case GRUB_BTRFS_CHUNK_TYPE_RAID10: { grub_uint64_t middle, high; grub_uint64_t low; + grub_uint16_t nsubstripes; + nsubstripes = grub_le_to_cpu16 (chunk->nsubstripes) ? : 1; middle = grub_divmod64 (off, - grub_le_to_cpu64 (chunk->stripe_length), + chunk_stripe_length, &low); high = grub_divmod64 (middle, - grub_le_to_cpu16 (chunk->nstripes) - / grub_le_to_cpu16 (chunk->nsubstripes), + nstripes / nsubstripes ? : 1, &stripen); - stripen *= grub_le_to_cpu16 (chunk->nsubstripes); - redundancy = grub_le_to_cpu16 (chunk->nsubstripes); - stripe_offset = low + grub_le_to_cpu64 (chunk->stripe_length) + stripen *= nsubstripes; + redundancy = nsubstripes; + stripe_offset = low + chunk_stripe_length * high; - csize = grub_le_to_cpu64 (chunk->stripe_length) - low; + csize = chunk_stripe_length - low; + + /* + * Substripes only apply to RAID10, and there + * should be exactly 2 sub-stripes. + */ + if (grub_le_to_cpu16 (chunk->nsubstripes) != 2) + { + grub_dprintf ("btrfs", "invalid RAID10: nsubstripes != 2 (%u)", + grub_le_to_cpu16 (chunk->nsubstripes)); + return grub_error (GRUB_ERR_BAD_FS, + "invalid RAID10: nsubstripes != 2 (%u)", + grub_le_to_cpu16 (chunk->nsubstripes)); + } + + break; + } + case GRUB_BTRFS_CHUNK_TYPE_RAID5: + case GRUB_BTRFS_CHUNK_TYPE_RAID6: + { + grub_uint64_t nparities, stripe_nr, high, low; + + redundancy = 1; /* no redundancy for now */ + + if (grub_le_to_cpu64 (chunk->type) & GRUB_BTRFS_CHUNK_TYPE_RAID5) + { + grub_dprintf ("btrfs", "RAID5\n"); + nparities = 1; + } + else + { + grub_dprintf ("btrfs", "RAID6\n"); + nparities = 2; + } + + /* + * RAID 6 layout consists of several stripes spread over + * the disks, e.g.: + * + * Disk_0 Disk_1 Disk_2 Disk_3 + * A0 B0 P0 Q0 + * Q1 A1 B1 P1 + * P2 Q2 A2 B2 + * + * Note: placement of the parities depend on row number. + * + * Pay attention that the btrfs terminology may differ from + * terminology used in other RAID implementations, e.g. LVM, + * dm or md. The main difference is that btrfs calls contiguous + * block of data on a given disk, e.g. A0, stripe instead of chunk. + * + * The variables listed below have following meaning: + * - stripe_nr is the stripe number excluding the parities + * (A0 = 0, B0 = 1, A1 = 2, B1 = 3, etc.), + * - high is the row number (0 for A0...Q0, 1 for Q1...P1, etc.), + * - stripen is the disk number in a row (0 for A0, Q1, P2, + * 1 for B0, A1, Q2, etc.), + * - off is the logical address to read, + * - chunk_stripe_length is the size of a stripe (typically 64 KiB), + * - nstripes is the number of disks in a row, + * - low is the offset of the data inside a stripe, + * - stripe_offset is the data offset in an array, + * - csize is the "potential" data to read; it will be reduced + * to size if the latter is smaller, + * - nparities is the number of parities (1 for RAID 5, 2 for + * RAID 6); used only in RAID 5/6 code. + */ + stripe_nr = grub_divmod64 (off, chunk_stripe_length, &low); + + /* + * stripen is computed without the parities + * (0 for A0, A1, A2, 1 for B0, B1, B2, etc.). + */ + if (nparities >= nstripes) + return grub_error (GRUB_ERR_BAD_FS, + "invalid RAID5/6: nparities >= nstripes"); + high = grub_divmod64 (stripe_nr, nstripes - nparities, &stripen); + + /* + * The stripes are spread over the disks. Every each row their + * positions are shifted by 1 place. So, the real disks number + * change. Hence, we have to take into account current row number + * modulo nstripes (0 for A0, 1 for A1, 2 for A2, etc.). + */ + grub_divmod64 (high + stripen, nstripes, &stripen); + + /* + * parities_pos is equal to ((high - nparities) % nstripes) + * (see the diagram above). However, (high - nparities) can + * be negative, e.g. when high == 0, leading to an incorrect + * results. (high + nstripes - nparities) is always positive and + * modulo nstripes is equal to ((high - nparities) % nstripes). + */ + grub_divmod64 (high + nstripes - nparities, nstripes, &parities_pos); + + stripe_offset = chunk_stripe_length * high + low; + csize = chunk_stripe_length - low; + break; } default: @@ -780,51 +1176,68 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr, if (csize > (grub_uint64_t) size) csize = size; + /* + * The space for a chunk stripe is limited to the space provide in the super-block's + * bootstrap mapping with an initial btrfs key at the start of each chunk. + */ + grub_size_t avail_stripes = sizeof (data->sblock.bootstrap_mapping) / + (sizeof (struct grub_btrfs_key) + sizeof (struct grub_btrfs_chunk_stripe)); + for (j = 0; j < 2; j++) { - for (i = 0; i < redundancy; i++) + grub_size_t est_chunk_alloc = 0; + + grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T + "+0x%" PRIxGRUB_UINT64_T + " (%d stripes (%d substripes) of %" + PRIxGRUB_UINT64_T ")\n", + grub_le_to_cpu64 (key->offset), + grub_le_to_cpu64 (chunk->size), + grub_le_to_cpu16 (chunk->nstripes), + grub_le_to_cpu16 (chunk->nsubstripes), + grub_le_to_cpu64 (chunk->stripe_length)); + grub_dprintf ("btrfs", "reading laddr 0x%" PRIxGRUB_UINT64_T "\n", + addr); + + if (grub_mul (sizeof (struct grub_btrfs_chunk_stripe), + grub_le_to_cpu16 (chunk->nstripes), &est_chunk_alloc) || + grub_add (est_chunk_alloc, + sizeof (struct grub_btrfs_chunk_item), &est_chunk_alloc) || + est_chunk_alloc > chunk->size) { - struct grub_btrfs_chunk_stripe *stripe; - grub_disk_addr_t paddr; - - stripe = (struct grub_btrfs_chunk_stripe *) (chunk + 1); - /* Right now the redundancy handling is easy. - With RAID5-like it will be more difficult. */ - stripe += stripen + i; - - paddr = grub_le_to_cpu64 (stripe->offset) + stripe_offset; - - grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T - "+0x%" PRIxGRUB_UINT64_T - " (%d stripes (%d substripes) of %" - PRIxGRUB_UINT64_T ") stripe %" PRIxGRUB_UINT64_T - " maps to 0x%" PRIxGRUB_UINT64_T "\n", - grub_le_to_cpu64 (key->offset), - grub_le_to_cpu64 (chunk->size), - grub_le_to_cpu16 (chunk->nstripes), - grub_le_to_cpu16 (chunk->nsubstripes), - grub_le_to_cpu64 (chunk->stripe_length), - stripen, stripe->offset); - grub_dprintf ("btrfs", "reading paddr 0x%" PRIxGRUB_UINT64_T - " for laddr 0x%" PRIxGRUB_UINT64_T "\n", paddr, - addr); - - dev = find_device (data, stripe->device_id, j); - if (!dev) - { - err = grub_errno; - grub_errno = GRUB_ERR_NONE; - continue; - } - - err = grub_disk_read (dev->disk, paddr >> GRUB_DISK_SECTOR_BITS, - paddr & (GRUB_DISK_SECTOR_SIZE - 1), - csize, buf); - if (!err) - break; - grub_errno = GRUB_ERR_NONE; + err = GRUB_ERR_BAD_FS; + break; } - if (i != redundancy) + + if (grub_le_to_cpu16 (chunk->nstripes) > avail_stripes) + { + err = GRUB_ERR_BAD_FS; + break; + } + + if (is_raid56) + { + err = btrfs_read_from_chunk (data, chunk, stripen, + stripe_offset, + 0, /* no mirror */ + csize, buf); + grub_errno = GRUB_ERR_NONE; + if (err) + err = raid56_read_retry (data, chunk, stripe_offset, + stripen, csize, buf, parities_pos); + } + else + for (i = 0; i < redundancy; i++) + { + err = btrfs_read_from_chunk (data, chunk, stripen, + stripe_offset, + i, /* redundancy */ + csize, buf); + if (!err) + break; + grub_errno = GRUB_ERR_NONE; + } + if (!err) break; } if (err) @@ -863,8 +1276,8 @@ grub_btrfs_mount (grub_device_t dev) } data->n_devices_allocated = 16; - data->devices_attached = grub_malloc (sizeof (data->devices_attached[0]) - * data->n_devices_allocated); + data->devices_attached = grub_calloc (data->n_devices_allocated, + sizeof (data->devices_attached[0])); if (!data->devices_attached) { grub_free (data); @@ -883,7 +1296,8 @@ grub_btrfs_unmount (struct grub_btrfs_data *data) unsigned i; /* The device 0 is closed one layer upper. */ for (i = 1; i < data->n_devices_attached; i++) - grub_device_close (data->devices_attached[i].dev); + if (data->devices_attached[i].dev) + grub_device_close (data->devices_attached[i].dev); grub_free (data->devices_attached); grub_free (data->extent); grub_free (data); @@ -914,13 +1328,102 @@ grub_btrfs_read_inode (struct grub_btrfs_data *data, return grub_btrfs_read_logical (data, elemaddr, inode, sizeof (*inode), 0); } +static void *grub_zstd_malloc (void *state __attribute__((unused)), size_t size) +{ + return grub_malloc (size); +} + +static void grub_zstd_free (void *state __attribute__((unused)), void *address) +{ + return grub_free (address); +} + +static ZSTD_customMem grub_zstd_allocator (void) +{ + ZSTD_customMem allocator; + + allocator.customAlloc = &grub_zstd_malloc; + allocator.customFree = &grub_zstd_free; + allocator.opaque = NULL; + + return allocator; +} + +static grub_ssize_t +grub_btrfs_zstd_decompress (char *ibuf, grub_size_t isize, grub_off_t off, + char *obuf, grub_size_t osize) +{ + void *allocated = NULL; + char *otmpbuf = obuf; + grub_size_t otmpsize = osize; + ZSTD_DCtx *dctx = NULL; + grub_size_t zstd_ret; + grub_ssize_t ret = -1; + + /* + * Zstd will fail if it can't fit the entire output in the destination + * buffer, so if osize isn't large enough, allocate a temporary buffer. + */ + if (otmpsize < ZSTD_BTRFS_MAX_INPUT) + { + allocated = grub_malloc (ZSTD_BTRFS_MAX_INPUT); + if (!allocated) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed allocate a zstd buffer"); + goto err; + } + otmpbuf = (char *) allocated; + otmpsize = ZSTD_BTRFS_MAX_INPUT; + } + + /* Create the ZSTD_DCtx. */ + dctx = ZSTD_createDCtx_advanced (grub_zstd_allocator ()); + if (!dctx) + { + /* ZSTD_createDCtx_advanced() only fails if it is out of memory. */ + grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to create a zstd context"); + goto err; + } + + /* + * Get the real input size, there may be junk at the + * end of the frame. + */ + isize = ZSTD_findFrameCompressedSize (ibuf, isize); + if (ZSTD_isError (isize)) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "zstd data corrupted"); + goto err; + } + + /* Decompress and check for errors. */ + zstd_ret = ZSTD_decompressDCtx (dctx, otmpbuf, otmpsize, ibuf, isize); + if (ZSTD_isError (zstd_ret)) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "zstd data corrupted"); + goto err; + } + + /* + * Move the requested data into the obuf. obuf may be equal + * to otmpbuf, which is why grub_memmove() is required. + */ + grub_memmove (obuf, otmpbuf + off, osize); + ret = osize; + +err: + grub_free (allocated); + ZSTD_freeDCtx (dctx); + + return ret; +} + static grub_ssize_t grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off, char *obuf, grub_size_t osize) { grub_uint32_t total_size, cblock_size; grub_size_t ret = 0; - unsigned char buf[GRUB_BTRFS_LZO_BLOCK_SIZE]; char *ibuf0 = ibuf; total_size = grub_le_to_cpu32 (grub_get_unaligned32 (ibuf)); @@ -964,13 +1467,21 @@ grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off, if (off > 0 || osize < GRUB_BTRFS_LZO_BLOCK_SIZE) { grub_size_t to_copy = GRUB_BTRFS_LZO_BLOCK_SIZE - off; + grub_uint8_t *buf; if (to_copy > osize) to_copy = osize; + buf = grub_malloc (GRUB_BTRFS_LZO_BLOCK_SIZE); + if (!buf) + return -1; + if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, buf, &usize, NULL) != LZO_E_OK) - return -1; + { + grub_free (buf); + return -1; + } if (to_copy > usize) to_copy = usize; @@ -981,6 +1492,8 @@ grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off, obuf += to_copy; ibuf += cblock_size; off = 0; + + grub_free (buf); continue; } @@ -1009,6 +1522,8 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, grub_size_t csize; grub_err_t err; grub_off_t extoff; + struct grub_btrfs_leaf_descriptor desc; + if (!data->extent || data->extstart > pos || data->extino != ino || data->exttree != tree || data->extend <= pos) { @@ -1021,9 +1536,12 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, key_in.type = GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM; key_in.offset = grub_cpu_to_le64 (pos); err = lower_bound (data, &key_in, &key_out, tree, - &elemaddr, &elemsize, NULL, 0); + &elemaddr, &elemsize, &desc, 0); if (err) - return -1; + { + grub_free (desc.data); + return -1; + } if (key_out.object_id != ino || key_out.type != GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM) { @@ -1051,7 +1569,7 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, data->extend = data->extstart + grub_le_to_cpu64 (data->extent->size); if (data->extent->type == GRUB_BTRFS_EXTENT_REGULAR - && (char *) &data->extent + elemsize + && (char *) data->extent + elemsize >= (char *) &data->extent->filled + sizeof (data->extent->filled)) data->extend = data->extstart + grub_le_to_cpu64 (data->extent->filled); @@ -1060,10 +1578,40 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, PRIxGRUB_UINT64_T "\n", grub_le_to_cpu64 (key_out.offset), grub_le_to_cpu64 (data->extent->size)); + /* + * The way of extent item iteration is pretty bad, it completely + * requires all extents are contiguous, which is not ensured. + * + * Features like NO_HOLE and mixed inline/regular extents can cause + * gaps between file extent items. + * + * The correct way is to follow Linux kernel/U-boot to iterate item + * by item, without any assumption on the file offset continuity. + * + * Here we just manually skip to next item and re-do the verification. + * + * TODO: Rework the whole extent item iteration code, if not the + * whole btrfs implementation. + */ if (data->extend <= pos) { - grub_error (GRUB_ERR_BAD_FS, "extent not found"); - return -1; + err = next (data, &desc, &elemaddr, &elemsize, &key_out); + if (err < 0) + return -1; + /* No next item for the inode, we hit the end. */ + if (err == 0 || key_out.object_id != ino || + key_out.type != GRUB_BTRFS_ITEM_TYPE_EXTENT_ITEM) + return pos - pos0; + + csize = grub_le_to_cpu64 (key_out.offset) - pos; + if (csize > len) + csize = len; + + grub_memset (buf, 0, csize); + buf += csize; + pos += csize; + len -= csize; + continue; } } csize = data->extend - pos; @@ -1080,7 +1628,8 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, if (data->extent->compression != GRUB_BTRFS_COMPRESSION_NONE && data->extent->compression != GRUB_BTRFS_COMPRESSION_ZLIB - && data->extent->compression != GRUB_BTRFS_COMPRESSION_LZO) + && data->extent->compression != GRUB_BTRFS_COMPRESSION_LZO + && data->extent->compression != GRUB_BTRFS_COMPRESSION_ZSTD) { grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "compression type 0x%x not supported", @@ -1104,7 +1653,12 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, - (grub_uint8_t *) data->extent), extoff, buf, csize) != (grub_ssize_t) csize) - return -1; + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "premature end of compressed"); + return -1; + } } else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_LZO) { @@ -1115,6 +1669,15 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, != (grub_ssize_t) csize) return -1; } + else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZSTD) + { + if (grub_btrfs_zstd_decompress (data->extent->inl, data->extsize - + ((grub_uint8_t *) data->extent->inl + - (grub_uint8_t *) data->extent), + extoff, buf, csize) + != (grub_ssize_t) csize) + return -1; + } else grub_memcpy (buf, data->extent->inl + extoff, csize); break; @@ -1152,13 +1715,22 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, ret = grub_btrfs_lzo_decompress (tmp, zsize, extoff + grub_le_to_cpu64 (data->extent->offset), buf, csize); + else if (data->extent->compression == GRUB_BTRFS_COMPRESSION_ZSTD) + ret = grub_btrfs_zstd_decompress (tmp, zsize, extoff + + grub_le_to_cpu64 (data->extent->offset), + buf, csize); else ret = -1; grub_free (tmp); if (ret != (grub_ssize_t) csize) - return -1; + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "premature end of compressed"); + return -1; + } break; } @@ -1181,6 +1753,40 @@ grub_btrfs_extent_read (struct grub_btrfs_data *data, return pos - pos0; } +static grub_err_t +get_root (struct grub_btrfs_data *data, struct grub_btrfs_key *key, + grub_uint64_t *tree, grub_uint8_t *type) +{ + grub_err_t err; + grub_disk_addr_t elemaddr; + grub_size_t elemsize; + struct grub_btrfs_key key_out, key_in; + struct grub_btrfs_root_item ri; + + key_in.object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_ROOT_VOL_OBJECTID); + key_in.offset = 0; + key_in.type = GRUB_BTRFS_ITEM_TYPE_ROOT_ITEM; + err = lower_bound (data, &key_in, &key_out, + data->sblock.root_tree, + &elemaddr, &elemsize, NULL, 0); + if (err) + return err; + if (key_in.object_id != key_out.object_id + || key_in.type != key_out.type + || key_in.offset != key_out.offset) + return grub_error (GRUB_ERR_BAD_FS, "no root"); + err = grub_btrfs_read_logical (data, elemaddr, &ri, + sizeof (ri), 0); + if (err) + return err; + key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; + key->offset = 0; + key->object_id = grub_cpu_to_le64_compile_time (GRUB_BTRFS_OBJECT_ID_CHUNK); + *tree = ri.tree; + *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; + return GRUB_ERR_NONE; +} + static grub_err_t find_path (struct grub_btrfs_data *data, const char *path, struct grub_btrfs_key *key, @@ -1193,42 +1799,32 @@ find_path (struct grub_btrfs_data *data, grub_size_t allocated = 0; struct grub_btrfs_dir_item *direl = NULL; struct grub_btrfs_key key_out; - int skip_default; const char *ctoken; grub_size_t ctokenlen; char *path_alloc = NULL; char *origpath = NULL; unsigned symlinks_max = 32; + grub_size_t sz; + + err = get_root (data, key, tree, type); + if (err) + return err; - *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; - *tree = data->sblock.root_tree; - key->object_id = data->sblock.root_dir_objectid; - key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; - key->offset = 0; - skip_default = 1; origpath = grub_strdup (path); if (!origpath) return grub_errno; while (1) { - if (!skip_default) - { - while (path[0] == '/') - path++; - if (!path[0]) - break; - slash = grub_strchr (path, '/'); - if (!slash) - slash = path + grub_strlen (path); - ctoken = path; - ctokenlen = slash - path; - } - else - { - ctoken = "default"; - ctokenlen = sizeof ("default") - 1; - } + while (path[0] == '/') + path++; + if (!path[0]) + break; + slash = grub_strchr (path, '/'); + if (!slash) + slash = path + grub_strlen (path); + ctoken = path; + ctokenlen = slash - path; if (*type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) { @@ -1239,10 +1835,8 @@ find_path (struct grub_btrfs_data *data, if (ctokenlen == 1 && ctoken[0] == '.') { - if (!skip_default) - path = slash; - skip_default = 0; - continue; + path = slash; + continue; } if (ctokenlen == 2 && ctoken[0] == '.' && ctoken[1] == '.') { @@ -1272,9 +1866,7 @@ find_path (struct grub_btrfs_data *data, *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; key->object_id = key_out.offset; - if (!skip_default) - path = slash; - skip_default = 0; + path = slash; continue; } @@ -1303,9 +1895,15 @@ find_path (struct grub_btrfs_data *data, struct grub_btrfs_dir_item *cdirel; if (elemsize > allocated) { - allocated = 2 * elemsize; + if (grub_mul (2, elemsize, &allocated) || + grub_add (allocated, 1, &sz)) + { + grub_free (path_alloc); + grub_free (origpath); + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory item size overflow")); + } grub_free (direl); - direl = grub_malloc (allocated + 1); + direl = grub_malloc (sz); if (!direl) { grub_free (path_alloc); @@ -1344,9 +1942,7 @@ find_path (struct grub_btrfs_data *data, return err; } - if (!skip_default) - path = slash; - skip_default = 0; + path = slash; if (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_SYMLINK) { struct grub_btrfs_inode inode; @@ -1369,8 +1965,16 @@ find_path (struct grub_btrfs_data *data, grub_free (origpath); return err; } - tmp = grub_malloc (grub_le_to_cpu64 (inode.size) - + grub_strlen (path) + 1); + + if (grub_add (grub_le_to_cpu64 (inode.size), grub_strlen (path), &sz) || + grub_add (sz, 1, &sz)) + { + grub_free (direl); + grub_free (path_alloc); + grub_free (origpath); + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("buffer size overflow")); + } + tmp = grub_malloc (sz); if (!tmp) { grub_free (direl); @@ -1396,12 +2000,14 @@ find_path (struct grub_btrfs_data *data, path = path_alloc = tmp; if (path[0] == '/') { - *type = GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY; - *tree = data->sblock.root_tree; - key->object_id = data->sblock.root_dir_objectid; - key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; - key->offset = 0; - skip_default = 1; + err = get_root (data, key, tree, type); + if (err) + { + grub_free (direl); + grub_free (path_alloc); + grub_free (origpath); + return err; + } } continue; } @@ -1476,8 +2082,7 @@ find_path (struct grub_btrfs_data *data, static grub_err_t grub_btrfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { struct grub_btrfs_data *data = grub_btrfs_mount (device); struct grub_btrfs_key key_in, key_out; @@ -1490,6 +2095,8 @@ grub_btrfs_dir (grub_device_t device, const char *path, int r = 0; grub_uint64_t tree; grub_uint8_t type; + grub_size_t est_size = 0; + grub_size_t sz; if (!data) return grub_errno; @@ -1511,6 +2118,7 @@ grub_btrfs_dir (grub_device_t device, const char *path, if (err) { grub_btrfs_unmount (data); + grub_free (desc.data); return err; } if (key_out.type != GRUB_BTRFS_ITEM_TYPE_DIR_ITEM @@ -1531,9 +2139,15 @@ grub_btrfs_dir (grub_device_t device, const char *path, } if (elemsize > allocated) { - allocated = 2 * elemsize; + if (grub_mul (2, elemsize, &allocated) || + grub_add (allocated, 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory element size overflow")); + r = -grub_errno; + break; + } grub_free (direl); - direl = grub_malloc (allocated + 1); + direl = grub_malloc (sz); if (!direl) { r = -grub_errno; @@ -1548,6 +2162,18 @@ grub_btrfs_dir (grub_device_t device, const char *path, break; } + if (direl == NULL || + grub_add (grub_le_to_cpu16 (direl->n), + grub_le_to_cpu16 (direl->m), &est_size) || + grub_add (est_size, sizeof (*direl), &est_size) || + grub_sub (est_size, sizeof (direl->name), &est_size) || + est_size > allocated) + { + grub_errno = GRUB_ERR_OUT_OF_RANGE; + r = -grub_errno; + goto out; + } + for (cdirel = direl; (grub_uint8_t *) cdirel - (grub_uint8_t *) direl < (grub_ssize_t) elemsize; @@ -1558,6 +2184,19 @@ grub_btrfs_dir (grub_device_t device, const char *path, char c; struct grub_btrfs_inode inode; struct grub_dirhook_info info; + + if (cdirel == NULL || + grub_add (grub_le_to_cpu16 (cdirel->n), + grub_le_to_cpu16 (cdirel->m), &est_size) || + grub_add (est_size, sizeof (*cdirel), &est_size) || + grub_sub (est_size, sizeof (cdirel->name), &est_size) || + est_size > allocated) + { + grub_errno = GRUB_ERR_OUT_OF_RANGE; + r = -grub_errno; + goto out; + } + err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id, tree); grub_memset (&info, 0, sizeof (info)); @@ -1571,7 +2210,7 @@ grub_btrfs_dir (grub_device_t device, const char *path, c = cdirel->name[grub_le_to_cpu16 (cdirel->n)]; cdirel->name[grub_le_to_cpu16 (cdirel->n)] = 0; info.dir = (cdirel->type == GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY); - if (hook (cdirel->name, &info)) + if (hook (cdirel->name, &info, hook_data)) goto out; cdirel->name[grub_le_to_cpu16 (cdirel->n)] = c; } @@ -1688,6 +2327,33 @@ grub_btrfs_label (grub_device_t device, char **label) } #ifdef GRUB_UTIL + +struct embed_region { + unsigned int start; + unsigned int secs; +}; + +/* + * https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT + * The first 1 MiB on each device is unused with the exception of primary + * superblock that is on the offset 64 KiB and spans 4 KiB. + */ + +static const struct { + struct embed_region available; + struct embed_region used[6]; +} btrfs_head = { + .available = {0, GRUB_DISK_KiB_TO_SECTORS (1024)}, /* The first 1 MiB. */ + .used = { + {0, 1}, /* boot.S. */ + {GRUB_DISK_KiB_TO_SECTORS (64) - 1, 1}, /* Overflow guard. */ + {GRUB_DISK_KiB_TO_SECTORS (64), GRUB_DISK_KiB_TO_SECTORS (4)}, /* 4 KiB superblock. */ + {GRUB_DISK_KiB_TO_SECTORS (68), 1}, /* Overflow guard. */ + {GRUB_DISK_KiB_TO_SECTORS (1024) - 1, 1}, /* Overflow guard. */ + {0, 0} /* Array terminator. */ + } +}; + static grub_err_t grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), unsigned int *nsectors, @@ -1695,25 +2361,62 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), grub_embed_type_t embed_type, grub_disk_addr_t **sectors) { - unsigned i; + unsigned int i, j, n = 0; + const struct embed_region *u; + grub_disk_addr_t *map; if (embed_type != GRUB_EMBED_PCBIOS) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "BtrFS currently supports only PC-BIOS embedding"); - if (64 * 2 - 1 < *nsectors) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - N_("your core.img is unusually large. " - "It won't fit in the embedding area")); - - *nsectors = 64 * 2 - 1; - if (*nsectors > max_nsectors) - *nsectors = max_nsectors; - *sectors = grub_malloc (*nsectors * sizeof (**sectors)); - if (!*sectors) + map = grub_calloc (btrfs_head.available.secs, sizeof (*map)); + if (map == NULL) return grub_errno; - for (i = 0; i < *nsectors; i++) - (*sectors)[i] = i + 1; + + /* + * Populating the map array so that it can be used to index if a disk + * address is available to embed: + * - 0: available, + * - 1: unavailable. + */ + for (u = btrfs_head.used; u->secs; ++u) + { + unsigned int end = u->start + u->secs; + + if (end > btrfs_head.available.secs) + end = btrfs_head.available.secs; + for (i = u->start; i < end; ++i) + map[i] = 1; + } + + /* Adding up n until it matches total size of available embedding area. */ + for (i = 0; i < btrfs_head.available.secs; ++i) + if (map[i] == 0) + n++; + + if (n < *nsectors) + { + grub_free (map); + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("your core.img is unusually large. " + "It won't fit in the embedding area")); + } + + if (n > max_nsectors) + n = max_nsectors; + + /* + * Populating the array so that it can used to index disk block address for + * an image file's offset to be embedded on disk (the unit is in sectors): + * - i: The disk block address relative to btrfs_head.available.start, + * - j: The offset in image file. + */ + for (i = 0, j = 0; i < btrfs_head.available.secs && j < n; ++i) + if (map[i] == 0) + map[j++] = btrfs_head.available.start + i; + + *nsectors = n; + *sectors = map; return GRUB_ERR_NONE; } @@ -1721,14 +2424,14 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), static struct grub_fs grub_btrfs_fs = { .name = "btrfs", - .dir = grub_btrfs_dir, - .open = grub_btrfs_open, - .read = grub_btrfs_read, - .close = grub_btrfs_close, - .uuid = grub_btrfs_uuid, - .label = grub_btrfs_label, + .fs_dir = grub_btrfs_dir, + .fs_open = grub_btrfs_open, + .fs_read = grub_btrfs_read, + .fs_close = grub_btrfs_close, + .fs_uuid = grub_btrfs_uuid, + .fs_label = grub_btrfs_label, #ifdef GRUB_UTIL - .embed = grub_btrfs_embed, + .fs_embed = grub_btrfs_embed, .reserved_first_sector = 1, .blocklist_install = 0, #endif @@ -1736,6 +2439,7 @@ static struct grub_fs grub_btrfs_fs = { GRUB_MOD_INIT (btrfs) { + grub_btrfs_fs.mod = mod; grub_fs_register (&grub_btrfs_fs); } diff --git a/grub-core/fs/cbfs.c b/grub-core/fs/cbfs.c new file mode 100644 index 000000000..b62c8777c --- /dev/null +++ b/grub-core/fs/cbfs.c @@ -0,0 +1,408 @@ +/* cbfs.c - cbfs and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + + +struct grub_archelp_data +{ + grub_disk_t disk; + grub_off_t hofs, next_hofs; + grub_off_t dofs; + grub_off_t size; + grub_off_t cbfs_start; + grub_off_t cbfs_end; + grub_off_t cbfs_align; +}; + +static grub_err_t +grub_cbfs_find_file (struct grub_archelp_data *data, char **name, + grub_int32_t *mtime, + grub_uint32_t *mode) +{ + grub_size_t offset; + for (;; + data->dofs = data->hofs + offset, + data->next_hofs = ALIGN_UP (data->dofs + data->size, data->cbfs_align)) + { + struct cbfs_file hd; + grub_size_t namesize; + + data->hofs = data->next_hofs; + + if (data->hofs >= data->cbfs_end) + { + *mode = GRUB_ARCHELP_ATTR_END; + return GRUB_ERR_NONE; + } + + if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) + return grub_errno; + + if (grub_memcmp (hd.magic, CBFS_FILE_MAGIC, sizeof (hd.magic)) != 0) + { + *mode = GRUB_ARCHELP_ATTR_END; + return GRUB_ERR_NONE; + } + data->size = grub_be_to_cpu32 (hd.len); + (void) mtime; + offset = grub_be_to_cpu32 (hd.offset); + + *mode = GRUB_ARCHELP_ATTR_FILE | GRUB_ARCHELP_ATTR_NOTIME; + + namesize = offset; + if (namesize >= sizeof (hd)) + namesize -= sizeof (hd); + if (namesize == 0) + continue; + *name = grub_malloc (namesize + 1); + if (*name == NULL) + return grub_errno; + + if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), + namesize, *name)) + { + grub_free (*name); + return grub_errno; + } + + if ((*name)[0] == '\0') + { + grub_free (*name); + *name = NULL; + continue; + } + + (*name)[namesize] = 0; + + data->dofs = data->hofs + offset; + data->next_hofs = ALIGN_UP (data->dofs + data->size, data->cbfs_align); + return GRUB_ERR_NONE; + } +} + +static void +grub_cbfs_rewind (struct grub_archelp_data *data) +{ + data->next_hofs = data->cbfs_start; +} + +static struct grub_archelp_ops arcops = + { + .find_file = grub_cbfs_find_file, + .rewind = grub_cbfs_rewind + }; + +static int +validate_head (struct cbfs_header *head) +{ + return (head->magic == grub_cpu_to_be32_compile_time (CBFS_HEADER_MAGIC) + && (head->version + == grub_cpu_to_be32_compile_time (CBFS_HEADER_VERSION1) + || head->version + == grub_cpu_to_be32_compile_time (CBFS_HEADER_VERSION2)) + && (grub_be_to_cpu32 (head->bootblocksize) + < grub_be_to_cpu32 (head->romsize)) + && (grub_be_to_cpu32 (head->offset) + < grub_be_to_cpu32 (head->romsize)) + && (grub_be_to_cpu32 (head->offset) + + grub_be_to_cpu32 (head->bootblocksize) + < grub_be_to_cpu32 (head->romsize)) + && head->align != 0 + && (head->align & (head->align - 1)) == 0 + && head->romsize != 0); +} + +static struct grub_archelp_data * +grub_cbfs_mount (grub_disk_t disk) +{ + struct cbfs_file hd; + struct grub_archelp_data *data = NULL; + grub_uint32_t ptr; + grub_off_t header_off; + struct cbfs_header head; + + if (grub_disk_native_sectors (disk) == GRUB_DISK_SIZE_UNKNOWN) + goto fail; + + if (grub_disk_read (disk, grub_disk_native_sectors (disk) - 1, + GRUB_DISK_SECTOR_SIZE - sizeof (ptr), + sizeof (ptr), &ptr)) + goto fail; + + ptr = grub_cpu_to_le32 (ptr); + header_off = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS) + + (grub_int32_t) ptr; + + if (grub_disk_read (disk, 0, header_off, + sizeof (head), &head)) + goto fail; + + if (!validate_head (&head)) + goto fail; + + data = (struct grub_archelp_data *) grub_zalloc (sizeof (*data)); + if (!data) + goto fail; + + data->cbfs_start = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS) + - (grub_be_to_cpu32 (head.romsize) - grub_be_to_cpu32 (head.offset)); + data->cbfs_end = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS) + - grub_be_to_cpu32 (head.bootblocksize); + data->cbfs_align = grub_be_to_cpu32 (head.align); + + if (data->cbfs_start >= (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS)) + goto fail; + if (data->cbfs_end > (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS)) + data->cbfs_end = (grub_disk_native_sectors (disk) << GRUB_DISK_SECTOR_BITS); + + data->next_hofs = data->cbfs_start; + + if (grub_disk_read (disk, 0, data->cbfs_start, sizeof (hd), &hd)) + goto fail; + + if (grub_memcmp (hd.magic, CBFS_FILE_MAGIC, sizeof (CBFS_FILE_MAGIC) - 1)) + goto fail; + + data->disk = disk; + + return data; + +fail: + grub_free (data); + grub_error (GRUB_ERR_BAD_FS, "not a cbfs filesystem"); + return 0; +} + +static grub_err_t +grub_cbfs_dir (grub_device_t device, const char *path_in, + grub_fs_dir_hook_t hook, void *hook_data) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cbfs_mount (device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_dir (data, &arcops, + path_in, hook, hook_data); + + grub_free (data); + + return err; +} + +static grub_err_t +grub_cbfs_open (grub_file_t file, const char *name_in) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cbfs_mount (file->device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_open (data, &arcops, name_in); + if (err) + { + grub_free (data); + } + else + { + file->data = data; + file->size = data->size; + } + return err; +} + +static grub_ssize_t +grub_cbfs_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_archelp_data *data; + grub_ssize_t ret; + + data = file->data; + data->disk->read_hook = file->read_hook; + data->disk->read_hook_data = file->read_hook_data; + + ret = (grub_disk_read (data->disk, 0, data->dofs + file->offset, + len, buf)) ? -1 : (grub_ssize_t) len; + data->disk->read_hook = 0; + + return ret; +} + +static grub_err_t +grub_cbfs_close (grub_file_t file) +{ + struct grub_archelp_data *data; + + data = file->data; + grub_free (data); + + return grub_errno; +} + +#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) \ + && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN) + +static char *cbfsdisk_addr; +static grub_off_t cbfsdisk_size = 0; + +static int +grub_cbfsdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +{ + if (pull != GRUB_DISK_PULL_NONE) + return 0; + + return hook ("cbfsdisk", hook_data); +} + +static grub_err_t +grub_cbfsdisk_open (const char *name, grub_disk_t disk) +{ + if (grub_strcmp (name, "cbfsdisk")) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a cbfsdisk"); + + disk->total_sectors = cbfsdisk_size / GRUB_DISK_SECTOR_SIZE; + disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; + disk->id = 0; + + return GRUB_ERR_NONE; +} + +static void +grub_cbfsdisk_close (grub_disk_t disk __attribute((unused))) +{ +} + +static grub_err_t +grub_cbfsdisk_read (grub_disk_t disk __attribute((unused)), + grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_memcpy (buf, cbfsdisk_addr + (sector << GRUB_DISK_SECTOR_BITS), + size << GRUB_DISK_SECTOR_BITS); + return 0; +} + +static grub_err_t +grub_cbfsdisk_write (grub_disk_t disk __attribute__ ((unused)), + grub_disk_addr_t sector __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused)), + const char *buf __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "rom flashing isn't implemented yet"); +} + +static struct grub_disk_dev grub_cbfsdisk_dev = + { + .name = "cbfsdisk", + .id = GRUB_DISK_DEVICE_CBFSDISK_ID, + .disk_iterate = grub_cbfsdisk_iterate, + .disk_open = grub_cbfsdisk_open, + .disk_close = grub_cbfsdisk_close, + .disk_read = grub_cbfsdisk_read, + .disk_write = grub_cbfsdisk_write, + .next = 0 + }; + +static void +init_cbfsdisk (void) +{ + grub_uint32_t ptr; + struct cbfs_header *head; + + ptr = *((grub_uint32_t *) grub_absolute_pointer (0xfffffffc)); + head = (struct cbfs_header *) (grub_addr_t) ptr; + grub_dprintf ("cbfs", "head=%p\n", head); + + /* coreboot current supports only ROMs <= 16 MiB. Bigger ROMs will + have problems as RCBA is 18 MiB below end of 32-bit typically, + so either memory map would have to be rearranged or we'd need to support + reading ROMs through controller directly. + */ + if (ptr < 0xff000000 + || 0xffffffff - ptr < (grub_uint32_t) sizeof (*head) + 0xf + || !validate_head (head)) + return; + + cbfsdisk_size = ALIGN_UP (grub_be_to_cpu32 (head->romsize), + GRUB_DISK_SECTOR_SIZE); + cbfsdisk_addr = (void *) (grub_addr_t) (0x100000000ULL - cbfsdisk_size); + + grub_disk_dev_register (&grub_cbfsdisk_dev); +} + +static void +fini_cbfsdisk (void) +{ + if (! cbfsdisk_size) + return; + grub_disk_dev_unregister (&grub_cbfsdisk_dev); +} + +#endif + +static struct grub_fs grub_cbfs_fs = { + .name = "cbfs", + .fs_dir = grub_cbfs_dir, + .fs_open = grub_cbfs_open, + .fs_read = grub_cbfs_read, + .fs_close = grub_cbfs_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, + .blocklist_install = 0, +#endif +}; + +GRUB_MOD_INIT (cbfs) +{ +#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN) + init_cbfsdisk (); +#endif + if (!grub_is_lockdown ()) + { + grub_cbfs_fs.mod = mod; + grub_fs_register (&grub_cbfs_fs); + } +} + +GRUB_MOD_FINI (cbfs) +{ + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_cbfs_fs); +#if (defined (__i386__) || defined (__x86_64__)) && !defined (GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_XEN) + fini_cbfsdisk (); +#endif +} diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index e9236cd97..1799f7ff5 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -1,7 +1,7 @@ /* cpio.c - cpio and tar filesystem. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, 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 @@ -17,66 +17,11 @@ * along with this program. If not, see . */ -#include -#include #include -#include -#include -#include -GRUB_MOD_LICENSE ("GPLv3+"); - -#define ATTR_TYPE 0160000 -#define ATTR_FILE 0100000 -#define ATTR_DIR 0040000 -#define ATTR_LNK 0120000 - -#ifdef MODE_ODC -#define ALIGN_CPIO(x) x -#define MAGIC "070707" -struct head -{ - char magic[6]; - char dev[6]; - char ino[6]; - char mode[6]; - char uid[6]; - char gid[6]; - char nlink[6]; - char rdev[6]; - char mtime[11]; - char namesize[6]; - char filesize[11]; -} __attribute__ ((packed)); -#elif defined (MODE_NEWC) -#define ALIGN_CPIO(x) (ALIGN_UP ((x), 4)) -#define MAGIC "070701" -#define MAGIC2 "070702" -struct head -{ - char magic[6]; - char ino[8]; - char mode[8]; - char uid[8]; - char gid[8]; - char nlink[8]; - char mtime[8]; - char filesize[8]; - char devmajor[8]; - char devminor[8]; - char rdevmajor[8]; - char rdevminor[8]; - char namesize[8]; - char check[8]; -} __attribute__ ((packed)); -#elif !defined (MODE_USTAR) /* cpio support */ #define ALIGN_CPIO(x) (ALIGN_UP ((x), 2)) -#ifdef MODE_BIGENDIAN -#define MAGIC "\x71\xc7" -#else #define MAGIC "\xc7\x71" -#endif struct head { grub_uint16_t magic[1]; @@ -90,695 +35,28 @@ struct head grub_uint16_t mtime[2]; grub_uint16_t namesize[1]; grub_uint16_t filesize[2]; -} __attribute__ ((packed)); -#else -/* tar support */ -#define MAGIC "ustar" -struct head -{ - char name[100]; - char mode[8]; - char uid[8]; - char gid[8]; - char size[12]; - char mtime[12]; - char chksum[8]; - char typeflag; - char linkname[100]; - char magic[6]; - char version[2]; - char uname[32]; - char gname[32]; - char devmajor[8]; - char devminor[8]; - char prefix[155]; -} __attribute__ ((packed)); -#endif +} GRUB_PACKED; -struct grub_cpio_data -{ - grub_disk_t disk; - grub_off_t hofs; - grub_off_t dofs; - grub_off_t size; -#ifdef MODE_USTAR - char *linkname; - grub_size_t linkname_alloc; -#endif -}; - -static grub_dl_t my_mod; - -static inline void -canonicalize (char *name) -{ - char *iptr, *optr; - for (iptr = name, optr = name; *iptr; ) - { - while (*iptr == '/') - iptr++; - if (iptr[0] == '.' && (iptr[1] == '/' || iptr[1] == 0)) - { - iptr += 2; - continue; - } - if (iptr[0] == '.' && iptr[1] == '.' && (iptr[2] == '/' || iptr[2] == 0)) - { - iptr += 3; - if (optr == name) - continue; - for (optr -= 2; optr >= name && *optr != '/'; optr--); - optr++; - continue; - } - while (*iptr && *iptr != '/') - *optr++ = *iptr++; - if (*iptr) - *optr++ = *iptr++; - } - *optr = 0; -} - -#if defined (MODE_ODC) || defined (MODE_USTAR) -static inline unsigned long long -read_number (const char *str, grub_size_t size) -{ - unsigned long long ret = 0; - while (size-- && *str >= '0' && *str <= '7') - ret = (ret << 3) | (*str++ & 0xf); - return ret; -} -#elif defined (MODE_NEWC) -static inline unsigned long long -read_number (const char *str, grub_size_t size) -{ - unsigned long long ret = 0; - while (size-- && grub_isxdigit (*str)) - { - char dig = *str++; - if (dig >= '0' && dig <= '9') - dig &= 0xf; - else if (dig >= 'a' && dig <= 'f') - dig -= 'a' - 10; - else - dig -= 'A' - 10; - ret = (ret << 4) | (dig); - } - return ret; -} -#else static inline unsigned long long read_number (const grub_uint16_t *arr, grub_size_t size) { long long ret = 0; -#ifdef MODE_BIGENDIAN - while (size--) - ret = (ret << 16) | grub_be_to_cpu16 (*arr++); -#else while (size--) ret = (ret << 16) | grub_le_to_cpu16 (*arr++); -#endif return ret; } -#endif -static grub_err_t -grub_cpio_find_file (struct grub_cpio_data *data, char **name, - grub_int32_t *mtime, grub_disk_addr_t *ofs, - grub_uint32_t *mode) -{ -#ifndef MODE_USTAR - struct head hd; - grub_size_t namesize; - grub_uint32_t modeval; +#define FSNAME "cpiofs" - if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) - return grub_errno; +#include "cpio_common.c" - if (grub_memcmp (hd.magic, MAGIC, sizeof (hd.magic)) != 0 -#ifdef MAGIC2 - && grub_memcmp (hd.magic, MAGIC2, sizeof (hd.magic)) != 0 -#endif - ) - return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive"); - data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize)); - if (mtime) - *mtime = read_number (hd.mtime, ARRAY_SIZE (hd.mtime)); - modeval = read_number (hd.mode, ARRAY_SIZE (hd.mode)); - namesize = read_number (hd.namesize, ARRAY_SIZE (hd.namesize)); - - if (mode) - *mode = modeval; - - *name = grub_malloc (namesize + 1); - if (*name == NULL) - return grub_errno; - - if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), - namesize, *name)) - { - grub_free (*name); - return grub_errno; - } - (*name)[namesize] = 0; - - if (data->size == 0 && modeval == 0 && namesize == 11 - && grub_memcmp(*name, "TRAILER!!!", 11) == 0) - { - *ofs = 0; - grub_free (*name); - return GRUB_ERR_NONE; - } - - canonicalize (*name); - - data->dofs = data->hofs + ALIGN_CPIO (sizeof (hd) + namesize); - *ofs = data->dofs + ALIGN_CPIO (data->size); -#else - struct head hd; - int reread = 0, have_longname = 0, have_longlink = 0; - - for (reread = 0; reread < 3; reread++) - { - if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) - return grub_errno; - - if (!hd.name[0] && !hd.prefix[0]) - { - *ofs = 0; - return GRUB_ERR_NONE; - } - - if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1)) - return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive"); - - if (hd.typeflag == 'L') - { - grub_err_t err; - grub_size_t namesize = read_number (hd.size, sizeof (hd.size)); - *name = grub_malloc (namesize + 1); - if (*name == NULL) - return grub_errno; - err = grub_disk_read (data->disk, 0, - data->hofs + GRUB_DISK_SECTOR_SIZE, namesize, - *name); - (*name)[namesize] = 0; - if (err) - return err; - data->hofs += GRUB_DISK_SECTOR_SIZE - + ((namesize + GRUB_DISK_SECTOR_SIZE - 1) & - ~(GRUB_DISK_SECTOR_SIZE - 1)); - have_longname = 1; - continue; - } - - if (hd.typeflag == 'K') - { - grub_err_t err; - grub_size_t linksize = read_number (hd.size, sizeof (hd.size)); - if (data->linkname_alloc < linksize + 1) - { - char *n; - n = grub_malloc (2 * (linksize + 1)); - if (!n) - return grub_errno; - grub_free (data->linkname); - data->linkname = n; - data->linkname_alloc = 2 * (linksize + 1); - } - - err = grub_disk_read (data->disk, 0, - data->hofs + GRUB_DISK_SECTOR_SIZE, linksize, - data->linkname); - if (err) - return err; - data->linkname[linksize] = 0; - data->hofs += GRUB_DISK_SECTOR_SIZE - + ((linksize + GRUB_DISK_SECTOR_SIZE - 1) & - ~(GRUB_DISK_SECTOR_SIZE - 1)); - have_longlink = 1; - continue; - } - - if (!have_longname) - { - grub_size_t extra_size = 0; - - while (extra_size < sizeof (hd.prefix) - && hd.prefix[extra_size]) - extra_size++; - *name = grub_malloc (sizeof (hd.name) + extra_size + 2); - if (*name == NULL) - return grub_errno; - if (hd.prefix[0]) - { - grub_memcpy (*name, hd.prefix, extra_size); - (*name)[extra_size++] = '/'; - } - grub_memcpy (*name + extra_size, hd.name, sizeof (hd.name)); - (*name)[extra_size + sizeof (hd.name)] = 0; - } - - data->size = read_number (hd.size, sizeof (hd.size)); - data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; - *ofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & - ~(GRUB_DISK_SECTOR_SIZE - 1)); - if (mtime) - *mtime = read_number (hd.mtime, sizeof (hd.mtime)); - if (mode) - { - *mode = read_number (hd.mode, sizeof (hd.mode)); - switch (hd.typeflag) - { - /* Hardlink. */ - case '1': - /* Symlink. */ - case '2': - *mode |= ATTR_LNK; - break; - case '0': - *mode |= ATTR_FILE; - break; - case '5': - *mode |= ATTR_DIR; - break; - } - } - if (!have_longlink) - { - if (data->linkname_alloc < 101) - { - char *n; - n = grub_malloc (101); - if (!n) - return grub_errno; - grub_free (data->linkname); - data->linkname = n; - data->linkname_alloc = 101; - } - grub_memcpy (data->linkname, hd.linkname, sizeof (hd.linkname)); - data->linkname[100] = 0; - } - - canonicalize (*name); - return GRUB_ERR_NONE; - } -#endif - return GRUB_ERR_NONE; -} - -static struct grub_cpio_data * -grub_cpio_mount (grub_disk_t disk) -{ - struct head hd; - struct grub_cpio_data *data; - - if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd)) - goto fail; - - if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1) -#ifdef MAGIC2 - && grub_memcmp (hd.magic, MAGIC2, sizeof (MAGIC2) - 1) -#endif - ) - goto fail; - - data = (struct grub_cpio_data *) grub_zalloc (sizeof (*data)); - if (!data) - goto fail; - - data->disk = disk; - - return data; - -fail: - grub_error (GRUB_ERR_BAD_FS, "not a " -#ifdef MODE_USTAR - "tar" -#else - "cpio" -#endif - " filesystem"); - return 0; -} - -static grub_err_t -handle_symlink (struct grub_cpio_data *data, - const char *fn, char **name, - grub_uint32_t mode, int *restart) -{ - grub_size_t flen; - char *target; -#ifndef MODE_USTAR - grub_err_t err; -#endif - char *ptr; - char *lastslash; - grub_size_t prefixlen; - char *rest; - grub_size_t size; - - *restart = 0; - - if ((mode & ATTR_TYPE) != ATTR_LNK) - return GRUB_ERR_NONE; - flen = grub_strlen (fn); - if (grub_memcmp (*name, fn, flen) != 0 - || ((*name)[flen] != 0 && (*name)[flen] != '/')) - return GRUB_ERR_NONE; - rest = *name + flen; - lastslash = rest; - if (*rest) - rest++; - while (lastslash >= *name && *lastslash != '/') - lastslash--; - if (lastslash >= *name) - prefixlen = lastslash - *name; - else - prefixlen = 0; - - if (prefixlen) - prefixlen++; - -#ifdef MODE_USTAR - size = grub_strlen (data->linkname); -#else - size = data->size; -#endif - if (size == 0) - return GRUB_ERR_NONE; - target = grub_malloc (size + grub_strlen (*name) + 2); - if (!target) - return grub_errno; - -#ifdef MODE_USTAR - grub_memcpy (target + prefixlen, data->linkname, size); -#else - err = grub_disk_read (data->disk, 0, data->dofs, data->size, - target + prefixlen); - if (err) - return err; -#endif - if (target[prefixlen] == '/') - { - grub_memmove (target, target + prefixlen, size); - ptr = target + size; - ptr = grub_stpcpy (ptr, rest); - *ptr = 0; - grub_dprintf ("cpio", "symlink redirected %s to %s\n", - *name, target); - grub_free (*name); - - canonicalize (target); - *name = target; - *restart = 1; - return GRUB_ERR_NONE; - } - if (prefixlen) - { - grub_memcpy (target, *name, prefixlen); - target[prefixlen-1] = '/'; - } - ptr = target + prefixlen + size; - ptr = grub_stpcpy (ptr, rest); - *ptr = 0; - grub_dprintf ("cpio", "symlink redirected %s to %s\n", - *name, target); - grub_free (*name); - canonicalize (target); - *name = target; - *restart = 1; - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_cpio_dir (grub_device_t device, const char *path_in, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) -{ - struct grub_cpio_data *data; - grub_disk_addr_t ofs; - char *prev, *name, *path, *ptr; - grub_size_t len; - int symlinknest = 0; - - path = grub_strdup (path_in + 1); - if (!path) - return grub_errno; - canonicalize (path); - for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--) - *ptr = 0; - - grub_dl_ref (my_mod); - - prev = 0; - - data = grub_cpio_mount (device->disk); - if (!data) - { - grub_free (path); - return grub_errno; - } - - len = grub_strlen (path); - data->hofs = 0; - while (1) - { - grub_int32_t mtime; - grub_uint32_t mode; - grub_err_t err; - - if (grub_cpio_find_file (data, &name, &mtime, &ofs, &mode)) - goto fail; - - if (!ofs) - break; - - if (grub_memcmp (path, name, len) == 0 - && (name[len] == 0 || name[len] == '/' || len == 0)) - { - char *p, *n; - - n = name + len; - while (*n == '/') - n++; - - p = grub_strchr (n, '/'); - if (p) - *p = 0; - - if (((!prev) || (grub_strcmp (prev, name) != 0)) && *n != 0) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = (p != NULL) || ((mode & ATTR_TYPE) == ATTR_DIR); - info.mtime = mtime; - info.mtimeset = 1; - - if (hook (n, &info)) - { - grub_free (name); - goto fail; - } - grub_free (prev); - prev = name; - } - else - { - int restart = 0; - err = handle_symlink (data, name, &path, mode, &restart); - grub_free (name); - if (err) - goto fail; - if (restart) - { - len = grub_strlen (path); - if (++symlinknest == 8) - { - grub_error (GRUB_ERR_SYMLINK_LOOP, - N_("too deep nesting of symlinks")); - goto fail; - } - ofs = 0; - } - } - } - else - grub_free (name); - data->hofs = ofs; - } - -fail: - - grub_free (path); - grub_free (prev); -#ifdef MODE_USTAR - grub_free (data->linkname); -#endif - grub_free (data); - - grub_dl_unref (my_mod); - - return grub_errno; -} - -static grub_err_t -grub_cpio_open (grub_file_t file, const char *name_in) -{ - struct grub_cpio_data *data; - grub_disk_addr_t ofs; - char *fn; - char *name = grub_strdup (name_in + 1); - int symlinknest = 0; - - if (!name) - return grub_errno; - - canonicalize (name); - - grub_dl_ref (my_mod); - - data = grub_cpio_mount (file->device->disk); - if (!data) - { - grub_free (name); - return grub_errno; - } - - data->hofs = 0; - while (1) - { - grub_uint32_t mode; - int restart; - - if (grub_cpio_find_file (data, &fn, NULL, &ofs, &mode)) - goto fail; - - if (!ofs) - { - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name_in); - break; - } - - if (handle_symlink (data, fn, &name, mode, &restart)) - { - grub_free (fn); - goto fail; - } - - if (restart) - { - ofs = 0; - if (++symlinknest == 8) - { - grub_error (GRUB_ERR_SYMLINK_LOOP, - N_("too deep nesting of symlinks")); - goto fail; - } - goto no_match; - } - - if (grub_strcmp (name, fn) != 0) - goto no_match; - - file->data = data; - file->size = data->size; - grub_free (fn); - grub_free (name); - - return GRUB_ERR_NONE; - - no_match: - - grub_free (fn); - data->hofs = ofs; - } - -fail: -#ifdef MODE_USTAR - grub_free (data->linkname); -#endif - grub_free (data); - grub_free (name); - - grub_dl_unref (my_mod); - - return grub_errno; -} - -static grub_ssize_t -grub_cpio_read (grub_file_t file, char *buf, grub_size_t len) -{ - struct grub_cpio_data *data; - - data = file->data; - return (grub_disk_read (data->disk, 0, data->dofs + file->offset, - len, buf)) ? -1 : (grub_ssize_t) len; -} - -static grub_err_t -grub_cpio_close (grub_file_t file) -{ - struct grub_cpio_data *data; - - data = file->data; -#ifdef MODE_USTAR - grub_free (data->linkname); -#endif - grub_free (data); - - grub_dl_unref (my_mod); - - return grub_errno; -} - -static struct grub_fs grub_cpio_fs = { -#ifdef MODE_USTAR - .name = "tarfs", -#elif defined (MODE_ODC) - .name = "odc", -#elif defined (MODE_NEWC) - .name = "newc", -#else - .name = "cpiofs", -#endif - .dir = grub_cpio_dir, - .open = grub_cpio_open, - .read = grub_cpio_read, - .close = grub_cpio_close, -#ifdef GRUB_UTIL - .reserved_first_sector = 0, - .blocklist_install = 0, -#endif -}; - -#ifdef MODE_USTAR -GRUB_MOD_INIT (tar) -#elif defined (MODE_ODC) -GRUB_MOD_INIT (odc) -#elif defined (MODE_NEWC) -GRUB_MOD_INIT (newc) -#elif defined (MODE_BIGENDIAN) -GRUB_MOD_INIT (cpio_be) -#else GRUB_MOD_INIT (cpio) -#endif { + grub_cpio_fs.mod = mod; grub_fs_register (&grub_cpio_fs); - my_mod = mod; } -#ifdef MODE_USTAR -GRUB_MOD_FINI (tar) -#elif defined (MODE_ODC) -GRUB_MOD_FINI (odc) -#elif defined (MODE_NEWC) -GRUB_MOD_FINI (newc) -#elif defined (MODE_BIGENDIAN) -GRUB_MOD_FINI (cpio_be) -#else GRUB_MOD_FINI (cpio) -#endif { grub_fs_unregister (&grub_cpio_fs); } diff --git a/grub-core/fs/cpio_be.c b/grub-core/fs/cpio_be.c index 8bad314cd..7bed1b848 100644 --- a/grub-core/fs/cpio_be.c +++ b/grub-core/fs/cpio_be.c @@ -1,2 +1,62 @@ -#define MODE_BIGENDIAN 1 -#include "cpio.c" +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#define ALIGN_CPIO(x) (ALIGN_UP ((x), 2)) +#define MAGIC "\x71\xc7" + +struct head +{ + grub_uint16_t magic[1]; + grub_uint16_t dev; + grub_uint16_t ino; + grub_uint16_t mode[1]; + grub_uint16_t uid; + grub_uint16_t gid; + grub_uint16_t nlink; + grub_uint16_t rdev; + grub_uint16_t mtime[2]; + grub_uint16_t namesize[1]; + grub_uint16_t filesize[2]; +} GRUB_PACKED; + +static inline unsigned long long +read_number (const grub_uint16_t *arr, grub_size_t size) +{ + long long ret = 0; + while (size--) + ret = (ret << 16) | grub_be_to_cpu16 (*arr++); + return ret; +} + +#define FSNAME "cpiofs_be" + +#include "cpio_common.c" + +GRUB_MOD_INIT (cpio_be) +{ + grub_cpio_fs.mod = mod; + grub_fs_register (&grub_cpio_fs); +} + +GRUB_MOD_FINI (cpio_be) +{ + grub_fs_unregister (&grub_cpio_fs); +} diff --git a/grub-core/fs/cpio_common.c b/grub-core/fs/cpio_common.c new file mode 100644 index 000000000..45ac119a8 --- /dev/null +++ b/grub-core/fs/cpio_common.c @@ -0,0 +1,275 @@ +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_archelp_data +{ + grub_disk_t disk; + grub_off_t hofs; + grub_off_t next_hofs; + grub_off_t dofs; + grub_off_t size; +}; + +#if __GNUC__ >= 9 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" +#endif + +static grub_err_t +grub_cpio_find_file (struct grub_archelp_data *data, char **name, + grub_int32_t *mtime, grub_uint32_t *mode) +{ + struct head hd; + grub_size_t namesize; + grub_uint32_t modeval; + grub_size_t sz; + + data->hofs = data->next_hofs; + + if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) + return grub_errno; + + if (grub_memcmp (hd.magic, MAGIC, sizeof (hd.magic)) != 0 +#ifdef MAGIC2 + && grub_memcmp (hd.magic, MAGIC2, sizeof (hd.magic)) != 0 +#endif + ) + return grub_error (GRUB_ERR_BAD_FS, "invalid cpio archive"); + + if (grub_cast (read_number (hd.filesize, ARRAY_SIZE (hd.filesize)), &data->size)) + return grub_error (GRUB_ERR_BAD_FS, N_("data size overflow")); + + if (mtime) + { + if (grub_cast (read_number (hd.mtime, ARRAY_SIZE (hd.mtime)), mtime)) + return grub_error (GRUB_ERR_BAD_FS, N_("mtime overflow")); + } + + if (grub_cast (read_number (hd.mode, ARRAY_SIZE (hd.mode)), &modeval)) + return grub_error (GRUB_ERR_BAD_FS, N_("mode overflow")); + + if (grub_cast (read_number (hd.namesize, ARRAY_SIZE (hd.namesize)), &namesize)) + return grub_error (GRUB_ERR_BAD_FS, N_("namesize overflow")); + + /* Don't allow negative numbers. */ + if (namesize >= 0x80000000) + { + /* Probably a corruption, don't attempt to recover. */ + *mode = GRUB_ARCHELP_ATTR_END; + return GRUB_ERR_NONE; + } + + *mode = modeval; + + if (grub_add (namesize, 1, &sz)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("file name size overflow")); + + *name = grub_malloc (sz); + if (*name == NULL) + return grub_errno; + + if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), + namesize, *name)) + { + grub_free (*name); + return grub_errno; + } + (*name)[namesize] = 0; + + if (data->size == 0 && modeval == 0 && namesize == 11 + && grub_memcmp(*name, "TRAILER!!!", 11) == 0) + { + *mode = GRUB_ARCHELP_ATTR_END; + grub_free (*name); + return GRUB_ERR_NONE; + } + + data->dofs = data->hofs + ALIGN_CPIO (sizeof (hd) + namesize); + data->next_hofs = data->dofs + ALIGN_CPIO (data->size); + return GRUB_ERR_NONE; +} + +#if __GNUC__ >= 9 +#pragma GCC diagnostic pop +#endif + +static char * +grub_cpio_get_link_target (struct grub_archelp_data *data) +{ + char *ret; + grub_err_t err; + grub_size_t sz; + + if (data->size == 0) + return grub_strdup (""); + + if (grub_add (data->size, 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("target data size overflow")); + return NULL; + } + ret = grub_malloc (sz); + if (!ret) + return NULL; + + err = grub_disk_read (data->disk, 0, data->dofs, data->size, + ret); + if (err) + { + grub_free (ret); + return NULL; + } + ret[data->size] = '\0'; + return ret; +} + +static void +grub_cpio_rewind (struct grub_archelp_data *data) +{ + data->next_hofs = 0; +} + +static struct grub_archelp_ops arcops = + { + .find_file = grub_cpio_find_file, + .get_link_target = grub_cpio_get_link_target, + .rewind = grub_cpio_rewind + }; + +static struct grub_archelp_data * +grub_cpio_mount (grub_disk_t disk) +{ + struct head hd; + struct grub_archelp_data *data; + + if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd)) + goto fail; + + if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1) +#ifdef MAGIC2 + && grub_memcmp (hd.magic, MAGIC2, sizeof (MAGIC2) - 1) +#endif + ) + goto fail; + + data = (struct grub_archelp_data *) grub_zalloc (sizeof (*data)); + if (!data) + goto fail; + + data->disk = disk; + + return data; + +fail: + grub_error (GRUB_ERR_BAD_FS, "not a " FSNAME " filesystem"); + return 0; +} + +static grub_err_t +grub_cpio_dir (grub_device_t device, const char *path_in, + grub_fs_dir_hook_t hook, void *hook_data) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cpio_mount (device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_dir (data, &arcops, + path_in, hook, hook_data); + + grub_free (data); + + return err; +} + +static grub_err_t +grub_cpio_open (grub_file_t file, const char *name_in) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cpio_mount (file->device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_open (data, &arcops, name_in); + if (err) + { + grub_free (data); + } + else + { + file->data = data; + file->size = data->size; + } + return err; +} + +static grub_ssize_t +grub_cpio_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_archelp_data *data; + grub_ssize_t ret; + + data = file->data; + data->disk->read_hook = file->read_hook; + data->disk->read_hook_data = file->read_hook_data; + + ret = (grub_disk_read (data->disk, 0, data->dofs + file->offset, + len, buf)) ? -1 : (grub_ssize_t) len; + data->disk->read_hook = 0; + + return ret; +} + +static grub_err_t +grub_cpio_close (grub_file_t file) +{ + struct grub_archelp_data *data; + + data = file->data; + grub_free (data); + + return grub_errno; +} + +static struct grub_fs grub_cpio_fs = { + .name = FSNAME, + .fs_dir = grub_cpio_dir, + .fs_open = grub_cpio_open, + .fs_read = grub_cpio_read, + .fs_close = grub_cpio_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, + .blocklist_install = 0, +#endif +}; diff --git a/grub-core/fs/erofs.c b/grub-core/fs/erofs.c new file mode 100644 index 000000000..82a05051d --- /dev/null +++ b/grub-core/fs/erofs.c @@ -0,0 +1,1006 @@ +/* erofs.c - Enhanced Read-Only File System */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2024 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define EROFS_SUPER_OFFSET 1024 +#define EROFS_MAGIC 0xE0F5E1E2 +#define EROFS_ISLOTBITS 5 + +#define EROFS_FEATURE_INCOMPAT_CHUNKED_FILE 0x00000004 +#define EROFS_ALL_FEATURE_INCOMPAT EROFS_FEATURE_INCOMPAT_CHUNKED_FILE + +struct grub_erofs_super +{ + grub_uint32_t magic; + grub_uint32_t checksum; + grub_uint32_t feature_compat; + grub_uint8_t log2_blksz; + grub_uint8_t sb_extslots; + + grub_uint16_t root_nid; + grub_uint64_t inos; + + grub_uint64_t build_time; + grub_uint32_t build_time_nsec; + grub_uint32_t blocks; + grub_uint32_t meta_blkaddr; + grub_uint32_t xattr_blkaddr; + grub_packed_guid_t uuid; + grub_uint8_t volume_name[16]; + grub_uint32_t feature_incompat; + + union + { + grub_uint16_t available_compr_algs; + grub_uint16_t lz4_max_distance; + } GRUB_PACKED u1; + + grub_uint16_t extra_devices; + grub_uint16_t devt_slotoff; + grub_uint8_t log2_dirblksz; + grub_uint8_t xattr_prefix_count; + grub_uint32_t xattr_prefix_start; + grub_uint64_t packed_nid; + grub_uint8_t reserved2[24]; +} GRUB_PACKED; + +#define EROFS_INODE_LAYOUT_COMPACT 0 +#define EROFS_INODE_LAYOUT_EXTENDED 1 + +#define EROFS_INODE_FLAT_PLAIN 0 +#define EROFS_INODE_COMPRESSED_FULL 1 +#define EROFS_INODE_FLAT_INLINE 2 +#define EROFS_INODE_COMPRESSED_COMPACT 3 +#define EROFS_INODE_CHUNK_BASED 4 + +#define EROFS_I_VERSION_MASKS 0x01 +#define EROFS_I_DATALAYOUT_MASKS 0x07 + +#define EROFS_I_VERSION_BIT 0 +#define EROFS_I_DATALAYOUT_BIT 1 + +struct grub_erofs_inode_chunk_info +{ + grub_uint16_t format; + grub_uint16_t reserved; +} GRUB_PACKED; + +#define EROFS_CHUNK_FORMAT_BLKBITS_MASK 0x001F +#define EROFS_CHUNK_FORMAT_INDEXES 0x0020 + +#define EROFS_BLOCK_MAP_ENTRY_SIZE 4 +#define EROFS_MAP_MAPPED 0x02 + +#define EROFS_NULL_ADDR 1 +#define EROFS_NAME_LEN 255 +#define EROFS_PATH_LEN 4096 +#define EROFS_MIN_LOG2_BLOCK_SIZE 9 +#define EROFS_MAX_LOG2_BLOCK_SIZE 16 + +struct grub_erofs_inode_chunk_index +{ + grub_uint16_t advise; + grub_uint16_t device_id; + grub_uint32_t blkaddr; +}; + +union grub_erofs_inode_i_u +{ + grub_uint32_t compressed_blocks; + grub_uint32_t raw_blkaddr; + + grub_uint32_t rdev; + + struct grub_erofs_inode_chunk_info c; +}; + +struct grub_erofs_inode_compact +{ + grub_uint16_t i_format; + + grub_uint16_t i_xattr_icount; + grub_uint16_t i_mode; + grub_uint16_t i_nlink; + grub_uint32_t i_size; + grub_uint32_t i_reserved; + + union grub_erofs_inode_i_u i_u; + + grub_uint32_t i_ino; + grub_uint16_t i_uid; + grub_uint16_t i_gid; + grub_uint32_t i_reserved2; +} GRUB_PACKED; + +struct grub_erofs_inode_extended +{ + grub_uint16_t i_format; + + grub_uint16_t i_xattr_icount; + grub_uint16_t i_mode; + grub_uint16_t i_reserved; + grub_uint64_t i_size; + + union grub_erofs_inode_i_u i_u; + + grub_uint32_t i_ino; + + grub_uint32_t i_uid; + grub_uint32_t i_gid; + grub_uint64_t i_mtime; + grub_uint32_t i_mtime_nsec; + grub_uint32_t i_nlink; + grub_uint8_t i_reserved2[16]; +} GRUB_PACKED; + +union grub_erofs_inode +{ + struct grub_erofs_inode_compact c; + struct grub_erofs_inode_extended e; +} GRUB_PACKED; + +#define EROFS_FT_UNKNOWN 0 +#define EROFS_FT_REG_FILE 1 +#define EROFS_FT_DIR 2 +#define EROFS_FT_CHRDEV 3 +#define EROFS_FT_BLKDEV 4 +#define EROFS_FT_FIFO 5 +#define EROFS_FT_SOCK 6 +#define EROFS_FT_SYMLINK 7 + +struct grub_erofs_dirent +{ + grub_uint64_t nid; + grub_uint16_t nameoff; + grub_uint8_t file_type; + grub_uint8_t reserved; +} GRUB_PACKED; + +struct grub_erofs_map_blocks +{ + grub_uint64_t m_pa; /* physical address */ + grub_uint64_t m_la; /* logical address */ + grub_uint64_t m_plen; /* physical length */ + grub_uint64_t m_llen; /* logical length */ + grub_uint32_t m_flags; +}; + +struct grub_erofs_xattr_ibody_header +{ + grub_uint32_t h_reserved; + grub_uint8_t h_shared_count; + grub_uint8_t h_reserved2[7]; + grub_uint32_t h_shared_xattrs[0]; +}; + +struct grub_fshelp_node +{ + struct grub_erofs_data *data; + union grub_erofs_inode inode; + + grub_uint64_t ino; + grub_uint8_t inode_type; + grub_uint8_t inode_datalayout; + + /* If the inode has been read into memory? */ + bool inode_loaded; +}; + +struct grub_erofs_data +{ + grub_disk_t disk; + struct grub_erofs_super sb; + + struct grub_fshelp_node inode; +}; + +#define erofs_blocksz(data) (((grub_uint32_t) 1) << data->sb.log2_blksz) + +static grub_size_t +grub_erofs_strnlen (const char *s, grub_size_t n) +{ + const char *p = s; + + if (n == 0) + return 0; + + while (n-- && *p) + p++; + + return p - s; +} + +static grub_uint64_t +erofs_iloc (grub_fshelp_node_t node) +{ + struct grub_erofs_super *sb = &node->data->sb; + + return ((grub_uint64_t) grub_le_to_cpu32 (sb->meta_blkaddr) << sb->log2_blksz) + + (node->ino << EROFS_ISLOTBITS); +} + +static grub_err_t +erofs_read_inode (struct grub_erofs_data *data, grub_fshelp_node_t node) +{ + union grub_erofs_inode *di; + grub_err_t err; + grub_uint16_t i_format; + grub_uint64_t addr = erofs_iloc (node); + + di = (union grub_erofs_inode *) &node->inode; + + err = grub_disk_read (data->disk, addr >> GRUB_DISK_SECTOR_BITS, + addr & (GRUB_DISK_SECTOR_SIZE - 1), + sizeof (struct grub_erofs_inode_compact), &di->c); + if (err != GRUB_ERR_NONE) + return err; + + i_format = grub_le_to_cpu16 (di->c.i_format); + node->inode_type = (i_format >> EROFS_I_VERSION_BIT) & EROFS_I_VERSION_MASKS; + node->inode_datalayout = (i_format >> EROFS_I_DATALAYOUT_BIT) & EROFS_I_DATALAYOUT_MASKS; + + switch (node->inode_type) + { + case EROFS_INODE_LAYOUT_EXTENDED: + addr += sizeof (struct grub_erofs_inode_compact); + err = grub_disk_read (data->disk, addr >> GRUB_DISK_SECTOR_BITS, + addr & (GRUB_DISK_SECTOR_SIZE - 1), + sizeof (struct grub_erofs_inode_extended) - sizeof (struct grub_erofs_inode_compact), + (grub_uint8_t *) di + sizeof (struct grub_erofs_inode_compact)); + if (err != GRUB_ERR_NONE) + return err; + break; + case EROFS_INODE_LAYOUT_COMPACT: + break; + default: + return grub_error (GRUB_ERR_BAD_FS, "invalid type %u @ inode %" PRIuGRUB_UINT64_T, + node->inode_type, node->ino); + } + + node->inode_loaded = true; + + return 0; +} + +static grub_uint64_t +erofs_inode_size (grub_fshelp_node_t node) +{ + return node->inode_type == EROFS_INODE_LAYOUT_COMPACT + ? sizeof (struct grub_erofs_inode_compact) + : sizeof (struct grub_erofs_inode_extended); +} + +static grub_uint64_t +erofs_inode_file_size (grub_fshelp_node_t node) +{ + union grub_erofs_inode *di = (union grub_erofs_inode *) &node->inode; + + return node->inode_type == EROFS_INODE_LAYOUT_COMPACT + ? grub_le_to_cpu32 (di->c.i_size) + : grub_le_to_cpu64 (di->e.i_size); +} + +static grub_uint32_t +erofs_inode_xattr_ibody_size (grub_fshelp_node_t node) +{ + grub_uint16_t cnt = grub_le_to_cpu16 (node->inode.e.i_xattr_icount); + + if (cnt == 0) + return 0; + + return sizeof (struct grub_erofs_xattr_ibody_header) + ((cnt - 1) * sizeof (grub_uint32_t)); +} + +static grub_uint64_t +erofs_inode_mtime (grub_fshelp_node_t node) +{ + return node->inode_type == EROFS_INODE_LAYOUT_COMPACT + ? grub_le_to_cpu64 (node->data->sb.build_time) + : grub_le_to_cpu64 (node->inode.e.i_mtime); +} + +static grub_err_t +erofs_map_blocks_flatmode (grub_fshelp_node_t node, + struct grub_erofs_map_blocks *map) +{ + grub_uint64_t nblocks, lastblk, file_size; + bool tailendpacking = (node->inode_datalayout == EROFS_INODE_FLAT_INLINE); + grub_uint64_t blocksz = erofs_blocksz (node->data); + + /* `file_size` is checked by caller and cannot be zero, hence nblocks > 0. */ + file_size = erofs_inode_file_size (node); + if (grub_add (file_size, blocksz - 1, &nblocks)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "nblocks overflow"); + nblocks >>= node->data->sb.log2_blksz; + lastblk = nblocks - tailendpacking; + + map->m_flags = EROFS_MAP_MAPPED; + + /* No overflow as (lastblk <= nblocks) && (nblocks * blocksz <= UINT64_MAX - blocksz + 1). */ + if (map->m_la < (lastblk * blocksz)) + { + if (grub_mul ((grub_uint64_t) grub_le_to_cpu32 (node->inode.e.i_u.raw_blkaddr), blocksz, &map->m_pa) || + grub_add (map->m_pa, map->m_la, &map->m_pa)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "m_pa overflow"); + if (grub_sub (lastblk * blocksz, map->m_la, &map->m_plen)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "m_plen underflow"); + } + else if (tailendpacking) + { + if (grub_add (erofs_iloc (node), erofs_inode_size (node), &map->m_pa) || + grub_add (map->m_pa, erofs_inode_xattr_ibody_size (node), &map->m_pa) || + grub_add (map->m_pa, map->m_la & (blocksz - 1), &map->m_pa)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "m_pa overflow when handling tailpacking"); + if (grub_sub (file_size, map->m_la, &map->m_plen)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "m_plen overflow when handling tailpacking"); + + /* No overflow as map->m_plen <= UINT64_MAX - blocksz + 1. */ + if (((map->m_pa & (blocksz - 1)) + map->m_plen) > blocksz) + return grub_error (GRUB_ERR_BAD_FS, + "inline data cross block boundary @ inode %" PRIuGRUB_UINT64_T, + node->ino); + } + else + return grub_error (GRUB_ERR_BAD_FS, + "invalid map->m_la=%" PRIuGRUB_UINT64_T + " @ inode %" PRIuGRUB_UINT64_T, + map->m_la, node->ino); + + map->m_llen = map->m_plen; + return GRUB_ERR_NONE; +} + +static grub_err_t +erofs_map_blocks_chunkmode (grub_fshelp_node_t node, + struct grub_erofs_map_blocks *map) +{ + grub_uint16_t chunk_format = grub_le_to_cpu16 (node->inode.e.i_u.c.format); + grub_uint64_t unit, pos, chunknr, blkaddr; + grub_uint8_t chunkbits; + grub_err_t err; + + if (chunk_format & EROFS_CHUNK_FORMAT_INDEXES) + unit = sizeof (struct grub_erofs_inode_chunk_index); + else + unit = EROFS_BLOCK_MAP_ENTRY_SIZE; + + chunkbits = node->data->sb.log2_blksz + (chunk_format & EROFS_CHUNK_FORMAT_BLKBITS_MASK); + if (chunkbits > 63) + return grub_error (GRUB_ERR_BAD_FS, "invalid chunkbits %u @ inode %" PRIuGRUB_UINT64_T, + chunkbits, node->ino); + + chunknr = map->m_la >> chunkbits; + + if (grub_add (erofs_iloc (node), erofs_inode_size (node), &pos)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "chunkmap position overflow when adding inode size"); + + if (grub_add (pos, erofs_inode_xattr_ibody_size (node), &pos)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "chunkmap position overflow when adding xattr size"); + + if (ALIGN_UP_OVF (pos, unit, &pos)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "position overflow when seeking at the start of chunkmap"); + + /* No overflow for multiplication as chunkbits >= 9 and sizeof(unit) <= 8. */ + if (grub_add (pos, chunknr * unit, &pos)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "chunkmap position overflow when finding the specific chunk"); + + map->m_la = chunknr << chunkbits; + + if (grub_sub (erofs_inode_file_size (node), map->m_la, &map->m_plen)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "m_plen underflow"); + map->m_plen = grub_min (((grub_uint64_t) 1) << chunkbits, + ALIGN_UP (map->m_plen, erofs_blocksz (node->data))); + + if (chunk_format & EROFS_CHUNK_FORMAT_INDEXES) + { + struct grub_erofs_inode_chunk_index idx; + + err = grub_disk_read (node->data->disk, pos >> GRUB_DISK_SECTOR_BITS, + pos & (GRUB_DISK_SECTOR_SIZE - 1), unit, &idx); + if (err != GRUB_ERR_NONE) + return err; + + blkaddr = grub_le_to_cpu32 (idx.blkaddr); + } + else + { + grub_uint32_t blkaddr_le; + + err = grub_disk_read (node->data->disk, pos >> GRUB_DISK_SECTOR_BITS, + pos & (GRUB_DISK_SECTOR_SIZE - 1), unit, &blkaddr_le); + if (err != GRUB_ERR_NONE) + return err; + + blkaddr = grub_le_to_cpu32 (blkaddr_le); + } + + if (blkaddr == EROFS_NULL_ADDR) + { + map->m_pa = 0; + map->m_flags = 0; + } + else + { + map->m_pa = blkaddr << node->data->sb.log2_blksz; + map->m_flags = EROFS_MAP_MAPPED; + } + + map->m_llen = map->m_plen; + return GRUB_ERR_NONE; +} + +static grub_err_t +erofs_map_blocks (grub_fshelp_node_t node, struct grub_erofs_map_blocks *map) +{ + if (map->m_la >= erofs_inode_file_size (node)) + { + map->m_llen = map->m_plen = 0; + map->m_pa = 0; + map->m_flags = 0; + return GRUB_ERR_NONE; + } + + if (node->inode_datalayout != EROFS_INODE_CHUNK_BASED) + return erofs_map_blocks_flatmode (node, map); + else + return erofs_map_blocks_chunkmode (node, map); +} + +static grub_err_t +erofs_read_raw_data (grub_fshelp_node_t node, grub_uint8_t *buf, grub_uint64_t size, + grub_uint64_t offset, grub_uint64_t *bytes) +{ + struct grub_erofs_map_blocks map = {0}; + grub_uint64_t cur; + grub_err_t err; + + if (bytes) + *bytes = 0; + + if (node->inode_loaded == false) + { + err = erofs_read_inode (node->data, node); + if (err != GRUB_ERR_NONE) + return err; + } + + cur = offset; + while (cur < offset + size) + { + grub_uint8_t *const estart = buf + cur - offset; + grub_uint64_t eend, moff = 0; + + map.m_la = cur; + err = erofs_map_blocks (node, &map); + if (err != GRUB_ERR_NONE) + return err; + + if (grub_add(map.m_la, map.m_llen, &eend)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "eend overflow"); + + eend = grub_min (eend, offset + size); + if (!(map.m_flags & EROFS_MAP_MAPPED)) + { + if (!map.m_llen) + { + /* Reached EOF. */ + grub_memset (estart, 0, offset + size - cur); + cur = offset + size; + continue; + } + + /* It's a hole. */ + grub_memset (estart, 0, eend - cur); + if (bytes) + *bytes += eend - cur; + cur = eend; + continue; + } + + if (cur > map.m_la) + { + moff = cur - map.m_la; + map.m_la = cur; + } + + err = grub_disk_read (node->data->disk, + (map.m_pa + moff) >> GRUB_DISK_SECTOR_BITS, + (map.m_pa + moff) & (GRUB_DISK_SECTOR_SIZE - 1), + eend - map.m_la, estart); + if (err != GRUB_ERR_NONE) + return err; + + if (bytes) + *bytes += eend - map.m_la; + + cur = eend; + } + + return GRUB_ERR_NONE; +} + +static int +erofs_iterate_dir (grub_fshelp_node_t dir, grub_fshelp_iterate_dir_hook_t hook, + void *hook_data) +{ + grub_uint64_t offset = 0, file_size; + grub_uint32_t blocksz = erofs_blocksz (dir->data); + grub_uint8_t *buf; + grub_err_t err; + + if (dir->inode_loaded == false) + { + err = erofs_read_inode (dir->data, dir); + if (err != GRUB_ERR_NONE) + return 0; + } + + file_size = erofs_inode_file_size (dir); + buf = grub_malloc (blocksz); + if (buf == NULL) + return 0; + + while (offset < file_size) + { + grub_uint64_t maxsize = grub_min (blocksz, file_size - offset); + struct grub_erofs_dirent *de = (void *) buf, *end; + grub_uint16_t nameoff; + + err = erofs_read_raw_data (dir, buf, maxsize, offset, NULL); + if (err != GRUB_ERR_NONE) + goto not_found; + + nameoff = grub_le_to_cpu16 (de->nameoff); + if (nameoff < sizeof (struct grub_erofs_dirent) || nameoff >= maxsize) + { + grub_error (GRUB_ERR_BAD_FS, + "invalid nameoff %u @ inode %" PRIuGRUB_UINT64_T, + nameoff, dir->ino); + goto not_found; + } + + end = (struct grub_erofs_dirent *) ((grub_uint8_t *) de + nameoff); + while (de < end) + { + struct grub_fshelp_node *fdiro; + enum grub_fshelp_filetype type; + char filename[EROFS_NAME_LEN + 1]; + grub_size_t de_namelen; + const char *de_name; + + fdiro = grub_malloc (sizeof (struct grub_fshelp_node)); + if (fdiro == NULL) + goto not_found; + + fdiro->data = dir->data; + fdiro->ino = grub_le_to_cpu64 (de->nid); + fdiro->inode_loaded = false; + + nameoff = grub_le_to_cpu16 (de->nameoff); + if (nameoff < sizeof (struct grub_erofs_dirent) || nameoff >= maxsize) + { + grub_error (GRUB_ERR_BAD_FS, + "invalid nameoff %u @ inode %" PRIuGRUB_UINT64_T, + nameoff, dir->ino); + grub_free (fdiro); + goto not_found; + } + + de_name = (char *) buf + nameoff; + if (de + 1 >= end) + de_namelen = grub_erofs_strnlen (de_name, maxsize - nameoff); + else + { + if (grub_sub (grub_le_to_cpu16 (de[1].nameoff), nameoff, &de_namelen)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "de_namelen underflow"); + grub_free (fdiro); + goto not_found; + } + } + + if (nameoff + de_namelen > maxsize || de_namelen > EROFS_NAME_LEN) + { + grub_error (GRUB_ERR_BAD_FS, + "invalid de_namelen %" PRIuGRUB_SIZE + " @ inode %" PRIuGRUB_UINT64_T, + de_namelen, dir->ino); + grub_free (fdiro); + goto not_found; + } + + grub_memcpy (filename, de_name, de_namelen); + filename[de_namelen] = '\0'; + + switch (grub_le_to_cpu16 (de->file_type)) + { + case EROFS_FT_REG_FILE: + case EROFS_FT_BLKDEV: + case EROFS_FT_CHRDEV: + case EROFS_FT_FIFO: + case EROFS_FT_SOCK: + type = GRUB_FSHELP_REG; + break; + case EROFS_FT_DIR: + type = GRUB_FSHELP_DIR; + break; + case EROFS_FT_SYMLINK: + type = GRUB_FSHELP_SYMLINK; + break; + case EROFS_FT_UNKNOWN: + default: + type = GRUB_FSHELP_UNKNOWN; + } + + if (hook (filename, type, fdiro, hook_data)) + { + grub_free (buf); + return 1; + } + + ++de; + } + + offset += maxsize; + } + + not_found: + grub_free (buf); + return 0; +} + +static char * +erofs_read_symlink (grub_fshelp_node_t node) +{ + char *symlink; + grub_size_t sz, lsz; + grub_err_t err; + + if (node->inode_loaded == false) + { + err = erofs_read_inode (node->data, node); + if (err != GRUB_ERR_NONE) + return NULL; + } + + sz = erofs_inode_file_size (node); + if (sz >= EROFS_PATH_LEN) + { + grub_error (GRUB_ERR_BAD_FS, + "symlink too long @ inode %" PRIuGRUB_UINT64_T, node->ino); + return NULL; + } + + if (grub_add (sz, 1, &lsz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink size overflow")); + return NULL; + } + symlink = grub_malloc (lsz); + if (symlink == NULL) + return NULL; + + err = erofs_read_raw_data (node, (grub_uint8_t *) symlink, sz, 0, NULL); + if (err != GRUB_ERR_NONE) + { + grub_free (symlink); + return NULL; + } + + symlink[sz] = '\0'; + return symlink; +} + +static struct grub_erofs_data * +erofs_mount (grub_disk_t disk, bool read_root) +{ + struct grub_erofs_super sb; + grub_err_t err; + struct grub_erofs_data *data; + grub_uint32_t feature; + + err = grub_disk_read (disk, EROFS_SUPER_OFFSET >> GRUB_DISK_SECTOR_BITS, 0, + sizeof (sb), &sb); + if (err != GRUB_ERR_NONE) + return NULL; + if (sb.magic != grub_cpu_to_le32_compile_time (EROFS_MAGIC) || + grub_le_to_cpu32 (sb.log2_blksz) < EROFS_MIN_LOG2_BLOCK_SIZE || + grub_le_to_cpu32 (sb.log2_blksz) > EROFS_MAX_LOG2_BLOCK_SIZE) + { + grub_error (GRUB_ERR_BAD_FS, "not a valid erofs filesystem"); + return NULL; + } + + feature = grub_le_to_cpu32 (sb.feature_incompat); + if (feature & ~EROFS_ALL_FEATURE_INCOMPAT) + { + grub_error (GRUB_ERR_BAD_FS, "unsupported features: 0x%x", + feature & ~EROFS_ALL_FEATURE_INCOMPAT); + return NULL; + } + + data = grub_malloc (sizeof (*data)); + if (data == NULL) + return NULL; + + data->disk = disk; + data->sb = sb; + + if (read_root) + { + data->inode.data = data; + data->inode.ino = grub_le_to_cpu16 (sb.root_nid); + err = erofs_read_inode (data, &data->inode); + if (err != GRUB_ERR_NONE) + { + grub_free (data); + return NULL; + } + } + + return data; +} + +/* Context for grub_erofs_dir. */ +struct grub_erofs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; + struct grub_erofs_data *data; +}; + +/* Helper for grub_erofs_dir. */ +static int +erofs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_erofs_dir_ctx *ctx = data; + struct grub_dirhook_info info = {0}; + grub_err_t err; + + if (node->inode_loaded == false) + { + err = erofs_read_inode (ctx->data, node); + if (err != GRUB_ERR_NONE) + return 0; + } + + if (node->inode_loaded == true) + { + info.mtimeset = 1; + info.mtime = erofs_inode_mtime (node); + } + + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + +static grub_err_t +grub_erofs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, + void *hook_data) +{ + grub_fshelp_node_t fdiro = NULL; + grub_err_t err; + struct grub_erofs_dir_ctx ctx = { + .hook = hook, + .hook_data = hook_data + }; + + ctx.data = erofs_mount (device->disk, true); + if (ctx.data == NULL) + goto fail; + + err = grub_fshelp_find_file (path, &ctx.data->inode, &fdiro, erofs_iterate_dir, + erofs_read_symlink, GRUB_FSHELP_DIR); + if (err != GRUB_ERR_NONE) + goto fail; + + erofs_iterate_dir (fdiro, erofs_dir_iter, &ctx); + + fail: + if (fdiro != &ctx.data->inode) + grub_free (fdiro); + grub_free (ctx.data); + + return grub_errno; +} + +static grub_err_t +grub_erofs_open (grub_file_t file, const char *name) +{ + struct grub_erofs_data *data; + struct grub_fshelp_node *fdiro = NULL; + grub_err_t err; + + data = erofs_mount (file->device->disk, true); + if (data == NULL) + { + err = grub_errno; + goto fail; + } + + err = grub_fshelp_find_file (name, &data->inode, &fdiro, erofs_iterate_dir, + erofs_read_symlink, GRUB_FSHELP_REG); + if (err != GRUB_ERR_NONE) + goto fail; + + if (fdiro->inode_loaded == false) + { + err = erofs_read_inode (data, fdiro); + if (err != GRUB_ERR_NONE) + goto fail; + } + + grub_memcpy (&data->inode, fdiro, sizeof (*fdiro)); + grub_free (fdiro); + + file->data = data; + file->size = erofs_inode_file_size (&data->inode); + + return GRUB_ERR_NONE; + + fail: + if (fdiro != &data->inode) + grub_free (fdiro); + grub_free (data); + + return err; +} + +static grub_ssize_t +grub_erofs_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_erofs_data *data = file->data; + struct grub_fshelp_node *inode = &data->inode; + grub_off_t off = file->offset; + grub_uint64_t ret = 0, file_size; + grub_err_t err; + + if (inode->inode_loaded == false) + { + err = erofs_read_inode (data, inode); + if (err != GRUB_ERR_NONE) + return -1; + } + + file_size = erofs_inode_file_size (inode); + + if (off > file_size) + { + grub_error (GRUB_ERR_IO, "read past EOF @ inode %" PRIuGRUB_UINT64_T, inode->ino); + return -1; + } + if (off == file_size) + return 0; + + if (off + len > file_size) + len = file_size - off; + + err = erofs_read_raw_data (inode, (grub_uint8_t *) buf, len, off, &ret); + if (err != GRUB_ERR_NONE) + return -1; + + return ret; +} + +static grub_err_t +grub_erofs_close (grub_file_t file) +{ + grub_free (file->data); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_erofs_uuid (grub_device_t device, char **uuid) +{ + struct grub_erofs_data *data; + + data = erofs_mount (device->disk, false); + if (data == NULL) + { + *uuid = NULL; + return grub_errno; + } + + *uuid = grub_xasprintf ("%pG", &data->sb.uuid); + + grub_free (data); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_erofs_label (grub_device_t device, char **label) +{ + struct grub_erofs_data *data; + + data = erofs_mount (device->disk, false); + if (data == NULL) + { + *label = NULL; + return grub_errno; + } + + *label = grub_strndup ((char *) data->sb.volume_name, sizeof (data->sb.volume_name)); + grub_free (data); + + if (*label == NULL) + return grub_errno; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_erofs_mtime (grub_device_t device, grub_int64_t *tm) +{ + struct grub_erofs_data *data; + + data = erofs_mount (device->disk, false); + if (data == NULL) + { + *tm = 0; + return grub_errno; + } + + *tm = grub_le_to_cpu64 (data->sb.build_time); + + grub_free (data); + + return GRUB_ERR_NONE; +} + +static struct grub_fs grub_erofs_fs = { + .name = "erofs", + .fs_dir = grub_erofs_dir, + .fs_open = grub_erofs_open, + .fs_read = grub_erofs_read, + .fs_close = grub_erofs_close, + .fs_uuid = grub_erofs_uuid, + .fs_label = grub_erofs_label, + .fs_mtime = grub_erofs_mtime, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, + .blocklist_install = 0, +#endif + .next = 0, +}; + +GRUB_MOD_INIT (erofs) +{ + grub_erofs_fs.mod = mod; + grub_fs_register (&grub_erofs_fs); +} + +GRUB_MOD_FINI (erofs) +{ + grub_fs_unregister (&grub_erofs_fs); +} diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c index c50e379d6..2f262dc34 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -46,6 +46,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -58,14 +59,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); (grub_le_to_cpu32 (data->sblock.log2_block_size) + 10) /* The size of an ext2 block in bytes. */ -#define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE (data)) +#define EXT2_BLOCK_SIZE(data) (1U << LOG2_BLOCK_SIZE (data)) /* The revision level. */ #define EXT2_REVISION(data) grub_le_to_cpu32 (data->sblock.revision_level) /* The inode size. */ #define EXT2_INODE_SIZE(data) \ - (EXT2_REVISION (data) == EXT2_GOOD_OLD_REVISION \ + (data->sblock.revision_level \ + == grub_cpu_to_le32_compile_time (EXT2_GOOD_OLD_REVISION) \ ? EXT2_GOOD_OLD_INODE_SIZE \ : grub_le_to_cpu16 (data->sblock.inode_size)) @@ -99,22 +101,46 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define EXT2_FEATURE_INCOMPAT_META_BG 0x0010 #define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* Extents used */ #define EXT4_FEATURE_INCOMPAT_64BIT 0x0080 +#define EXT4_FEATURE_INCOMPAT_MMP 0x0100 #define EXT4_FEATURE_INCOMPAT_FLEX_BG 0x0200 +#define EXT4_FEATURE_INCOMPAT_CSUM_SEED 0x2000 +#define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3 level htree */ +#define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000 /* The set of back-incompatible features this driver DOES support. Add (OR) * flags here as the related features are implemented into the driver. */ #define EXT2_DRIVER_SUPPORTED_INCOMPAT ( EXT2_FEATURE_INCOMPAT_FILETYPE \ | EXT4_FEATURE_INCOMPAT_EXTENTS \ - | EXT4_FEATURE_INCOMPAT_FLEX_BG ) + | EXT4_FEATURE_INCOMPAT_FLEX_BG \ + | EXT2_FEATURE_INCOMPAT_META_BG \ + | EXT4_FEATURE_INCOMPAT_64BIT \ + | EXT4_FEATURE_INCOMPAT_ENCRYPT) /* List of rationales for the ignored "incompatible" features: * needs_recovery: Not really back-incompatible - was added as such to forbid * ext2 drivers from mounting an ext3 volume with a dirty * journal because they will ignore the journal, but the next * ext3 driver to mount the volume will find the journal and * replay it, potentially corrupting the metadata written by - * the ext2 drivers. Safe to ignore for this RO driver. */ -#define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER ) - + * the ext2 drivers. Safe to ignore for this RO driver. + * mmp: Not really back-incompatible - was added as such to + * avoid multiple read-write mounts. Safe to ignore for this + * RO driver. + * checksum seed: Not really back-incompatible - was added to allow tools + * such as tune2fs to change the UUID on a mounted metadata + * checksummed filesystem. Safe to ignore for now since the + * driver doesn't support checksum verification. However, it + * has to be removed from this list if the support is added later. + * large_dir: Not back-incompatible given that the GRUB ext2 driver does + * not implement EXT2_FEATURE_COMPAT_DIR_INDEX. If the GRUB + * eventually supports the htree feature (aka dir_index) + * it should support 3 level htrees and then move + * EXT4_FEATURE_INCOMPAT_LARGEDIR to + * EXT2_DRIVER_SUPPORTED_INCOMPAT. + */ +#define EXT2_DRIVER_IGNORED_INCOMPAT ( EXT3_FEATURE_INCOMPAT_RECOVER \ + | EXT4_FEATURE_INCOMPAT_MMP \ + | EXT4_FEATURE_INCOMPAT_CSUM_SEED \ + | EXT4_FEATURE_INCOMPAT_LARGEDIR) #define EXT3_JOURNAL_MAGIC_NUMBER 0xc03b3998U @@ -129,6 +155,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define EXT3_JOURNAL_FLAG_DELETED 4 #define EXT3_JOURNAL_FLAG_LAST_TAG 8 +#define EXT4_ENCRYPT_FLAG 0x800 #define EXT4_EXTENTS_FLAG 0x80000 /* The ext2 superblock. */ @@ -179,7 +206,7 @@ struct grub_ext2_sblock grub_uint32_t hash_seed[4]; grub_uint8_t def_hash_version; grub_uint8_t jnl_backup_type; - grub_uint16_t reserved_word_pad; + grub_uint16_t group_desc_size; grub_uint32_t default_mount_opts; grub_uint32_t first_meta_bg; grub_uint32_t mkfs_time; @@ -197,6 +224,14 @@ struct grub_ext2_block_group grub_uint16_t used_dirs; grub_uint16_t pad; grub_uint32_t reserved[3]; + grub_uint32_t block_id_hi; + grub_uint32_t inode_id_hi; + grub_uint32_t inode_table_id_hi; + grub_uint16_t free_blocks_hi; + grub_uint16_t free_inodes_hi; + grub_uint16_t used_dirs_hi; + grub_uint16_t pad2; + grub_uint32_t reserved2[3]; }; /* The ext2 inode. */ @@ -237,6 +272,7 @@ struct ext2_dirent { grub_uint32_t inode; grub_uint16_t direntlen; +#define MAX_NAMELEN 255 grub_uint8_t namelen; grub_uint8_t filetype; }; @@ -310,6 +346,7 @@ struct grub_fshelp_node struct grub_ext2_data { struct grub_ext2_sblock sblock; + int log_group_desc_size; grub_disk_t disk; struct grub_ext2_inode *inode; struct grub_fshelp_node diropen; @@ -319,25 +356,80 @@ static grub_dl_t my_mod; +/* Check is a = b^x for some x. */ +static inline int +is_power_of (grub_uint64_t a, grub_uint32_t b) +{ + grub_uint64_t c; + /* Prevent overflow assuming b < 8. */ + if (a >= (1LL << 60)) + return 0; + for (c = 1; c <= a; c *= b); + return (c == a); +} + + +static inline int +group_has_super_block (struct grub_ext2_data *data, grub_uint64_t group) +{ + if (!(data->sblock.feature_ro_compat + & grub_cpu_to_le32_compile_time(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER))) + return 1; + /* Algorithm looked up in Linux source. */ + if (group <= 1) + return 1; + /* Even number is never a power of odd number. */ + if (!(group & 1)) + return 0; + return (is_power_of(group, 7) || is_power_of(group, 5) || + is_power_of(group, 3)); +} + /* Read into BLKGRP the blockgroup descriptor of blockgroup GROUP of the mounted filesystem DATA. */ inline static grub_err_t -grub_ext2_blockgroup (struct grub_ext2_data *data, int group, +grub_ext2_blockgroup (struct grub_ext2_data *data, grub_uint64_t group, struct grub_ext2_block_group *blkgrp) { + grub_uint64_t full_offset = (group << data->log_group_desc_size); + grub_uint64_t block, offset; + block = (full_offset >> LOG2_BLOCK_SIZE (data)); + offset = (full_offset & ((1 << LOG2_BLOCK_SIZE (data)) - 1)); + if ((data->sblock.feature_incompat + & grub_cpu_to_le32_compile_time (EXT2_FEATURE_INCOMPAT_META_BG)) + && block >= grub_le_to_cpu32(data->sblock.first_meta_bg)) + { + grub_uint64_t first_block_group; + /* Find the first block group for which a descriptor + is stored in given block. */ + first_block_group = (block << (LOG2_BLOCK_SIZE (data) + - data->log_group_desc_size)); + + block = (first_block_group + * grub_le_to_cpu32(data->sblock.blocks_per_group)); + + if (group_has_super_block (data, first_block_group)) + block++; + } + else + /* Superblock. */ + block++; return grub_disk_read (data->disk, - ((grub_le_to_cpu32 (data->sblock.first_data_block) + 1) - << LOG2_EXT2_BLOCK_SIZE (data)), - group * sizeof (struct grub_ext2_block_group), + ((grub_le_to_cpu32 (data->sblock.first_data_block) + + block) + << LOG2_EXT2_BLOCK_SIZE (data)), offset, sizeof (struct grub_ext2_block_group), blkgrp); } -static struct grub_ext4_extent_header * -grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf, +static grub_err_t +grub_ext4_find_leaf (struct grub_ext2_data *data, struct grub_ext4_extent_header *ext_block, - grub_uint32_t fileblock) + grub_uint32_t fileblock, + struct grub_ext4_extent_header **leaf) { struct grub_ext4_extent_idx *index; + void *buf = NULL; + *leaf = NULL; while (1) { @@ -346,11 +438,14 @@ grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf, index = (struct grub_ext4_extent_idx *) (ext_block + 1); - if (grub_le_to_cpu16(ext_block->magic) != EXT4_EXT_MAGIC) - return 0; + if (ext_block->magic != grub_cpu_to_le16_compile_time (EXT4_EXT_MAGIC)) + goto fail; if (ext_block->depth == 0) - return ext_block; + { + *leaf = ext_block; + return GRUB_ERR_NONE; + } for (i = 0; i < grub_le_to_cpu16 (ext_block->entries); i++) { @@ -359,17 +454,27 @@ grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf, } if (--i < 0) - return 0; + { + grub_free (buf); + return GRUB_ERR_NONE; + } block = grub_le_to_cpu16 (index[i].leaf_hi); - block = (block << 32) + grub_le_to_cpu32 (index[i].leaf); + block = (block << 32) | grub_le_to_cpu32 (index[i].leaf); + if (!buf) + buf = grub_malloc (EXT2_BLOCK_SIZE(data)); + if (!buf) + goto fail; if (grub_disk_read (data->disk, block << LOG2_EXT2_BLOCK_SIZE (data), 0, EXT2_BLOCK_SIZE(data), buf)) - return 0; + goto fail; - ext_block = (struct grub_ext4_extent_header *) buf; + ext_block = buf; } + fail: + grub_free (buf); + return GRUB_ERR_BAD_FS; } static grub_disk_addr_t @@ -377,28 +482,54 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { struct grub_ext2_data *data = node->data; struct grub_ext2_inode *inode = &node->inode; - int blknr = -1; unsigned int blksz = EXT2_BLOCK_SIZE (data); + grub_disk_addr_t blksz_quarter = blksz / 4; int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data); + int log_perblock = log2_blksz + 9 - 2; + grub_uint32_t indir; + int shift; - if (grub_le_to_cpu32(inode->flags) & EXT4_EXTENTS_FLAG) + if (inode->flags & grub_cpu_to_le32_compile_time (EXT4_EXTENTS_FLAG)) { - GRUB_PROPERLY_ALIGNED_ARRAY (buf, EXT2_BLOCK_SIZE(data)); struct grub_ext4_extent_header *leaf; struct grub_ext4_extent *ext; int i; + grub_disk_addr_t ret; + grub_uint16_t nent; + /* Maximum number of extent entries in the inode's inline extent area. */ + const grub_uint16_t max_inline_ext = sizeof (inode->blocks) / sizeof (*ext) - 1; /* Minus 1 extent header. */ + /* Maximum number of extent entries in the external extent block. */ + const grub_uint16_t max_external_ext = EXT2_BLOCK_SIZE (data) / sizeof (*ext) - 1; /* Minus 1 extent header. */ - leaf = grub_ext4_find_leaf (data, buf, - (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, - fileblock); - if (! leaf) + if (grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, + fileblock, &leaf) != GRUB_ERR_NONE) { grub_error (GRUB_ERR_BAD_FS, "invalid extent"); return -1; } + if (leaf == NULL) + /* Leaf for the given block is absent (i.e. sparse) */ + return 0; + ext = (struct grub_ext4_extent *) (leaf + 1); - for (i = 0; i < grub_le_to_cpu16 (leaf->entries); i++) + + nent = grub_le_to_cpu16 (leaf->entries); + + /* + * Determine the effective number of extent entries (nent) to process. + * If the extent header (leaf) is stored inline in the inode’s block + * area, i.e. at inode->blocks.dir_blocks, then only max_inline_ext + * entries can fit. Otherwise, if the header was read from an external + * extent block use the larger limit, max_external_ext, based on the + * full block size. + */ + if (leaf == (struct grub_ext4_extent_header *) inode->blocks.dir_blocks) + nent = grub_min (nent, max_inline_ext); + else + nent = grub_min (nent, max_external_ext); + + for (i = 0; i < nent; i++) { if (fileblock < grub_le_to_cpu32 (ext[i].block)) break; @@ -408,7 +539,7 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { fileblock -= grub_le_to_cpu32 (ext[i].block); if (fileblock >= grub_le_to_cpu16 (ext[i].len)) - return 0; + ret = 0; else { grub_disk_addr_t start; @@ -416,107 +547,80 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) start = grub_le_to_cpu16 (ext[i].start_hi); start = (start << 32) + grub_le_to_cpu32 (ext[i].start); - return fileblock + start; + ret = fileblock + start; } } else { grub_error (GRUB_ERR_BAD_FS, "something wrong with extent"); - return -1; + ret = -1; } + + if (leaf != (struct grub_ext4_extent_header *) inode->blocks.dir_blocks) + grub_free (leaf); + + return ret; } + /* Direct blocks. */ if (fileblock < INDIRECT_BLOCKS) - blknr = grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]); + return grub_le_to_cpu32 (inode->blocks.dir_blocks[fileblock]); + fileblock -= INDIRECT_BLOCKS; /* Indirect. */ - else if (fileblock < INDIRECT_BLOCKS + blksz / 4) + if (fileblock < blksz_quarter) { - grub_uint32_t indir[blksz / 4]; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (inode->blocks.indir_block)) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]); + indir = inode->blocks.indir_block; + shift = 0; + goto indirect; } + fileblock -= blksz_quarter; /* Double indirect. */ - else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1)) + if (fileblock < blksz_quarter * blksz_quarter) { - unsigned int perblock = blksz / 4; - unsigned int rblock = fileblock - (INDIRECT_BLOCKS - + blksz / 4); - grub_uint32_t indir[blksz / 4]; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (inode->blocks.double_indir_block)) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (indir[rblock / perblock])) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - - blknr = grub_le_to_cpu32 (indir[rblock % perblock]); + indir = inode->blocks.double_indir_block; + shift = 1; + goto indirect; } - /* triple indirect. */ - else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1) - + (blksz / 4) * (blksz / 4) * (blksz / 4 + 1)) + fileblock -= blksz_quarter * blksz_quarter; + /* Triple indirect. */ + if (fileblock < blksz_quarter * blksz_quarter * (blksz_quarter + 1)) { - unsigned int perblock = blksz / 4; - unsigned int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 - * (blksz / 4 + 1)); - grub_uint32_t indir[blksz / 4]; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (inode->blocks.triple_indir_block)) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (indir[(rblock / perblock) / perblock])) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) - grub_le_to_cpu32 (indir[(rblock / perblock) % perblock])) - << log2_blksz, - 0, blksz, indir)) - return grub_errno; - - blknr = grub_le_to_cpu32 (indir[rblock % perblock]); - } - else - { - grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "ext2fs doesn't support quadruple indirect blocks"); + indir = inode->blocks.triple_indir_block; + shift = 2; + goto indirect; } + grub_error (GRUB_ERR_BAD_FS, + "ext2fs doesn't support quadruple indirect blocks"); + return -1; - return blknr; +indirect: + do { + /* If the indirect block is zero, all child blocks are absent + (i.e. filled with zeros.) */ + if (indir == 0) + return 0; + if (grub_disk_read (data->disk, + ((grub_disk_addr_t) grub_le_to_cpu32 (indir)) + << log2_blksz, + ((fileblock >> (log_perblock * shift)) + & ((1 << log_perblock) - 1)) + * sizeof (indir), + sizeof (indir), &indir)) + return -1; + } while (shift--); + + return grub_le_to_cpu32 (indir); } /* Read LEN bytes from the file described by DATA starting with byte POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_ext2_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { - return grub_fshelp_read_file (node->data->disk, node, read_hook, + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, pos, len, buf, grub_ext2_read_block, grub_cpu_to_le32 (node->inode.size) | (((grub_off_t) grub_cpu_to_le32 (node->inode.size_high)) << 32), @@ -535,6 +639,7 @@ grub_ext2_read_inode (struct grub_ext2_data *data, int inodes_per_block; unsigned int blkno; unsigned int blkoff; + grub_disk_addr_t base; /* It is easier to calculate if the first inode is 0. */ ino--; @@ -551,10 +656,14 @@ grub_ext2_read_inode (struct grub_ext2_data *data, blkoff = (ino % grub_le_to_cpu32 (sblock->inodes_per_group)) % inodes_per_block; + base = grub_le_to_cpu32 (blkgrp.inode_table_id); + if (data->log_group_desc_size >= 6) + base |= (((grub_disk_addr_t) grub_le_to_cpu32 (blkgrp.inode_table_id_hi)) + << 32); + /* Read the inode. */ if (grub_disk_read (data->disk, - (((grub_disk_addr_t) grub_le_to_cpu32 (blkgrp.inode_table_id) + blkno) - << LOG2_EXT2_BLOCK_SIZE (data)), + ((base + blkno) << LOG2_EXT2_BLOCK_SIZE (data)), EXT2_INODE_SIZE (data) * blkoff, sizeof (struct grub_ext2_inode), inode)) return grub_errno; @@ -578,21 +687,42 @@ grub_ext2_mount (grub_disk_t disk) goto fail; /* Make sure this is an ext2 filesystem. */ - if (grub_le_to_cpu16 (data->sblock.magic) != EXT2_MAGIC - || grub_le_to_cpu32 (data->sblock.log2_block_size) >= 16) + if (data->sblock.magic != grub_cpu_to_le16_compile_time (EXT2_MAGIC) + || grub_le_to_cpu32 (data->sblock.log2_block_size) >= 16 + || data->sblock.inodes_per_group == 0 + /* 20 already means 1GiB blocks. We don't want to deal with blocks overflowing int32. */ + || grub_le_to_cpu32 (data->sblock.log2_block_size) > 20 + || EXT2_INODE_SIZE (data) == 0 + || EXT2_BLOCK_SIZE (data) / EXT2_INODE_SIZE (data) == 0) { grub_error (GRUB_ERR_BAD_FS, "not an ext2 filesystem"); goto fail; } /* Check the FS doesn't have feature bits enabled that we don't support. */ - if (grub_le_to_cpu32 (data->sblock.feature_incompat) - & ~(EXT2_DRIVER_SUPPORTED_INCOMPAT | EXT2_DRIVER_IGNORED_INCOMPAT)) + if (data->sblock.revision_level != grub_cpu_to_le32_compile_time (EXT2_GOOD_OLD_REVISION) + && (data->sblock.feature_incompat + & grub_cpu_to_le32_compile_time (~(EXT2_DRIVER_SUPPORTED_INCOMPAT + | EXT2_DRIVER_IGNORED_INCOMPAT)))) { grub_error (GRUB_ERR_BAD_FS, "filesystem has unsupported incompatible features"); goto fail; } + if (data->sblock.revision_level != grub_cpu_to_le32_compile_time (EXT2_GOOD_OLD_REVISION) + && (data->sblock.feature_incompat + & grub_cpu_to_le32_compile_time (EXT4_FEATURE_INCOMPAT_64BIT)) + && data->sblock.group_desc_size != 0 + && ((data->sblock.group_desc_size & (data->sblock.group_desc_size - 1)) + == 0) + && (data->sblock.group_desc_size & grub_cpu_to_le16_compile_time (0x1fe0))) + { + grub_uint16_t b = grub_le_to_cpu16 (data->sblock.group_desc_size); + for (data->log_group_desc_size = 0; b != (1 << data->log_group_desc_size); + data->log_group_desc_size++); + } + else + data->log_group_desc_size = 5; data->disk = disk; @@ -621,28 +751,42 @@ grub_ext2_read_symlink (grub_fshelp_node_t node) { char *symlink; struct grub_fshelp_node *diro = node; + grub_size_t sz; if (! diro->inode_read) { grub_ext2_read_inode (diro->data, diro->ino, &diro->inode); if (grub_errno) return 0; + + if (diro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG)) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "symlink is encrypted"); + return 0; + } } - symlink = grub_malloc (grub_le_to_cpu32 (diro->inode.size) + 1); + if (grub_add (grub_le_to_cpu32 (diro->inode.size), 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + return NULL; + } + + symlink = grub_malloc (sz); if (! symlink) return 0; - /* If the filesize of the symlink is bigger than - 60 the symlink is stored in a separate block, - otherwise it is stored in the inode. */ - if (grub_le_to_cpu32 (diro->inode.size) <= 60) - grub_strncpy (symlink, - diro->inode.symlink, - grub_le_to_cpu32 (diro->inode.size)); + /* + * If the filesize of the symlink is equal to or bigger than 60 the symlink + * is stored in a separate block, otherwise it is stored in the inode. + */ + if (grub_le_to_cpu32 (diro->inode.size) < sizeof (diro->inode.symlink)) + grub_memcpy (symlink, + diro->inode.symlink, + grub_le_to_cpu32 (diro->inode.size)); else { - grub_ext2_read_file (diro, 0, 0, + grub_ext2_read_file (diro, 0, 0, 0, grub_le_to_cpu32 (diro->inode.size), symlink); if (grub_errno) @@ -658,10 +802,7 @@ grub_ext2_read_symlink (grub_fshelp_node_t node) static int grub_ext2_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { unsigned int fpos = 0; struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; @@ -673,12 +814,18 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir, return 0; } + if (diro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG)) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "directory is encrypted"); + return 0; + } + /* Search the file. */ while (fpos < grub_le_to_cpu32 (diro->inode.size)) { struct ext2_dirent dirent; - grub_ext2_read_file (diro, 0, fpos, sizeof (struct ext2_dirent), + grub_ext2_read_file (diro, 0, 0, fpos, sizeof (struct ext2_dirent), (char *) &dirent); if (grub_errno) return 0; @@ -688,11 +835,11 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir, if (dirent.inode != 0 && dirent.namelen != 0) { - char filename[dirent.namelen + 1]; + char filename[MAX_NAMELEN + 1]; struct grub_fshelp_node *fdiro; enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; - grub_ext2_read_file (diro, 0, fpos + sizeof (struct ext2_dirent), + grub_ext2_read_file (diro, 0, 0, fpos + sizeof (struct ext2_dirent), dirent.namelen, filename); if (grub_errno) return 0; @@ -743,7 +890,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir, type = GRUB_FSHELP_REG; } - if (hook (filename, type, fdiro)) + if (hook (filename, type, fdiro, hook_data)) return 1; } @@ -783,6 +930,12 @@ grub_ext2_open (struct grub_file *file, const char *name) goto fail; } + if (fdiro->inode.flags & grub_cpu_to_le32_compile_time (EXT4_ENCRYPT_FLAG)) + { + err = grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "file is encrypted"); + goto fail; + } + grub_memcpy (data->inode, &fdiro->inode, sizeof (struct grub_ext2_inode)); grub_free (fdiro); @@ -819,64 +972,75 @@ grub_ext2_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_ext2_data *data = (struct grub_ext2_data *) file->data; - return grub_ext2_read_file (&data->diropen, file->read_hook, + return grub_ext2_read_file (&data->diropen, + file->read_hook, file->read_hook_data, file->offset, len, buf); } -static grub_err_t -grub_ext2_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) +/* Context for grub_ext2_dir. */ +struct grub_ext2_dir_ctx { - struct grub_ext2_data *data = 0; - struct grub_fshelp_node *fdiro = 0; + grub_fs_dir_hook_t hook; + void *hook_data; + struct grub_ext2_data *data; +}; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); +/* Helper for grub_ext2_dir. */ +static int +grub_ext2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_ext2_dir_ctx *ctx = data; + struct grub_dirhook_info info; - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) + grub_memset (&info, 0, sizeof (info)); + if (! node->inode_read) { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - if (! node->inode_read) - { - grub_ext2_read_inode (data, node->ino, &node->inode); - if (!grub_errno) - node->inode_read = 1; - grub_errno = GRUB_ERR_NONE; - } - if (node->inode_read) - { - info.mtimeset = 1; - info.mtime = grub_le_to_cpu32 (node->inode.mtime); - } - - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - grub_free (node); - return hook (filename, &info); + grub_ext2_read_inode (ctx->data, node->ino, &node->inode); + if (!grub_errno) + node->inode_read = 1; + grub_errno = GRUB_ERR_NONE; } + if (node->inode_read) + { + info.mtimeset = 1; + info.mtime = grub_le_to_cpu32 (node->inode.mtime); + } + + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + +static grub_err_t +grub_ext2_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, + void *hook_data) +{ + struct grub_ext2_dir_ctx ctx = { + .hook = hook, + .hook_data = hook_data + }; + struct grub_fshelp_node *fdiro = 0; grub_dl_ref (my_mod); - data = grub_ext2_mount (device->disk); - if (! data) + ctx.data = grub_ext2_mount (device->disk); + if (! ctx.data) goto fail; - grub_fshelp_find_file (path, &data->diropen, &fdiro, grub_ext2_iterate_dir, - grub_ext2_read_symlink, GRUB_FSHELP_DIR); + grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro, + grub_ext2_iterate_dir, grub_ext2_read_symlink, + GRUB_FSHELP_DIR); if (grub_errno) goto fail; - grub_ext2_iterate_dir (fdiro, iterate); + grub_ext2_iterate_dir (fdiro, grub_ext2_dir_iter, &ctx); fail: - if (fdiro != &data->diropen) + if (fdiro != &ctx.data->diropen) grub_free (fdiro); - grub_free (data); + grub_free (ctx.data); grub_dl_unref (my_mod); @@ -938,7 +1102,7 @@ grub_ext2_uuid (grub_device_t device, char **uuid) /* Get mtime. */ static grub_err_t -grub_ext2_mtime (grub_device_t device, grub_int32_t *tm) +grub_ext2_mtime (grub_device_t device, grub_int64_t *tm) { struct grub_ext2_data *data; grub_disk_t disk = device->disk; @@ -964,13 +1128,13 @@ grub_ext2_mtime (grub_device_t device, grub_int32_t *tm) static struct grub_fs grub_ext2_fs = { .name = "ext2", - .dir = grub_ext2_dir, - .open = grub_ext2_open, - .read = grub_ext2_read, - .close = grub_ext2_close, - .label = grub_ext2_label, - .uuid = grub_ext2_uuid, - .mtime = grub_ext2_mtime, + .fs_dir = grub_ext2_dir, + .fs_open = grub_ext2_open, + .fs_read = grub_ext2_read, + .fs_close = grub_ext2_close, + .fs_label = grub_ext2_label, + .fs_uuid = grub_ext2_uuid, + .fs_mtime = grub_ext2_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, @@ -980,6 +1144,7 @@ static struct grub_fs grub_ext2_fs = GRUB_MOD_INIT(ext2) { + grub_ext2_fs.mod = mod; grub_fs_register (&grub_ext2_fs); my_mod = mod; } diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c new file mode 100644 index 000000000..72b4aa1e6 --- /dev/null +++ b/grub-core/fs/f2fs.c @@ -0,0 +1,1377 @@ +/* + * f2fs.c - Flash-Friendly File System + * + * Written by Jaegeuk Kim + * + * Copyright (C) 2015 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* F2FS Magic Number. */ +#define F2FS_SUPER_MAGIC 0xf2f52010 + +#define CHECKSUM_OFFSET 4092 /* Must be aligned 4 bytes. */ +#define U32_CHECKSUM_OFFSET (CHECKSUM_OFFSET >> 2) +#define CRCPOLY_LE 0xedb88320 + +/* Byte-size offset. */ +#define F2FS_SUPER_OFFSET ((grub_disk_addr_t)1024) +#define F2FS_SUPER_OFFSET0 (F2FS_SUPER_OFFSET >> GRUB_DISK_SECTOR_BITS) +#define F2FS_SUPER_OFFSET1 ((F2FS_SUPER_OFFSET + F2FS_BLKSIZE) >> \ + GRUB_DISK_SECTOR_BITS) + +/* 9 bits for 512 bytes. */ +#define F2FS_MIN_LOG_SECTOR_SIZE 9 + +/* Support only 4KB block. */ +#define F2FS_BLK_BITS 12 +#define F2FS_BLKSIZE (1 << F2FS_BLK_BITS) +#define F2FS_BLK_SEC_BITS (F2FS_BLK_BITS - GRUB_DISK_SECTOR_BITS) + +#define VERSION_LEN 256 +#define F2FS_MAX_EXTENSION 64 + +#define CP_COMPACT_SUM_FLAG 0x00000004 +#define CP_UMOUNT_FLAG 0x00000001 + +#define MAX_ACTIVE_LOGS 16 +#define MAX_ACTIVE_NODE_LOGS 8 +#define MAX_ACTIVE_DATA_LOGS 8 +#define NR_CURSEG_DATA_TYPE 3 +#define NR_CURSEG_NODE_TYPE 3 +#define NR_CURSEG_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE) + +#define ENTRIES_IN_SUM 512 +#define SUMMARY_SIZE 7 +#define SUM_FOOTER_SIZE 5 +#define JENTRY_SIZE (sizeof(struct grub_f2fs_nat_jent)) +#define SUM_ENTRIES_SIZE (SUMMARY_SIZE * ENTRIES_IN_SUM) +#define SUM_JOURNAL_SIZE (F2FS_BLKSIZE - SUM_FOOTER_SIZE - SUM_ENTRIES_SIZE) +#define NAT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) / JENTRY_SIZE) +#define NAT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) % JENTRY_SIZE) + +#define NAT_ENTRY_SIZE (sizeof(struct grub_f2fs_nat_entry)) +#define NAT_ENTRY_PER_BLOCK (F2FS_BLKSIZE / NAT_ENTRY_SIZE) + +#define F2FS_NAME_LEN 255 +#define F2FS_SLOT_LEN 8 +#define NR_DENTRY_IN_BLOCK 214 +#define SIZE_OF_DIR_ENTRY 11 /* By byte. */ +#define BITS_PER_BYTE 8 +#define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \ + BITS_PER_BYTE) +#define SIZE_OF_RESERVED (F2FS_BLKSIZE - \ + ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \ + NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP)) + +#define F2FS_INLINE_XATTR_ADDRS 50 /* 200 bytes for inline xattrs. */ +#define DEF_ADDRS_PER_INODE 923 /* Address Pointers in an Inode. */ + +#define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block. */ +#define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block. */ +#define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1) +#define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2) +#define NODE_IND1_BLOCK (DEF_ADDRS_PER_INODE + 3) +#define NODE_IND2_BLOCK (DEF_ADDRS_PER_INODE + 4) +#define NODE_DIND_BLOCK (DEF_ADDRS_PER_INODE + 5) + +#define MAX_INLINE_DATA (4 * (DEF_ADDRS_PER_INODE - \ + F2FS_INLINE_XATTR_ADDRS - 1)) +#define NR_INLINE_DENTRY (MAX_INLINE_DATA * BITS_PER_BYTE / \ + ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \ + BITS_PER_BYTE + 1)) +#define INLINE_DENTRY_BITMAP_SIZE ((NR_INLINE_DENTRY + BITS_PER_BYTE - 1) / \ + BITS_PER_BYTE) +#define INLINE_RESERVED_SIZE (MAX_INLINE_DATA - \ + ((SIZE_OF_DIR_ENTRY + F2FS_SLOT_LEN) * \ + NR_INLINE_DENTRY + \ + INLINE_DENTRY_BITMAP_SIZE)) +#define CURSEG_HOT_DATA 0 + +#define CKPT_FLAG_SET(ckpt, f) (ckpt)->ckpt_flags & \ + grub_cpu_to_le32_compile_time (f) + +#define F2FS_INLINE_XATTR 0x01 /* File inline xattr flag. */ +#define F2FS_INLINE_DATA 0x02 /* File inline data flag. */ +#define F2FS_INLINE_DENTRY 0x04 /* File inline dentry flag. */ +#define F2FS_DATA_EXIST 0x08 /* File inline data exist flag. */ +#define F2FS_INLINE_DOTS 0x10 /* File having implicit dot dentries. */ + +#define MAX_VOLUME_NAME 512 +#define MAX_NAT_BITMAP_SIZE 3900 + +enum FILE_TYPE +{ + F2FS_FT_UNKNOWN, + F2FS_FT_REG_FILE = 1, + F2FS_FT_DIR = 2, + F2FS_FT_SYMLINK = 7 +}; + +struct grub_f2fs_superblock +{ + grub_uint32_t magic; + grub_uint16_t dummy1[2]; + grub_uint32_t log_sectorsize; + grub_uint32_t log_sectors_per_block; + grub_uint32_t log_blocksize; + grub_uint32_t log_blocks_per_seg; + grub_uint32_t segs_per_sec; + grub_uint32_t secs_per_zone; + grub_uint32_t checksum_offset; + grub_uint8_t dummy2[40]; + grub_uint32_t cp_blkaddr; + grub_uint32_t sit_blkaddr; + grub_uint32_t nat_blkaddr; + grub_uint32_t ssa_blkaddr; + grub_uint32_t main_blkaddr; + grub_uint32_t root_ino; + grub_uint32_t node_ino; + grub_uint32_t meta_ino; + grub_uint8_t uuid[16]; + grub_uint16_t volume_name[MAX_VOLUME_NAME]; + grub_uint32_t extension_count; + grub_uint8_t extension_list[F2FS_MAX_EXTENSION][8]; + grub_uint32_t cp_payload; + grub_uint8_t version[VERSION_LEN]; + grub_uint8_t init_version[VERSION_LEN]; +} GRUB_PACKED; + +struct grub_f2fs_checkpoint +{ + grub_uint64_t checkpoint_ver; + grub_uint64_t user_block_count; + grub_uint64_t valid_block_count; + grub_uint32_t rsvd_segment_count; + grub_uint32_t overprov_segment_count; + grub_uint32_t free_segment_count; + grub_uint32_t cur_node_segno[MAX_ACTIVE_NODE_LOGS]; + grub_uint16_t cur_node_blkoff[MAX_ACTIVE_NODE_LOGS]; + grub_uint32_t cur_data_segno[MAX_ACTIVE_DATA_LOGS]; + grub_uint16_t cur_data_blkoff[MAX_ACTIVE_DATA_LOGS]; + grub_uint32_t ckpt_flags; + grub_uint32_t cp_pack_total_block_count; + grub_uint32_t cp_pack_start_sum; + grub_uint32_t valid_node_count; + grub_uint32_t valid_inode_count; + grub_uint32_t next_free_nid; + grub_uint32_t sit_ver_bitmap_bytesize; + grub_uint32_t nat_ver_bitmap_bytesize; + grub_uint32_t checksum_offset; + grub_uint64_t elapsed_time; + grub_uint8_t alloc_type[MAX_ACTIVE_LOGS]; + grub_uint8_t sit_nat_version_bitmap[MAX_NAT_BITMAP_SIZE]; + grub_uint32_t checksum; +} GRUB_PACKED; + +struct grub_f2fs_nat_entry { + grub_uint8_t version; + grub_uint32_t ino; + grub_uint32_t block_addr; +} GRUB_PACKED; + +struct grub_f2fs_nat_jent +{ + grub_uint32_t nid; + struct grub_f2fs_nat_entry ne; +} GRUB_PACKED; + +struct grub_f2fs_nat_journal { + grub_uint16_t n_nats; + struct grub_f2fs_nat_jent entries[NAT_JOURNAL_ENTRIES]; + grub_uint8_t reserved[NAT_JOURNAL_RESERVED]; +} GRUB_PACKED; + +struct grub_f2fs_nat_block { + struct grub_f2fs_nat_entry ne[NAT_ENTRY_PER_BLOCK]; +} GRUB_PACKED; + +struct grub_f2fs_dir_entry +{ + grub_uint32_t hash_code; + grub_uint32_t ino; + grub_uint16_t name_len; + grub_uint8_t file_type; +} GRUB_PACKED; + +struct grub_f2fs_inline_dentry +{ + grub_uint8_t dentry_bitmap[INLINE_DENTRY_BITMAP_SIZE]; + grub_uint8_t reserved[INLINE_RESERVED_SIZE]; + struct grub_f2fs_dir_entry dentry[NR_INLINE_DENTRY]; + grub_uint8_t filename[NR_INLINE_DENTRY][F2FS_SLOT_LEN]; +} GRUB_PACKED; + +struct grub_f2fs_dentry_block { + grub_uint8_t dentry_bitmap[SIZE_OF_DENTRY_BITMAP]; + grub_uint8_t reserved[SIZE_OF_RESERVED]; + struct grub_f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK]; + grub_uint8_t filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN]; +} GRUB_PACKED; + +struct grub_f2fs_inode +{ + grub_uint16_t i_mode; + grub_uint8_t i_advise; + grub_uint8_t i_inline; + grub_uint32_t i_uid; + grub_uint32_t i_gid; + grub_uint32_t i_links; + grub_uint64_t i_size; + grub_uint64_t i_blocks; + grub_uint64_t i_atime; + grub_uint64_t i_ctime; + grub_uint64_t i_mtime; + grub_uint32_t i_atime_nsec; + grub_uint32_t i_ctime_nsec; + grub_uint32_t i_mtime_nsec; + grub_uint32_t i_generation; + grub_uint32_t i_current_depth; + grub_uint32_t i_xattr_nid; + grub_uint32_t i_flags; + grub_uint32_t i_pino; + grub_uint32_t i_namelen; + grub_uint8_t i_name[F2FS_NAME_LEN]; + grub_uint8_t i_dir_level; + grub_uint8_t i_ext[12]; + grub_uint32_t i_addr[DEF_ADDRS_PER_INODE]; + grub_uint32_t i_nid[5]; +} GRUB_PACKED; + +struct grub_direct_node { + grub_uint32_t addr[ADDRS_PER_BLOCK]; +} GRUB_PACKED; + +struct grub_indirect_node { + grub_uint32_t nid[NIDS_PER_BLOCK]; +} GRUB_PACKED; + +struct grub_f2fs_node +{ + union + { + struct grub_f2fs_inode i; + struct grub_direct_node dn; + struct grub_indirect_node in; + /* Should occupy F2FS_BLKSIZE totally. */ + char buf[F2FS_BLKSIZE - 40]; + }; + grub_uint8_t dummy[40]; +} GRUB_PACKED; + +struct grub_fshelp_node +{ + struct grub_f2fs_data *data; + struct grub_f2fs_node inode; + grub_uint32_t ino; + int inode_read; +}; + +struct grub_f2fs_data +{ + struct grub_f2fs_superblock sblock; + struct grub_f2fs_checkpoint ckpt; + + grub_uint32_t root_ino; + grub_uint32_t blocks_per_seg; + grub_uint32_t cp_blkaddr; + grub_uint32_t nat_blkaddr; + + struct grub_f2fs_nat_journal nat_j; + char *nat_bitmap; + grub_uint32_t nat_bitmap_size; + + grub_disk_t disk; + struct grub_f2fs_node *inode; + struct grub_fshelp_node diropen; +}; + +struct grub_f2fs_dir_iter_ctx +{ + struct grub_f2fs_data *data; + grub_fshelp_iterate_dir_hook_t hook; + void *hook_data; + grub_uint8_t *bitmap; + grub_uint8_t (*filename)[F2FS_SLOT_LEN]; + struct grub_f2fs_dir_entry *dentry; + int max; +}; + +struct grub_f2fs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; + struct grub_f2fs_data *data; +}; + +static grub_dl_t my_mod; + +static int +grub_f2fs_test_bit_le (int nr, const grub_uint8_t *addr) +{ + return addr[nr >> 3] & (1 << (nr & 7)); +} + +static char * +get_inline_addr (struct grub_f2fs_inode *inode) +{ + return (char *) &inode->i_addr[1]; +} + +static grub_uint64_t +grub_f2fs_file_size (struct grub_f2fs_inode *inode) +{ + return grub_le_to_cpu64 (inode->i_size); +} + +static grub_uint32_t +start_cp_addr (struct grub_f2fs_data *data) +{ + struct grub_f2fs_checkpoint *ckpt = &data->ckpt; + grub_uint32_t start_addr = data->cp_blkaddr; + + if (!(ckpt->checkpoint_ver & grub_cpu_to_le64_compile_time(1))) + return start_addr + data->blocks_per_seg; + + return start_addr; +} + +static grub_uint32_t +start_sum_block (struct grub_f2fs_data *data) +{ + struct grub_f2fs_checkpoint *ckpt = &data->ckpt; + + return start_cp_addr (data) + grub_le_to_cpu32 (ckpt->cp_pack_start_sum); +} + +static grub_uint32_t +sum_blk_addr (struct grub_f2fs_data *data, int base, int type) +{ + struct grub_f2fs_checkpoint *ckpt = &data->ckpt; + + return start_cp_addr (data) + + grub_le_to_cpu32 (ckpt->cp_pack_total_block_count) - + (base + 1) + type; +} + +static void * +nat_bitmap_ptr (struct grub_f2fs_data *data, grub_uint32_t *nat_bitmap_size) +{ + struct grub_f2fs_checkpoint *ckpt = &data->ckpt; + grub_uint32_t offset; + *nat_bitmap_size = MAX_NAT_BITMAP_SIZE; + + if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0) + return ckpt->sit_nat_version_bitmap; + + offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize); + if (offset >= MAX_NAT_BITMAP_SIZE) + return NULL; + + *nat_bitmap_size = *nat_bitmap_size - offset; + + return ckpt->sit_nat_version_bitmap + offset; +} + +static grub_uint32_t +get_node_id (struct grub_f2fs_node *rn, int off, int inode_block) +{ + if (inode_block) + return grub_le_to_cpu32 (rn->i.i_nid[off - NODE_DIR1_BLOCK]); + + return grub_le_to_cpu32 (rn->in.nid[off]); +} + +static grub_err_t +grub_f2fs_block_read (struct grub_f2fs_data *data, grub_uint32_t blkaddr, + void *buf) +{ + return grub_disk_read (data->disk, + ((grub_disk_addr_t)blkaddr) << F2FS_BLK_SEC_BITS, + 0, F2FS_BLKSIZE, buf); +} + +/* CRC32 */ +static grub_uint32_t +grub_f2fs_cal_crc32 (const void *buf, const grub_uint32_t len) +{ + grub_uint32_t crc = F2FS_SUPER_MAGIC; + unsigned char *p = (unsigned char *)buf; + grub_uint32_t tmp = len; + int i; + + while (tmp--) + { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); + } + + return crc; +} + +static int +grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len) +{ + grub_uint32_t cal_crc = 0; + + cal_crc = grub_f2fs_cal_crc32 (buf, len); + + return (cal_crc == blk_crc) ? 1 : 0; +} + +static int +grub_f2fs_test_bit (grub_uint32_t nr, const char *p, grub_uint32_t len) +{ + int mask; + grub_uint32_t shifted_nr = (nr >> 3); + + if (shifted_nr >= len) + return -1; + + p += shifted_nr; + mask = 1 << (7 - (nr & 0x07)); + + return mask & *p; +} + +static int +grub_f2fs_sanity_check_sb (struct grub_f2fs_superblock *sb) +{ + grub_uint32_t log_sectorsize, log_sectors_per_block; + + if (sb->magic != grub_cpu_to_le32_compile_time (F2FS_SUPER_MAGIC)) + return -1; + + if (sb->log_blocksize != grub_cpu_to_le32_compile_time (F2FS_BLK_BITS)) + return -1; + + log_sectorsize = grub_le_to_cpu32 (sb->log_sectorsize); + log_sectors_per_block = grub_le_to_cpu32 (sb->log_sectors_per_block); + + if (log_sectorsize > F2FS_BLK_BITS) + return -1; + + if (log_sectorsize < F2FS_MIN_LOG_SECTOR_SIZE) + return -1; + + if (log_sectors_per_block + log_sectorsize != F2FS_BLK_BITS) + return -1; + + return 0; +} + +static int +grub_f2fs_read_sb (struct grub_f2fs_data *data, grub_disk_addr_t offset) +{ + grub_disk_t disk = data->disk; + grub_err_t err; + + /* Read first super block. */ + err = grub_disk_read (disk, offset, 0, sizeof (data->sblock), &data->sblock); + if (err) + return -1; + + return grub_f2fs_sanity_check_sb (&data->sblock); +} + +static void * +validate_checkpoint (struct grub_f2fs_data *data, grub_uint32_t cp_addr, + grub_uint64_t *version) +{ + grub_uint32_t *cp_page_1, *cp_page_2; + struct grub_f2fs_checkpoint *cp_block; + grub_uint64_t cur_version = 0, pre_version = 0; + grub_uint32_t crc = 0; + grub_uint32_t crc_offset; + grub_err_t err; + + /* Read the 1st cp block in this CP pack. */ + cp_page_1 = grub_malloc (F2FS_BLKSIZE); + if (!cp_page_1) + return NULL; + + err = grub_f2fs_block_read (data, cp_addr, cp_page_1); + if (err) + goto invalid_cp1; + + cp_block = (struct grub_f2fs_checkpoint *)cp_page_1; + crc_offset = grub_le_to_cpu32 (cp_block->checksum_offset); + if (crc_offset != CHECKSUM_OFFSET) + goto invalid_cp1; + + crc = grub_le_to_cpu32 (*(cp_page_1 + U32_CHECKSUM_OFFSET)); + if (!grub_f2fs_crc_valid (crc, cp_block, crc_offset)) + goto invalid_cp1; + + pre_version = grub_le_to_cpu64 (cp_block->checkpoint_ver); + + /* Read the 2nd cp block in this CP pack. */ + cp_page_2 = grub_malloc (F2FS_BLKSIZE); + if (!cp_page_2) + goto invalid_cp1; + + cp_addr += grub_le_to_cpu32 (cp_block->cp_pack_total_block_count) - 1; + + err = grub_f2fs_block_read (data, cp_addr, cp_page_2); + if (err) + goto invalid_cp2; + + cp_block = (struct grub_f2fs_checkpoint *)cp_page_2; + crc_offset = grub_le_to_cpu32 (cp_block->checksum_offset); + if (crc_offset != CHECKSUM_OFFSET) + goto invalid_cp2; + + crc = grub_le_to_cpu32 (*(cp_page_2 + U32_CHECKSUM_OFFSET)); + if (!grub_f2fs_crc_valid (crc, cp_block, crc_offset)) + goto invalid_cp2; + + cur_version = grub_le_to_cpu64 (cp_block->checkpoint_ver); + if (cur_version == pre_version) + { + *version = cur_version; + grub_free (cp_page_2); + + return cp_page_1; + } + + invalid_cp2: + grub_free (cp_page_2); + + invalid_cp1: + grub_free (cp_page_1); + + return NULL; +} + +static grub_err_t +grub_f2fs_read_cp (struct grub_f2fs_data *data) +{ + void *cp1, *cp2, *cur_page; + grub_uint64_t cp1_version = 0, cp2_version = 0; + grub_uint64_t cp_start_blk_no; + + /* + * Finding out valid cp block involves read both + * sets (cp pack1 and cp pack 2). + */ + cp_start_blk_no = data->cp_blkaddr; + cp1 = validate_checkpoint (data, cp_start_blk_no, &cp1_version); + if (!cp1 && grub_errno) + return grub_errno; + + /* The second checkpoint pack should start at the next segment. */ + cp_start_blk_no += data->blocks_per_seg; + cp2 = validate_checkpoint (data, cp_start_blk_no, &cp2_version); + if (!cp2 && grub_errno) + { + grub_free (cp1); + return grub_errno; + } + + if (cp1 && cp2) + cur_page = (cp2_version > cp1_version) ? cp2 : cp1; + else if (cp1) + cur_page = cp1; + else if (cp2) + cur_page = cp2; + else + return grub_error (GRUB_ERR_BAD_FS, "no checkpoints"); + + grub_memcpy (&data->ckpt, cur_page, F2FS_BLKSIZE); + + grub_free (cp1); + grub_free (cp2); + + return 0; +} + +static grub_err_t +get_nat_journal (struct grub_f2fs_data *data) +{ + grub_uint32_t block; + char *buf; + grub_err_t err; + + buf = grub_malloc (F2FS_BLKSIZE); + if (!buf) + return grub_errno; + + if (CKPT_FLAG_SET(&data->ckpt, CP_COMPACT_SUM_FLAG)) + block = start_sum_block (data); + else if (CKPT_FLAG_SET (&data->ckpt, CP_UMOUNT_FLAG)) + block = sum_blk_addr (data, NR_CURSEG_TYPE, CURSEG_HOT_DATA); + else + block = sum_blk_addr (data, NR_CURSEG_DATA_TYPE, CURSEG_HOT_DATA); + + err = grub_f2fs_block_read (data, block, buf); + if (err) + goto fail; + + if (CKPT_FLAG_SET (&data->ckpt, CP_COMPACT_SUM_FLAG)) + grub_memcpy (&data->nat_j, buf, SUM_JOURNAL_SIZE); + else + grub_memcpy (&data->nat_j, buf + SUM_ENTRIES_SIZE, SUM_JOURNAL_SIZE); + + fail: + grub_free (buf); + + return err; +} + +static grub_err_t +get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid, + grub_uint32_t *blkaddr) +{ + grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats); + grub_uint16_t i; + + if (n > NAT_JOURNAL_ENTRIES) + return grub_error (GRUB_ERR_BAD_FS, + "invalid number of nat journal entries"); + + for (i = 0; i < n; i++) + { + if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid) + { + *blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr); + break; + } + } + + return GRUB_ERR_NONE; +} + +static grub_uint32_t +get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid) +{ + struct grub_f2fs_nat_block *nat_block; + grub_uint32_t seg_off, block_off, entry_off, block_addr; + grub_uint32_t blkaddr = 0; + grub_err_t err; + int result_bit; + + err = get_blkaddr_from_nat_journal (data, nid, &blkaddr); + if (err != GRUB_ERR_NONE) + return 0; + + if (blkaddr) + return blkaddr; + + nat_block = grub_malloc (F2FS_BLKSIZE); + if (!nat_block) + return 0; + + block_off = nid / NAT_ENTRY_PER_BLOCK; + entry_off = nid % NAT_ENTRY_PER_BLOCK; + + seg_off = block_off / data->blocks_per_seg; + block_addr = data->nat_blkaddr + + ((seg_off * data->blocks_per_seg) << 1) + + (block_off & (data->blocks_per_seg - 1)); + + result_bit = grub_f2fs_test_bit (block_off, data->nat_bitmap, + data->nat_bitmap_size); + if (result_bit > 0) + block_addr += data->blocks_per_seg; + else if (result_bit == -1) + { + grub_free (nat_block); + return 0; + } + + err = grub_f2fs_block_read (data, block_addr, nat_block); + if (err) + { + grub_free (nat_block); + return 0; + } + + blkaddr = grub_le_to_cpu32 (nat_block->ne[entry_off].block_addr); + + grub_free (nat_block); + + return blkaddr; +} + +static int +grub_get_node_path (struct grub_f2fs_inode *inode, grub_uint32_t block, + grub_uint32_t offset[4], grub_uint32_t noffset[4]) +{ + grub_uint32_t direct_blks = ADDRS_PER_BLOCK; + grub_uint32_t dptrs_per_blk = NIDS_PER_BLOCK; + grub_uint32_t indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK; + grub_uint32_t dindirect_blks = indirect_blks * NIDS_PER_BLOCK; + grub_uint32_t direct_index = DEF_ADDRS_PER_INODE; + int n = 0; + int level = -1; + + if (inode->i_inline & F2FS_INLINE_XATTR) + direct_index -= F2FS_INLINE_XATTR_ADDRS; + + noffset[0] = 0; + + if (block < direct_index) + { + offset[n] = block; + level = 0; + goto got; + } + + block -= direct_index; + if (block < direct_blks) + { + offset[n++] = NODE_DIR1_BLOCK; + noffset[n] = 1; + offset[n] = block; + level = 1; + goto got; + } + + block -= direct_blks; + if (block < direct_blks) + { + offset[n++] = NODE_DIR2_BLOCK; + noffset[n] = 2; + offset[n] = block; + level = 1; + goto got; + } + + block -= direct_blks; + if (block < indirect_blks) + { + offset[n++] = NODE_IND1_BLOCK; + noffset[n] = 3; + offset[n++] = block / direct_blks; + noffset[n] = 4 + offset[n - 1]; + offset[n] = block % direct_blks; + level = 2; + goto got; + } + + block -= indirect_blks; + if (block < indirect_blks) + { + offset[n++] = NODE_IND2_BLOCK; + noffset[n] = 4 + dptrs_per_blk; + offset[n++] = block / direct_blks; + noffset[n] = 5 + dptrs_per_blk + offset[n - 1]; + offset[n] = block % direct_blks; + level = 2; + goto got; + } + + block -= indirect_blks; + if (block < dindirect_blks) + { + offset[n++] = NODE_DIND_BLOCK; + noffset[n] = 5 + (dptrs_per_blk * 2); + offset[n++] = block / indirect_blks; + noffset[n] = 6 + (dptrs_per_blk * 2) + + offset[n - 1] * (dptrs_per_blk + 1); + offset[n++] = (block / direct_blks) % dptrs_per_blk; + noffset[n] = 7 + (dptrs_per_blk * 2) + + offset[n - 2] * (dptrs_per_blk + 1) + offset[n - 1]; + offset[n] = block % direct_blks; + level = 3; + goto got; + } + + got: + return level; +} + +static grub_err_t +grub_f2fs_read_node (struct grub_f2fs_data *data, + grub_uint32_t nid, struct grub_f2fs_node *np) +{ + grub_uint32_t blkaddr; + + blkaddr = get_node_blkaddr (data, nid); + if (!blkaddr) + return grub_errno; + + return grub_f2fs_block_read (data, blkaddr, np); +} + +static struct grub_f2fs_data * +grub_f2fs_mount (grub_disk_t disk) +{ + struct grub_f2fs_data *data; + grub_err_t err; + + data = grub_malloc (sizeof (*data)); + if (!data) + return NULL; + + data->disk = disk; + + if (grub_f2fs_read_sb (data, F2FS_SUPER_OFFSET0)) + { + if (grub_f2fs_read_sb (data, F2FS_SUPER_OFFSET1)) + { + if (grub_errno == GRUB_ERR_NONE) + grub_error (GRUB_ERR_BAD_FS, + "not a F2FS filesystem (no superblock)"); + goto fail; + } + } + + data->root_ino = grub_le_to_cpu32 (data->sblock.root_ino); + data->cp_blkaddr = grub_le_to_cpu32 (data->sblock.cp_blkaddr); + data->nat_blkaddr = grub_le_to_cpu32 (data->sblock.nat_blkaddr); + data->blocks_per_seg = 1 << + grub_le_to_cpu32 (data->sblock.log_blocks_per_seg); + + err = grub_f2fs_read_cp (data); + if (err) + goto fail; + + data->nat_bitmap = nat_bitmap_ptr (data, &data->nat_bitmap_size); + if (data->nat_bitmap == NULL) + goto fail; + + err = get_nat_journal (data); + if (err) + goto fail; + + data->diropen.data = data; + data->diropen.ino = data->root_ino; + data->diropen.inode_read = 1; + data->inode = &data->diropen.inode; + + err = grub_f2fs_read_node (data, data->root_ino, data->inode); + if (err) + goto fail; + + return data; + + fail: + if (grub_errno == GRUB_ERR_NONE) + grub_error (GRUB_ERR_BAD_FS, "not a F2FS filesystem"); + + grub_free (data); + + return NULL; +} + +/* Guarantee inline_data was handled by caller. */ +static grub_disk_addr_t +grub_f2fs_get_block (grub_fshelp_node_t node, grub_disk_addr_t block_ofs) +{ + struct grub_f2fs_data *data = node->data; + struct grub_f2fs_inode *inode = &node->inode.i; + grub_uint32_t offset[4], noffset[4], nids[4]; + struct grub_f2fs_node *node_block; + grub_uint32_t block_addr = -1; + int level, i; + + level = grub_get_node_path (inode, block_ofs, offset, noffset); + + if (level < 0) + return -1; + + if (level == 0) + return grub_le_to_cpu32 (inode->i_addr[offset[0]]); + + node_block = grub_malloc (F2FS_BLKSIZE); + if (!node_block) + return -1; + + nids[1] = get_node_id (&node->inode, offset[0], 1); + + /* Get indirect or direct nodes. */ + for (i = 1; i <= level; i++) + { + grub_f2fs_read_node (data, nids[i], node_block); + if (grub_errno) + goto fail; + + if (i < level) + nids[i + 1] = get_node_id (node_block, offset[i], 0); + } + + block_addr = grub_le_to_cpu32 (node_block->dn.addr[offset[level]]); + + fail: + grub_free (node_block); + + return block_addr; +} + +static grub_ssize_t +grub_f2fs_read_file (grub_fshelp_node_t node, + grub_disk_read_hook_t read_hook, void *read_hook_data, + grub_off_t pos, grub_size_t len, char *buf) +{ + struct grub_f2fs_inode *inode = &node->inode.i; + grub_off_t filesize = grub_f2fs_file_size (inode); + char *inline_addr = get_inline_addr (inode); + + if (inode->i_inline & F2FS_INLINE_DATA) + { + if (filesize > MAX_INLINE_DATA) + return -1; + + if (len > filesize - pos) + len = filesize - pos; + + grub_memcpy (buf, inline_addr + pos, len); + return len; + } + + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, + pos, len, buf, grub_f2fs_get_block, + filesize, + F2FS_BLK_SEC_BITS, 0); +} + +static char * +grub_f2fs_read_symlink (grub_fshelp_node_t node) +{ + char *symlink; + struct grub_fshelp_node *diro = node; + grub_uint64_t filesize; + grub_size_t sz; + + if (!diro->inode_read) + { + grub_f2fs_read_node (diro->data, diro->ino, &diro->inode); + if (grub_errno) + return 0; + } + + filesize = grub_f2fs_file_size(&diro->inode.i); + + if (grub_add (filesize, 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink size overflow")); + return 0; + } + symlink = grub_malloc (sz); + if (!symlink) + return 0; + + grub_f2fs_read_file (diro, 0, 0, 0, filesize, symlink); + if (grub_errno) + { + grub_free (symlink); + return 0; + } + + symlink[filesize] = '\0'; + + return symlink; +} + +static int +grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx) +{ + struct grub_fshelp_node *fdiro; + int i; + + for (i = 0; i < ctx->max;) + { + char *filename; + enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; + enum FILE_TYPE ftype; + int name_len; + int ret; + int sz; + + if (grub_f2fs_test_bit_le (i, ctx->bitmap) == 0) + { + i++; + continue; + } + + ftype = ctx->dentry[i].file_type; + name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len); + + if (name_len >= F2FS_NAME_LEN) + return 0; + + if (grub_add (name_len, 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory entry name length overflow")); + return 0; + } + filename = grub_malloc (sz); + if (!filename) + return 0; + + grub_memcpy (filename, ctx->filename[i], name_len); + filename[name_len] = 0; + + fdiro = grub_malloc (sizeof (struct grub_fshelp_node)); + if (!fdiro) + { + grub_free(filename); + return 0; + } + + if (ftype == F2FS_FT_DIR) + type = GRUB_FSHELP_DIR; + else if (ftype == F2FS_FT_SYMLINK) + type = GRUB_FSHELP_SYMLINK; + else if (ftype == F2FS_FT_REG_FILE) + type = GRUB_FSHELP_REG; + + fdiro->data = ctx->data; + fdiro->ino = grub_le_to_cpu32 (ctx->dentry[i].ino); + fdiro->inode_read = 0; + + ret = ctx->hook (filename, type, fdiro, ctx->hook_data); + grub_free(filename); + if (ret) + return 1; + + i += (name_len + F2FS_SLOT_LEN - 1) / F2FS_SLOT_LEN; + } + + return 0; +} + +static int +grub_f2fs_iterate_inline_dir (struct grub_f2fs_inode *dir, + struct grub_f2fs_dir_iter_ctx *ctx) +{ + struct grub_f2fs_inline_dentry *de_blk; + + de_blk = (struct grub_f2fs_inline_dentry *) get_inline_addr (dir); + + ctx->bitmap = de_blk->dentry_bitmap; + ctx->dentry = de_blk->dentry; + ctx->filename = de_blk->filename; + ctx->max = NR_INLINE_DENTRY; + + return grub_f2fs_check_dentries (ctx); +} + +static int +grub_f2fs_iterate_dir (grub_fshelp_node_t dir, + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) +{ + struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; + struct grub_f2fs_inode *inode; + struct grub_f2fs_dir_iter_ctx ctx = { + .data = diro->data, + .hook = hook, + .hook_data = hook_data + }; + grub_off_t fpos = 0; + + if (!diro->inode_read) + { + grub_f2fs_read_node (diro->data, diro->ino, &diro->inode); + if (grub_errno) + return 0; + } + + inode = &diro->inode.i; + + if (inode->i_inline & F2FS_INLINE_DENTRY) + return grub_f2fs_iterate_inline_dir (inode, &ctx); + + while (fpos < grub_f2fs_file_size (inode)) + { + struct grub_f2fs_dentry_block *de_blk; + char *buf; + int ret; + + buf = grub_zalloc (F2FS_BLKSIZE); + if (!buf) + return 0; + + grub_f2fs_read_file (diro, 0, 0, fpos, F2FS_BLKSIZE, buf); + if (grub_errno) + { + grub_free (buf); + return 0; + } + + de_blk = (struct grub_f2fs_dentry_block *) buf; + + ctx.bitmap = de_blk->dentry_bitmap; + ctx.dentry = de_blk->dentry; + ctx.filename = de_blk->filename; + ctx.max = NR_DENTRY_IN_BLOCK; + + ret = grub_f2fs_check_dentries (&ctx); + grub_free (buf); + if (ret) + return 1; + + fpos += F2FS_BLKSIZE; + } + + return 0; +} + +static int +grub_f2fs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_f2fs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + if (!node->inode_read) + { + grub_f2fs_read_node (ctx->data, node->ino, &node->inode); + if (!grub_errno) + node->inode_read = 1; + grub_errno = GRUB_ERR_NONE; + } + if (node->inode_read) + { + info.mtimeset = 1; + info.mtime = grub_le_to_cpu64 (node->inode.i.i_mtime); + } + + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); + + return ctx->hook (filename, &info, ctx->hook_data); +} + +static grub_err_t +grub_f2fs_dir (grub_device_t device, const char *path, + grub_fs_dir_hook_t hook, void *hook_data) +{ + struct grub_f2fs_dir_ctx ctx = { + .hook = hook, + .hook_data = hook_data + }; + struct grub_fshelp_node *fdiro = 0; + + grub_dl_ref (my_mod); + + ctx.data = grub_f2fs_mount (device->disk); + if (!ctx.data) + goto fail; + + grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro, + grub_f2fs_iterate_dir, grub_f2fs_read_symlink, + GRUB_FSHELP_DIR); + if (grub_errno) + goto fail; + + grub_f2fs_iterate_dir (fdiro, grub_f2fs_dir_iter, &ctx); + + fail: + if (fdiro != &ctx.data->diropen) + grub_free (fdiro); + grub_free (ctx.data); + grub_dl_unref (my_mod); + + return grub_errno; +} + +/* Open a file named NAME and initialize FILE. */ +static grub_err_t +grub_f2fs_open (struct grub_file *file, const char *name) +{ + struct grub_f2fs_data *data = NULL; + struct grub_fshelp_node *fdiro = 0; + struct grub_f2fs_inode *inode; + + grub_dl_ref (my_mod); + + data = grub_f2fs_mount (file->device->disk); + if (!data) + goto fail; + + grub_fshelp_find_file (name, &data->diropen, &fdiro, + grub_f2fs_iterate_dir, grub_f2fs_read_symlink, + GRUB_FSHELP_REG); + if (grub_errno) + goto fail; + + if (!fdiro->inode_read) + { + grub_f2fs_read_node (data, fdiro->ino, &fdiro->inode); + if (grub_errno) + goto fail; + } + + grub_memcpy (data->inode, &fdiro->inode, sizeof (*data->inode)); + grub_free (fdiro); + + inode = &(data->inode->i); + file->size = grub_f2fs_file_size (inode); + file->data = data; + file->offset = 0; + + if (inode->i_inline & F2FS_INLINE_DATA && file->size > MAX_INLINE_DATA) + grub_error (GRUB_ERR_BAD_FS, "corrupted inline_data: need fsck"); + + return 0; + + fail: + if (fdiro != &data->diropen) + grub_free (fdiro); + grub_free (data); + + grub_dl_unref (my_mod); + + return grub_errno; +} + +static grub_ssize_t +grub_f2fs_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_f2fs_data *data = (struct grub_f2fs_data *) file->data; + + return grub_f2fs_read_file (&data->diropen, + file->read_hook, file->read_hook_data, + file->offset, len, buf); +} + +static grub_err_t +grub_f2fs_close (grub_file_t file) +{ + struct grub_f2fs_data *data = (struct grub_f2fs_data *) file->data; + + grub_free (data); + + grub_dl_unref (my_mod); + + return GRUB_ERR_NONE; +} + +static grub_uint8_t * +grub_f2fs_utf16_to_utf8 (grub_uint16_t *in_buf_le) +{ + grub_uint16_t in_buf[MAX_VOLUME_NAME]; + grub_uint8_t *out_buf; + int len = 0; + + out_buf = grub_malloc (MAX_VOLUME_NAME * GRUB_MAX_UTF8_PER_UTF16 + 1); + if (!out_buf) + return NULL; + + while (*in_buf_le != 0 && len < MAX_VOLUME_NAME) { + in_buf[len] = grub_le_to_cpu16 (in_buf_le[len]); + len++; + } + + *grub_utf16_to_utf8 (out_buf, in_buf, len) = '\0'; + + return out_buf; +} + +#if __GNUC__ >= 9 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" +#endif + +static grub_err_t +grub_f2fs_label (grub_device_t device, char **label) +{ + struct grub_f2fs_data *data; + grub_disk_t disk = device->disk; + + grub_dl_ref (my_mod); + + data = grub_f2fs_mount (disk); + if (data) + *label = (char *) grub_f2fs_utf16_to_utf8 (data->sblock.volume_name); + else + *label = NULL; + + grub_free (data); + grub_dl_unref (my_mod); + + return grub_errno; +} + +#if __GNUC__ >= 9 +#pragma GCC diagnostic pop +#endif + +static grub_err_t +grub_f2fs_uuid (grub_device_t device, char **uuid) +{ + struct grub_f2fs_data *data; + grub_disk_t disk = device->disk; + + grub_dl_ref (my_mod); + + data = grub_f2fs_mount (disk); + if (data) + { + *uuid = + grub_xasprintf + ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + data->sblock.uuid[0], data->sblock.uuid[1], + data->sblock.uuid[2], data->sblock.uuid[3], + data->sblock.uuid[4], data->sblock.uuid[5], + data->sblock.uuid[6], data->sblock.uuid[7], + data->sblock.uuid[8], data->sblock.uuid[9], + data->sblock.uuid[10], data->sblock.uuid[11], + data->sblock.uuid[12], data->sblock.uuid[13], + data->sblock.uuid[14], data->sblock.uuid[15]); + } + else + *uuid = NULL; + + grub_free (data); + grub_dl_unref (my_mod); + + return grub_errno; +} + +static struct grub_fs grub_f2fs_fs = { + .name = "f2fs", + .fs_dir = grub_f2fs_dir, + .fs_open = grub_f2fs_open, + .fs_read = grub_f2fs_read, + .fs_close = grub_f2fs_close, + .fs_label = grub_f2fs_label, + .fs_uuid = grub_f2fs_uuid, +#ifdef GRUB_UTIL + .reserved_first_sector = 1, + .blocklist_install = 0, +#endif + .next = 0 +}; + +GRUB_MOD_INIT (f2fs) +{ + grub_f2fs_fs.mod = mod; + grub_fs_register (&grub_f2fs_fs); + my_mod = mod; +} + +GRUB_MOD_FINI (f2fs) +{ + grub_fs_unregister (&grub_f2fs_fs); +} diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index 119fc945f..6e62b915d 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -26,7 +26,13 @@ #include #include #include +#include +#ifndef MODE_EXFAT #include +#else +#include +#endif +#include #include GRUB_MOD_LICENSE ("GPLv3+"); @@ -60,33 +66,16 @@ enum }; #ifdef MODE_EXFAT -struct grub_exfat_bpb -{ - grub_uint8_t jmp_boot[3]; - grub_uint8_t oem_name[8]; - grub_uint8_t mbz[53]; - grub_uint64_t num_hidden_sectors; - grub_uint64_t num_total_sectors; - grub_uint32_t num_reserved_sectors; - grub_uint32_t sectors_per_fat; - grub_uint32_t cluster_offset; - grub_uint32_t cluster_count; - grub_uint32_t root_cluster; - grub_uint32_t num_serial; - grub_uint16_t fs_revision; - grub_uint16_t volume_flags; - grub_uint8_t bytes_per_sector_shift; - grub_uint8_t sectors_per_cluster_shift; - grub_uint8_t num_fats; - grub_uint8_t num_ph_drive; - grub_uint8_t reserved[8]; -} __attribute__ ((packed)); typedef struct grub_exfat_bpb grub_current_fat_bpb_t; #else typedef struct grub_fat_bpb grub_current_fat_bpb_t; #endif #ifdef MODE_EXFAT +enum + { + FLAG_CONTIGUOUS = 2 + }; struct grub_fat_dir_entry { grub_uint8_t entry_type; @@ -105,7 +94,7 @@ struct grub_fat_dir_entry grub_uint8_t m_time_tenth; grub_uint8_t a_time_tenth; grub_uint8_t reserved2[9]; - } __attribute__ ((packed)) file; + } GRUB_PACKED file; struct { grub_uint8_t flags; grub_uint8_t reserved1; @@ -116,17 +105,17 @@ struct grub_fat_dir_entry grub_uint32_t reserved3; grub_uint32_t first_cluster; grub_uint64_t file_size; - } __attribute__ ((packed)) stream_extension; + } GRUB_PACKED stream_extension; struct { grub_uint8_t flags; grub_uint16_t str[15]; - } __attribute__ ((packed)) file_name; + } GRUB_PACKED file_name; struct { grub_uint8_t character_count; grub_uint16_t str[15]; - } __attribute__ ((packed)) volume_label; - } __attribute__ ((packed)) type_specific; -} __attribute__ ((packed)); + } GRUB_PACKED volume_label; + } GRUB_PACKED type_specific; +} GRUB_PACKED; struct grub_fat_dir_node { @@ -135,7 +124,7 @@ struct grub_fat_dir_node grub_uint64_t file_size; grub_uint64_t valid_size; int have_stream; - int is_label; + int is_contiguous; }; typedef struct grub_fat_dir_node grub_fat_dir_node_t; @@ -155,7 +144,7 @@ struct grub_fat_dir_entry grub_uint16_t w_date; grub_uint16_t first_cluster_low; grub_uint32_t file_size; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_fat_long_name_entry { @@ -167,7 +156,7 @@ struct grub_fat_long_name_entry grub_uint16_t name2[6]; grub_uint16_t first_cluster; grub_uint16_t name3[2]; -} __attribute__ ((packed)); +} GRUB_PACKED; typedef struct grub_fat_dir_entry grub_fat_dir_node_t; @@ -193,13 +182,26 @@ struct grub_fat_data grub_uint32_t cluster_sector; grub_uint32_t num_clusters; + grub_uint32_t uuid; +}; + +struct grub_fshelp_node { + grub_disk_t disk; + struct grub_fat_data *data; + grub_uint8_t attr; - grub_ssize_t file_size; +#ifndef MODE_EXFAT + grub_uint32_t file_size; +#else + grub_uint64_t file_size; +#endif grub_uint32_t file_cluster; grub_uint32_t cur_cluster_num; grub_uint32_t cur_cluster; - grub_uint32_t uuid; +#ifdef MODE_EXFAT + int is_contiguous; +#endif }; static grub_dl_t my_mod; @@ -244,7 +246,7 @@ grub_fat_mount (grub_disk_t disk) #ifdef MODE_EXFAT if (grub_memcmp ((const char *) bpb.oem_name, "EXFAT ", sizeof (bpb.oem_name)) != 0) - goto fail; + goto fail; #endif /* Get the sizes of logical sectors and clusters. */ @@ -319,7 +321,7 @@ grub_fat_mount (grub_disk_t disk) #endif #ifdef MODE_EXFAT - data->cluster_sector = (grub_le_to_cpu32 (bpb.cluster_offset) + data->cluster_sector = (grub_le_to_cpu32 (bpb.cluster_offset) << data->logical_sector_bits); data->num_clusters = (grub_le_to_cpu32 (bpb.cluster_count) << data->logical_sector_bits); @@ -336,13 +338,12 @@ grub_fat_mount (grub_disk_t disk) #ifdef MODE_EXFAT { /* exFAT. */ - grub_uint16_t flags = grub_le_to_cpu16 (bpb.volume_flags); - data->root_cluster = grub_le_to_cpu32 (bpb.root_cluster); data->fat_size = 32; data->cluster_eof_mark = 0xffffffff; - if ((flags & 0x1) && bpb.num_fats > 1) + if ((bpb.volume_flags & grub_cpu_to_le16_compile_time (0x1)) + && bpb.num_fats > 1) data->fat_sector += data->sectors_per_fat; } #else @@ -439,10 +440,6 @@ grub_fat_mount (grub_disk_t disk) (void) magic; #endif - /* Start from the root directory. */ - data->file_cluster = data->root_cluster; - data->cur_cluster_num = ~0U; - data->attr = GRUB_FAT_ATTR_DIRECTORY; return data; fail: @@ -453,9 +450,8 @@ grub_fat_mount (grub_disk_t disk) } static grub_ssize_t -grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), +grub_fat_read_data (grub_disk_t disk, grub_fshelp_node_t node, + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t offset, grub_size_t len, char *buf) { grub_size_t size; @@ -467,67 +463,87 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, #ifndef MODE_EXFAT /* This is a special case. FAT12 and FAT16 doesn't have the root directory in clusters. */ - if (data->file_cluster == ~0U) + if (node->file_cluster == ~0U) { - size = (data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset; + size = (node->data->num_root_sectors << GRUB_DISK_SECTOR_BITS) - offset; if (size > len) size = len; - if (grub_disk_read (disk, data->root_sector, offset, size, buf)) + if (grub_disk_read (disk, node->data->root_sector, offset, size, buf)) return -1; return size; } #endif +#ifdef MODE_EXFAT + if (node->is_contiguous) + { + /* Read the data here. */ + sector = (node->data->cluster_sector + + ((node->file_cluster - 2) + << node->data->cluster_bits)); + + disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; + grub_disk_read (disk, sector + (offset >> GRUB_DISK_SECTOR_BITS), + offset & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); + disk->read_hook = 0; + if (grub_errno) + return -1; + + return len; + } +#endif + /* Calculate the logical cluster number and offset. */ - logical_cluster_bits = (data->cluster_bits + logical_cluster_bits = (node->data->cluster_bits + GRUB_DISK_SECTOR_BITS); logical_cluster = offset >> logical_cluster_bits; offset &= (1ULL << logical_cluster_bits) - 1; - if (logical_cluster < data->cur_cluster_num) + if (logical_cluster < node->cur_cluster_num) { - data->cur_cluster_num = 0; - data->cur_cluster = data->file_cluster; + node->cur_cluster_num = 0; + node->cur_cluster = node->file_cluster; } while (len) { - while (logical_cluster > data->cur_cluster_num) + while (logical_cluster > node->cur_cluster_num) { /* Find next cluster. */ grub_uint32_t next_cluster; - unsigned long fat_offset; + grub_uint32_t fat_offset; - switch (data->fat_size) + switch (node->data->fat_size) { case 32: - fat_offset = data->cur_cluster << 2; + fat_offset = node->cur_cluster << 2; break; case 16: - fat_offset = data->cur_cluster << 1; + fat_offset = node->cur_cluster << 1; break; default: /* case 12: */ - fat_offset = data->cur_cluster + (data->cur_cluster >> 1); + fat_offset = node->cur_cluster + (node->cur_cluster >> 1); break; } /* Read the FAT. */ - if (grub_disk_read (disk, data->fat_sector, fat_offset, - (data->fat_size + 7) >> 3, + if (grub_disk_read (disk, node->data->fat_sector, fat_offset, + (node->data->fat_size + 7) >> 3, (char *) &next_cluster)) return -1; next_cluster = grub_le_to_cpu32 (next_cluster); - switch (data->fat_size) + switch (node->data->fat_size) { case 16: next_cluster &= 0xFFFF; break; case 12: - if (data->cur_cluster & 1) + if (node->cur_cluster & 1) next_cluster >>= 4; next_cluster &= 0x0FFF; @@ -535,32 +551,33 @@ grub_fat_read_data (grub_disk_t disk, struct grub_fat_data *data, } grub_dprintf ("fat", "fat_size=%d, next_cluster=%u\n", - data->fat_size, next_cluster); + node->data->fat_size, next_cluster); /* Check the end. */ - if (next_cluster >= data->cluster_eof_mark) + if (next_cluster >= node->data->cluster_eof_mark) return ret; - if (next_cluster < 2 || next_cluster >= data->num_clusters) + if (next_cluster < 2 || next_cluster >= node->data->num_clusters) { grub_error (GRUB_ERR_BAD_FS, "invalid cluster %u", next_cluster); return -1; } - data->cur_cluster = next_cluster; - data->cur_cluster_num++; + node->cur_cluster = next_cluster; + node->cur_cluster_num++; } /* Read the data here. */ - sector = (data->cluster_sector - + ((data->cur_cluster - 2) - << data->cluster_bits)); + sector = (node->data->cluster_sector + + ((node->cur_cluster - 2) + << node->data->cluster_bits)); size = (1 << logical_cluster_bits) - offset; if (size > len) size = len; disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; grub_disk_read (disk, sector, offset, size, buf); disk->read_hook = 0; if (grub_errno) @@ -580,6 +597,7 @@ struct grub_fat_iterate_context { #ifdef MODE_EXFAT struct grub_fat_dir_node dir; + struct grub_fat_dir_entry entry; #else struct grub_fat_dir_entry dir; #endif @@ -620,39 +638,39 @@ grub_fat_iterate_fini (struct grub_fat_iterate_context *ctxt) #ifdef MODE_EXFAT static grub_err_t -grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, +grub_fat_iterate_dir_next (grub_fshelp_node_t node, struct grub_fat_iterate_context *ctxt) { grub_memset (&ctxt->dir, 0, sizeof (ctxt->dir)); while (1) { - struct grub_fat_dir_entry dir; + struct grub_fat_dir_entry *dir = &ctxt->entry; - ctxt->offset += sizeof (dir); + ctxt->offset += sizeof (*dir); - if (grub_fat_read_data (disk, data, 0, ctxt->offset, sizeof (dir), - (char *) &dir) - != sizeof (dir)) + if (grub_fat_read_data (node->disk, node, 0, 0, ctxt->offset, sizeof (*dir), + (char *) dir) + != sizeof (*dir)) break; - if (dir.entry_type == 0) + if (dir->entry_type == 0) break; - if (!(dir.entry_type & 0x80)) + if (!(dir->entry_type & 0x80)) continue; - if (dir.entry_type == 0x85) + if (dir->entry_type == 0x85) { unsigned i, nsec, slots = 0; - nsec = dir.type_specific.file.secondary_count; + nsec = dir->type_specific.file.secondary_count; - ctxt->dir.attr = grub_cpu_to_le16 (dir.type_specific.file.attr); + ctxt->dir.attr = grub_cpu_to_le16 (dir->type_specific.file.attr); ctxt->dir.have_stream = 0; for (i = 0; i < nsec; i++) { struct grub_fat_dir_entry sec; ctxt->offset += sizeof (sec); - if (grub_fat_read_data (disk, data, 0, + if (grub_fat_read_data (node->disk, node, 0, 0, ctxt->offset, sizeof (sec), (char *) &sec) != sizeof (sec)) break; @@ -669,12 +687,14 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, ctxt->dir.file_size = grub_cpu_to_le64 (sec.type_specific.stream_extension.file_size); ctxt->dir.have_stream = 1; + ctxt->dir.is_contiguous = !!(sec.type_specific.stream_extension.flags + & grub_cpu_to_le16_compile_time (FLAG_CONTIGUOUS)); break; case 0xc1: { int j; for (j = 0; j < 15; j++) - ctxt->unibuf[slots * 15 + j] + ctxt->unibuf[slots * 15 + j] = grub_le_to_cpu16 (sec.type_specific.file_name.str[j]); slots++; } @@ -687,7 +707,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, if (i != nsec) { - ctxt->offset -= sizeof (dir); + ctxt->offset -= sizeof (*dir); continue; } @@ -697,24 +717,51 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, return 0; } /* Allocation bitmap. */ - if (dir.entry_type == 0x81) + if (dir->entry_type == 0x81) continue; /* Upcase table. */ - if (dir.entry_type == 0x82) + if (dir->entry_type == 0x82) continue; /* Volume label. */ - if (dir.entry_type == 0x83) + if (dir->entry_type == 0x83) continue; grub_dprintf ("exfat", "unknown primary type 0x%02x\n", - dir.entry_type); + dir->entry_type); } return grub_errno ? : GRUB_ERR_EOF; } +/* + * Convert a timestamp in exFAT format to seconds since the UNIX epoch + * according to sections 7.4.8 and 7.4.9 in the exFAT specification. + * https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification + */ +static int +grub_exfat_timestamp (grub_uint32_t field, grub_uint8_t msec, grub_int64_t *nix) { + struct grub_datetime datetime = { + .year = (field >> 25) + 1980, + .month = (field & 0x01E00000) >> 21, + .day = (field & 0x001F0000) >> 16, + .hour = (field & 0x0000F800) >> 11, + .minute = (field & 0x000007E0) >> 5, + .second = (field & 0x0000001F) * 2 + (msec >= 100 ? 1 : 0), + }; + + /* The conversion below allows seconds=60, so don't trust its validation. */ + if ((field & 0x1F) > 29) + return 0; + + /* Validate the 10-msec field even though it is rounded down to seconds. */ + if (msec > 199) + return 0; + + return grub_datetime2unixtime (&datetime, nix); +} + #else static grub_err_t -grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, +grub_fat_iterate_dir_next (grub_fshelp_node_t node, struct grub_fat_iterate_context *ctxt) { char *filep = 0; @@ -729,7 +776,7 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, ctxt->offset += sizeof (ctxt->dir); /* Read a directory entry. */ - if (grub_fat_read_data (disk, data, 0, + if (grub_fat_read_data (node->disk, node, 0, 0, ctxt->offset, sizeof (ctxt->dir), (char *) &ctxt->dir) != sizeof (ctxt->dir) || ctxt->dir.name[0] == 0) @@ -816,7 +863,9 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, i--; } - *filep++ = '.'; + /* XXX should we check that dir position is 0 or 1? */ + if (i > 2 || filep[0] != '.' || (i == 2 && filep[1] != '.')) + *filep++ = '.'; for (i = 8; i < 11 && ctxt->dir.name[i]; i++) *filep++ = grub_tolower (ctxt->dir.name[i]); @@ -836,65 +885,45 @@ grub_fat_iterate_dir_next (grub_disk_t disk, struct grub_fat_data *data, return grub_errno ? : GRUB_ERR_EOF; } +/* + * Convert a date and time in FAT format to seconds since the UNIX epoch + * according to sections 11.3.5 and 11.3.6 in ECMA-107. + * https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-107.pdf + */ +static int +grub_fat_timestamp (grub_uint16_t time, grub_uint16_t date, grub_int64_t *nix) { + struct grub_datetime datetime = { + .year = (date >> 9) + 1980, + .month = (date & 0x01E0) >> 5, + .day = (date & 0x001F), + .hour = (time >> 11), + .minute = (time & 0x07E0) >> 5, + .second = (time & 0x001F) * 2, + }; + + /* The conversion below allows seconds=60, so don't trust its validation. */ + if ((time & 0x1F) > 29) + return 0; + + return grub_datetime2unixtime (&datetime, nix); +} + #endif -/* Find the underlying directory or file in PATH and return the - next path. If there is no next path or an error occurs, return NULL. - If HOOK is specified, call it with each file name. */ -static char * -grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, - const char *path, const char *origpath, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) +static grub_err_t lookup_file (grub_fshelp_node_t node, + const char *name, + grub_fshelp_node_t *foundnode, + enum grub_fshelp_filetype *foundtype) { - char *dirname, *dirp; - int call_hook; - int found = 0; - struct grub_fat_iterate_context ctxt; grub_err_t err; - - if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY)) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - return 0; - } - - /* Extract a directory name. */ - while (*path == '/') - path++; - - dirp = grub_strchr (path, '/'); - if (dirp) - { - unsigned len = dirp - path; - - dirname = grub_malloc (len + 1); - if (! dirname) - goto fail; - - grub_memcpy (dirname, path, len); - dirname[len] = '\0'; - } - else - /* This is actually a file. */ - dirname = grub_strdup (path); - - call_hook = (! dirp && hook); + struct grub_fat_iterate_context ctxt; err = grub_fat_iterate_init (&ctxt); if (err) - { - grub_free (dirname); - return 0; - } + return err; - while (!(err = grub_fat_iterate_dir_next (disk, data, &ctxt))) + while (!(err = grub_fat_iterate_dir_next (node, &ctxt))) { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - - info.dir = !! (ctxt.dir.attr & GRUB_FAT_ATTR_DIRECTORY); - info.case_insensitive = 1; #ifdef MODE_EXFAT if (!ctxt.dir.have_stream) @@ -903,32 +932,33 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID) continue; #endif - if (*dirname == '\0' && call_hook) - { - if (hook (ctxt.filename, &info)) - break; - else - continue; - } - if (grub_strcasecmp (dirname, ctxt.filename) == 0) + if (grub_strcasecmp (name, ctxt.filename) == 0) { - found = 1; - data->attr = ctxt.dir.attr; + *foundnode = grub_malloc (sizeof (struct grub_fshelp_node)); + if (!*foundnode) + return grub_errno; + (*foundnode)->attr = ctxt.dir.attr; #ifdef MODE_EXFAT - data->file_size = ctxt.dir.file_size; - data->file_cluster = ctxt.dir.first_cluster; + (*foundnode)->file_size = ctxt.dir.file_size; + (*foundnode)->file_cluster = ctxt.dir.first_cluster; + (*foundnode)->is_contiguous = ctxt.dir.is_contiguous; #else - data->file_size = grub_le_to_cpu32 (ctxt.dir.file_size); - data->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16) + (*foundnode)->file_size = grub_le_to_cpu32 (ctxt.dir.file_size); + (*foundnode)->file_cluster = ((grub_le_to_cpu16 (ctxt.dir.first_cluster_high) << 16) | grub_le_to_cpu16 (ctxt.dir.first_cluster_low)); + /* If directory points to root, starting cluster is 0 */ + if (!(*foundnode)->file_cluster) + (*foundnode)->file_cluster = node->data->root_cluster; #endif - data->cur_cluster_num = ~0U; + (*foundnode)->cur_cluster_num = ~0U; + (*foundnode)->data = node->data; + (*foundnode)->disk = node->disk; - if (call_hook) - hook (ctxt.filename, &info); + *foundtype = ((*foundnode)->attr & GRUB_FAT_ATTR_DIRECTORY) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG; - break; + grub_fat_iterate_fini (&ctxt); + return GRUB_ERR_NONE; } } @@ -936,25 +966,19 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, if (err == GRUB_ERR_EOF) err = 0; - if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook) - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath); + return err; - fail: - grub_free (dirname); - - return found ? dirp : 0; } static grub_err_t -grub_fat_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) +grub_fat_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, + void *hook_data) { struct grub_fat_data *data = 0; grub_disk_t disk = device->disk; - grub_size_t len; - char *dirname = 0; - char *p; + grub_fshelp_node_t found = NULL; + grub_err_t err; + struct grub_fat_iterate_context ctxt; grub_dl_ref (my_mod); @@ -962,27 +986,59 @@ grub_fat_dir (grub_device_t device, const char *path, if (! data) goto fail; - /* Make sure that DIRNAME terminates with '/'. */ - len = grub_strlen (path); - dirname = grub_malloc (len + 1 + 1); - if (! dirname) - goto fail; - grub_memcpy (dirname, path, len); - p = dirname + len; - if (path[len - 1] != '/') - *p++ = '/'; - *p = '\0'; - p = dirname; + struct grub_fshelp_node root = { + .data = data, + .disk = disk, + .attr = GRUB_FAT_ATTR_DIRECTORY, + .file_size = 0, + .file_cluster = data->root_cluster, + .cur_cluster_num = ~0U, + .cur_cluster = 0, +#ifdef MODE_EXFAT + .is_contiguous = 0, +#endif + }; - do + err = grub_fshelp_find_file_lookup (path, &root, &found, lookup_file, NULL, GRUB_FSHELP_DIR); + if (err) + goto fail; + + err = grub_fat_iterate_init (&ctxt); + if (err) + goto fail; + + while (!(err = grub_fat_iterate_dir_next (found, &ctxt))) { - p = grub_fat_find_dir (disk, data, p, path, hook); + struct grub_dirhook_info info; + grub_memset (&info, 0, sizeof (info)); + + info.dir = !! (ctxt.dir.attr & GRUB_FAT_ATTR_DIRECTORY); + info.case_insensitive = 1; +#ifdef MODE_EXFAT + if (!ctxt.dir.have_stream) + continue; + info.mtimeset = grub_exfat_timestamp (grub_le_to_cpu32 (ctxt.entry.type_specific.file.m_time), + ctxt.entry.type_specific.file.m_time_tenth, + &info.mtime); +#else + if (ctxt.dir.attr & GRUB_FAT_ATTR_VOLUME_ID) + continue; + info.mtimeset = grub_fat_timestamp (grub_le_to_cpu16 (ctxt.dir.w_time), + grub_le_to_cpu16 (ctxt.dir.w_date), + &info.mtime); +#endif + + if (hook (ctxt.filename, &info, hook_data)) + break; } - while (p && grub_errno == GRUB_ERR_NONE); + grub_fat_iterate_fini (&ctxt); + if (err == GRUB_ERR_EOF) + err = 0; fail: + if (found != &root) + grub_free (found); - grub_free (dirname); grub_free (data); grub_dl_unref (my_mod); @@ -994,35 +1050,43 @@ static grub_err_t grub_fat_open (grub_file_t file, const char *name) { struct grub_fat_data *data = 0; - char *p = (char *) name; + grub_fshelp_node_t found = NULL; + grub_err_t err; + grub_disk_t disk = file->device->disk; grub_dl_ref (my_mod); - data = grub_fat_mount (file->device->disk); + data = grub_fat_mount (disk); if (! data) goto fail; - do - { - p = grub_fat_find_dir (file->device->disk, data, p, name, 0); - if (grub_errno != GRUB_ERR_NONE) - goto fail; - } - while (p); + struct grub_fshelp_node root = { + .data = data, + .disk = disk, + .attr = GRUB_FAT_ATTR_DIRECTORY, + .file_size = 0, + .file_cluster = data->root_cluster, + .cur_cluster_num = ~0U, + .cur_cluster = 0, +#ifdef MODE_EXFAT + .is_contiguous = 0, +#endif + }; - if (data->attr & GRUB_FAT_ATTR_DIRECTORY) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); - goto fail; - } + err = grub_fshelp_find_file_lookup (name, &root, &found, lookup_file, NULL, GRUB_FSHELP_REG); + if (err) + goto fail; - file->data = data; - file->size = data->file_size; + file->data = found; + file->size = found->file_size; return GRUB_ERR_NONE; fail: + if (found != &root) + grub_free (found); + grub_free (data); grub_dl_unref (my_mod); @@ -1033,14 +1097,18 @@ grub_fat_open (grub_file_t file, const char *name) static grub_ssize_t grub_fat_read (grub_file_t file, char *buf, grub_size_t len) { - return grub_fat_read_data (file->device->disk, file->data, file->read_hook, + return grub_fat_read_data (file->device->disk, file->data, + file->read_hook, file->read_hook_data, file->offset, len, buf); } static grub_err_t grub_fat_close (grub_file_t file) { - grub_free (file->data); + grub_fshelp_node_t node = file->data; + + grub_free (node->data); + grub_free (node); grub_dl_unref (my_mod); @@ -1053,20 +1121,29 @@ grub_fat_label (grub_device_t device, char **label) { struct grub_fat_dir_entry dir; grub_ssize_t offset = -sizeof(dir); - struct grub_fat_data *data; grub_disk_t disk = device->disk; + struct grub_fshelp_node root = { + .disk = disk, + .attr = GRUB_FAT_ATTR_DIRECTORY, + .file_size = 0, + .cur_cluster_num = ~0U, + .cur_cluster = 0, + .is_contiguous = 0, + }; - data = grub_fat_mount (disk); - if (! data) + root.data = grub_fat_mount (disk); + if (! root.data) return grub_errno; + root.file_cluster = root.data->root_cluster; + *label = NULL; while (1) { offset += sizeof (dir); - if (grub_fat_read_data (disk, data, 0, + if (grub_fat_read_data (disk, &root, 0, 0, offset, sizeof (dir), (char *) &dir) != sizeof (dir)) break; @@ -1086,7 +1163,7 @@ grub_fat_label (grub_device_t device, char **label) * GRUB_MAX_UTF8_PER_UTF16 + 1); if (!*label) { - grub_free (data); + grub_free (root.data); return grub_errno; } chc = dir.type_specific.volume_label.character_count; @@ -1098,7 +1175,7 @@ grub_fat_label (grub_device_t device, char **label) } } - grub_free (data); + grub_free (root.data); return grub_errno; } @@ -1107,30 +1184,32 @@ grub_fat_label (grub_device_t device, char **label) static grub_err_t grub_fat_label (grub_device_t device, char **label) { - struct grub_fat_data *data; grub_disk_t disk = device->disk; grub_err_t err; struct grub_fat_iterate_context ctxt; + struct grub_fshelp_node root = { + .disk = disk, + .attr = GRUB_FAT_ATTR_DIRECTORY, + .file_size = 0, + .cur_cluster_num = ~0U, + .cur_cluster = 0, + }; *label = 0; grub_dl_ref (my_mod); - data = grub_fat_mount (disk); - if (! data) + root.data = grub_fat_mount (disk); + if (! root.data) goto fail; - if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY)) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - return 0; - } + root.file_cluster = root.data->root_cluster; err = grub_fat_iterate_init (&ctxt); if (err) goto fail; - while (!(err = grub_fat_iterate_dir_next (disk, data, &ctxt))) + while (!(err = grub_fat_iterate_dir_next (&root, &ctxt))) if ((ctxt.dir.attr & ~GRUB_FAT_ATTR_ARCHIVE) == GRUB_FAT_ATTR_VOLUME_ID) { *label = grub_strdup (ctxt.filename); @@ -1143,7 +1222,7 @@ grub_fat_label (grub_device_t device, char **label) grub_dl_unref (my_mod); - grub_free (data); + grub_free (root.data); return grub_errno; } @@ -1178,6 +1257,29 @@ grub_fat_uuid (grub_device_t device, char **uuid) return grub_errno; } +#ifdef GRUB_UTIL +#ifndef MODE_EXFAT +grub_disk_addr_t +grub_fat_get_cluster_sector (grub_disk_t disk, grub_uint64_t *sec_per_lcn) +#else +grub_disk_addr_t + grub_exfat_get_cluster_sector (grub_disk_t disk, grub_uint64_t *sec_per_lcn) +#endif +{ + grub_disk_addr_t ret; + struct grub_fat_data *data; + data = grub_fat_mount (disk); + if (!data) + return 0; + ret = data->cluster_sector; + + *sec_per_lcn = 1ULL << data->cluster_bits; + + grub_free (data); + return ret; +} +#endif + static struct grub_fs grub_fat_fs = { #ifdef MODE_EXFAT @@ -1185,12 +1287,12 @@ static struct grub_fs grub_fat_fs = #else .name = "fat", #endif - .dir = grub_fat_dir, - .open = grub_fat_open, - .read = grub_fat_read, - .close = grub_fat_close, - .label = grub_fat_label, - .uuid = grub_fat_uuid, + .fs_dir = grub_fat_dir, + .fs_open = grub_fat_open, + .fs_read = grub_fat_read, + .fs_close = grub_fat_close, + .fs_label = grub_fat_label, + .fs_uuid = grub_fat_uuid, #ifdef GRUB_UTIL #ifdef MODE_EXFAT /* ExFAT BPB is 30 larger than FAT32 one. */ @@ -1210,6 +1312,7 @@ GRUB_MOD_INIT(fat) #endif { COMPILE_TIME_ASSERT (sizeof (struct grub_fat_dir_entry) == 32); + grub_fat_fs.mod = mod; grub_fs_register (&grub_fat_fs); my_mod = mod; } diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c index 21a72de84..cb41934b4 100644 --- a/grub-core/fs/fshelp.c +++ b/grub-core/fs/fshelp.c @@ -27,195 +27,281 @@ GRUB_MOD_LICENSE ("GPLv3+"); -/* Lookup the node PATH. The node ROOTNODE describes the root of the - directory tree. The node found is returned in FOUNDNODE, which is - either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to - iterate over all directory entries in the current node. - READ_SYMLINK is used to read the symlink if a node is a symlink. - EXPECTTYPE is the type node that is expected by the called, an - error is generated if the node is not of the expected type. Make - sure you use the NESTED_FUNC_ATTR macro for HOOK, this is required - because GCC has a nasty bug when using regparm=3. */ -grub_err_t -grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, - grub_fshelp_node_t *foundnode, - int (*iterate_dir) (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR (*hook) - (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)), - char *(*read_symlink) (grub_fshelp_node_t node), - enum grub_fshelp_filetype expecttype) +typedef int (*iterate_dir_func) (grub_fshelp_node_t dir, + grub_fshelp_iterate_dir_hook_t hook, + void *data); +typedef grub_err_t (*lookup_file_func) (grub_fshelp_node_t dir, + const char *name, + grub_fshelp_node_t *foundnode, + enum grub_fshelp_filetype *foundtype); +typedef char *(*read_symlink_func) (grub_fshelp_node_t node); + +struct stack_element { + struct stack_element *parent; + grub_fshelp_node_t node; + enum grub_fshelp_filetype type; +}; + +/* Context for grub_fshelp_find_file. */ +struct grub_fshelp_find_file_ctx { - grub_err_t err; - enum grub_fshelp_filetype foundtype = GRUB_FSHELP_DIR; - int symlinknest = 0; + /* Inputs. */ + const char *path; + grub_fshelp_node_t rootnode; - auto grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath, - grub_fshelp_node_t currroot, - grub_fshelp_node_t *currfound); + /* Global options. */ + int symlinknest; - grub_err_t NESTED_FUNC_ATTR find_file (const char *currpath, - grub_fshelp_node_t currroot, - grub_fshelp_node_t *currfound) + /* Current file being traversed and its parents. */ + struct stack_element *currnode; +}; + +/* Helper for find_file_iter. */ +static void +free_node (grub_fshelp_node_t node, struct grub_fshelp_find_file_ctx *ctx) +{ + if (node != ctx->rootnode) + grub_free (node); +} + +static void +pop_element (struct grub_fshelp_find_file_ctx *ctx) +{ + struct stack_element *el; + el = ctx->currnode; + ctx->currnode = el->parent; + free_node (el->node, ctx); + grub_free (el); +} + +static void +free_stack (struct grub_fshelp_find_file_ctx *ctx) +{ + while (ctx->currnode) + pop_element (ctx); +} + +static void +go_up_a_level (struct grub_fshelp_find_file_ctx *ctx) +{ + if (!ctx->currnode->parent) + return; + pop_element (ctx); +} + +static grub_err_t +push_node (struct grub_fshelp_find_file_ctx *ctx, grub_fshelp_node_t node, enum grub_fshelp_filetype filetype) +{ + struct stack_element *nst; + nst = grub_malloc (sizeof (*nst)); + if (!nst) + return grub_errno; + nst->node = node; + nst->type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE; + nst->parent = ctx->currnode; + ctx->currnode = nst; + return GRUB_ERR_NONE; +} + +static grub_err_t +go_to_root (struct grub_fshelp_find_file_ctx *ctx) +{ + free_stack (ctx); + return push_node (ctx, ctx->rootnode, GRUB_FSHELP_DIR); +} + +struct grub_fshelp_find_file_iter_ctx +{ + const char *name; + grub_fshelp_node_t *foundnode; + enum grub_fshelp_filetype *foundtype; +}; + +/* Helper for grub_fshelp_find_file. */ +static int +find_file_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_fshelp_find_file_iter_ctx *ctx = data; + + if (filetype == GRUB_FSHELP_UNKNOWN || + ((filetype & GRUB_FSHELP_CASE_INSENSITIVE) + ? grub_strcasecmp (ctx->name, filename) + : grub_strcmp (ctx->name, filename))) { - char fpath[grub_strlen (currpath) + 1]; - char *name = fpath; - char *next; - enum grub_fshelp_filetype type = GRUB_FSHELP_DIR; - grub_fshelp_node_t currnode = currroot; - grub_fshelp_node_t oldnode = currroot; + grub_free (node); + return 0; + } - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); + /* The node is found, stop iterating over the nodes. */ + *ctx->foundnode = node; + *ctx->foundtype = filetype; + return 1; +} - auto void free_node (grub_fshelp_node_t node); +static grub_err_t +directory_find_file (grub_fshelp_node_t node, const char *name, grub_fshelp_node_t *foundnode, + enum grub_fshelp_filetype *foundtype, iterate_dir_func iterate_dir) +{ + int found; + struct grub_fshelp_find_file_iter_ctx ctx = { + .foundnode = foundnode, + .foundtype = foundtype, + .name = name + }; + found = iterate_dir (node, find_file_iter, &ctx); + if (! found) + { + if (grub_errno) + return grub_errno; + } + return GRUB_ERR_NONE; +} - void free_node (grub_fshelp_node_t node) - { - if (node != rootnode && node != currroot) - grub_free (node); - } - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - if (filetype == GRUB_FSHELP_UNKNOWN || - (grub_strcmp (name, filename) && - (! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) || - grub_strcasecmp (name, filename)))) - { - grub_free (node); - return 0; - } - - /* The node is found, stop iterating over the nodes. */ - type = filetype & ~GRUB_FSHELP_CASE_INSENSITIVE; - oldnode = currnode; - currnode = node; - - return 1; - } - - grub_strncpy (fpath, currpath, grub_strlen (currpath) + 1); +static grub_err_t +find_file (char *currpath, + iterate_dir_func iterate_dir, lookup_file_func lookup_file, + read_symlink_func read_symlink, + struct grub_fshelp_find_file_ctx *ctx) +{ + char *name, *next; + grub_err_t err; + for (name = currpath; ; name = next) + { + char c; + grub_fshelp_node_t foundnode = NULL; + enum grub_fshelp_filetype foundtype = 0; /* Remove all leading slashes. */ while (*name == '/') name++; + /* Found the node! */ if (! *name) + return 0; + + /* Extract the actual part from the pathname. */ + for (next = name; *next && *next != '/'; next++); + + /* At this point it is expected that the current node is a + directory, check if this is true. */ + if (ctx->currnode->type != GRUB_FSHELP_DIR) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); + + /* Don't rely on fs providing actual . in the listing. */ + if (next - name == 1 && name[0] == '.') + continue; + + /* Don't rely on fs providing actual .. in the listing. */ + if (next - name == 2 && name[0] == '.' && name[1] == '.') { - *currfound = currnode; - return 0; + go_up_a_level (ctx); + continue; } - for (;;) + /* Iterate over the directory. */ + c = *next; + *next = '\0'; + if (lookup_file) + err = lookup_file (ctx->currnode->node, name, &foundnode, &foundtype); + else + err = directory_find_file (ctx->currnode->node, name, &foundnode, &foundtype, iterate_dir); + *next = c; + + if (err) + return err; + + if (!foundnode) + break; + + push_node (ctx, foundnode, foundtype); + + /* Read in the symlink and follow it. */ + if (ctx->currnode->type == GRUB_FSHELP_SYMLINK) { - int found; + char *symlink; - /* Extract the actual part from the pathname. */ - next = grub_strchr (name, '/'); - if (next) + /* Test if the symlink does not loop. */ + if (++ctx->symlinknest == 8) + return grub_error (GRUB_ERR_SYMLINK_LOOP, + N_("too deep nesting of symlinks")); + + symlink = read_symlink (ctx->currnode->node); + + if (!symlink) + return grub_errno; + + /* The symlink is an absolute path, go back to the root inode. */ + if (symlink[0] == '/') { - /* Remove all leading slashes. */ - while (*next == '/') - *(next++) = '\0'; + err = go_to_root (ctx); + if (err) + return err; + } + else + { + /* Get from symlink to containing directory. */ + go_up_a_level (ctx); } - /* At this point it is expected that the current node is a - directory, check if this is true. */ - if (type != GRUB_FSHELP_DIR) - { - free_node (currnode); - currnode = 0; - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - } - /* Iterate over the directory. */ - found = iterate_dir (currnode, iterate); - if (! found) - { - free_node (currnode); - currnode = 0; - if (grub_errno) - return grub_errno; + /* Lookup the node the symlink points to. */ + find_file (symlink, iterate_dir, lookup_file, read_symlink, ctx); + grub_free (symlink); - break; - } - - /* Read in the symlink and follow it. */ - if (type == GRUB_FSHELP_SYMLINK) - { - char *symlink; - - /* Test if the symlink does not loop. */ - if (++symlinknest == 8) - { - free_node (currnode); - free_node (oldnode); - currnode = 0; - return grub_error (GRUB_ERR_SYMLINK_LOOP, - N_("too deep nesting of symlinks")); - } - - symlink = read_symlink (currnode); - free_node (currnode); - currnode = 0; - - if (!symlink) - { - free_node (oldnode); - return grub_errno; - } - - /* The symlink is an absolute path, go back to the root inode. */ - if (symlink[0] == '/') - { - free_node (oldnode); - oldnode = rootnode; - } - - /* Lookup the node the symlink points to. */ - find_file (symlink, oldnode, &currnode); - type = foundtype; - grub_free (symlink); - - if (grub_errno) - { - free_node (oldnode); - return grub_errno; - } - } - - if (oldnode != currnode) - free_node (oldnode); - - /* Found the node! */ - if (! next || *next == '\0') - { - *currfound = currnode; - foundtype = type; - return 0; - } - - name = next; + if (grub_errno) + return grub_errno; } - - return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); } + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), + ctx->path); +} + +static grub_err_t +grub_fshelp_find_file_real (const char *path, grub_fshelp_node_t rootnode, + grub_fshelp_node_t *foundnode, + iterate_dir_func iterate_dir, + lookup_file_func lookup_file, + read_symlink_func read_symlink, + enum grub_fshelp_filetype expecttype) +{ + struct grub_fshelp_find_file_ctx ctx = { + .path = path, + .rootnode = rootnode, + .symlinknest = 0, + .currnode = 0 + }; + grub_err_t err; + enum grub_fshelp_filetype foundtype; + char *duppath; + if (!path || path[0] != '/') { - grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); - return grub_errno; + return grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); } - err = find_file (path, rootnode, foundnode); + err = go_to_root (&ctx); if (err) return err; + duppath = grub_strdup (path); + if (!duppath) + return grub_errno; + err = find_file (duppath, iterate_dir, lookup_file, read_symlink, &ctx); + grub_free (duppath); + if (err) + { + free_stack (&ctx); + return err; + } + + *foundnode = ctx.currnode->node; + foundtype = ctx.currnode->type; + /* Avoid the node being freed. */ + ctx.currnode->node = 0; + free_stack (&ctx); + /* Check if the node that was found was of the expected type. */ if (expecttype == GRUB_FSHELP_REG && foundtype != expecttype) return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); @@ -225,16 +311,48 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, return 0; } +/* Lookup the node PATH. The node ROOTNODE describes the root of the + directory tree. The node found is returned in FOUNDNODE, which is + either a ROOTNODE or a new malloc'ed node. ITERATE_DIR is used to + iterate over all directory entries in the current node. + READ_SYMLINK is used to read the symlink if a node is a symlink. + EXPECTTYPE is the type node that is expected by the called, an + error is generated if the node is not of the expected type. */ +grub_err_t +grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, + grub_fshelp_node_t *foundnode, + iterate_dir_func iterate_dir, + read_symlink_func read_symlink, + enum grub_fshelp_filetype expecttype) +{ + return grub_fshelp_find_file_real (path, rootnode, foundnode, + iterate_dir, NULL, + read_symlink, expecttype); + +} + +grub_err_t +grub_fshelp_find_file_lookup (const char *path, grub_fshelp_node_t rootnode, + grub_fshelp_node_t *foundnode, + lookup_file_func lookup_file, + read_symlink_func read_symlink, + enum grub_fshelp_filetype expecttype) +{ + return grub_fshelp_find_file_real (path, rootnode, foundnode, + NULL, lookup_file, + read_symlink, expecttype); + +} + /* Read LEN bytes from the file NODE on disk DISK into the buffer BUF, beginning with the block POS. READ_HOOK should be set before - reading a block from the file. GET_BLOCK is used to translate file - blocks to disk blocks. The file is FILESIZE bytes big and the + reading a block from the file. READ_HOOK_DATA is passed through as + the DATA argument to READ_HOOK. GET_BLOCK is used to translate + file blocks to disk blocks. The file is FILESIZE bytes big and the blocks have a size of LOG2BLOCKSIZE (in log2). */ grub_ssize_t grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf, grub_disk_addr_t (*get_block) (grub_fshelp_node_t node, grub_disk_addr_t block), @@ -244,6 +362,25 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, grub_disk_addr_t i, blockcnt; int blocksize = 1 << (log2blocksize + GRUB_DISK_SECTOR_BITS); + /* + * Catch blatantly invalid log2blocksize. We could be a lot stricter, but + * this is the most permissive we can be before we start to see integer + * overflow/underflow issues. + */ + if (log2blocksize + GRUB_DISK_SECTOR_BITS >= 31) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("blocksize too large")); + return -1; + } + + if (pos > filesize) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("attempt to read past the end of file")); + return -1; + } + /* Adjust LEN so it we can't read past the end of the file. */ if (pos + len > filesize) len = filesize - pos; @@ -286,6 +423,7 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, if (blknr) { disk->read_hook = read_hook; + disk->read_hook_data = read_hook_data; grub_disk_read (disk, blknr + blocks_start, skipfirst, blockend, buf); @@ -301,24 +439,3 @@ grub_fshelp_read_file (grub_disk_t disk, grub_fshelp_node_t node, return len; } - -unsigned int -grub_fshelp_log2blksize (unsigned int blksize, unsigned int *pow) -{ - int mod; - - *pow = 0; - while (blksize > 1) - { - mod = blksize - ((blksize >> 1) << 1); - blksize >>= 1; - - /* Check if it really is a power of two. */ - if (mod) - return grub_error (GRUB_ERR_BAD_NUMBER, - "the blocksize is not a power of two"); - (*pow)++; - } - - return GRUB_ERR_NONE; -} diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index 0a249ccb8..ce7581dd5 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -65,7 +67,7 @@ struct grub_hfs_node grub_uint8_t level; grub_uint16_t reccnt; grub_uint16_t unused; -} __attribute__ ((packed)); +} GRUB_PACKED; /* The head of the B*-Tree. */ struct grub_hfs_treeheader @@ -81,7 +83,7 @@ struct grub_hfs_treeheader grub_uint32_t nodes; grub_uint32_t free_nodes; grub_uint8_t unused[76]; -} __attribute__ ((packed)); +} GRUB_PACKED; /* The state of a mounted HFS filesystem. */ struct grub_hfs_data @@ -112,7 +114,7 @@ struct grub_hfs_catalog_key /* Filename. */ grub_uint8_t str[31]; -} __attribute__ ((packed)); +} GRUB_PACKED; /* The key as used on disk in a extent overflow tree. Using this key the extents can be looked up using a fileid and logical start block @@ -125,7 +127,7 @@ struct grub_hfs_extent_key grub_uint8_t forktype; grub_uint32_t fileid; grub_uint16_t first_block; -} __attribute__ ((packed)); +} GRUB_PACKED; /* A directory record. This is used to find out the directory ID. */ struct grub_hfs_dirrec @@ -136,7 +138,7 @@ struct grub_hfs_dirrec grub_uint32_t dirid; grub_uint32_t ctime; grub_uint32_t mtime; -} __attribute__ ((packed)); +} GRUB_PACKED; /* Information about a file. */ struct grub_hfs_filerec @@ -154,22 +156,22 @@ struct grub_hfs_filerec /* The first 3 extents of the file. The other extents can be found in the extent overflow file. */ grub_hfs_datarecord_t extents; -} __attribute__ ((packed)); +} GRUB_PACKED; /* A record descriptor, both key and data, used to pass to call back functions. */ struct grub_hfs_record { void *key; - int keylen; + grub_size_t keylen; void *data; - int datalen; + grub_size_t datalen; }; static grub_dl_t my_mod; static int grub_hfs_find_node (struct grub_hfs_data *, char *, - grub_uint32_t, int, char *, int); + grub_uint32_t, int, char *, grub_size_t); /* Find block BLOCK of the file FILE in the mounted UFS filesystem DATA. The first 3 extents are described by DAT. If cache is set, @@ -243,17 +245,17 @@ grub_hfs_block (struct grub_hfs_data *data, grub_hfs_datarecord_t dat, POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_hfs_read_file (struct grub_hfs_data *data, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), - grub_off_t pos, grub_size_t len, char *buf) + grub_disk_read_hook_t read_hook, void *read_hook_data, + grub_uint32_t pos, grub_size_t len, char *buf) { grub_off_t i; grub_off_t blockcnt; - blockcnt = grub_divmod64 (((len + pos) - + data->blksz - 1), data->blksz, 0); + /* Files are at most 2G/4G - 1 bytes on hfs. Avoid 64-bit division. + Moreover len > 0 as checked in upper layer. */ + blockcnt = (len + pos - 1) / data->blksz + 1; - for (i = grub_divmod64 (pos, data->blksz, 0); i < blockcnt; i++) + for (i = pos / data->blksz; i < blockcnt; i++) { grub_disk_addr_t blknr; grub_off_t blockoff; @@ -261,7 +263,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, int skipfirst = 0; - grub_divmod64 (pos, data->blksz, &blockoff); + blockoff = pos % data->blksz; blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1); if (grub_errno) @@ -270,7 +272,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, /* Last block. */ if (i == blockcnt - 1) { - grub_divmod64 ((len + pos), data->blksz, &blockend); + blockend = (len + pos) % data->blksz; /* The last portion is exactly EXT2_BLOCK_SIZE (data). */ if (! blockend) @@ -278,7 +280,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, } /* First block. */ - if (i == grub_divmod64 (pos, data->blksz, 0)) + if (i == pos / data->blksz) { skipfirst = blockoff; blockend -= skipfirst; @@ -289,6 +291,7 @@ grub_hfs_read_file (struct grub_hfs_data *data, if (blknr) { data->disk->read_hook = read_hook; + data->disk->read_hook_data = read_hook_data; grub_disk_read (data->disk, blknr, skipfirst, blockend, buf); data->disk->read_hook = 0; @@ -329,6 +332,7 @@ grub_hfs_mount (grub_disk_t disk) /* Check if this is a HFS filesystem. */ if (grub_be_to_cpu16 (data->sblock.magic) != GRUB_HFS_MAGIC + || data->sblock.blksz == 0 || (data->sblock.blksz & grub_cpu_to_be32_compile_time (0xc00001ff))) { grub_error (GRUB_ERR_BAD_FS, "not an HFS filesystem"); @@ -366,11 +370,16 @@ grub_hfs_mount (grub_disk_t disk) data->cat_root = grub_be_to_cpu32 (treehead.head.root_node); data->cat_size = grub_be_to_cpu16 (treehead.head.node_size); + if (data->cat_size == 0 + || data->blksz < data->cat_size + || data->blksz < data->ext_size) + goto fail; + /* Lookup the root directory node in the catalog tree using the volume name. */ - key.parent_dir = grub_cpu_to_be32 (1); + key.parent_dir = grub_cpu_to_be32_compile_time (1); key.strlen = data->sblock.volname[0]; - grub_strcpy ((char *) key.str, (char *) (data->sblock.volname + 1)); + grub_strlcpy ((char *) key.str, (char *) (data->sblock.volname + 1), sizeof (key.str)); if (grub_hfs_find_node (data, (char *) &key, data->cat_root, 0, (char *) &dir, sizeof (dir)) == 0) @@ -396,8 +405,8 @@ grub_hfs_mount (grub_disk_t disk) /* Compare the K1 and K2 catalog file keys using HFS character ordering. */ static int -grub_hfs_cmp_catkeys (struct grub_hfs_catalog_key *k1, - struct grub_hfs_catalog_key *k2) +grub_hfs_cmp_catkeys (const struct grub_hfs_catalog_key *k1, + const struct grub_hfs_catalog_key *k2) { /* Taken from hfsutils 3.2.6 and converted to a readable form */ static const unsigned char hfs_charorder[256] = { @@ -640,8 +649,8 @@ grub_hfs_cmp_catkeys (struct grub_hfs_catalog_key *k1, /* Compare the K1 and K2 extent overflow file keys. */ static int -grub_hfs_cmp_extkeys (struct grub_hfs_extent_key *k1, - struct grub_hfs_extent_key *k2) +grub_hfs_cmp_extkeys (const struct grub_hfs_extent_key *k1, + const struct grub_hfs_extent_key *k2) { int cmp = k1->forktype - k2->forktype; if (cmp == 0) @@ -660,22 +669,32 @@ grub_hfs_cmp_extkeys (struct grub_hfs_extent_key *k1, static grub_err_t grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx, int this, int (*node_hook) (struct grub_hfs_node *hnd, - struct grub_hfs_record *)) + struct grub_hfs_record *, + void *hook_arg), + void *hook_arg) { - int nodesize = type == 0 ? data->cat_size : data->ext_size; + grub_size_t nodesize = type == 0 ? data->cat_size : data->ext_size; - union + union node_union { struct grub_hfs_node node; - char rawnode[nodesize]; - grub_uint16_t offsets[nodesize / 2]; - } node; + char rawnode[0]; + grub_uint16_t offsets[0]; + } *node; + + if (nodesize < sizeof (struct grub_hfs_node)) + nodesize = sizeof (struct grub_hfs_node); + + node = grub_malloc (nodesize); + if (!node) + return grub_errno; do { int i; struct grub_hfs_extent *dat; int blk; + grub_uint16_t reccnt; dat = (struct grub_hfs_extent *) (type == 0 ? (&data->sblock.catalog_recs) @@ -686,40 +705,101 @@ grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx, (type == 0) ? GRUB_HFS_CNID_CAT : GRUB_HFS_CNID_EXT, idx / (data->blksz / nodesize), 0); blk += (idx % (data->blksz / nodesize)); - if (grub_errno) - return grub_errno; - if (grub_disk_read (data->disk, blk, 0, - sizeof (node), &node)) - return grub_errno; + if (grub_errno || grub_disk_read (data->disk, blk, 0, + nodesize, node)) + { + grub_free (node); + return grub_errno; + } + + reccnt = grub_be_to_cpu16 (node->node.reccnt); + if (reccnt > (nodesize >> 1)) + reccnt = (nodesize >> 1); /* Iterate over all records in this node. */ - for (i = 0; i < grub_be_to_cpu16 (node.node.reccnt); i++) + for (i = 0; i < reccnt; i++) { int pos = (nodesize >> 1) - 1 - i; struct pointer { grub_uint8_t keylen; grub_uint8_t key; - } __attribute__ ((packed)) *pnt; - pnt = (struct pointer *) (grub_be_to_cpu16 (node.offsets[pos]) - + node.rawnode); + } GRUB_PACKED *pnt; + grub_uint16_t off = grub_be_to_cpu16 (node->offsets[pos]); + if (off > nodesize - sizeof(*pnt)) + continue; + pnt = (struct pointer *) (off + node->rawnode); + if (nodesize < (grub_size_t) off + pnt->keylen + 1) + continue; struct grub_hfs_record rec = { &pnt->key, pnt->keylen, &pnt->key + pnt->keylen +(pnt->keylen + 1) % 2, - nodesize - grub_be_to_cpu16 (node.offsets[pos]) - - pnt->keylen - 1 + nodesize - off - pnt->keylen - 1 }; - if (node_hook (&node.node, &rec)) - return 0; + if (node_hook (&node->node, &rec, hook_arg)) + { + grub_free (node); + return 0; + } } - idx = grub_be_to_cpu32 (node.node.next); + idx = grub_be_to_cpu32 (node->node.next); } while (idx && this); + grub_free (node); + return 0; +} + +struct grub_hfs_find_node_node_found_ctx +{ + int found; + int isleaf; + int done; + int type; + const char *key; + char *datar; + grub_size_t datalen; +}; + +static int +grub_hfs_find_node_node_found (struct grub_hfs_node *hnd, struct grub_hfs_record *rec, + void *hook_arg) +{ + struct grub_hfs_find_node_node_found_ctx *ctx = hook_arg; + int cmp = 1; + + if (ctx->type == 0) + cmp = grub_hfs_cmp_catkeys (rec->key, (const void *) ctx->key); + else + cmp = grub_hfs_cmp_extkeys (rec->key, (const void *) ctx->key); + + /* If the key is smaller or equal to the current node, mark the + entry. In case of a non-leaf mode it will be used to lookup + the rest of the tree. */ + if (cmp <= 0) + ctx->found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); + else /* The key can not be found in the tree. */ + return 1; + + /* Check if this node is a leaf node. */ + if (hnd->type == GRUB_HFS_NODE_LEAF) + { + ctx->isleaf = 1; + + /* Found it!!!! */ + if (cmp == 0) + { + ctx->done = 1; + + grub_memcpy (ctx->datar, rec->data, + rec->datalen < ctx->datalen ? rec->datalen : ctx->datalen); + return 1; + } + } return 0; } @@ -731,64 +811,84 @@ grub_hfs_iterate_records (struct grub_hfs_data *data, int type, int idx, the data in DATAR with a maximum length of DATALEN. */ static int grub_hfs_find_node (struct grub_hfs_data *data, char *key, - grub_uint32_t idx, int type, char *datar, int datalen) + grub_uint32_t idx, int type, char *datar, grub_size_t datalen) { - int found = -1; - int isleaf = 0; - int done = 0; - - auto int node_found (struct grub_hfs_node *, struct grub_hfs_record *); - - int node_found (struct grub_hfs_node *hnd, struct grub_hfs_record *rec) + struct grub_hfs_find_node_node_found_ctx ctx = { - int cmp = 1; - - if (type == 0) - cmp = grub_hfs_cmp_catkeys (rec->key, (void *) key); - else - cmp = grub_hfs_cmp_extkeys (rec->key, (void *) key); - - /* If the key is smaller or equal to the current node, mark the - entry. In case of a non-leaf mode it will be used to lookup - the rest of the tree. */ - if (cmp <= 0) - found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); - else /* The key can not be found in the tree. */ - return 1; - - /* Check if this node is a leaf node. */ - if (hnd->type == GRUB_HFS_NODE_LEAF) - { - isleaf = 1; - - /* Found it!!!! */ - if (cmp == 0) - { - done = 1; - - grub_memcpy (datar, rec->data, - rec->datalen < datalen ? rec->datalen : datalen); - return 1; - } - } - - return 0; - } + .found = -1, + .isleaf = 0, + .done = 0, + .type = type, + .key = key, + .datar = datar, + .datalen = datalen + }; do { - found = -1; + ctx.found = -1; - if (grub_hfs_iterate_records (data, type, idx, 0, node_found)) + if (grub_hfs_iterate_records (data, type, idx, 0, grub_hfs_find_node_node_found, &ctx)) return 0; - if (found == -1) + if (ctx.found == -1) return 0; - idx = found; - } while (! isleaf); + idx = ctx.found; + } while (! ctx.isleaf); - return done; + return ctx.done; +} + +struct grub_hfs_iterate_dir_node_found_ctx +{ + grub_uint32_t dir_be; + int found; + int isleaf; + grub_uint32_t next; + int (*hook) (struct grub_hfs_record *, void *hook_arg); + void *hook_arg; +}; + +static int +grub_hfs_iterate_dir_node_found (struct grub_hfs_node *hnd, struct grub_hfs_record *rec, + void *hook_arg) +{ + struct grub_hfs_iterate_dir_node_found_ctx *ctx = hook_arg; + struct grub_hfs_catalog_key *ckey = rec->key; + + /* The lowest key possible with DIR as root directory. */ + const struct grub_hfs_catalog_key key = {0, ctx->dir_be, 0, ""}; + + if (grub_hfs_cmp_catkeys (rec->key, &key) <= 0) + ctx->found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); + + if (hnd->type == 0xFF && ckey->strlen > 0) + { + ctx->isleaf = 1; + ctx->next = grub_be_to_cpu32 (hnd->next); + + /* An entry was found. */ + if (ckey->parent_dir == ctx->dir_be) + return ctx->hook (rec, ctx->hook_arg); + } + + return 0; +} + +static int +grub_hfs_iterate_dir_it_dir (struct grub_hfs_node *hnd __attribute ((unused)), + struct grub_hfs_record *rec, + void *hook_arg) +{ + struct grub_hfs_catalog_key *ckey = rec->key; + struct grub_hfs_iterate_dir_node_found_ctx *ctx = hook_arg; + + /* Stop when the entries do not match anymore. */ + if (ckey->parent_dir != ctx->dir_be) + return 1; + + return ctx->hook (rec, ctx->hook_arg); } @@ -797,70 +897,35 @@ grub_hfs_find_node (struct grub_hfs_data *data, char *key, call HOOK. */ static grub_err_t grub_hfs_iterate_dir (struct grub_hfs_data *data, grub_uint32_t root_idx, - unsigned int dir, int (*hook) (struct grub_hfs_record *)) + grub_uint32_t dir, int (*hook) (struct grub_hfs_record *, void *hook_arg), + void *hook_arg) { - int found = -1; - int isleaf = 0; - int next = 0; - - /* The lowest key possible with DIR as root directory. */ - struct grub_hfs_catalog_key key = {0, grub_cpu_to_be32 (dir), 0, ""}; - - auto int node_found (struct grub_hfs_node *, struct grub_hfs_record *); - auto int it_dir (struct grub_hfs_node * __attribute ((unused)), - struct grub_hfs_record *); - - - int node_found (struct grub_hfs_node *hnd, struct grub_hfs_record *rec) - { - struct grub_hfs_catalog_key *ckey = rec->key; - - if (grub_hfs_cmp_catkeys (rec->key, (void *) &key) <= 0) - found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); - - if (hnd->type == 0xFF && ckey->strlen > 0) - { - isleaf = 1; - next = grub_be_to_cpu32 (hnd->next); - - /* An entry was found. */ - if (grub_be_to_cpu32 (ckey->parent_dir) == dir) - return hook (rec); - } - - return 0; - } - - int it_dir (struct grub_hfs_node *hnd __attribute ((unused)), - struct grub_hfs_record *rec) - { - struct grub_hfs_catalog_key *ckey = rec->key; - struct grub_hfs_catalog_key *origkey = &key; - - /* Stop when the entries do not match anymore. */ - if (grub_be_to_cpu32 (ckey->parent_dir) - != grub_be_to_cpu32 ((origkey)->parent_dir)) - return 1; - - return hook (rec); - } + struct grub_hfs_iterate_dir_node_found_ctx ctx = + { + .dir_be = grub_cpu_to_be32 (dir), + .found = -1, + .isleaf = 0, + .next = 0, + .hook = hook, + .hook_arg = hook_arg + }; do { - found = -1; + ctx.found = -1; - if (grub_hfs_iterate_records (data, 0, root_idx, 0, node_found)) + if (grub_hfs_iterate_records (data, 0, root_idx, 0, grub_hfs_iterate_dir_node_found, &ctx)) return grub_errno; - if (found == -1) + if (ctx.found == -1) return 0; - root_idx = found; - } while (! isleaf); + root_idx = ctx.found; + } while (! ctx.isleaf); /* If there was a matching record in this leaf node, continue the iteration until the last record was found. */ - grub_hfs_iterate_records (data, 0, next, 1, it_dir); + grub_hfs_iterate_records (data, 0, ctx.next, 1, grub_hfs_iterate_dir_it_dir, &ctx); return grub_errno; } @@ -1012,7 +1077,7 @@ macroman_to_utf8 (char *to, const grub_uint8_t *from, grub_size_t len, { *optr++ = ':'; continue; - } + } if (!(*iptr & 0x80)) { *optr++ = *iptr; @@ -1029,7 +1094,7 @@ utf8_to_macroman (grub_uint8_t *to, const char *from) grub_uint8_t *end = to + 31; grub_uint8_t *optr = to; const char *iptr = from; - + while (*iptr && optr < end) { int i, clen; @@ -1039,7 +1104,7 @@ utf8_to_macroman (grub_uint8_t *to, const char *from) *optr++ = '/'; iptr++; continue; - } + } if (!(*iptr & 0x80)) { *optr++ = *iptr++; @@ -1062,143 +1127,145 @@ utf8_to_macroman (grub_uint8_t *to, const char *from) return optr - to; } +union grub_hfs_anyrec { + struct grub_hfs_filerec frec; + struct grub_hfs_dirrec dir; +}; + +struct grub_fshelp_node +{ + struct grub_hfs_data *data; + union grub_hfs_anyrec fdrec; + grub_uint32_t inode; +}; + +static grub_err_t +lookup_file (grub_fshelp_node_t dir, + const char *name, + grub_fshelp_node_t *foundnode, + enum grub_fshelp_filetype *foundtype) +{ + struct grub_hfs_catalog_key key; + grub_ssize_t slen; + union grub_hfs_anyrec fdrec; + + key.parent_dir = grub_cpu_to_be32 (dir->inode); + slen = utf8_to_macroman (key.str, name); + if (slen < 0) + /* Not found */ + return GRUB_ERR_NONE; + key.strlen = slen; + + /* Lookup this node. */ + if (! grub_hfs_find_node (dir->data, (char *) &key, dir->data->cat_root, + 0, (char *) &fdrec.frec, sizeof (fdrec.frec))) + /* Not found */ + return GRUB_ERR_NONE; + + *foundnode = grub_malloc (sizeof (struct grub_fshelp_node)); + if (!*foundnode) + return grub_errno; + + (*foundnode)->inode = grub_be_to_cpu32 (fdrec.dir.dirid); + (*foundnode)->fdrec = fdrec; + (*foundnode)->data = dir->data; + *foundtype = (fdrec.frec.type == GRUB_HFS_FILETYPE_DIR) ? GRUB_FSHELP_DIR : GRUB_FSHELP_REG; + return GRUB_ERR_NONE; +} /* Find a file or directory with the pathname PATH in the filesystem DATA. Return the file record in RETDATA when it is non-zero. Return the directory number in RETINODE when it is non-zero. */ static grub_err_t grub_hfs_find_dir (struct grub_hfs_data *data, const char *path, - struct grub_hfs_filerec *retdata, int *retinode) + grub_fshelp_node_t *found, + enum grub_fshelp_filetype exptype) { - int inode = data->rootdir; - char *next; - char *origpath; - union { - struct grub_hfs_filerec frec; - struct grub_hfs_dirrec dir; - } fdrec; - - fdrec.frec.type = GRUB_HFS_FILETYPE_DIR; - - if (path[0] != '/') - { - grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); - return 0; + struct grub_fshelp_node root = { + .data = data, + .inode = data->rootdir, + .fdrec = { + .frec = { + .type = GRUB_HFS_FILETYPE_DIR + } } + }; + grub_err_t err; - origpath = grub_strdup (path); - if (!origpath) - return grub_errno; + err = grub_fshelp_find_file_lookup (path, &root, found, lookup_file, NULL, exptype); - path = origpath; - while (*path == '/') - path++; - - while (path && grub_strlen (path)) + if (&root == *found) { - grub_ssize_t slen; - if (fdrec.frec.type != GRUB_HFS_FILETYPE_DIR) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - goto fail; - } - - /* Isolate a part of the path. */ - next = grub_strchr (path, '/'); - if (next) - { - while (*next == '/') - *(next++) = '\0'; - } - - struct grub_hfs_catalog_key key; - - key.parent_dir = grub_cpu_to_be32 (inode); - slen = utf8_to_macroman (key.str, path); - if (slen < 0) - { - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); - goto fail; - } - key.strlen = slen; - - /* Lookup this node. */ - if (! grub_hfs_find_node (data, (char *) &key, data->cat_root, - 0, (char *) &fdrec.frec, sizeof (fdrec.frec))) - { - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath); - goto fail; - } - - if (grub_errno) - goto fail; - - inode = grub_be_to_cpu32 (fdrec.dir.dirid); - path = next; + *found = grub_malloc (sizeof (root)); + if (!*found) + return grub_errno; + grub_memcpy (*found, &root, sizeof (root)); } - - if (retdata) - grub_memcpy (retdata, &fdrec.frec, sizeof (fdrec.frec)); - - if (retinode) - *retinode = inode; - - fail: - grub_free (origpath); - return grub_errno; + return err; } +struct grub_hfs_dir_hook_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +static int +grub_hfs_dir_hook (struct grub_hfs_record *rec, void *hook_arg) +{ + struct grub_hfs_dir_hook_ctx *ctx = hook_arg; + struct grub_hfs_dirrec *drec = rec->data; + struct grub_hfs_filerec *frec = rec->data; + struct grub_hfs_catalog_key *ckey = rec->key; + char fname[sizeof (ckey->str) * MAX_UTF8_PER_MAC_ROMAN + 1]; + struct grub_dirhook_info info; + grub_size_t len; + + grub_memset (fname, 0, sizeof (fname)); + + grub_memset (&info, 0, sizeof (info)); + + len = ckey->strlen; + if (len > sizeof (ckey->str)) + len = sizeof (ckey->str); + macroman_to_utf8 (fname, ckey->str, len, 1); + + info.case_insensitive = 1; + + if (drec->type == GRUB_HFS_FILETYPE_DIR) + { + info.dir = 1; + info.mtimeset = 1; + info.inodeset = 1; + info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800; + info.inode = grub_be_to_cpu32 (drec->dirid); + return ctx->hook (fname, &info, ctx->hook_data); + } + if (frec->type == GRUB_HFS_FILETYPE_FILE) + { + info.dir = 0; + info.mtimeset = 1; + info.inodeset = 1; + info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800; + info.inode = grub_be_to_cpu32 (frec->fileid); + return ctx->hook (fname, &info, ctx->hook_data); + } + + return 0; +} static grub_err_t -grub_hfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) +grub_hfs_dir (grub_device_t device, const char *path, grub_fs_dir_hook_t hook, + void *hook_data) { - int inode; - - auto int dir_hook (struct grub_hfs_record *rec); - - int dir_hook (struct grub_hfs_record *rec) - { - struct grub_hfs_dirrec *drec = rec->data; - struct grub_hfs_filerec *frec = rec->data; - struct grub_hfs_catalog_key *ckey = rec->key; - char fname[sizeof (ckey->str) * MAX_UTF8_PER_MAC_ROMAN + 1]; - struct grub_dirhook_info info; - grub_size_t len; - - grub_memset (fname, 0, sizeof (fname)); - - grub_memset (&info, 0, sizeof (info)); - - len = ckey->strlen; - if (len > sizeof (ckey->str)) - len = sizeof (ckey->str); - macroman_to_utf8 (fname, ckey->str, len, 1); - - info.case_insensitive = 1; - - if (drec->type == GRUB_HFS_FILETYPE_DIR) - { - info.dir = 1; - info.mtimeset = 1; - info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800; - return hook (fname, &info); - } - if (frec->type == GRUB_HFS_FILETYPE_FILE) - { - info.dir = 0; - info.mtimeset = 1; - info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800; - return hook (fname, &info); - } - - return 0; - } - struct grub_hfs_data *data; - struct grub_hfs_filerec frec; + struct grub_hfs_dir_hook_ctx ctx = + { + .hook = hook, + .hook_data = hook_data + }; + grub_fshelp_node_t found = NULL; grub_dl_ref (my_mod); @@ -1207,18 +1274,13 @@ grub_hfs_dir (grub_device_t device, const char *path, goto fail; /* First the directory ID for the directory. */ - if (grub_hfs_find_dir (data, path, &frec, &inode)) + if (grub_hfs_find_dir (data, path, &found, GRUB_FSHELP_DIR)) goto fail; - if (frec.type != GRUB_HFS_FILETYPE_DIR) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - goto fail; - } - - grub_hfs_iterate_dir (data, data->cat_root, inode, dir_hook); + grub_hfs_iterate_dir (data, data->cat_root, found->inode, grub_hfs_dir_hook, &ctx); fail: + grub_free (found); grub_free (data); grub_dl_unref (my_mod); @@ -1232,35 +1294,36 @@ static grub_err_t grub_hfs_open (struct grub_file *file, const char *name) { struct grub_hfs_data *data; - struct grub_hfs_filerec frec; + grub_fshelp_node_t found = NULL; grub_dl_ref (my_mod); data = grub_hfs_mount (file->device->disk); - if (grub_hfs_find_dir (data, name, &frec, 0)) + if (!data) { - grub_free (data); grub_dl_unref (my_mod); return grub_errno; } - if (frec.type != GRUB_HFS_FILETYPE_FILE) + if (grub_hfs_find_dir (data, name, &found, GRUB_FSHELP_REG)) { grub_free (data); - grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); + grub_free (found); grub_dl_unref (my_mod); return grub_errno; } - grub_memcpy (data->extents, frec.extents, sizeof (grub_hfs_datarecord_t)); - file->size = grub_be_to_cpu32 (frec.size); - data->size = grub_be_to_cpu32 (frec.size); - data->fileid = grub_be_to_cpu32 (frec.fileid); + grub_memcpy (data->extents, found->fdrec.frec.extents, sizeof (grub_hfs_datarecord_t)); + file->size = grub_be_to_cpu32 (found->fdrec.frec.size); + data->size = grub_be_to_cpu32 (found->fdrec.frec.size); + data->fileid = grub_be_to_cpu32 (found->fdrec.frec.fileid); file->offset = 0; file->data = data; + grub_free (found); + return 0; } @@ -1270,7 +1333,8 @@ grub_hfs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_hfs_data *data = (struct grub_hfs_data *) file->data; - return grub_hfs_read_file (data, file->read_hook, file->offset, len, buf); + return grub_hfs_read_file (data, file->read_hook, file->read_hook_data, + file->offset, len, buf); } @@ -1297,7 +1361,7 @@ grub_hfs_label (grub_device_t device, char **label) grub_size_t len = data->sblock.volname[0]; if (len > sizeof (data->sblock.volname) - 1) len = sizeof (data->sblock.volname) - 1; - *label = grub_malloc (len * MAX_UTF8_PER_MAC_ROMAN + 1); + *label = grub_calloc (MAX_UTF8_PER_MAC_ROMAN + 1, len); if (*label) macroman_to_utf8 (*label, data->sblock.volname + 1, len + 1, 0); @@ -1310,7 +1374,7 @@ grub_hfs_label (grub_device_t device, char **label) } static grub_err_t -grub_hfs_mtime (grub_device_t device, grub_int32_t *tm) +grub_hfs_mtime (grub_device_t device, grub_int64_t *tm) { struct grub_hfs_data *data; @@ -1354,13 +1418,13 @@ grub_hfs_uuid (grub_device_t device, char **uuid) static struct grub_fs grub_hfs_fs = { .name = "hfs", - .dir = grub_hfs_dir, - .open = grub_hfs_open, - .read = grub_hfs_read, - .close = grub_hfs_close, - .label = grub_hfs_label, - .uuid = grub_hfs_uuid, - .mtime = grub_hfs_mtime, + .fs_dir = grub_hfs_dir, + .fs_open = grub_hfs_open, + .fs_read = grub_hfs_read, + .fs_close = grub_hfs_close, + .fs_label = grub_hfs_label, + .fs_uuid = grub_hfs_uuid, + .fs_mtime = grub_hfs_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, @@ -1370,11 +1434,14 @@ static struct grub_fs grub_hfs_fs = GRUB_MOD_INIT(hfs) { - grub_fs_register (&grub_hfs_fs); + grub_hfs_fs.mod = mod; + if (!grub_is_lockdown ()) + grub_fs_register (&grub_hfs_fs); my_mod = mod; } GRUB_MOD_FINI(hfs) { - grub_fs_unregister (&grub_hfs_fs); + if (!grub_is_lockdown()) + grub_fs_unregister (&grub_hfs_fs); } diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 981246475..3f203abcc 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -19,6 +19,7 @@ /* HFS+ is documented at http://developer.apple.com/technotes/tn/tn1150.html */ +#define grub_fshelp_node grub_hfsplus_file #include #include #include @@ -29,50 +30,11 @@ #include #include #include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); -#define GRUB_HFSPLUS_MAGIC 0x482B -#define GRUB_HFSPLUSX_MAGIC 0x4858 -#define GRUB_HFSPLUS_SBLOCK 2 - -/* A HFS+ extent. */ -struct grub_hfsplus_extent -{ - /* The first block of a file on disk. */ - grub_uint32_t start; - /* The amount of blocks described by this extent. */ - grub_uint32_t count; -} __attribute__ ((packed)); - -/* The descriptor of a fork. */ -struct grub_hfsplus_forkdata -{ - grub_uint64_t size; - grub_uint32_t clumpsize; - grub_uint32_t blocks; - struct grub_hfsplus_extent extents[8]; -} __attribute__ ((packed)); - -/* The HFS+ Volume Header. */ -struct grub_hfsplus_volheader -{ - grub_uint16_t magic; - grub_uint16_t version; - grub_uint32_t attributes; - grub_uint8_t unused1[12]; - grub_uint32_t utime; - grub_uint8_t unused2[16]; - grub_uint32_t blksize; - grub_uint8_t unused3[60]; - grub_uint64_t num_serial; - struct grub_hfsplus_forkdata allocations_file; - struct grub_hfsplus_forkdata extents_file; - struct grub_hfsplus_forkdata catalog_file; - struct grub_hfsplus_forkdata attrib_file; - struct grub_hfsplus_forkdata startup_file; -} __attribute__ ((packed)); - /* The type of node. */ enum grub_hfsplus_btnode_type { @@ -82,16 +44,6 @@ enum grub_hfsplus_btnode_type GRUB_HFSPLUS_BTNODE_TYPE_MAP = 2, }; -struct grub_hfsplus_btnode -{ - grub_uint32_t next; - grub_uint32_t prev; - grub_int8_t type; - grub_uint8_t height; - grub_uint16_t count; - grub_uint16_t unused; -} __attribute__ ((packed)); - /* The header of a HFS+ B+ Tree. */ struct grub_hfsplus_btheader { @@ -109,36 +61,7 @@ struct grub_hfsplus_btheader grub_uint8_t btree_type; grub_uint8_t key_compare; grub_uint32_t attributes; -} __attribute__ ((packed)); - -/* The on disk layout of a catalog key. */ -struct grub_hfsplus_catkey -{ - grub_uint16_t keylen; - grub_uint32_t parent; - grub_uint16_t namelen; - grub_uint16_t name[30]; -} __attribute__ ((packed)); - -/* The on disk layout of an extent overflow file key. */ -struct grub_hfsplus_extkey -{ - grub_uint16_t keylen; - grub_uint8_t type; - grub_uint8_t unused; - grub_uint32_t fileid; - grub_uint32_t start; -} __attribute__ ((packed)); - -struct grub_hfsplus_key -{ - union - { - struct grub_hfsplus_extkey extkey; - struct grub_hfsplus_catkey catkey; - grub_uint16_t keylen; - }; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_hfsplus_catfile { @@ -153,7 +76,7 @@ struct grub_hfsplus_catfile grub_uint8_t unused3[44]; struct grub_hfsplus_forkdata data; struct grub_hfsplus_forkdata resource; -} __attribute__ ((packed)); +} GRUB_PACKED; /* Filetype information as used in inodes. */ #define GRUB_HFSPLUS_FILEMODE_MASK 0170000 @@ -161,10 +84,20 @@ struct grub_hfsplus_catfile #define GRUB_HFSPLUS_FILEMODE_DIRECTORY 0040000 #define GRUB_HFSPLUS_FILEMODE_SYMLINK 0120000 +#define HFSPLUS_BTNODE_MINSZ (1 << 9) +#define HFSPLUS_BTNODE_MAXSZ (1 << 15) + +#define HFSPLUS_CATKEY_MIN_LEN 6 +#define HFSPLUS_CATKEY_MAX_LEN 516 + /* Some pre-defined file IDs. */ -#define GRUB_HFSPLUS_FILEID_ROOTDIR 2 -#define GRUB_HFSPLUS_FILEID_OVERFLOW 3 -#define GRUB_HFSPLUS_FILEID_CATALOG 4 +enum + { + GRUB_HFSPLUS_FILEID_ROOTDIR = 2, + GRUB_HFSPLUS_FILEID_OVERFLOW = 3, + GRUB_HFSPLUS_FILEID_CATALOG = 4, + GRUB_HFSPLUS_FILEID_ATTR = 8 + }; enum grub_hfsplus_filetype { @@ -177,98 +110,15 @@ enum grub_hfsplus_filetype #define GRUB_HFSPLUSX_BINARYCOMPARE 0xBC #define GRUB_HFSPLUSX_CASEFOLDING 0xCF -/* Internal representation of a catalog key. */ -struct grub_hfsplus_catkey_internal -{ - grub_uint32_t parent; - const grub_uint16_t *name; - grub_size_t namelen; -}; - -/* Internal representation of an extent overflow key. */ -struct grub_hfsplus_extkey_internal -{ - grub_uint32_t fileid; - grub_uint8_t type; - grub_uint32_t start; -}; - -struct grub_hfsplus_key_internal -{ - union - { - struct grub_hfsplus_extkey_internal extkey; - struct grub_hfsplus_catkey_internal catkey; - }; -}; - - - -struct grub_fshelp_node -{ - struct grub_hfsplus_data *data; - struct grub_hfsplus_extent extents[8]; - grub_uint64_t size; - grub_uint32_t fileid; - grub_int32_t mtime; -}; - -struct grub_hfsplus_btree -{ - grub_uint32_t root; - grub_size_t nodesize; - - /* Catalog file node. */ - struct grub_fshelp_node file; -}; - -/* Information about a "mounted" HFS+ filesystem. */ -struct grub_hfsplus_data -{ - struct grub_hfsplus_volheader volheader; - grub_disk_t disk; - - unsigned int log2blksize; - - struct grub_hfsplus_btree catalog_tree; - struct grub_hfsplus_btree extoverflow_tree; - - struct grub_fshelp_node dirroot; - struct grub_fshelp_node opened_file; - - /* This is the offset into the physical disk for an embedded HFS+ - filesystem (one inside a plain HFS wrapper). */ - grub_disk_addr_t embedded_offset; - int case_sensitive; -}; - static grub_dl_t my_mod; -/* Return the offset of the record with the index INDEX, in the node - NODE which is part of the B+ tree BTREE. */ -static inline grub_off_t -grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree, - struct grub_hfsplus_btnode *node, int index) -{ - char *cnode = (char *) node; - void *recptr; - recptr = (&cnode[btree->nodesize - index * sizeof (grub_uint16_t) - 2]); - return grub_be_to_cpu16 (grub_get_unaligned16 (recptr)); -} - -/* Return a pointer to the record with the index INDEX, in the node - NODE which is part of the B+ tree BTREE. */ -static inline struct grub_hfsplus_key * -grub_hfsplus_btree_recptr (struct grub_hfsplus_btree *btree, - struct grub_hfsplus_btnode *node, int index) -{ - char *cnode = (char *) node; - grub_off_t offset; - offset = grub_hfsplus_btree_recoffset (btree, node, index); - return (struct grub_hfsplus_key *) &cnode[offset]; -} +grub_err_t (*grub_hfsplus_open_compressed) (struct grub_fshelp_node *node); +grub_ssize_t (*grub_hfsplus_read_compressed) (struct grub_hfsplus_file *node, + grub_off_t pos, + grub_size_t len, + char *buf); /* Find the extent that points to FILEBLOCK. If it is not in one of the 8 extents described by EXTENT, return -1. In that case set @@ -292,14 +142,6 @@ grub_hfsplus_find_block (struct grub_hfsplus_extent *extent, return 0xffffffffffffffffULL; } -static grub_err_t -grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, - struct grub_hfsplus_key_internal *key, - int (*compare_keys) (struct grub_hfsplus_key *keya, - struct grub_hfsplus_key_internal *keyb), - struct grub_hfsplus_btnode **matchnode, - grub_off_t *keyoffset); - static int grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya, struct grub_hfsplus_key_internal *keyb); @@ -310,7 +152,8 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { struct grub_hfsplus_btnode *nnode = 0; grub_disk_addr_t blksleft = fileblock; - struct grub_hfsplus_extent *extents = &node->extents[0]; + struct grub_hfsplus_extent *extents = node->compressed + ? &node->resource_extents[0] : &node->extents[0]; while (1) { @@ -340,17 +183,30 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) break; } + /* + * If the extent overflow tree isn't ready yet, we can't look + * in it. This can happen where the catalog file is corrupted. + */ + if (!node->data->extoverflow_tree_ready) + { + grub_error (GRUB_ERR_BAD_FS, + "attempted to read extent overflow tree before loading"); + break; + } + /* Set up the key to look for in the extent overflow file. */ extoverflow.extkey.fileid = node->fileid; extoverflow.extkey.type = 0; extoverflow.extkey.start = fileblock - blksleft; - + extoverflow.extkey.type = node->compressed ? 0xff : 0; if (grub_hfsplus_btree_search (&node->data->extoverflow_tree, &extoverflow, - grub_hfsplus_cmp_extkey, &nnode, &ptr)) + grub_hfsplus_cmp_extkey, &nnode, &ptr) + || !nnode) { grub_error (GRUB_ERR_READ_ERROR, - "no block found for the file id 0x%x and the block offset 0x%x", + "no block found for the file id 0x%x and the block" + " offset 0x%" PRIuGRUB_UINT64_T, node->fileid, fileblock); break; } @@ -373,13 +229,13 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) /* Read LEN bytes from the file described by DATA starting with byte POS. Return the amount of read bytes in READ. */ -static grub_ssize_t +grub_ssize_t grub_hfsplus_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { - return grub_fshelp_read_file (node->data->disk, node, read_hook, + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, pos, len, buf, grub_hfsplus_read_block, node->size, node->data->log2blksize - GRUB_DISK_SECTOR_BITS, @@ -403,6 +259,7 @@ grub_hfsplus_mount (grub_disk_t disk) return 0; data->disk = disk; + data->extoverflow_tree_ready = 0; /* Read the bootblock. */ grub_disk_read (disk, GRUB_HFSPLUS_SBLOCK, 0, sizeof (volheader), @@ -460,15 +317,27 @@ grub_hfsplus_mount (grub_disk_t disk) /* Make a new node for the catalog tree. */ data->catalog_tree.file.data = data; data->catalog_tree.file.fileid = GRUB_HFSPLUS_FILEID_CATALOG; + data->catalog_tree.file.compressed = 0; grub_memcpy (&data->catalog_tree.file.extents, data->volheader.catalog_file.extents, sizeof data->volheader.catalog_file.extents); data->catalog_tree.file.size = grub_be_to_cpu64 (data->volheader.catalog_file.size); + data->attr_tree.file.data = data; + data->attr_tree.file.fileid = GRUB_HFSPLUS_FILEID_ATTR; + grub_memcpy (&data->attr_tree.file.extents, + data->volheader.attr_file.extents, + sizeof data->volheader.attr_file.extents); + + data->attr_tree.file.size = + grub_be_to_cpu64 (data->volheader.attr_file.size); + data->attr_tree.file.compressed = 0; + /* Make a new node for the extent overflow file. */ data->extoverflow_tree.file.data = data; data->extoverflow_tree.file.fileid = GRUB_HFSPLUS_FILEID_OVERFLOW; + data->extoverflow_tree.file.compressed = 0; grub_memcpy (&data->extoverflow_tree.file.extents, data->volheader.extents_file.extents, sizeof data->volheader.catalog_file.extents); @@ -477,7 +346,7 @@ grub_hfsplus_mount (grub_disk_t disk) grub_be_to_cpu64 (data->volheader.extents_file.size); /* Read the essential information about the trees. */ - if (grub_hfsplus_read_file (&data->catalog_tree.file, 0, + if (grub_hfsplus_read_file (&data->catalog_tree.file, 0, 0, sizeof (struct grub_hfsplus_btnode), sizeof (header), (char *) &header) <= 0) goto fail; @@ -487,20 +356,48 @@ grub_hfsplus_mount (grub_disk_t disk) data->case_sensitive = ((magic == GRUB_HFSPLUSX_MAGIC) && (header.key_compare == GRUB_HFSPLUSX_BINARYCOMPARE)); - if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, + if (data->catalog_tree.nodesize < 2) + { + grub_error (GRUB_ERR_BAD_FS, "invalid catalog node size"); + goto fail; + } + + if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0, sizeof (struct grub_hfsplus_btnode), sizeof (header), (char *) &header) <= 0) goto fail; data->extoverflow_tree.root = grub_be_to_cpu32 (header.root); - if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0, + if (grub_hfsplus_read_file (&data->extoverflow_tree.file, 0, 0, 0, sizeof (node), (char *) &node) <= 0) goto fail; data->extoverflow_tree.root = grub_be_to_cpu32 (header.root); data->extoverflow_tree.nodesize = grub_be_to_cpu16 (header.nodesize); + if (data->extoverflow_tree.nodesize < 2) + { + grub_error (GRUB_ERR_BAD_FS, "invalid extents overflow node size"); + goto fail; + } + + data->extoverflow_tree_ready = 1; + + if (grub_hfsplus_read_file (&data->attr_tree.file, 0, 0, + sizeof (struct grub_hfsplus_btnode), + sizeof (header), (char *) &header) <= 0) + { + grub_errno = 0; + data->attr_tree.root = 0; + data->attr_tree.nodesize = 0; + } + else + { + data->attr_tree.root = grub_be_to_cpu32 (header.root); + data->attr_tree.nodesize = grub_be_to_cpu16 (header.nodesize); + } + data->dirroot.data = data; data->dirroot.fileid = GRUB_HFSPLUS_FILEID_ROOTDIR; @@ -508,7 +405,7 @@ grub_hfsplus_mount (grub_disk_t disk) fail: - if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + if (grub_errno == GRUB_ERR_OUT_OF_RANGE || grub_errno == GRUB_ERR_NONE) grub_error (GRUB_ERR_BAD_FS, "not a HFS+ filesystem"); grub_free (data); @@ -586,7 +483,13 @@ grub_hfsplus_cmp_extkey (struct grub_hfsplus_key *keya, return 1; if (extkey_a->type < extkey_b->type) return -1; - + + if (extkey_a->type > extkey_b->type) + return +1; + + if (extkey_a->type < extkey_b->type) + return -1; + akey = grub_be_to_cpu32 (extkey_a->start); if (akey > extkey_b->start) return 1; @@ -600,12 +503,16 @@ grub_hfsplus_read_symlink (grub_fshelp_node_t node) { char *symlink; grub_ssize_t numread; + grub_size_t sz = node->size; - symlink = grub_malloc (node->size + 1); + if (grub_add (sz, 1, &sz)) + return NULL; + + symlink = grub_malloc (sz); if (!symlink) return 0; - numread = grub_hfsplus_read_file (node, 0, 0, node->size, symlink); + numread = grub_hfsplus_read_file (node, 0, 0, 0, node->size, symlink); if (numread != (grub_ssize_t) node->size) { grub_free (symlink); @@ -620,7 +527,8 @@ static int grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree, struct grub_hfsplus_btnode *first_node, grub_disk_addr_t first_rec, - int (*hook) (void *record)) + int (*hook) (void *record, void *hook_arg), + void *hook_arg) { grub_disk_addr_t rec; grub_uint64_t saved_node = -1; @@ -633,7 +541,7 @@ grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree, /* Iterate over all records in this node. */ for (rec = first_rec; rec < grub_be_to_cpu16 (first_node->count); rec++) { - if (hook (grub_hfsplus_btree_recptr (btree, first_node, rec))) + if (hook (grub_hfsplus_btree_recptr (btree, first_node, rec), hook_arg)) return 1; } @@ -649,7 +557,7 @@ grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree, saved_node = first_node->next; node_count++; - if (grub_hfsplus_read_file (&btree->file, 0, + if (grub_hfsplus_read_file (&btree->file, 0, 0, (((grub_disk_addr_t) grub_be_to_cpu32 (first_node->next)) * btree->nodesize), @@ -667,12 +575,12 @@ grub_hfsplus_btree_iterate_node (struct grub_hfsplus_btree *btree, keys using the function COMPARE_KEYS. When a match is found, return the node in MATCHNODE and a pointer to the data in this node in KEYOFFSET. MATCHNODE should be freed by the caller. */ -static grub_err_t +grub_err_t grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, struct grub_hfsplus_key_internal *key, int (*compare_keys) (struct grub_hfsplus_key *keya, struct grub_hfsplus_key_internal *keyb), - struct grub_hfsplus_btnode **matchnode, + struct grub_hfsplus_btnode **matchnode, grub_off_t *keyoffset) { grub_uint64_t currnode; @@ -682,6 +590,16 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, grub_uint64_t save_node; grub_uint64_t node_count = 0; + if (!btree->nodesize) + { + *matchnode = 0; + return 0; + } + + if (btree->nodesize < HFSPLUS_BTNODE_MINSZ || + btree->nodesize > HFSPLUS_BTNODE_MAXSZ) + return grub_error (GRUB_ERR_BAD_FS, "invalid HFS+ btree node size"); + node = grub_malloc (btree->nodesize); if (! node) return grub_errno; @@ -702,7 +620,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, node_count++; /* Read a node. */ - if (grub_hfsplus_read_file (&btree->file, 0, + if (grub_hfsplus_read_file (&btree->file, 0, 0, (grub_disk_addr_t) currnode * (grub_disk_addr_t) btree->nodesize, btree->nodesize, (char *) node) <= 0) @@ -748,6 +666,13 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, pointer = ((char *) currkey + grub_be_to_cpu16 (currkey->keylen) + 2); + + if ((char *) pointer > node + btree->nodesize - 2) + { + grub_free (node); + return grub_error (GRUB_ERR_BAD_FS, "HFS+ key beyond end of node"); + } + currnode = grub_be_to_cpu32 (grub_get_unaligned32 (pointer)); match = 1; } @@ -759,135 +684,169 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, { *matchnode = 0; grub_free (node); - return 1; + return 0; } } } -static int -grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) +struct list_nodes_ctx { - int ret = 0; + int ret; + grub_fshelp_node_t dir; + grub_fshelp_iterate_dir_hook_t hook; + void *hook_data; +}; - auto int list_nodes (void *record); - int list_nodes (void *record) +static int +list_nodes (void *record, void *hook_arg) +{ + struct grub_hfsplus_catkey *catkey; + char *filename; + int i; + struct grub_fshelp_node *node; + grub_uint16_t *keyname; + struct grub_hfsplus_catfile *fileinfo; + enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; + struct list_nodes_ctx *ctx = hook_arg; + + catkey = (struct grub_hfsplus_catkey *) record; + + if (grub_be_to_cpu16 (catkey->keylen) < HFSPLUS_CATKEY_MIN_LEN || + grub_be_to_cpu16 (catkey->keylen) > HFSPLUS_CATKEY_MAX_LEN) { - struct grub_hfsplus_catkey *catkey; - char *filename; - int i; - struct grub_fshelp_node *node; - struct grub_hfsplus_catfile *fileinfo; - enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; + grub_error (GRUB_ERR_BAD_FS, "catalog key length is out of range"); + return 1; + } - catkey = (struct grub_hfsplus_catkey *) record; + fileinfo = + (struct grub_hfsplus_catfile *) ((char *) record + + grub_be_to_cpu16 (catkey->keylen) + + 2 + (grub_be_to_cpu16(catkey->keylen) + % 2)); - fileinfo = - (struct grub_hfsplus_catfile *) ((char *) record - + grub_be_to_cpu16 (catkey->keylen) - + 2 + (grub_be_to_cpu16(catkey->keylen) - % 2)); + /* Stop iterating when the last directory entry is found. */ + if (grub_be_to_cpu32 (catkey->parent) != ctx->dir->fileid) + return 1; - /* Stop iterating when the last directory entry is found. */ - if (grub_be_to_cpu32 (catkey->parent) != dir->fileid) - return 1; + /* Determine the type of the node that is found. */ + switch (fileinfo->type) + { + case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_REG): + { + int mode = (grub_be_to_cpu16 (fileinfo->mode) + & GRUB_HFSPLUS_FILEMODE_MASK); - /* Determine the type of the node that is found. */ - switch (fileinfo->type) - { - case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_REG): - { - int mode = (grub_be_to_cpu16 (fileinfo->mode) - & GRUB_HFSPLUS_FILEMODE_MASK); - - if (mode == GRUB_HFSPLUS_FILEMODE_REG) - type = GRUB_FSHELP_REG; - else if (mode == GRUB_HFSPLUS_FILEMODE_SYMLINK) - type = GRUB_FSHELP_SYMLINK; - else - type = GRUB_FSHELP_UNKNOWN; - break; - } - case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_DIR): - type = GRUB_FSHELP_DIR; - break; - case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_DIR_THREAD): - if (dir->fileid == 2) - return 0; - node = grub_malloc (sizeof (*node)); - if (!node) - return 1; - node->data = dir->data; - node->mtime = 0; - node->size = 0; - node->fileid = grub_be_to_cpu32 (fileinfo->parentid); - - ret = hook ("..", GRUB_FSHELP_DIR, node); - return ret; - } - - if (type == GRUB_FSHELP_UNKNOWN) + if (mode == GRUB_HFSPLUS_FILEMODE_REG) + type = GRUB_FSHELP_REG; + else if (mode == GRUB_HFSPLUS_FILEMODE_SYMLINK) + type = GRUB_FSHELP_SYMLINK; + else + type = GRUB_FSHELP_UNKNOWN; + break; + } + case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_DIR): + type = GRUB_FSHELP_DIR; + break; + case grub_cpu_to_be16_compile_time (GRUB_HFSPLUS_FILETYPE_DIR_THREAD): + if (ctx->dir->fileid == 2) return 0; - - filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen) - * GRUB_MAX_UTF8_PER_UTF16 + 1); - if (! filename) - return 0; - - /* Make sure the byte order of the UTF16 string is correct. */ - for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) - { - catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); - - if (catkey->name[i] == '/') - catkey->name[i] = ':'; - - /* If the name is obviously invalid, skip this node. */ - if (catkey->name[i] == 0) - return 0; - } - - *grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name, - grub_be_to_cpu16 (catkey->namelen)) = '\0'; - - /* Restore the byte order to what it was previously. */ - for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) - { - if (catkey->name[i] == ':') - catkey->name[i] = '/'; - catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); - } - - /* hfs+ is case insensitive. */ - if (! dir->data->case_sensitive) - type |= GRUB_FSHELP_CASE_INSENSITIVE; - - /* A valid node is found; setup the node and call the - callback function. */ node = grub_malloc (sizeof (*node)); if (!node) return 1; - node->data = dir->data; + node->data = ctx->dir->data; + node->mtime = 0; + node->size = 0; + node->fileid = grub_be_to_cpu32 (fileinfo->parentid); - grub_memcpy (node->extents, fileinfo->data.extents, - sizeof (node->extents)); - node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800; - node->size = grub_be_to_cpu64 (fileinfo->data.size); - node->fileid = grub_be_to_cpu32 (fileinfo->fileid); - - ret = hook (filename, type, node); - - grub_free (filename); - - return ret; + ctx->ret = ctx->hook ("..", GRUB_FSHELP_DIR, node, ctx->hook_data); + return ctx->ret; } + if (type == GRUB_FSHELP_UNKNOWN) + return 0; + + filename = grub_calloc (grub_be_to_cpu16 (catkey->namelen), + GRUB_MAX_UTF8_PER_UTF16 + 1); + if (! filename) + return 0; + + keyname = grub_calloc (grub_be_to_cpu16 (catkey->namelen), sizeof (*keyname)); + if (!keyname) + { + grub_free (filename); + return 0; + } + + /* Make sure the byte order of the UTF16 string is correct. */ + for (i = 0; i < grub_be_to_cpu16 (catkey->namelen); i++) + { + keyname[i] = grub_be_to_cpu16 (catkey->name[i]); + + if (keyname[i] == '/') + keyname[i] = ':'; + + /* If the name is obviously invalid, skip this node. */ + if (keyname[i] == 0) + { + grub_free (keyname); + grub_free (filename); + return 0; + } + } + + *grub_utf16_to_utf8 ((grub_uint8_t *) filename, keyname, + grub_be_to_cpu16 (catkey->namelen)) = '\0'; + + grub_free (keyname); + + /* hfs+ is case insensitive. */ + if (! ctx->dir->data->case_sensitive) + type |= GRUB_FSHELP_CASE_INSENSITIVE; + + /* A valid node is found; setup the node and call the + callback function. */ + node = grub_malloc (sizeof (*node)); + if (!node) + { + grub_free (filename); + return 1; + } + node->data = ctx->dir->data; + node->compressed = 0; + node->cbuf = 0; + node->compress_index = 0; + + grub_memcpy (node->extents, fileinfo->data.extents, + sizeof (node->extents)); + grub_memcpy (node->resource_extents, fileinfo->resource.extents, + sizeof (node->resource_extents)); + node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800; + node->size = grub_be_to_cpu64 (fileinfo->data.size); + node->resource_size = grub_be_to_cpu64 (fileinfo->resource.size); + node->fileid = grub_be_to_cpu32 (fileinfo->fileid); + + ctx->ret = ctx->hook (filename, type, node, ctx->hook_data); + + grub_free (filename); + + return ctx->ret; +} + +static int +grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) +{ + struct list_nodes_ctx ctx = + { + .ret = 0, + .dir = dir, + .hook = hook, + .hook_data = hook_data + }; + struct grub_hfsplus_key_internal intern; - struct grub_hfsplus_btnode *node; - grub_disk_addr_t ptr; + struct grub_hfsplus_btnode *node = NULL; + grub_disk_addr_t ptr = 0; { struct grub_fshelp_node *fsnode; @@ -895,7 +854,7 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, if (!fsnode) return 1; *fsnode = *dir; - if (hook (".", GRUB_FSHELP_DIR, fsnode)) + if (hook (".", GRUB_FSHELP_DIR, fsnode, hook_data)) return 1; } @@ -906,16 +865,17 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, /* First lookup the first entry. */ if (grub_hfsplus_btree_search (&dir->data->catalog_tree, &intern, - grub_hfsplus_cmp_catkey, &node, &ptr)) + grub_hfsplus_cmp_catkey, &node, &ptr) + || !node) return 0; /* Iterate over all entries in this directory. */ grub_hfsplus_btree_iterate_node (&dir->data->catalog_tree, node, ptr, - list_nodes); + list_nodes, &ctx); grub_free (node); - return ret; + return ctx.ret; } /* Open a file named NAME and initialize FILE. */ @@ -937,6 +897,14 @@ grub_hfsplus_open (struct grub_file *file, const char *name) if (grub_errno) goto fail; + if (grub_hfsplus_open_compressed) + { + grub_err_t err; + err = grub_hfsplus_open_compressed (fdiro); + if (err) + goto fail; + } + file->size = fdiro->size; data->opened_file = *fdiro; grub_free (fdiro); @@ -960,7 +928,13 @@ grub_hfsplus_open (struct grub_file *file, const char *name) static grub_err_t grub_hfsplus_close (grub_file_t file) { - grub_free (file->data); + struct grub_hfsplus_data *data = + (struct grub_hfsplus_data *) file->data; + + grub_free (data->opened_file.cbuf); + grub_free (data->opened_file.compress_index); + + grub_free (data); grub_dl_unref (my_mod); @@ -974,36 +948,52 @@ grub_hfsplus_read (grub_file_t file, char *buf, grub_size_t len) struct grub_hfsplus_data *data = (struct grub_hfsplus_data *) file->data; - return grub_hfsplus_read_file (&data->opened_file, file->read_hook, - file->offset, len, buf); + data->opened_file.file = file; + + if (grub_hfsplus_read_compressed && data->opened_file.compressed) + return grub_hfsplus_read_compressed (&data->opened_file, + file->offset, len, buf); + + return grub_hfsplus_read_file (&data->opened_file, + file->read_hook, file->read_hook_data, + file->offset, len, buf); +} + +/* Context for grub_hfsplus_dir. */ +struct grub_hfsplus_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_hfsplus_dir. */ +static int +grub_hfsplus_dir_iter (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_hfsplus_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = node->mtime; + info.inodeset = 1; + info.inode = node->fileid; + info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); } static grub_err_t grub_hfsplus_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_hfsplus_dir_ctx ctx = { hook, hook_data }; struct grub_hfsplus_data *data = 0; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = 1; - info.mtime = node->mtime; - info.case_insensitive = !! (filetype & GRUB_FSHELP_CASE_INSENSITIVE); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_hfsplus_mount (device->disk); @@ -1018,7 +1008,7 @@ grub_hfsplus_dir (grub_device_t device, const char *path, goto fail; /* Iterate over all entries in this directory. */ - grub_hfsplus_iterate_dir (fdiro, iterate); + grub_hfsplus_iterate_dir (fdiro, grub_hfsplus_dir_iter, &ctx); fail: if (data && fdiro != &data->dirroot) @@ -1038,9 +1028,10 @@ grub_hfsplus_label (grub_device_t device, char **label) grub_disk_t disk = device->disk; struct grub_hfsplus_catkey *catkey; int i, label_len; + grub_uint16_t *label_name; struct grub_hfsplus_key_internal intern; - struct grub_hfsplus_btnode *node; - grub_disk_addr_t ptr; + struct grub_hfsplus_btnode *node = NULL; + grub_disk_addr_t ptr = 0; *label = 0; @@ -1055,7 +1046,8 @@ grub_hfsplus_label (grub_device_t device, char **label) /* First lookup the first entry. */ if (grub_hfsplus_btree_search (&data->catalog_tree, &intern, - grub_hfsplus_cmp_catkey_id, &node, &ptr)) + grub_hfsplus_cmp_catkey_id, &node, &ptr) + || !node) { grub_free (data); return 0; @@ -1065,22 +1057,50 @@ grub_hfsplus_label (grub_device_t device, char **label) grub_hfsplus_btree_recptr (&data->catalog_tree, node, ptr); label_len = grub_be_to_cpu16 (catkey->namelen); - for (i = 0; i < label_len; i++) - { - catkey->name[i] = grub_be_to_cpu16 (catkey->name[i]); - /* If the name is obviously invalid, skip this node. */ - if (catkey->name[i] == 0) - return 0; + /* Ensure that the length is >= 0. */ + if (label_len < 0) + label_len = 0; + + /* Ensure label length is at most 255 Unicode characters. */ + if (label_len > 255) + label_len = 255; + + label_name = grub_calloc (label_len, sizeof (*label_name)); + if (!label_name) + { + grub_free (node); + grub_free (data); + return grub_errno; } - *label = grub_malloc (label_len * GRUB_MAX_UTF8_PER_UTF16 + 1); - if (! *label) - return grub_errno; + for (i = 0; i < label_len; i++) + { + label_name[i] = grub_be_to_cpu16 (catkey->name[i]); - *grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name, + /* If the name is obviously invalid, skip this node. */ + if (label_name[i] == 0) + { + grub_free (label_name); + grub_free (node); + grub_free (data); + return 0; + } + } + + *label = grub_calloc (label_len, GRUB_MAX_UTF8_PER_UTF16 + 1); + if (! *label) + { + grub_free (label_name); + grub_free (node); + grub_free (data); + return grub_errno; + } + + *grub_utf16_to_utf8 ((grub_uint8_t *) (*label), label_name, label_len) = '\0'; + grub_free (label_name); grub_free (node); grub_free (data); @@ -1089,7 +1109,7 @@ grub_hfsplus_label (grub_device_t device, char **label) /* Get mtime. */ static grub_err_t -grub_hfsplus_mtime (grub_device_t device, grub_int32_t *tm) +grub_hfsplus_mtime (grub_device_t device, grub_int64_t *tm) { struct grub_hfsplus_data *data; grub_disk_t disk = device->disk; @@ -1140,13 +1160,13 @@ grub_hfsplus_uuid (grub_device_t device, char **uuid) static struct grub_fs grub_hfsplus_fs = { .name = "hfsplus", - .dir = grub_hfsplus_dir, - .open = grub_hfsplus_open, - .read = grub_hfsplus_read, - .close = grub_hfsplus_close, - .label = grub_hfsplus_label, - .mtime = grub_hfsplus_mtime, - .uuid = grub_hfsplus_uuid, + .fs_dir = grub_hfsplus_dir, + .fs_open = grub_hfsplus_open, + .fs_read = grub_hfsplus_read, + .fs_close = grub_hfsplus_close, + .fs_label = grub_hfsplus_label, + .fs_mtime = grub_hfsplus_mtime, + .fs_uuid = grub_hfsplus_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, @@ -1156,6 +1176,7 @@ static struct grub_fs grub_hfsplus_fs = GRUB_MOD_INIT(hfsplus) { + grub_hfsplus_fs.mod = mod; grub_fs_register (&grub_hfsplus_fs); my_mod = mod; } diff --git a/grub-core/fs/hfspluscomp.c b/grub-core/fs/hfspluscomp.c new file mode 100644 index 000000000..a80954ee6 --- /dev/null +++ b/grub-core/fs/hfspluscomp.c @@ -0,0 +1,322 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +/* HFS+ is documented at http://developer.apple.com/technotes/tn/tn1150.html */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* big-endian. */ +struct grub_hfsplus_compress_header1 +{ + grub_uint32_t header_size; + grub_uint32_t end_descriptor_offset; + grub_uint32_t total_compressed_size_including_seek_blocks_and_header2; + grub_uint32_t value_0x32; + grub_uint8_t unused[0xf0]; +} GRUB_PACKED; + +/* big-endian. */ +struct grub_hfsplus_compress_header2 +{ + grub_uint32_t total_compressed_size_including_seek_blocks; +} GRUB_PACKED; + +/* little-endian. */ +struct grub_hfsplus_compress_header3 +{ + grub_uint32_t num_chunks; +} GRUB_PACKED; + +/* little-endian. */ +struct grub_hfsplus_compress_block_descriptor +{ + grub_uint32_t offset; + grub_uint32_t size; +}; + +struct grub_hfsplus_compress_end_descriptor +{ + grub_uint8_t always_the_same[50]; +} GRUB_PACKED; + +struct grub_hfsplus_attr_header +{ + grub_uint8_t unused[3]; + grub_uint8_t type; + grub_uint32_t unknown[1]; + grub_uint64_t size; +} GRUB_PACKED; + +struct grub_hfsplus_compress_attr +{ + grub_uint32_t magic; + grub_uint32_t type; + grub_uint32_t uncompressed_inline_size; + grub_uint32_t always_0; +} GRUB_PACKED; + +enum + { + HFSPLUS_COMPRESSION_INLINE = 3, + HFSPLUS_COMPRESSION_RESOURCE = 4 + }; + +static int +grub_hfsplus_cmp_attrkey (struct grub_hfsplus_key *keya, + struct grub_hfsplus_key_internal *keyb) +{ + struct grub_hfsplus_attrkey *attrkey_a = &keya->attrkey; + struct grub_hfsplus_attrkey_internal *attrkey_b = &keyb->attrkey; + grub_uint32_t aparent = grub_be_to_cpu32 (attrkey_a->cnid); + grub_size_t len; + int diff; + + if (aparent > attrkey_b->cnid) + return 1; + if (aparent < attrkey_b->cnid) + return -1; + + len = grub_be_to_cpu16 (attrkey_a->namelen); + if (len > attrkey_b->namelen) + len = attrkey_b->namelen; + /* Since it's big-endian memcmp gives the same result as manually comparing + uint16_t but may be faster. */ + diff = grub_memcmp (attrkey_a->name, attrkey_b->name, + len * sizeof (attrkey_a->name[0])); + if (diff == 0) + diff = grub_be_to_cpu16 (attrkey_a->namelen) - attrkey_b->namelen; + return diff; +} + +#define HFSPLUS_COMPRESS_BLOCK_SIZE 65536 + +static grub_ssize_t +hfsplus_read_compressed_real (struct grub_hfsplus_file *node, + grub_off_t pos, grub_size_t len, char *buf) +{ + char *tmp_buf = 0; + grub_size_t len0 = len; + + if (node->compressed == 1) + { + grub_memcpy (buf, node->cbuf + pos, len); + if (grub_file_progress_hook && node->file) + grub_file_progress_hook (0, 0, len, NULL, node->file); + return len; + } + + while (len) + { + grub_uint32_t block = pos / HFSPLUS_COMPRESS_BLOCK_SIZE; + grub_size_t curlen = HFSPLUS_COMPRESS_BLOCK_SIZE + - (pos % HFSPLUS_COMPRESS_BLOCK_SIZE); + + if (curlen > len) + curlen = len; + + if (node->cbuf_block != block) + { + grub_uint32_t sz = grub_le_to_cpu32 (node->compress_index[block].size); + grub_size_t ts; + if (!tmp_buf) + tmp_buf = grub_malloc (HFSPLUS_COMPRESS_BLOCK_SIZE); + if (!tmp_buf) + return -1; + if (grub_hfsplus_read_file (node, 0, 0, + grub_le_to_cpu32 (node->compress_index[block].start) + 0x104, + sz, tmp_buf) + != (grub_ssize_t) sz) + { + grub_free (tmp_buf); + return -1; + } + ts = HFSPLUS_COMPRESS_BLOCK_SIZE; + if (ts > node->size - (pos & ~(HFSPLUS_COMPRESS_BLOCK_SIZE))) + ts = node->size - (pos & ~(HFSPLUS_COMPRESS_BLOCK_SIZE)); + if (grub_zlib_decompress (tmp_buf, sz, 0, + node->cbuf, ts) != (grub_ssize_t) ts) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "premature end of compressed"); + + grub_free (tmp_buf); + return -1; + } + node->cbuf_block = block; + } + grub_memcpy (buf, node->cbuf + (pos % HFSPLUS_COMPRESS_BLOCK_SIZE), + curlen); + if (grub_file_progress_hook && node->file) + grub_file_progress_hook (0, 0, curlen, NULL, node->file); + buf += curlen; + pos += curlen; + len -= curlen; + } + grub_free (tmp_buf); + return len0; +} + +static grub_err_t +hfsplus_open_compressed_real (struct grub_hfsplus_file *node) +{ + grub_err_t err; + struct grub_hfsplus_btnode *attr_node; + grub_off_t attr_off; + struct grub_hfsplus_key_internal key; + struct grub_hfsplus_attr_header *attr_head; + struct grub_hfsplus_compress_attr *cmp_head; +#define c grub_cpu_to_be16_compile_time + const grub_uint16_t compress_attr_name[] = + { + c('c'), c('o'), c('m'), c('.'), c('a'), c('p'), c('p'), c('l'), c('e'), + c('.'), c('d'), c('e'), c('c'), c('m'), c('p'), c('f'), c('s') }; +#undef c + if (node->size) + return 0; + + key.attrkey.cnid = node->fileid; + key.attrkey.namelen = sizeof (compress_attr_name) / sizeof (compress_attr_name[0]); + key.attrkey.name = compress_attr_name; + + err = grub_hfsplus_btree_search (&node->data->attr_tree, &key, + grub_hfsplus_cmp_attrkey, + &attr_node, &attr_off); + if (err || !attr_node) + { + grub_errno = 0; + return 0; + } + + attr_head = (struct grub_hfsplus_attr_header *) + ((char *) grub_hfsplus_btree_recptr (&node->data->attr_tree, + attr_node, attr_off) + + sizeof (struct grub_hfsplus_attrkey) + sizeof (compress_attr_name)); + if (attr_head->type != 0x10 + || !(attr_head->size & grub_cpu_to_be64_compile_time(~0xfULL))) + { + grub_free (attr_node); + return 0; + } + cmp_head = (struct grub_hfsplus_compress_attr *) (attr_head + 1); + if (cmp_head->magic != grub_cpu_to_be32_compile_time (0x66706d63)) + { + grub_free (attr_node); + return 0; + } + node->size = grub_le_to_cpu32 (cmp_head->uncompressed_inline_size); + + if (cmp_head->type == grub_cpu_to_le32_compile_time (HFSPLUS_COMPRESSION_RESOURCE)) + { + grub_uint32_t index_size; + node->compressed = 2; + + if (grub_hfsplus_read_file (node, 0, 0, + 0x104, sizeof (index_size), + (char *) &index_size) + != 4) + { + node->compressed = 0; + grub_free (attr_node); + grub_errno = 0; + return 0; + } + node->compress_index_size = grub_le_to_cpu32 (index_size); + node->compress_index = grub_calloc (node->compress_index_size, + sizeof (node->compress_index[0])); + if (!node->compress_index) + { + node->compressed = 0; + grub_free (attr_node); + return grub_errno; + } + + /* + * The node->compress_index_size * sizeof (node->compress_index[0]) is safe here + * due to relevant checks done in grub_calloc() above. + */ + if (grub_hfsplus_read_file (node, 0, 0, + 0x104 + sizeof (index_size), + node->compress_index_size + * sizeof (node->compress_index[0]), + (char *) node->compress_index) + != (grub_ssize_t) (node->compress_index_size + * sizeof (node->compress_index[0]))) + { + node->compressed = 0; + grub_free (attr_node); + grub_free (node->compress_index); + grub_errno = 0; + return 0; + } + + node->cbuf_block = -1; + + node->cbuf = grub_malloc (HFSPLUS_COMPRESS_BLOCK_SIZE); + grub_free (attr_node); + if (!node->cbuf) + { + node->compressed = 0; + grub_free (node->compress_index); + return grub_errno; + } + return 0; + } + if (cmp_head->type != HFSPLUS_COMPRESSION_INLINE) + { + grub_free (attr_node); + return 0; + } + + node->cbuf = grub_malloc (node->size); + if (!node->cbuf) + return grub_errno; + + if (grub_zlib_decompress ((char *) (cmp_head + 1), + grub_cpu_to_be64 (attr_head->size) + - sizeof (*cmp_head), 0, + node->cbuf, node->size) + != (grub_ssize_t) node->size) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "premature end of compressed"); + return grub_errno; + } + node->compressed = 1; + return 0; +} + +GRUB_MOD_INIT(hfspluscomp) +{ + grub_hfsplus_open_compressed = hfsplus_open_compressed_real; + grub_hfsplus_read_compressed = hfsplus_read_compressed_real; +} + +GRUB_MOD_FINI(hfspluscomp) +{ + grub_hfsplus_open_compressed = 0; + grub_hfsplus_read_compressed = 0; +} diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index cd4acc8ec..c73cb9ce0 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -48,13 +49,16 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_ISO9660_VOLDESC_PART 3 #define GRUB_ISO9660_VOLDESC_END 255 +#define GRUB_ISO9660_SUSP_HEADER_SZ 4 +#define GRUB_ISO9660_MAX_CE_HOPS 100000 + /* The head of a volume descriptor. */ struct grub_iso9660_voldesc { grub_uint8_t type; grub_uint8_t magic[5]; grub_uint8_t version; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_iso9660_date2 { @@ -65,7 +69,7 @@ struct grub_iso9660_date2 grub_uint8_t minute; grub_uint8_t second; grub_uint8_t offset; -} __attribute__ ((packed)); +} GRUB_PACKED; /* A directory entry. */ struct grub_iso9660_dir @@ -79,8 +83,9 @@ struct grub_iso9660_dir struct grub_iso9660_date2 mtime; grub_uint8_t flags; grub_uint8_t unused2[6]; +#define MAX_NAMELEN 255 grub_uint8_t namelen; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_iso9660_date { @@ -92,7 +97,7 @@ struct grub_iso9660_date grub_uint8_t second[2]; grub_uint8_t hundredth[2]; grub_uint8_t offset; -} __attribute__ ((packed)); +} GRUB_PACKED; /* The primary volume descriptor. Only little endian is used. */ struct grub_iso9660_primary_voldesc @@ -111,7 +116,7 @@ struct grub_iso9660_primary_voldesc grub_uint8_t unused6[624]; struct grub_iso9660_date created; struct grub_iso9660_date modified; -} __attribute__ ((packed)); +} GRUB_PACKED; /* A single entry in the path table. */ struct grub_iso9660_path @@ -121,7 +126,7 @@ struct grub_iso9660_path grub_uint32_t first_sector; grub_uint16_t parentdir; grub_uint8_t name[0]; -} __attribute__ ((packed)); +} GRUB_PACKED; /* An entry in the System Usage area of the directory entry. */ struct grub_iso9660_susp_entry @@ -130,7 +135,7 @@ struct grub_iso9660_susp_entry grub_uint8_t len; grub_uint8_t version; grub_uint8_t data[0]; -} __attribute__ ((packed)); +} GRUB_PACKED; /* The CE entry. This is used to describe the next block where data can be found. */ @@ -143,7 +148,7 @@ struct grub_iso9660_susp_ce grub_uint32_t off_be; grub_uint32_t len; grub_uint32_t len_be; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_iso9660_data { @@ -176,10 +181,10 @@ static grub_dl_t my_mod; static grub_err_t -iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) +iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int64_t *nix) { struct grub_datetime datetime; - + if (! i->year[0] && ! i->year[1] && ! i->year[2] && ! i->year[3] && ! i->month[0] && ! i->month[1] @@ -196,7 +201,7 @@ iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) datetime.hour = (i->hour[0] - '0') * 10 + (i->hour[1] - '0'); datetime.minute = (i->minute[0] - '0') * 10 + (i->minute[1] - '0'); datetime.second = (i->second[0] - '0') * 10 + (i->second[1] - '0'); - + if (!grub_datetime2unixtime (&datetime, nix)) return grub_error (GRUB_ERR_BAD_NUMBER, "incorrect date"); *nix -= i->offset * 60 * 15; @@ -204,7 +209,7 @@ iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) } static int -iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix) +iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int64_t *nix) { struct grub_datetime datetime; @@ -214,7 +219,7 @@ iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix) datetime.hour = i->hour; datetime.minute = i->minute; datetime.second = i->second; - + if (!grub_datetime2unixtime (&datetime, nix)) return 0; *nix -= i->offset * 60 * 15; @@ -260,45 +265,44 @@ static grub_err_t grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off, grub_ssize_t sua_size, grub_err_t (*hook) - (struct grub_iso9660_susp_entry *entry)) + (struct grub_iso9660_susp_entry *entry, void *hook_arg), + void *hook_arg) { char *sua; struct grub_iso9660_susp_entry *entry; + grub_err_t err; + int ce_counter = 0; + grub_ssize_t ce_sua_size = 0; + grub_off_t ce_off; grub_disk_addr_t ce_block; - int is_ce = 0; - - auto grub_err_t load_sua (void); - - /* Load a part of the System Usage Area. */ - grub_err_t load_sua (void) - { - grub_err_t err; - sua = grub_malloc (sua_size); - if (!sua) - return grub_errno; - - if (is_ce) - err = grub_disk_read (node->data->disk, ce_block, off, - sua_size, sua); - else - err = read_node (node, off, sua_size, sua); - if (err) - return err; - - entry = (struct grub_iso9660_susp_entry *) sua; - return 0; - } if (sua_size <= 0) return GRUB_ERR_NONE; - if (load_sua ()) + if (sua_size < GRUB_ISO9660_SUSP_HEADER_SZ) + return grub_error (GRUB_ERR_BAD_FS, "invalid susp entry size"); + + sua = grub_malloc (sua_size); + if (!sua) return grub_errno; - for (; (char *) entry < (char *) sua + sua_size - 1; - entry = (struct grub_iso9660_susp_entry *) - ((char *) entry + entry->len)) + /* Load a part of the System Usage Area. */ + err = read_node (node, off, sua_size, sua); + if (err) { + grub_free (sua); + return err; + } + + entry = (struct grub_iso9660_susp_entry *) sua; + + next_susp_area: + while (entry->len > 0) + { + /* Ensure the entry is within System Use Area. */ + if ((char *) entry + entry->len > (sua + sua_size)) + break; + /* The last entry. */ if (grub_strncmp ((char *) entry->sig, "ST", 2) == 0) break; @@ -308,22 +312,61 @@ grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off, { struct grub_iso9660_susp_ce *ce; - is_ce = 1; + if (ce_sua_size > 0) + { + grub_free (sua); + return grub_error (GRUB_ERR_BAD_FS, + "more than one CE entry in SUSP area"); + } + + /* Buffer CE parameters for use after the end of this loop. */ ce = (struct grub_iso9660_susp_ce *) entry; - sua_size = grub_le_to_cpu32 (ce->len); - off = grub_le_to_cpu32 (ce->off); + ce_sua_size = grub_le_to_cpu32 (ce->len); + ce_off = grub_le_to_cpu32 (ce->off); ce_block = grub_le_to_cpu32 (ce->blk) << GRUB_ISO9660_LOG2_BLKSZ; - - grub_free (sua); - if (load_sua ()) - return grub_errno; } - - if (hook (entry)) + else if (hook (entry, hook_arg)) { grub_free (sua); return 0; } + + entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len); + + if (((sua + sua_size) - (char *) entry) < GRUB_ISO9660_SUSP_HEADER_SZ) + break; + } + + if (ce_sua_size > 0) + { + /* Load the next System Use Area by buffered CE entry parameters. */ + if (++ce_counter > GRUB_ISO9660_MAX_CE_HOPS) + { + grub_free (sua); + return grub_error (GRUB_ERR_BAD_FS, "suspecting endless CE loop"); + } + if (ce_sua_size < GRUB_ISO9660_SUSP_HEADER_SZ) + { + grub_free (sua); + return grub_error (GRUB_ERR_BAD_FS, "invalid continuation area in CE entry"); + } + + grub_free (sua); + sua = grub_malloc (ce_sua_size); + if (!sua) + return grub_errno; + + err = grub_disk_read (node->data->disk, ce_block, ce_off, ce_sua_size, sua); + if (err) + { + grub_free (sua); + return err; + } + entry = (struct grub_iso9660_susp_entry *) sua; + sua_size = ce_sua_size; + ce_sua_size = 0; + + goto next_susp_area; } grub_free (sua); @@ -335,11 +378,11 @@ grub_iso9660_convert_string (grub_uint8_t *us, int len) { char *p; int i; - grub_uint16_t t[len]; + grub_uint16_t t[MAX_NAMELEN / 2 + 1]; - p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1); + p = grub_calloc (len, GRUB_MAX_UTF8_PER_UTF16 + 1); if (! p) - return p; + return NULL; for (i=0; isig, "ER", 2) == 0) + { + data->rockridge = 1; + return 1; + } + return 0; +} + static grub_err_t set_rockridge (struct grub_iso9660_data *data) { @@ -358,20 +416,6 @@ set_rockridge (struct grub_iso9660_data *data) struct grub_iso9660_dir rootdir; struct grub_iso9660_susp_entry *entry; - auto grub_err_t susp_iterate (struct grub_iso9660_susp_entry *); - - grub_err_t susp_iterate (struct grub_iso9660_susp_entry *susp_entry) - { - /* The "ER" entry is used to detect extensions. The - `IEEE_P1285' extension means Rock ridge. */ - if (grub_strncmp ((char *) susp_entry->sig, "ER", 2) == 0) - { - data->rockridge = 1; - return 1; - } - return 0; - } - data->rockridge = 0; /* Read the system use area and test it to see if SUSP is @@ -389,6 +433,9 @@ set_rockridge (struct grub_iso9660_data *data) if (!sua_size) return GRUB_ERR_NONE; + if (sua_size < GRUB_ISO9660_SUSP_HEADER_SZ) + return grub_error (GRUB_ERR_BAD_FS, "invalid rock ridge entry size"); + sua = grub_malloc (sua_size); if (! sua) return grub_errno; @@ -415,15 +462,25 @@ set_rockridge (struct grub_iso9660_data *data) rootnode.have_symlink = 0; rootnode.dirents[0] = data->voldesc.rootdir; - /* The 2nd data byte stored how many bytes are skipped every time - to get to the SUA (System Usage Area). */ + /* The size of SP (version 1) is fixed to 7. */ + if (sua_size < 7 || entry->len < 7) + { + grub_free (sua); + return grub_error (GRUB_ERR_BAD_FS, "corrupted rock ridge entry"); + } + + /* + * The 2nd data byte stored how many bytes are skipped every time + * to get to the SUA (System Usage Area). + */ data->susp_skip = entry->data[2]; entry = (struct grub_iso9660_susp_entry *) ((char *) entry + entry->len); /* Iterate over the entries in the SUA area to detect extensions. */ if (grub_iso9660_susp_iterate (&rootnode, - sua_pos, sua_size, susp_iterate)) + sua_pos, sua_size, susp_iterate_set_rockridge, + data)) { grub_free (sua); return grub_errno; @@ -494,6 +551,9 @@ grub_iso9660_mount (grub_disk_t disk) return data; fail: + if (grub_errno == GRUB_ERR_NONE) + grub_error (GRUB_ERR_BAD_FS, "not a ISO9660 filesystem"); + grub_free (data); return 0; } @@ -502,7 +562,7 @@ grub_iso9660_mount (grub_disk_t disk) static char * grub_iso9660_read_symlink (grub_fshelp_node_t node) { - return node->have_symlink + return node->have_symlink ? grub_strdup (node->symlink + (node->have_dirents) * sizeof (node->dirents[0]) - sizeof (node->dirents)) : grub_strdup (""); @@ -519,157 +579,210 @@ get_node_size (grub_fshelp_node_t node) return ret; } +struct iterate_dir_ctx +{ + char *filename; + int filename_alloc; + enum grub_fshelp_filetype type; + char *symlink; + int was_continue; +}; + + /* Extend the symlink. */ +static void +add_part (struct iterate_dir_ctx *ctx, + const char *part, + int len2) +{ + int size = ctx->symlink ? grub_strlen (ctx->symlink) : 0; + grub_size_t sz; + char *new; + + if (grub_add (size, len2, &sz) || + grub_add (sz, 1, &sz)) + return; + + new = grub_realloc (ctx->symlink, sz); + if (!new) + { + grub_free (ctx->symlink); + ctx->symlink = NULL; + return; + } + ctx->symlink = new; + + grub_memcpy (ctx->symlink + size, part, len2); + ctx->symlink[size + len2] = 0; +} + +static grub_err_t +susp_iterate_dir (struct grub_iso9660_susp_entry *entry, + void *_ctx) +{ + struct iterate_dir_ctx *ctx = _ctx; + + /* The filename in the rock ridge entry. */ + if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0) + { + /* The flags are stored at the data position 0, here the + filename type is stored. */ + /* FIXME: Fix this slightly improper cast. */ + if (entry->data[0] & GRUB_ISO9660_RR_DOT) + { + if (ctx->filename_alloc) + grub_free (ctx->filename); + ctx->filename_alloc = 0; + ctx->filename = (char *) "."; + } + else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT) + { + if (ctx->filename_alloc) + grub_free (ctx->filename); + ctx->filename_alloc = 0; + ctx->filename = (char *) ".."; + } + else if (entry->len >= 5) + { + grub_size_t off = 0, csize = 1; + char *old; + grub_size_t sz; + + csize = entry->len - 5; + old = ctx->filename; + if (ctx->filename_alloc) + { + off = grub_strlen (ctx->filename); + if (grub_add (csize, off, &sz) || + grub_add (sz, 1, &sz)) + return GRUB_ERR_OUT_OF_RANGE; + ctx->filename = grub_realloc (ctx->filename, sz); + } + else + { + off = 0; + if (grub_add (csize, 1, &sz)) + return GRUB_ERR_OUT_OF_RANGE; + ctx->filename = grub_zalloc (sz); + } + if (!ctx->filename) + { + ctx->filename = old; + return grub_errno; + } + ctx->filename_alloc = 1; + grub_memcpy (ctx->filename + off, (char *) &entry->data[1], csize); + ctx->filename[off + csize] = '\0'; + } + } + /* The mode information (st_mode). */ + else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0) + { + /* At position 0 of the PX record the st_mode information is + stored (little-endian). */ + grub_uint32_t mode = ((entry->data[0] + (entry->data[1] << 8)) + & GRUB_ISO9660_FSTYPE_MASK); + + switch (mode) + { + case GRUB_ISO9660_FSTYPE_DIR: + ctx->type = GRUB_FSHELP_DIR; + break; + case GRUB_ISO9660_FSTYPE_REG: + ctx->type = GRUB_FSHELP_REG; + break; + case GRUB_ISO9660_FSTYPE_SYMLINK: + ctx->type = GRUB_FSHELP_SYMLINK; + break; + default: + ctx->type = GRUB_FSHELP_UNKNOWN; + } + } + else if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0) + { + unsigned int pos = 1; + unsigned int csize; + + /* The symlink is not stored as a POSIX symlink, translate it. */ + while ((pos + GRUB_ISO9660_SUSP_HEADER_SZ + 1) < entry->len) + { + /* + * entry->len is GRUB_ISO9660_SUSP_HEADER_SZ + 1 (the FLAGS) + + * length of the "Component Area". The length of a component + * record is 2 (pos and pos + 1) plus the "Component Content", + * of which starts at pos + 2. entry->data[pos] is the + * "Component Flags"; entry->data[pos + 1] is the length + * of the component. + */ + csize = entry->data[pos + 1] + 2; + if (GRUB_ISO9660_SUSP_HEADER_SZ + 1 + csize > entry->len) + break; + + /* The current position is the `Component Flag'. */ + switch (entry->data[pos] & 30) + { + case 0: + { + /* The data on pos + 2 is the actual data, pos + 1 + is the length. Both are part of the `Component + Record'. */ + if (ctx->symlink && !ctx->was_continue) + { + add_part (ctx, "/", 1); + if (grub_errno) + return grub_errno; + } + + add_part (ctx, (char *) &entry->data[pos + 2], + entry->data[pos + 1]); + ctx->was_continue = (entry->data[pos] & 1); + break; + } + + case 2: + add_part (ctx, "./", 2); + break; + + case 4: + add_part (ctx, "../", 3); + break; + + case 8: + add_part (ctx, "/", 1); + break; + } + + /* Check if grub_realloc() failed in add_part(). */ + if (grub_errno) + return grub_errno; + + /* In pos + 1 the length of the `Component Record' is + stored. */ + pos += entry->data[pos + 1] + 2; + } + + /* Check if `grub_realloc' failed. */ + if (grub_errno) + return grub_errno; + } + + return 0; +} + static int grub_iso9660_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { struct grub_iso9660_dir dirent; grub_off_t offset = 0; - char *filename = 0; - int filename_alloc = 0; - enum grub_fshelp_filetype type; grub_off_t len; - char *symlink = 0; - int was_continue = 0; - - /* Extend the symlink. */ - auto inline void __attribute__ ((always_inline)) add_part (const char *part, - int len2); - - auto inline void __attribute__ ((always_inline)) add_part (const char *part, - int len2) - { - int size = symlink ? grub_strlen (symlink) : 0; - - symlink = grub_realloc (symlink, size + len2 + 1); - if (! symlink) - return; - - symlink[size] = 0; - grub_strncat (symlink, part, len2); - } - - auto grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *); - - grub_err_t susp_iterate_dir (struct grub_iso9660_susp_entry *entry) - { - /* The filename in the rock ridge entry. */ - if (grub_strncmp ("NM", (char *) entry->sig, 2) == 0) - { - /* The flags are stored at the data position 0, here the - filename type is stored. */ - /* FIXME: Fix this slightly improper cast. */ - if (entry->data[0] & GRUB_ISO9660_RR_DOT) - filename = (char *) "."; - else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT) - filename = (char *) ".."; - else if (entry->len >= 5) - { - grub_size_t size = 1, csize = 1; - char *old; - csize = size = entry->len - 5; - old = filename; - if (filename_alloc) - { - size += grub_strlen (filename); - filename = grub_realloc (filename, size + 1); - } - else - { - filename_alloc = 1; - filename = grub_zalloc (size + 1); - filename[0] = 0; - } - if (!filename) - { - filename = old; - return grub_errno; - } - filename_alloc = 1; - grub_strncat (filename, (char *) &entry->data[1], csize); - filename[size] = '\0'; - } - } - /* The mode information (st_mode). */ - else if (grub_strncmp ((char *) entry->sig, "PX", 2) == 0) - { - /* At position 0 of the PX record the st_mode information is - stored (little-endian). */ - grub_uint32_t mode = ((entry->data[0] + (entry->data[1] << 8)) - & GRUB_ISO9660_FSTYPE_MASK); - - switch (mode) - { - case GRUB_ISO9660_FSTYPE_DIR: - type = GRUB_FSHELP_DIR; - break; - case GRUB_ISO9660_FSTYPE_REG: - type = GRUB_FSHELP_REG; - break; - case GRUB_ISO9660_FSTYPE_SYMLINK: - type = GRUB_FSHELP_SYMLINK; - break; - default: - type = GRUB_FSHELP_UNKNOWN; - } - } - else if (grub_strncmp ("SL", (char *) entry->sig, 2) == 0) - { - unsigned int pos = 1; - - /* The symlink is not stored as a POSIX symlink, translate it. */ - while (pos + sizeof (*entry) < entry->len) - { - /* The current position is the `Component Flag'. */ - switch (entry->data[pos] & 30) - { - case 0: - { - /* The data on pos + 2 is the actual data, pos + 1 - is the length. Both are part of the `Component - Record'. */ - if (symlink && !was_continue) - add_part ("/", 1); - add_part ((char *) &entry->data[pos + 2], - entry->data[pos + 1]); - was_continue = (entry->data[pos] & 1); - break; - } - - case 2: - add_part ("./", 2); - break; - - case 4: - add_part ("../", 3); - break; - - case 8: - add_part ("/", 1); - break; - } - /* In pos + 1 the length of the `Component Record' is - stored. */ - pos += entry->data[pos + 1] + 2; - } - - /* Check if `grub_realloc' failed. */ - if (grub_errno) - return grub_errno; - } - - return 0; - } + struct iterate_dir_ctx ctx; len = get_node_size (dir); for (; offset < len; offset += dirent.len) { - symlink = 0; - was_continue = 0; + ctx.symlink = 0; + ctx.was_continue = 0; if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) return 0; @@ -682,7 +795,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, } { - char name[dirent.namelen + 1]; + char name[MAX_NAMELEN + 1]; int nameoffset = offset + sizeof (dirent); struct grub_fshelp_node *node; int sua_off = (sizeof (dirent) + dirent.namelen + 1 @@ -691,13 +804,13 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, sua_off += offset + dir->data->susp_skip; - filename = 0; - filename_alloc = 0; - type = GRUB_FSHELP_UNKNOWN; + ctx.filename = 0; + ctx.filename_alloc = 0; + ctx.type = GRUB_FSHELP_UNKNOWN; if (dir->data->rockridge && grub_iso9660_susp_iterate (dir, sua_off, sua_size, - susp_iterate_dir)) + susp_iterate_dir, &ctx)) return 0; /* Read the name. */ @@ -717,81 +830,103 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, /* If the filetype was not stored using rockridge, use whatever is stored in the iso9660 filesystem. */ - if (type == GRUB_FSHELP_UNKNOWN) + if (ctx.type == GRUB_FSHELP_UNKNOWN) { if ((dirent.flags & FLAG_TYPE) == FLAG_TYPE_DIR) - type = GRUB_FSHELP_DIR; + ctx.type = GRUB_FSHELP_DIR; else - type = GRUB_FSHELP_REG; + ctx.type = GRUB_FSHELP_REG; } /* . and .. */ - if (!filename && dirent.namelen == 1 && name[0] == 0) - filename = (char *) "."; + if (!ctx.filename && dirent.namelen == 1 && name[0] == 0) + ctx.filename = (char *) "."; - if (!filename && dirent.namelen == 1 && name[0] == 1) - filename = (char *) ".."; + if (!ctx.filename && dirent.namelen == 1 && name[0] == 1) + ctx.filename = (char *) ".."; /* The filename was not stored in a rock ridge entry. Read it from the iso9660 filesystem. */ - if (!dir->data->joliet && !filename) + if (!dir->data->joliet && !ctx.filename) { char *ptr; name[dirent.namelen] = '\0'; - filename = grub_strrchr (name, ';'); - if (filename) - *filename = '\0'; + ctx.filename = grub_strrchr (name, ';'); + if (ctx.filename) + *ctx.filename = '\0'; /* ISO9660 names are not case-preserving. */ - type |= GRUB_FSHELP_CASE_INSENSITIVE; + ctx.type |= GRUB_FSHELP_CASE_INSENSITIVE; for (ptr = name; *ptr; ptr++) *ptr = grub_tolower (*ptr); if (ptr != name && *(ptr - 1) == '.') *(ptr - 1) = 0; - filename = name; + ctx.filename = name; } - if (dir->data->joliet && !filename) + if (dir->data->joliet && !ctx.filename) { - char *oldname, *semicolon; + char *semicolon; - oldname = name; - filename = grub_iso9660_convert_string - ((grub_uint8_t *) oldname, dirent.namelen >> 1); + ctx.filename = grub_iso9660_convert_string + ((grub_uint8_t *) name, dirent.namelen >> 1); - semicolon = grub_strrchr (filename, ';'); + semicolon = grub_strrchr (ctx.filename, ';'); if (semicolon) *semicolon = '\0'; - if (filename_alloc) - grub_free (oldname); - - filename_alloc = 1; + ctx.filename_alloc = 1; } node->dirents[0] = dirent; while (dirent.flags & FLAG_MORE_EXTENTS) { offset += dirent.len; - if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) + + /* offset should within the dir's len. */ + if (offset > len) { - if (filename_alloc) - grub_free (filename); + if (ctx.filename_alloc) + grub_free (ctx.filename); grub_free (node); return 0; } + + if (read_node (dir, offset, sizeof (dirent), (char *) &dirent)) + { + if (ctx.filename_alloc) + grub_free (ctx.filename); + grub_free (node); + return 0; + } + + /* + * It is either the end of block or zero-padded sector, + * skip to the next block. + */ + if (!dirent.len) + { + offset = (offset / GRUB_ISO9660_BLKSZ + 1) * GRUB_ISO9660_BLKSZ; + dirent.flags |= FLAG_MORE_EXTENTS; + continue; + } + if (node->have_dirents >= node->alloc_dirents) { struct grub_fshelp_node *new_node; - node->alloc_dirents *= 2; - new_node = grub_realloc (node, - sizeof (struct grub_fshelp_node) - + ((node->alloc_dirents - - ARRAY_SIZE (node->dirents)) - * sizeof (node->dirents[0]))); + grub_size_t sz; + + if (grub_mul (node->alloc_dirents, 2, &node->alloc_dirents) || + grub_sub (node->alloc_dirents, ARRAY_SIZE (node->dirents), &sz) || + grub_mul (sz, sizeof (node->dirents[0]), &sz) || + grub_add (sz, sizeof (struct grub_fshelp_node), &sz)) + goto fail_0; + + new_node = grub_realloc (node, sz); if (!new_node) { - if (filename_alloc) - grub_free (filename); + fail_0: + if (ctx.filename_alloc) + grub_free (ctx.filename); grub_free (node); return 0; } @@ -799,22 +934,26 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, } node->dirents[node->have_dirents++] = dirent; } - if (symlink) + if (ctx.symlink) { if ((node->alloc_dirents - node->have_dirents) - * sizeof (node->dirents[0]) < grub_strlen (symlink) + 1) + * sizeof (node->dirents[0]) < grub_strlen (ctx.symlink) + 1) { struct grub_fshelp_node *new_node; - new_node = grub_realloc (node, - sizeof (struct grub_fshelp_node) - + ((node->alloc_dirents - - ARRAY_SIZE (node->dirents)) - * sizeof (node->dirents[0])) - + grub_strlen (symlink) + 1); + grub_size_t sz; + + if (grub_sub (node->alloc_dirents, ARRAY_SIZE (node->dirents), &sz) || + grub_mul (sz, sizeof (node->dirents[0]), &sz) || + grub_add (sz, sizeof (struct grub_fshelp_node) + 1, &sz) || + grub_add (sz, grub_strlen (ctx.symlink), &sz)) + goto fail_1; + + new_node = grub_realloc (node, sz); if (!new_node) { - if (filename_alloc) - grub_free (filename); + fail_1: + if (ctx.filename_alloc) + grub_free (ctx.filename); grub_free (node); return 0; } @@ -823,19 +962,19 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, node->have_symlink = 1; grub_strcpy (node->symlink + node->have_dirents * sizeof (node->dirents[0]) - - sizeof (node->dirents), symlink); - grub_free (symlink); - symlink = 0; - was_continue = 0; + - sizeof (node->dirents), ctx.symlink); + grub_free (ctx.symlink); + ctx.symlink = 0; + ctx.was_continue = 0; } - if (hook (filename, type, node)) + if (hook (ctx.filename, ctx.type, node, hook_data)) { - if (filename_alloc) - grub_free (filename); + if (ctx.filename_alloc) + grub_free (ctx.filename); return 1; } - if (filename_alloc) - grub_free (filename); + if (ctx.filename_alloc) + grub_free (ctx.filename); } } @@ -844,32 +983,39 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, +/* Context for grub_iso9660_dir. */ +struct grub_iso9660_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_iso9660_dir. */ +static int +grub_iso9660_dir_iter (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_iso9660_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime); + + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_iso9660_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_iso9660_dir_ctx ctx = { hook, hook_data }; struct grub_iso9660_data *data = 0; struct grub_fshelp_node rootnode; struct grub_fshelp_node *foundnode; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = !!iso9660_to_unixtime2 (&node->dirents[0].mtime, &info.mtime); - - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_iso9660_mount (device->disk); @@ -891,7 +1037,7 @@ grub_iso9660_dir (grub_device_t device, const char *path, goto fail; /* List the files in the directory. */ - grub_iso9660_iterate_dir (foundnode, iterate); + grub_iso9660_iterate_dir (foundnode, grub_iso9660_dir_iter, &ctx); if (foundnode != &rootnode) grub_free (foundnode); @@ -954,13 +1100,15 @@ grub_iso9660_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_iso9660_data *data = (struct grub_iso9660_data *) file->data; + grub_err_t err; /* XXX: The file is stored in as a single extent. */ data->disk->read_hook = file->read_hook; - read_node (data->node, file->offset, len, buf); + data->disk->read_hook_data = file->read_hook_data; + err = read_node (data->node, file->offset, len, buf); data->disk->read_hook = NULL; - if (grub_errno) + if (err || grub_errno) return -1; return len; @@ -1066,8 +1214,8 @@ grub_iso9660_uuid (grub_device_t device, char **uuid) } /* Get writing time of filesystem. */ -static grub_err_t -grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf) +static grub_err_t +grub_iso9660_mtime (grub_device_t device, grub_int64_t *timebuf) { struct grub_iso9660_data *data; grub_disk_t disk = device->disk; @@ -1096,13 +1244,13 @@ grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf) static struct grub_fs grub_iso9660_fs = { .name = "iso9660", - .dir = grub_iso9660_dir, - .open = grub_iso9660_open, - .read = grub_iso9660_read, - .close = grub_iso9660_close, - .label = grub_iso9660_label, - .uuid = grub_iso9660_uuid, - .mtime = grub_iso9660_mtime, + .fs_dir = grub_iso9660_dir, + .fs_open = grub_iso9660_open, + .fs_read = grub_iso9660_read, + .fs_close = grub_iso9660_close, + .fs_label = grub_iso9660_label, + .fs_uuid = grub_iso9660_uuid, + .fs_mtime = grub_iso9660_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, @@ -1112,6 +1260,7 @@ static struct grub_fs grub_iso9660_fs = GRUB_MOD_INIT(iso9660) { + grub_iso9660_fs.mod = mod; grub_fs_register (&grub_iso9660_fs); my_mod = mod; } diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index b98a5a374..03be9ef4c 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -26,6 +26,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -41,6 +42,13 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_JFS_TREE_LEAF 2 +/* + * Define max entries stored in-line in an inode. + * https://jfs.sourceforge.net/project/pub/jfslayout.pdf + */ +#define GRUB_JFS_INODE_INLINE_ENTRIES 8 +#define GRUB_JFS_DIR_MAX_SLOTS 128 + struct grub_jfs_sblock { /* The magic for JFS. It should contain the string "JFS1". */ @@ -70,13 +78,16 @@ struct grub_jfs_extent /* The physical offset of the first block on the disk. */ grub_uint8_t blk1; grub_uint32_t blk2; -} __attribute__ ((packed)); +} GRUB_PACKED; + +#define GRUB_JFS_IAG_INODES_OFFSET 3072 +#define GRUB_JFS_IAG_INODES_COUNT 128 struct grub_jfs_iag { - grub_uint8_t unused[3072]; - struct grub_jfs_extent inodes[128]; -} __attribute__ ((packed)); + grub_uint8_t unused[GRUB_JFS_IAG_INODES_OFFSET]; + struct grub_jfs_extent inodes[GRUB_JFS_IAG_INODES_COUNT]; +} GRUB_PACKED; /* The head of the tree used to find extents. */ @@ -91,7 +102,7 @@ struct grub_jfs_treehead grub_uint16_t count; grub_uint16_t max; grub_uint8_t unused2[10]; -} __attribute__ ((packed)); +} GRUB_PACKED; /* A node in the extent tree. */ struct grub_jfs_tree_extent @@ -104,7 +115,7 @@ struct grub_jfs_tree_extent grub_uint32_t offset2; struct grub_jfs_extent extent; -} __attribute__ ((packed)); +} GRUB_PACKED; /* The tree of directory entries. */ struct grub_jfs_tree_dir @@ -125,7 +136,7 @@ struct grub_jfs_tree_dir /* The location of the sorted array of pointers to dirents. */ grub_uint8_t sindex; grub_uint8_t unused[10]; -} __attribute__ ((packed)); +} GRUB_PACKED; /* An internal node in the dirents tree. */ struct grub_jfs_internal_dirent @@ -134,7 +145,7 @@ struct grub_jfs_internal_dirent grub_uint8_t next; grub_uint8_t len; grub_uint16_t namepart[11]; -} __attribute__ ((packed)); +} GRUB_PACKED; /* A leaf node in the dirents tree. */ struct grub_jfs_leaf_dirent @@ -147,7 +158,7 @@ struct grub_jfs_leaf_dirent grub_uint8_t len; grub_uint16_t namepart[11]; grub_uint32_t index; -} __attribute__ ((packed)); +} GRUB_PACKED; /* A leaf in the dirents tree. This one is used if the previously dirent was not big enough to store the name. */ @@ -156,13 +167,13 @@ struct grub_jfs_leaf_next_dirent grub_uint8_t next; grub_uint8_t len; grub_uint16_t namepart[15]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_jfs_time { grub_int32_t sec; grub_int32_t nanosec; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_jfs_inode { @@ -182,7 +193,7 @@ struct grub_jfs_inode union { /* The tree describing the extents of the file. */ - struct __attribute__ ((packed)) + struct GRUB_PACKED { struct grub_jfs_treehead tree; struct grub_jfs_tree_extent extents[16]; @@ -200,18 +211,18 @@ struct grub_jfs_inode grub_uint8_t freecnt; grub_uint8_t freelist; grub_uint32_t idotdot; - grub_uint8_t sorted[8]; + grub_uint8_t sorted[GRUB_JFS_INODE_INLINE_ENTRIES]; } header; - struct grub_jfs_leaf_dirent dirents[8]; - } dir __attribute__ ((packed)); + struct grub_jfs_leaf_dirent dirents[GRUB_JFS_INODE_INLINE_ENTRIES]; + } GRUB_PACKED dir; /* Fast symlink. */ struct { grub_uint8_t unused[32]; grub_uint8_t path[256]; } symlink; - } __attribute__ ((packed)); -} __attribute__ ((packed)); + } GRUB_PACKED; +} GRUB_PACKED; struct grub_jfs_data { @@ -223,7 +234,7 @@ struct grub_jfs_data int pos; int linknest; int namecomponentlen; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_jfs_diropen { @@ -234,7 +245,7 @@ struct grub_jfs_diropen struct grub_jfs_leaf_dirent dirent[0]; struct grub_jfs_leaf_next_dirent next_dirent[0]; grub_uint8_t sorted[0]; - } *dirpage __attribute__ ((packed)); + } GRUB_PACKED *dirpage; struct grub_jfs_data *data; struct grub_jfs_inode *inode; int count; @@ -248,67 +259,102 @@ struct grub_jfs_diropen */ char name[256 * GRUB_MAX_UTF8_PER_UTF16 + 1]; grub_uint32_t ino; -} __attribute__ ((packed)); +} GRUB_PACKED; static grub_dl_t my_mod; static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino); +/* + * An extent's offset, physical and logical, is represented as a 40-bit value. + * This 40-bit value is split into two parts: + * - offset1: the most signficant 8 bits of the offset, + * - offset2: the least significant 32 bits of the offset. + * + * This function calculates and returns the 64-bit offset of an extent. + */ +static grub_uint64_t +get_ext_offset (grub_uint8_t offset1, grub_uint32_t offset2) +{ + return (((grub_uint64_t) offset1 << 32) | grub_le_to_cpu32 (offset2)); +} + +static grub_uint64_t +getblk (struct grub_jfs_treehead *treehead, + struct grub_jfs_tree_extent *extents, + int max_extents, + struct grub_jfs_data *data, + grub_uint64_t blk) +{ + int found = -1; + int i; + grub_uint64_t ext_offset, ext_blk; + + grub_errno = GRUB_ERR_NONE; + + for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2 && + i < max_extents; i++) + { + ext_offset = get_ext_offset (extents[i].offset1, extents[i].offset2); + ext_blk = get_ext_offset (extents[i].extent.blk1, extents[i].extent.blk2); + + if (treehead->flags & GRUB_JFS_TREE_LEAF) + { + /* Read the leafnode. */ + if (ext_offset <= blk + && ((grub_le_to_cpu16 (extents[i].extent.length)) + + (extents[i].extent.length2 << 16) + + ext_offset) > blk) + return (blk - ext_offset + ext_blk); + } + else + if (blk >= ext_offset) + found = i; + } + + if (found != -1) + { + grub_uint64_t ret = 0; + struct + { + struct grub_jfs_treehead treehead; + struct grub_jfs_tree_extent extents[254]; + } *tree; + + tree = grub_zalloc (sizeof (*tree)); + if (!tree) + return 0; + + if (!grub_disk_read (data->disk, + (grub_disk_addr_t) ext_blk + << (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS), + 0, sizeof (*tree), (char *) tree)) + { + if (grub_memcmp (&tree->treehead, treehead, sizeof (struct grub_jfs_treehead)) || + grub_memcmp (&tree->extents, extents, 254 * sizeof (struct grub_jfs_tree_extent))) + ret = getblk (&tree->treehead, &tree->extents[0], 254, data, blk); + else + { + grub_error (GRUB_ERR_BAD_FS, "jfs: infinite recursion detected"); + ret = 0; + } + } + grub_free (tree); + return ret; + } + + grub_error (GRUB_ERR_READ_ERROR, "jfs: block %" PRIuGRUB_UINT64_T " not found", blk); + return 0; +} + /* Get the block number for the block BLK in the node INODE in the mounted filesystem DATA. */ -static grub_int64_t +static grub_uint64_t grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode, grub_uint64_t blk) { - auto grub_int64_t getblk (struct grub_jfs_treehead *treehead, - struct grub_jfs_tree_extent *extents); - - grub_int64_t getblk (struct grub_jfs_treehead *treehead, - struct grub_jfs_tree_extent *extents) - { - int found = -1; - int i; - - for (i = 0; i < grub_le_to_cpu16 (treehead->count) - 2; i++) - { - if (treehead->flags & GRUB_JFS_TREE_LEAF) - { - /* Read the leafnode. */ - if (grub_le_to_cpu32 (extents[i].offset2) <= blk - && ((grub_le_to_cpu16 (extents[i].extent.length)) - + (extents[i].extent.length2 << 16) - + grub_le_to_cpu32 (extents[i].offset2)) > blk) - return (blk - grub_le_to_cpu32 (extents[i].offset2) - + grub_le_to_cpu32 (extents[i].extent.blk2)); - } - else - if (blk >= grub_le_to_cpu32 (extents[i].offset2)) - found = i; - } - - if (found != -1) - { - struct - { - struct grub_jfs_treehead treehead; - struct grub_jfs_tree_extent extents[254]; - } tree; - - if (grub_disk_read (data->disk, - ((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2)) - << (grub_le_to_cpu16 (data->sblock.log2_blksz) - - GRUB_DISK_SECTOR_BITS), 0, - sizeof (tree), (char *) &tree)) - return -1; - - return getblk (&tree.treehead, &tree.extents[0]); - } - - return -1; - } - - return getblk (&inode->file.tree, &inode->file.extents[0]); + return getblk (&inode->file.tree, &inode->file.extents[0], 16, data, blk); } @@ -316,7 +362,7 @@ static grub_err_t grub_jfs_read_inode (struct grub_jfs_data *data, grub_uint32_t ino, struct grub_jfs_inode *inode) { - struct grub_jfs_iag iag; + struct grub_jfs_extent iag_inodes[GRUB_JFS_IAG_INODES_COUNT]; grub_uint32_t iagnum = ino / 4096; unsigned inoext = (ino % 4096) / 32; unsigned inonum = (ino % 4096) % 32; @@ -330,11 +376,12 @@ grub_jfs_read_inode (struct grub_jfs_data *data, grub_uint32_t ino, /* Read in the IAG. */ if (grub_disk_read (data->disk, iagblk << (grub_le_to_cpu16 (data->sblock.log2_blksz) - - GRUB_DISK_SECTOR_BITS), 0, - sizeof (struct grub_jfs_iag), &iag)) + - GRUB_DISK_SECTOR_BITS), + GRUB_JFS_IAG_INODES_OFFSET, + sizeof (iag_inodes), &iag_inodes)) return grub_errno; - inoblk = grub_le_to_cpu32 (iag.inodes[inoext].blk2); + inoblk = get_ext_offset (iag_inodes[inoext].blk1, iag_inodes[inoext].blk2); inoblk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS); inoblk += inonum; @@ -433,6 +480,13 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode) /* Check if the entire tree is contained within the inode. */ if (inode->file.tree.flags & GRUB_JFS_TREE_LEAF) { + if (inode->dir.header.count > GRUB_JFS_INODE_INLINE_ENTRIES) + { + grub_free (diro); + grub_error (GRUB_ERR_BAD_FS, N_("invalid JFS inode")); + return 0; + } + diro->leaf = inode->dir.dirents; diro->next_leaf = (struct grub_jfs_leaf_next_dirent *) de; diro->sorted = inode->dir.header.sorted; @@ -448,7 +502,16 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode) return 0; } - blk = grub_le_to_cpu32 (de[inode->dir.header.sorted[0]].ex.blk2); + if (inode->dir.header.sorted[0] >= GRUB_JFS_DIR_MAX_SLOTS) + { + grub_error (GRUB_ERR_BAD_FS, N_("invalid directory slot index")); + grub_free (diro->dirpage); + grub_free (diro); + return 0; + } + + blk = get_ext_offset (de[inode->dir.header.sorted[0]].ex.blk1, + de[inode->dir.header.sorted[0]].ex.blk2); blk <<= (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS); /* Read in the nodes until we are on the leaf node level. */ @@ -466,7 +529,7 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode) de = (struct grub_jfs_internal_dirent *) diro->dirpage->dirent; index = diro->dirpage->sorted[diro->dirpage->header.sindex * 32]; - blk = (grub_le_to_cpu32 (de[index].ex.blk2) + blk = (get_ext_offset (de[index].ex.blk1, de[index].ex.blk2) << (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS)); } while (!(diro->dirpage->header.flags & GRUB_JFS_TREE_LEAF)); @@ -489,6 +552,17 @@ grub_jfs_closedir (struct grub_jfs_diropen *diro) grub_free (diro); } +static void +le_to_cpu16_copy (grub_uint16_t *out, grub_uint16_t *in, grub_size_t len) +{ + while (len--) + *out++ = grub_le_to_cpu16 (*in++); +} + +#if __GNUC__ >= 9 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" +#endif /* Read in the next dirent from the directory described by DIRO. */ static grub_err_t @@ -501,15 +575,6 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) int nextent; grub_uint16_t filename[256]; - auto void addstr (grub_uint16_t *uname, int ulen); - - /* Add the unicode string to the utf16 filename buffer. */ - void addstr (grub_uint16_t *name, int ulen) - { - while (ulen--) - filename[strpos++] = grub_le_to_cpu16 (*(name++)); - } - /* The last node, read in more. */ if (diro->index == diro->count) { @@ -547,18 +612,21 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) return grub_jfs_getent (diro); } - addstr (leaf->namepart, len < diro->data->namecomponentlen ? len - : diro->data->namecomponentlen); + le_to_cpu16_copy (filename + strpos, leaf->namepart, len < diro->data->namecomponentlen ? len + : diro->data->namecomponentlen); + strpos += len < diro->data->namecomponentlen ? len + : diro->data->namecomponentlen; diro->ino = grub_le_to_cpu32 (leaf->inode); len -= diro->data->namecomponentlen; /* Move down to the leaf level. */ nextent = leaf->next; - if (leaf->next != 255) + if (leaf->next != 255 && len > 0) do { next_leaf = &diro->next_leaf[nextent]; - addstr (next_leaf->namepart, len < 15 ? len : 15 ); + le_to_cpu16_copy (filename + strpos, next_leaf->namepart, len < 15 ? len : 15); + strpos += len < 15 ? len : 15; len -= 15; nextent = next_leaf->next; @@ -572,13 +640,15 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) return 0; } +#if __GNUC__ >= 9 +#pragma GCC diagnostic pop +#endif /* Read LEN bytes from the file described by DATA starting with byte POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_jfs_read_file (struct grub_jfs_data *data, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { grub_off_t i; @@ -616,6 +686,7 @@ grub_jfs_read_file (struct grub_jfs_data *data, } data->disk->read_hook = read_hook; + data->disk->read_hook_data = read_hook_data; grub_disk_read (data->disk, blknr << (grub_le_to_cpu16 (data->sblock.log2_blksz) - GRUB_DISK_SECTOR_BITS), @@ -638,136 +709,73 @@ static grub_err_t grub_jfs_find_file (struct grub_jfs_data *data, const char *path, grub_uint32_t start_ino) { - char fpath[grub_strlen (path)]; - char *name = fpath; - char *next; - struct grub_jfs_diropen *diro; - - grub_strncpy (fpath, path, grub_strlen (path) + 1); + const char *name; + const char *next = path; + struct grub_jfs_diropen *diro = NULL; if (grub_jfs_read_inode (data, start_ino, &data->currinode)) return grub_errno; - /* Skip the first slashes. */ - while (*name == '/') - { - name++; - if (!*name) - return 0; - } - - /* Extract the actual part from the pathname. */ - next = grub_strchr (name, '/'); - if (next) - { - while (*next == '/') - { - next[0] = '\0'; - next++; - } - } - diro = grub_jfs_opendir (data, &data->currinode); - if (!diro) - return grub_errno; - - for (;;) + while (1) { + name = next; + while (*name == '/') + name++; if (name[0] == 0) return GRUB_ERR_NONE; + for (next = name; *next && *next != '/'; next++); - if (name[0] == '.' && name[1] == 0) - { - if (!next) - return 0; + if (name[0] == '.' && name + 1 == next) + continue; - name = next; - next = grub_strchr (name, '/'); - while (next && *next == '/') - { - next[0] = '\0'; - next++; - } - continue; - } - - if (name[0] == '.' && name[1] == '.' && name[2] == 0) + if (name[0] == '.' && name[1] == '.' && name + 2 == next) { grub_uint32_t ino = grub_le_to_cpu32 (data->currinode.dir.header.idotdot); - grub_jfs_closedir (diro); - diro = 0; - if (grub_jfs_read_inode (data, ino, &data->currinode)) - break; - - if (!next) - return 0; - - name = next; - next = grub_strchr (name, '/'); - while (next && *next == '/') - { - next[0] = '\0'; - next++; - } - - /* Open this directory for reading dirents. */ - diro = grub_jfs_opendir (data, &data->currinode); - if (!diro) return grub_errno; continue; } - if (grub_jfs_getent (diro) == GRUB_ERR_OUT_OF_RANGE) - break; + diro = grub_jfs_opendir (data, &data->currinode); + if (!diro) + return grub_errno; - /* Check if the current direntry matches the current part of the - pathname. */ - if (data->caseins ? grub_strcasecmp (name, diro->name) == 0 - : grub_strcmp (name, diro->name) == 0) + for (;;) { - grub_uint32_t ino = diro->ino; - grub_uint32_t dirino = grub_le_to_cpu32 (data->currinode.inode); - - grub_jfs_closedir (diro); - diro = 0; - - if (grub_jfs_read_inode (data, ino, &data->currinode)) - break; - - /* Check if this is a symlink. */ - if ((grub_le_to_cpu32 (data->currinode.mode) - & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_LNK) + if (grub_jfs_getent (diro) == GRUB_ERR_OUT_OF_RANGE) { - grub_jfs_lookup_symlink (data, dirino); - if (grub_errno) - return grub_errno; + grub_jfs_closedir (diro); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); } - if (!next) - return 0; - - name = next; - next = grub_strchr (name, '/'); - while (next && *next == '/') + /* Check if the current direntry matches the current part of the + pathname. */ + if ((data->caseins ? grub_strncasecmp (name, diro->name, next - name) == 0 + : grub_strncmp (name, diro->name, next - name) == 0) && !diro->name[next - name]) { - next[0] = '\0'; - next++; + grub_uint32_t ino = diro->ino; + grub_uint32_t dirino = grub_le_to_cpu32 (data->currinode.inode); + + grub_jfs_closedir (diro); + + if (grub_jfs_read_inode (data, ino, &data->currinode)) + break; + + /* Check if this is a symlink. */ + if ((grub_le_to_cpu32 (data->currinode.mode) + & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_LNK) + { + grub_jfs_lookup_symlink (data, dirino); + if (grub_errno) + return grub_errno; + } + + break; } - - /* Open this directory for reading dirents. */ - diro = grub_jfs_opendir (data, &data->currinode); - if (!diro) - return grub_errno; - - continue; } } - - grub_jfs_closedir (diro); - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); - return grub_errno; } @@ -775,15 +783,21 @@ static grub_err_t grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino) { grub_size_t size = grub_le_to_cpu64 (data->currinode.size); - char symlink[size + 1]; + char *symlink; if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT) return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks")); - if (size <= sizeof (data->currinode.symlink.path)) - grub_strncpy (symlink, (char *) (data->currinode.symlink.path), size); - else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0) + symlink = grub_malloc (size + 1); + if (!symlink) return grub_errno; + if (size <= sizeof (data->currinode.symlink.path)) + grub_memcpy (symlink, (char *) (data->currinode.symlink.path), size); + else if (grub_jfs_read_file (data, 0, 0, 0, size, symlink) < 0) + { + grub_free (symlink); + return grub_errno; + } symlink[size] = '\0'; @@ -793,14 +807,15 @@ grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino) grub_jfs_find_file (data, symlink, ino); + grub_free (symlink); + return grub_errno; } static grub_err_t grub_jfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { struct grub_jfs_data *data = 0; struct grub_jfs_diropen *diro = 0; @@ -832,7 +847,7 @@ grub_jfs_dir (grub_device_t device, const char *path, & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR; info.mtimeset = 1; info.mtime = grub_le_to_cpu32 (inode.mtime.sec); - if (hook (diro->name, &info)) + if (hook (diro->name, &info, hook_data)) goto fail; } @@ -895,7 +910,8 @@ grub_jfs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_jfs_data *data = (struct grub_jfs_data *) file->data; - return grub_jfs_read_file (data, file->read_hook, file->offset, len, buf); + return grub_jfs_read_file (data, file->read_hook, file->read_hook_data, + file->offset, len, buf); } @@ -974,12 +990,12 @@ grub_jfs_label (grub_device_t device, char **label) static struct grub_fs grub_jfs_fs = { .name = "jfs", - .dir = grub_jfs_dir, - .open = grub_jfs_open, - .read = grub_jfs_read, - .close = grub_jfs_close, - .label = grub_jfs_label, - .uuid = grub_jfs_uuid, + .fs_dir = grub_jfs_dir, + .fs_open = grub_jfs_open, + .fs_read = grub_jfs_read, + .fs_close = grub_jfs_close, + .fs_label = grub_jfs_label, + .fs_uuid = grub_jfs_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, @@ -989,11 +1005,16 @@ static struct grub_fs grub_jfs_fs = GRUB_MOD_INIT(jfs) { - grub_fs_register (&grub_jfs_fs); + if (!grub_is_lockdown ()) + { + grub_jfs_fs.mod = mod; + grub_fs_register (&grub_jfs_fs); + } my_mod = mod; } GRUB_MOD_FINI(jfs) { - grub_fs_unregister (&grub_jfs_fs); + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_jfs_fs); } diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 1e1c13b56..4440fcca8 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -25,6 +25,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -38,6 +39,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_MINIX_MAGIC_30 0x138F #endif +#define EXT2_MAGIC 0xEF53 + #define GRUB_MINIX_INODE_DIR_BLOCKS 7 #define GRUB_MINIX_LOG2_BSIZE 1 #define GRUB_MINIX_ROOT_INODE 1 @@ -65,7 +68,6 @@ typedef grub_uint16_t grub_minix_uintn_t; #define grub_minix_to_cpu_n grub_minix_to_cpu16 #endif -#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t) #ifdef MODE_MINIX3 typedef grub_uint32_t grub_minix_ino_t; #define grub_minix_to_cpu_ino grub_minix_to_cpu32 @@ -83,19 +85,6 @@ typedef grub_uint16_t grub_minix_ino_t; #define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_to_cpu_n \ (data->inode.double_indir_zone)) -#ifndef MODE_MINIX3 -#define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \ - + grub_minix_to_cpu16 (data->sblock.log2_zone_size)) -#endif -#define GRUB_MINIX_ZONESZ ((grub_uint64_t) data->block_size << \ - (GRUB_DISK_SECTOR_BITS + grub_minix_to_cpu16 (data->sblock.log2_zone_size))) - -#ifdef MODE_MINIX3 -#define GRUB_MINIX_ZONE2SECT(zone) ((zone) * data->block_size) -#else -#define GRUB_MINIX_ZONE2SECT(zone) ((zone) << GRUB_MINIX_LOG2_ZONESZ) -#endif - #ifdef MODE_MINIX3 struct grub_minix_sblock @@ -110,10 +99,10 @@ struct grub_minix_sblock grub_uint32_t max_file_size; grub_uint32_t zones; grub_uint16_t magic; - + grub_uint16_t pad2; grub_uint16_t block_size; - grub_uint8_t disk_version; + grub_uint8_t disk_version; }; #else struct grub_minix_sblock @@ -161,11 +150,18 @@ struct grub_minix_inode #endif +#if defined(MODE_MINIX3) +#define MAX_MINIX_FILENAME_SIZE 60 +#else +#define MAX_MINIX_FILENAME_SIZE 30 +#endif + /* Information about a "mounted" minix filesystem. */ struct grub_minix_data { struct grub_minix_sblock sblock; struct grub_minix_inode inode; + grub_uint32_t block_per_zone; grub_minix_ino_t ino; int linknest; grub_disk_t disk; @@ -178,27 +174,41 @@ static grub_dl_t my_mod; static grub_err_t grub_minix_find_file (struct grub_minix_data *data, const char *path); +#ifdef MODE_MINIX3 +static inline grub_disk_addr_t +grub_minix_zone2sect (struct grub_minix_data *data, grub_minix_uintn_t zone) +{ + return ((grub_disk_addr_t) zone) * data->block_size; +} +#else +static inline grub_disk_addr_t +grub_minix_zone2sect (struct grub_minix_data *data, grub_minix_uintn_t zone) +{ + int log2_zonesz = (GRUB_MINIX_LOG2_BSIZE + + grub_minix_to_cpu16 (data->sblock.log2_zone_size)); + return (((grub_disk_addr_t) zone) << log2_zonesz); +} +#endif + + + /* Read the block pointer in ZONE, on the offset NUM. */ +static grub_minix_uintn_t +grub_get_indir (struct grub_minix_data *data, + grub_minix_uintn_t zone, + grub_minix_uintn_t num) +{ + grub_minix_uintn_t indirn; + grub_disk_read (data->disk, + grub_minix_zone2sect(data, zone), + sizeof (grub_minix_uintn_t) * num, + sizeof (grub_minix_uintn_t), (char *) &indirn); + return grub_minix_to_cpu_n (indirn); +} + static grub_minix_uintn_t grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) { grub_minix_uintn_t indir; - const grub_uint32_t block_per_zone = (GRUB_MINIX_ZONESZ - / GRUB_MINIX_INODE_BLKSZ (data)); - - auto grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t, - grub_minix_uintn_t); - - /* Read the block pointer in ZONE, on the offset NUM. */ - grub_minix_uintn_t grub_get_indir (grub_minix_uintn_t zone, - grub_minix_uintn_t num) - { - grub_minix_uintn_t indirn; - grub_disk_read (data->disk, - GRUB_MINIX_ZONE2SECT(zone), - sizeof (grub_minix_uintn_t) * num, - sizeof (grub_minix_uintn_t), (char *) &indirn); - return grub_minix_to_cpu_n (indirn); - } /* Direct block. */ if (blk < GRUB_MINIX_INODE_DIR_BLOCKS) @@ -206,33 +216,33 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) /* Indirect block. */ blk -= GRUB_MINIX_INODE_DIR_BLOCKS; - if (blk < block_per_zone) + if (blk < data->block_per_zone) { - indir = grub_get_indir (GRUB_MINIX_INODE_INDIR_ZONE (data), blk); + indir = grub_get_indir (data, GRUB_MINIX_INODE_INDIR_ZONE (data), blk); return indir; } /* Double indirect block. */ - blk -= block_per_zone; - if (blk < block_per_zone * block_per_zone) + blk -= data->block_per_zone; + if (blk < (grub_uint64_t) data->block_per_zone * (grub_uint64_t) data->block_per_zone) { - indir = grub_get_indir (GRUB_MINIX_INODE_DINDIR_ZONE (data), - blk / block_per_zone); + indir = grub_get_indir (data, GRUB_MINIX_INODE_DINDIR_ZONE (data), + blk / data->block_per_zone); - indir = grub_get_indir (indir, blk % block_per_zone); + indir = grub_get_indir (data, indir, blk % data->block_per_zone); return indir; } #if defined (MODE_MINIX3) || defined (MODE_MINIX2) - blk -= block_per_zone * block_per_zone; - if (blk < ((grub_uint64_t) block_per_zone * (grub_uint64_t) block_per_zone - * (grub_uint64_t) block_per_zone)) + blk -= data->block_per_zone * data->block_per_zone; + if (blk < ((grub_uint64_t) data->block_per_zone * (grub_uint64_t) data->block_per_zone + * (grub_uint64_t) data->block_per_zone)) { - indir = grub_get_indir (grub_minix_to_cpu_n (data->inode.triple_indir_zone), - (blk / block_per_zone) / block_per_zone); - indir = grub_get_indir (indir, (blk / block_per_zone) % block_per_zone); - indir = grub_get_indir (indir, blk % block_per_zone); + indir = grub_get_indir (data, grub_minix_to_cpu_n (data->inode.triple_indir_zone), + (blk / data->block_per_zone) / data->block_per_zone); + indir = grub_get_indir (data, indir, (blk / data->block_per_zone) % data->block_per_zone); + indir = grub_get_indir (data, indir, blk % data->block_per_zone); return indir; } @@ -249,8 +259,7 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_minix_read_file (struct grub_minix_data *data, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { grub_uint32_t i; @@ -258,15 +267,22 @@ grub_minix_read_file (struct grub_minix_data *data, grub_uint32_t posblock; grub_uint32_t blockoff; + if (pos > GRUB_MINIX_INODE_SIZE (data)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("attempt to read past the end of file")); + return -1; + } + /* Adjust len so it we can't read past the end of the file. */ if (len + pos > GRUB_MINIX_INODE_SIZE (data)) len = GRUB_MINIX_INODE_SIZE (data) - pos; + if (len == 0) + return 0; /* Files are at most 2G/4G - 1 bytes on minixfs. Avoid 64-bit division. */ - blockcnt = ((grub_uint32_t) ((len + pos - + (data->block_size << GRUB_DISK_SECTOR_BITS) - - 1) - >> GRUB_DISK_SECTOR_BITS)) / data->block_size; + blockcnt = ((grub_uint32_t) ((len + pos - 1) + >> GRUB_DISK_SECTOR_BITS)) / data->block_size + 1; posblock = (((grub_uint32_t) pos) / (data->block_size << GRUB_DISK_SECTOR_BITS)); blockoff = (((grub_uint32_t) pos) @@ -274,7 +290,7 @@ grub_minix_read_file (struct grub_minix_data *data, for (i = posblock; i < blockcnt; i++) { - grub_disk_addr_t blknr; + grub_minix_uintn_t blknr; grub_uint64_t blockend = data->block_size << GRUB_DISK_SECTOR_BITS; grub_off_t skipfirst = 0; @@ -301,8 +317,9 @@ grub_minix_read_file (struct grub_minix_data *data, } data->disk->read_hook = read_hook; + data->disk->read_hook_data = read_hook_data; grub_disk_read (data->disk, - GRUB_MINIX_ZONE2SECT(blknr), + grub_minix_zone2sect(data, blknr), skipfirst, blockend, buf); data->disk->read_hook = 0; if (grub_errno) @@ -328,13 +345,14 @@ grub_minix_read_inode (struct grub_minix_data *data, grub_minix_ino_t ino) /* The first inode in minix is inode 1. */ ino--; - block = GRUB_MINIX_ZONE2SECT (2 + grub_minix_to_cpu16 (sblock->inode_bmap_size) + block = grub_minix_zone2sect (data, + 2 + grub_minix_to_cpu16 (sblock->inode_bmap_size) + grub_minix_to_cpu16 (sblock->zone_bmap_size)); block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)); int offs = (ino % (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)) * sizeof (struct grub_minix_inode)); - + grub_disk_read (data->disk, block, offs, sizeof (struct grub_minix_inode), &data->inode); @@ -347,16 +365,19 @@ grub_minix_read_inode (struct grub_minix_data *data, grub_minix_ino_t ino) static grub_err_t grub_minix_lookup_symlink (struct grub_minix_data *data, grub_minix_ino_t ino) { - char symlink[GRUB_MINIX_INODE_SIZE (data) + 1]; + char *symlink; + grub_size_t sz = GRUB_MINIX_INODE_SIZE (data); if (++data->linknest > GRUB_MINIX_MAX_SYMLNK_CNT) return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks")); - if (grub_minix_read_file (data, 0, 0, - GRUB_MINIX_INODE_SIZE (data), symlink) < 0) + symlink = grub_malloc (sz + 1); + if (!symlink) return grub_errno; + if (grub_minix_read_file (data, 0, 0, 0, sz, symlink) < 0) + goto fail; - symlink[GRUB_MINIX_INODE_SIZE (data)] = '\0'; + symlink[sz] = '\0'; /* The symlink is an absolute path, go back to the root inode. */ if (symlink[0] == '/') @@ -364,10 +385,12 @@ grub_minix_lookup_symlink (struct grub_minix_data *data, grub_minix_ino_t ino) /* Now load in the old inode. */ if (grub_minix_read_inode (data, ino)) - return grub_errno; + goto fail; grub_minix_find_file (data, symlink); + fail: + grub_free(symlink); return grub_errno; } @@ -377,90 +400,70 @@ grub_minix_lookup_symlink (struct grub_minix_data *data, grub_minix_ino_t ino) static grub_err_t grub_minix_find_file (struct grub_minix_data *data, const char *path) { - char fpath[grub_strlen (path) + 1]; - char *name = fpath; - char *next; + const char *name; + const char *next = path; unsigned int pos = 0; grub_minix_ino_t dirino; - grub_strcpy (fpath, path); - - /* Skip the first slash. */ - while (*name == '/') - name++; - if (!*name) - return 0; - - /* Extract the actual part from the pathname. */ - next = grub_strchr (name, '/'); - if (next) + while (1) { - next[0] = '\0'; - next++; - while (*next == '/') - next++; - } - - do - { - grub_minix_ino_t ino; - char filename[data->filename_size + 1]; - - if (grub_strlen (name) == 0) + name = next; + /* Skip the first slash. */ + while (*name == '/') + name++; + if (!*name) return GRUB_ERR_NONE; - if (grub_minix_read_file (data, 0, pos, sizeof (ino), - (char *) &ino) < 0) - return grub_errno; - if (grub_minix_read_file (data, 0, pos + sizeof (ino), - data->filename_size, (char *) filename)< 0) - return grub_errno; + if ((GRUB_MINIX_INODE_MODE (data) + & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR) + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - filename[data->filename_size] = '\0'; + /* Extract the actual part from the pathname. */ + for (next = name; *next && *next != '/'; next++); - /* Check if the current direntry matches the current part of the - pathname. */ - if (!grub_strcmp (name, filename)) + for (pos = 0; ; ) { - dirino = data->ino; - grub_minix_read_inode (data, grub_minix_to_cpu_ino (ino)); + grub_minix_ino_t ino; + char filename[MAX_MINIX_FILENAME_SIZE + 1]; - /* Follow the symlink. */ - if ((GRUB_MINIX_INODE_MODE (data) - & GRUB_MINIX_IFLNK) == GRUB_MINIX_IFLNK) + if (pos >= GRUB_MINIX_INODE_SIZE (data)) { - grub_minix_lookup_symlink (data, dirino); - if (grub_errno) - return grub_errno; + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); + return grub_errno; } - if (!next) - return 0; + if (grub_minix_read_file (data, 0, 0, pos, sizeof (ino), + (char *) &ino) < 0) + return grub_errno; + if (grub_minix_read_file (data, 0, 0, pos + sizeof (ino), + data->filename_size, (char *) filename)< 0) + return grub_errno; - pos = 0; + pos += sizeof (ino) + data->filename_size; - name = next; - next = grub_strchr (name, '/'); - if (next) + filename[data->filename_size] = '\0'; + + /* Check if the current direntry matches the current part of the + pathname. */ + if (grub_strncmp (name, filename, next - name) == 0 + && filename[next - name] == '\0') { - next[0] = '\0'; - next++; - while (*next == '/') - next++; + dirino = data->ino; + grub_minix_read_inode (data, grub_minix_to_cpu_ino (ino)); + + /* Follow the symlink. */ + if ((GRUB_MINIX_INODE_MODE (data) + & GRUB_MINIX_IFLNK) == GRUB_MINIX_IFLNK) + { + grub_minix_lookup_symlink (data, dirino); + if (grub_errno) + return grub_errno; + } + + break; } - - if ((GRUB_MINIX_INODE_MODE (data) - & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - - continue; } - - pos += sizeof (ino) + data->filename_size; - } while (pos < GRUB_MINIX_INODE_SIZE (data)); - - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); - return grub_errno; + } } @@ -468,7 +471,21 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path) static struct grub_minix_data * grub_minix_mount (grub_disk_t disk) { - struct grub_minix_data *data; + struct grub_minix_data *data = NULL; + grub_uint16_t ext2_marker; + + grub_disk_read (disk, 2, 56, sizeof (ext2_marker), &ext2_marker); + if (grub_errno != GRUB_ERR_NONE) + goto fail; + + /* + * The ext2 filesystems can sometimes be mistakenly identified as MINIX, e.g. + * due to the number of free ext2 inodes being written to the same location + * where the MINIX superblock magic is found. Avoid such situations by + * skipping any filesystems that have the ext2 superblock magic. + */ + if (ext2_marker == grub_cpu_to_le16_compile_time (EXT2_MAGIC)) + goto fail; data = grub_malloc (sizeof (struct grub_minix_data)); if (!data) @@ -520,6 +537,12 @@ grub_minix_mount (grub_disk_t disk) data->block_size = 2; #endif + data->block_per_zone = (((grub_uint64_t) data->block_size << \ + (GRUB_DISK_SECTOR_BITS + grub_minix_to_cpu16 (data->sblock.log2_zone_size))) + / sizeof (grub_minix_uintn_t)); + if (!data->block_per_zone) + goto fail; + return data; fail: @@ -536,8 +559,7 @@ grub_minix_mount (grub_disk_t disk) static grub_err_t grub_minix_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { struct grub_minix_data *data = 0; unsigned int pos = 0; @@ -563,17 +585,17 @@ grub_minix_dir (grub_device_t device, const char *path, while (pos < GRUB_MINIX_INODE_SIZE (data)) { grub_minix_ino_t ino; - char filename[data->filename_size + 1]; + char filename[MAX_MINIX_FILENAME_SIZE + 1]; grub_minix_ino_t dirino = data->ino; struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); - if (grub_minix_read_file (data, 0, pos, sizeof (ino), + if (grub_minix_read_file (data, 0, 0, pos, sizeof (ino), (char *) &ino) < 0) return grub_errno; - if (grub_minix_read_file (data, 0, pos + sizeof (ino), + if (grub_minix_read_file (data, 0, 0, pos + sizeof (ino), data->filename_size, (char *) filename) < 0) return grub_errno; @@ -590,7 +612,7 @@ grub_minix_dir (grub_device_t device, const char *path, info.mtimeset = 1; info.mtime = grub_minix_to_cpu32 (data->inode.mtime); - if (hook (filename, &info) ? 1 : 0) + if (hook (filename, &info, hook_data) ? 1 : 0) break; /* Load the old inode back in. */ @@ -650,7 +672,8 @@ grub_minix_read (grub_file_t file, char *buf, grub_size_t len) struct grub_minix_data *data = (struct grub_minix_data *) file->data; - return grub_minix_read_file (data, file->read_hook, file->offset, len, buf); + return grub_minix_read_file (data, file->read_hook, file->read_hook_data, + file->offset, len, buf); } @@ -683,10 +706,10 @@ static struct grub_fs grub_minix_fs = .name = "minix", #endif #endif - .dir = grub_minix_dir, - .open = grub_minix_open, - .read = grub_minix_read, - .close = grub_minix_close, + .fs_dir = grub_minix_dir, + .fs_open = grub_minix_open, + .fs_read = grub_minix_read, + .fs_close = grub_minix_close, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, @@ -712,7 +735,11 @@ GRUB_MOD_INIT(minix) #endif #endif { - grub_fs_register (&grub_minix_fs); + if (!grub_is_lockdown ()) + { + grub_minix_fs.mod = mod; + grub_fs_register (&grub_minix_fs); + } my_mod = mod; } @@ -734,5 +761,6 @@ GRUB_MOD_FINI(minix) #endif #endif { - grub_fs_unregister (&grub_minix_fs); + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_minix_fs); } diff --git a/grub-core/fs/newc.c b/grub-core/fs/newc.c index fdcc160e8..43b7f8b64 100644 --- a/grub-core/fs/newc.c +++ b/grub-core/fs/newc.c @@ -1,2 +1,74 @@ -#define MODE_NEWC 1 -#include "cpio.c" +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#define ALIGN_CPIO(x) (ALIGN_UP ((x), 4)) +#define MAGIC "070701" +#define MAGIC2 "070702" +struct head +{ + char magic[6]; + char ino[8]; + char mode[8]; + char uid[8]; + char gid[8]; + char nlink[8]; + char mtime[8]; + char filesize[8]; + char devmajor[8]; + char devminor[8]; + char rdevmajor[8]; + char rdevminor[8]; + char namesize[8]; + char check[8]; +} GRUB_PACKED; + +static inline unsigned long long +read_number (const char *str, grub_size_t size) +{ + unsigned long long ret = 0; + while (size-- && grub_isxdigit (*str)) + { + char dig = *str++; + if (dig >= '0' && dig <= '9') + dig &= 0xf; + else if (dig >= 'a' && dig <= 'f') + dig -= 'a' - 10; + else + dig -= 'A' - 10; + ret = (ret << 4) | (dig); + } + return ret; +} + +#define FSNAME "newc" + +#include "cpio_common.c" + +GRUB_MOD_INIT (newc) +{ + grub_cpio_fs.mod = mod; + grub_fs_register (&grub_cpio_fs); +} + +GRUB_MOD_FINI (newc) +{ + grub_fs_unregister (&grub_cpio_fs); +} diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index f36c513fa..26e6077ff 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -1,5 +1,5 @@ -/* - * nilfs2.c - New Implementation of Log filesystem +/* + * nilfs2.c - New Implementation of Log filesystem * * Written by Jiro SEKIBA * @@ -34,6 +34,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -136,13 +137,14 @@ struct grub_nilfs2_dir_entry { grub_uint64_t inode; grub_uint16_t rec_len; +#define MAX_NAMELEN 255 grub_uint8_t name_len; grub_uint8_t file_type; #if 0 /* followed by file name. */ char name[NILFS_NAME_LEN]; char pad; #endif -} __attribute__ ((packed)); +} GRUB_PACKED; enum { @@ -214,6 +216,8 @@ struct grub_nilfs2_palloc_group_desc grub_uint32_t pg_nfrees; }; +#define LOG_SIZE_GROUP_DESC 2 + #define LOG_NILFS_DAT_ENTRY_SIZE 5 struct grub_nilfs2_dat_entry { @@ -311,10 +315,12 @@ grub_nilfs2_palloc_group (struct grub_nilfs2_data *data, } static inline grub_uint32_t -grub_nilfs2_palloc_groups_per_desc_block (struct grub_nilfs2_data *data) +grub_nilfs2_palloc_log_groups_per_desc_block (struct grub_nilfs2_data *data) { - return NILFS2_BLOCK_SIZE (data) / - sizeof (struct grub_nilfs2_palloc_group_desc); + return LOG2_BLOCK_SIZE (data) - LOG_SIZE_GROUP_DESC; + + COMPILE_TIME_ASSERT (sizeof (struct grub_nilfs2_palloc_group_desc) + == (1 << LOG_SIZE_GROUP_DESC)); } static inline grub_uint32_t @@ -338,8 +344,8 @@ static inline grub_uint32_t grub_nilfs2_blocks_per_desc_block_log (struct grub_nilfs2_data *data, unsigned long log_entry_size) { - return grub_nilfs2_palloc_groups_per_desc_block (data) * - grub_nilfs2_blocks_per_group_log (data, log_entry_size) + 1; + return(grub_nilfs2_blocks_per_group_log (data, log_entry_size) + << grub_nilfs2_palloc_log_groups_per_desc_block (data)) + 1; } static inline grub_uint32_t @@ -348,7 +354,7 @@ grub_nilfs2_palloc_desc_block_offset_log (struct grub_nilfs2_data *data, unsigned long log_entry_size) { grub_uint32_t desc_block = - group / grub_nilfs2_palloc_groups_per_desc_block (data); + group >> grub_nilfs2_palloc_log_groups_per_desc_block (data); return desc_block * grub_nilfs2_blocks_per_desc_block_log (data, log_entry_size); } @@ -358,8 +364,8 @@ grub_nilfs2_palloc_bitmap_block_offset (struct grub_nilfs2_data *data, unsigned long group, unsigned long log_entry_size) { - unsigned long desc_offset = group % - grub_nilfs2_palloc_groups_per_desc_block (data); + unsigned long desc_offset = group + & ((1 << grub_nilfs2_palloc_log_groups_per_desc_block (data)) - 1); return grub_nilfs2_palloc_desc_block_offset_log (data, group, log_entry_size) + 1 @@ -411,15 +417,35 @@ grub_nilfs2_btree_node_get_key (struct grub_nilfs2_btree_node *node, } static inline int -grub_nilfs2_btree_node_lookup (struct grub_nilfs2_btree_node *node, +grub_nilfs2_btree_node_nchildren_max (struct grub_nilfs2_data *data, + struct grub_nilfs2_btree_node *node) +{ + int node_children_max = ((NILFS2_BLOCK_SIZE (data) - + sizeof (struct grub_nilfs2_btree_node) - + NILFS_BTREE_NODE_EXTRA_PAD_SIZE) / + (sizeof (grub_uint64_t) + sizeof (grub_uint64_t))); + + return (node->bn_flags & NILFS_BTREE_NODE_ROOT) ? 3 : node_children_max; +} + +static inline int +grub_nilfs2_btree_node_lookup (struct grub_nilfs2_data *data, + struct grub_nilfs2_btree_node *node, grub_uint64_t key, int *indexp) { grub_uint64_t nkey; - int index, low, high, s; + int index = 0, low, high, s; low = 0; + high = grub_le_to_cpu16 (node->bn_nchildren) - 1; - index = 0; + if (high >= grub_nilfs2_btree_node_nchildren_max (data, node)) + { + grub_error (GRUB_ERR_BAD_FS, "too many children"); + *indexp = index; + return 0; + } + s = 0; while (low <= high) { @@ -454,18 +480,6 @@ grub_nilfs2_btree_node_lookup (struct grub_nilfs2_btree_node *node, return s == 0; } -static inline int -grub_nilfs2_btree_node_nchildren_max (struct grub_nilfs2_data *data, - struct grub_nilfs2_btree_node *node) -{ - int node_children_max = ((NILFS2_BLOCK_SIZE (data) - - sizeof (struct grub_nilfs2_btree_node) - - NILFS_BTREE_NODE_EXTRA_PAD_SIZE) / - (sizeof (grub_uint64_t) + sizeof (grub_uint64_t))); - - return (node->bn_flags & NILFS_BTREE_NODE_ROOT) ? 3 : node_children_max; -} - static inline grub_uint64_t * grub_nilfs2_btree_node_dptrs (struct grub_nilfs2_data *data, struct grub_nilfs2_btree_node *node) @@ -501,14 +515,22 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, grub_uint64_t key, int need_translate) { struct grub_nilfs2_btree_node *node; - GRUB_PROPERLY_ALIGNED_ARRAY (block, NILFS2_BLOCK_SIZE (data)); + void *block; grub_uint64_t ptr; - int level, found, index; + int level, found = 0, index; + + block = grub_malloc (NILFS2_BLOCK_SIZE (data)); + if (!block) + return -1; node = grub_nilfs2_btree_get_root (inode); level = grub_nilfs2_btree_get_level (node); - found = grub_nilfs2_btree_node_lookup (node, key, &index); + found = grub_nilfs2_btree_node_lookup (data, node, key, &index); + + if (grub_errno != GRUB_ERR_NONE) + goto fail; + ptr = grub_nilfs2_btree_node_get_ptr (data, node, index); if (need_translate) ptr = grub_nilfs2_dat_translate (data, ptr); @@ -518,22 +540,23 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, grub_nilfs2_btree_get_nonroot_node (data, ptr, block); if (grub_errno) { - return -1; + goto fail; } node = (struct grub_nilfs2_btree_node *) block; if (node->bn_level != level) { grub_error (GRUB_ERR_BAD_FS, "btree level mismatch\n"); - return -1; + goto fail; } if (!found) - found = grub_nilfs2_btree_node_lookup (node, key, &index); + found = grub_nilfs2_btree_node_lookup (data, node, key, &index); else index = 0; - if (index < grub_nilfs2_btree_node_nchildren_max (data, node)) + if (index < grub_nilfs2_btree_node_nchildren_max (data, node) && + grub_errno == GRUB_ERR_NONE) { ptr = grub_nilfs2_btree_node_get_ptr (data, node, index); if (need_translate) @@ -542,19 +565,29 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, else { grub_error (GRUB_ERR_BAD_FS, "btree corruption\n"); - return -1; + goto fail; } } + grub_free (block); + if (!found) return -1; return ptr; + fail: + grub_free (block); + return -1; } static inline grub_uint64_t grub_nilfs2_direct_lookup (struct grub_nilfs2_inode *inode, grub_uint64_t key) { + if (1 + key > 6) + { + grub_error (GRUB_ERR_BAD_FS, "key is too large"); + return 0xffffffffffffffff; + } return grub_le_to_cpu64 (inode->i_bmap[1 + key]); } @@ -570,7 +603,7 @@ grub_nilfs2_bmap_lookup (struct grub_nilfs2_data *data, { grub_uint64_t ptr; ptr = grub_nilfs2_direct_lookup (inode, key); - if (need_translate) + if (ptr != ((grub_uint64_t) 0xffffffffffffffff) && need_translate) ptr = grub_nilfs2_dat_translate (data, ptr); return ptr; } @@ -626,13 +659,11 @@ grub_nilfs2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_nilfs2_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t - sector, - unsigned offset, - unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { - return grub_fshelp_read_file (node->data->disk, node, read_hook, + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, pos, len, buf, grub_nilfs2_read_block, grub_le_to_cpu64 (node->inode.i_size), LOG2_NILFS2_BLOCK_SIZE (node->data), 0); @@ -650,12 +681,12 @@ grub_nilfs2_read_checkpoint (struct grub_nilfs2_data *data, grub_disk_t disk = data->disk; unsigned int nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data)); - /* Assume sizeof(struct grub_nilfs2_cpfile_header) < + /* Assume sizeof(struct grub_nilfs2_cpfile_header) < sizeof(struct grub_nilfs2_checkpoint). */ blockno = grub_divmod64 (cpno, NILFS2_BLOCK_SIZE (data) / sizeof (struct grub_nilfs2_checkpoint), &offset); - + pptr = grub_nilfs2_bmap_lookup (data, &data->sroot.sr_cpfile, blockno, 1); if (pptr == (grub_uint64_t) - 1) { @@ -712,6 +743,10 @@ grub_nilfs2_valid_sb (struct grub_nilfs2_super_block *sbp) if (grub_le_to_cpu32 (sbp->s_rev_level) != NILFS_SUPORT_REV) return 0; + /* 20 already means 1GiB blocks. We don't want to deal with blocks overflowing int32. */ + if (grub_le_to_cpu32 (sbp->s_log_block_size) > 20) + return 0; + return 1; } @@ -737,7 +772,7 @@ grub_nilfs2_load_sb (struct grub_nilfs2_data *data) partition_size = (grub_le_to_cpu64 (data->sblock.s_dev_size) >> GRUB_DISK_SECTOR_BITS); else - partition_size = grub_disk_get_size (disk); + partition_size = grub_disk_native_sectors (disk); if (partition_size != GRUB_DISK_SIZE_UNKNOWN) { /* Read second super block. */ @@ -852,7 +887,7 @@ grub_nilfs2_read_symlink (grub_fshelp_node_t node) if (!symlink) return 0; - grub_nilfs2_read_file (diro, 0, 0, + grub_nilfs2_read_file (diro, 0, 0, 0, grub_le_to_cpu64 (diro->inode.i_size), symlink); if (grub_errno) { @@ -866,10 +901,7 @@ grub_nilfs2_read_symlink (grub_fshelp_node_t node) static int grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { grub_off_t fpos = 0; struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; @@ -886,7 +918,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, { struct grub_nilfs2_dir_entry dirent; - grub_nilfs2_read_file (diro, 0, fpos, + grub_nilfs2_read_file (diro, 0, 0, fpos, sizeof (struct grub_nilfs2_dir_entry), (char *) &dirent); if (grub_errno) @@ -897,11 +929,11 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, if (dirent.name_len != 0) { - char filename[dirent.name_len + 1]; + char filename[MAX_NAMELEN + 1]; struct grub_fshelp_node *fdiro; enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN; - grub_nilfs2_read_file (diro, 0, + grub_nilfs2_read_file (diro, 0, 0, fpos + sizeof (struct grub_nilfs2_dir_entry), dirent.name_len, filename); if (grub_errno) @@ -953,7 +985,7 @@ grub_nilfs2_iterate_dir (grub_fshelp_node_t dir, type = GRUB_FSHELP_REG; } - if (hook (filename, type, fdiro)) + if (hook (filename, type, fdiro, hook_data)) return 1; } @@ -1024,64 +1056,74 @@ grub_nilfs2_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_nilfs2_data *data = (struct grub_nilfs2_data *) file->data; - return grub_nilfs2_read_file (&data->diropen, file->read_hook, + return grub_nilfs2_read_file (&data->diropen, + file->read_hook, file->read_hook_data, file->offset, len, buf); } +/* Context for grub_nilfs2_dir. */ +struct grub_nilfs2_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; + struct grub_nilfs2_data *data; +}; + +/* Helper for grub_nilfs2_dir. */ +static int +grub_nilfs2_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_nilfs2_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + if (!node->inode_read) + { + grub_nilfs2_read_inode (ctx->data, node->ino, &node->inode); + if (!grub_errno) + node->inode_read = 1; + grub_errno = GRUB_ERR_NONE; + } + if (node->inode_read) + { + info.mtimeset = 1; + info.mtime = grub_le_to_cpu64 (node->inode.i_mtime); + } + + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_nilfs2_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info * info)) + grub_fs_dir_hook_t hook, void *hook_data) { - struct grub_nilfs2_data *data = 0; + struct grub_nilfs2_dir_ctx ctx = { + .hook = hook, + .hook_data = hook_data + }; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - if (!node->inode_read) - { - grub_nilfs2_read_inode (data, node->ino, &node->inode); - if (!grub_errno) - node->inode_read = 1; - grub_errno = GRUB_ERR_NONE; - } - if (node->inode_read) - { - info.mtimeset = 1; - info.mtime = grub_le_to_cpu64 (node->inode.i_mtime); - } - - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); - data = grub_nilfs2_mount (device->disk); - if (!data) + ctx.data = grub_nilfs2_mount (device->disk); + if (!ctx.data) goto fail; - grub_fshelp_find_file (path, &data->diropen, &fdiro, + grub_fshelp_find_file (path, &ctx.data->diropen, &fdiro, grub_nilfs2_iterate_dir, grub_nilfs2_read_symlink, GRUB_FSHELP_DIR); if (grub_errno) goto fail; - grub_nilfs2_iterate_dir (fdiro, iterate); + grub_nilfs2_iterate_dir (fdiro, grub_nilfs2_dir_iter, &ctx); fail: - if (fdiro != &data->diropen) + if (fdiro != &ctx.data->diropen) grub_free (fdiro); - grub_free (data); + grub_free (ctx.data); grub_dl_unref (my_mod); @@ -1145,7 +1187,7 @@ grub_nilfs2_uuid (grub_device_t device, char **uuid) /* Get mtime. */ static grub_err_t -grub_nilfs2_mtime (grub_device_t device, grub_int32_t * tm) +grub_nilfs2_mtime (grub_device_t device, grub_int64_t * tm) { struct grub_nilfs2_data *data; grub_disk_t disk = device->disk; @@ -1169,13 +1211,13 @@ grub_nilfs2_mtime (grub_device_t device, grub_int32_t * tm) static struct grub_fs grub_nilfs2_fs = { .name = "nilfs2", - .dir = grub_nilfs2_dir, - .open = grub_nilfs2_open, - .read = grub_nilfs2_read, - .close = grub_nilfs2_close, - .label = grub_nilfs2_label, - .uuid = grub_nilfs2_uuid, - .mtime = grub_nilfs2_mtime, + .fs_dir = grub_nilfs2_dir, + .fs_open = grub_nilfs2_open, + .fs_read = grub_nilfs2_read, + .fs_close = grub_nilfs2_close, + .fs_label = grub_nilfs2_label, + .fs_uuid = grub_nilfs2_uuid, + .fs_mtime = grub_nilfs2_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 0, @@ -1190,11 +1232,16 @@ GRUB_MOD_INIT (nilfs2) grub_nilfs2_dat_entry)); COMPILE_TIME_ASSERT (1 << LOG_INODE_SIZE == sizeof (struct grub_nilfs2_inode)); - grub_fs_register (&grub_nilfs2_fs); + if (!grub_is_lockdown ()) + { + grub_nilfs2_fs.mod = mod; + grub_fs_register (&grub_nilfs2_fs); + } my_mod = mod; } GRUB_MOD_FINI (nilfs2) { - grub_fs_unregister (&grub_nilfs2_fs); + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_nilfs2_fs); } diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index b9762b6a0..b3117bf92 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -#define grub_fshelp_node grub_ntfs_file +#define grub_fshelp_node grub_ntfs_file #include #include @@ -27,12 +27,13 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); static grub_dl_t my_mod; -#define grub_fshelp_node grub_ntfs_file +#define grub_fshelp_node grub_ntfs_file static inline grub_uint16_t u16at (void *ptr, grub_size_t ofs) @@ -52,13 +53,195 @@ u64at (void *ptr, grub_size_t ofs) return grub_le_to_cpu64 (grub_get_unaligned64 ((char *) ptr + ofs)); } +static grub_uint16_t +first_attr_off (void *mft_buf_ptr) +{ + return u16at (mft_buf_ptr, 0x14); +} + +static grub_uint16_t +res_attr_data_off (void *res_attr_ptr) +{ + return u16at (res_attr_ptr, 0x14); +} + +static grub_uint32_t +res_attr_data_len (void *res_attr_ptr) +{ + return u32at (res_attr_ptr, 0x10); +} + +/* + * Check if the attribute is valid and doesn't exceed the allocated region. + * This accounts for resident and non-resident data. + * + * This is based off the documentation from the linux-ntfs project: + * https://flatcap.github.io/linux-ntfs/ntfs/concepts/attribute_header.html + */ +static bool +validate_attribute (grub_uint8_t *attr, void *end) +{ + grub_size_t attr_size = 0; + grub_size_t min_size = 0; + grub_size_t spare = (grub_uint8_t *) end - attr; + /* + * Just used as a temporary variable to try and deal with cases where someone + * tries to overlap fields. + */ + grub_size_t curr = 0; + + /* Need verify we can entirely read the attributes header. */ + if (attr + GRUB_NTFS_ATTRIBUTE_HEADER_SIZE >= (grub_uint8_t *) end) + goto fail; + + /* + * So, the rest of this code uses a 16bit int for the attribute length but + * from reading the all the documentation I could find it says this field is + * actually 32bit. But let's be consistent with the rest of the code. + * + * https://elixir.bootlin.com/linux/v6.10.7/source/fs/ntfs3/ntfs.h#L370 + */ + attr_size = u16at (attr, GRUB_NTFS_ATTRIBUTE_LENGTH); + + if (attr_size > spare) + goto fail; + + /* Not an error case, just reached the end of the attributes. */ + if (attr_size == 0) + return false; + + /* + * Extra validation by trying to calculate a minimum possible size for this + * attribute. +8 from the size of the resident data struct which is the + * minimum that can be added. + */ + min_size = GRUB_NTFS_ATTRIBUTE_HEADER_SIZE + 8; + + if (min_size > attr_size) + goto fail; + + /* Is the data is resident (0) or not (1). */ + if (attr[GRUB_NTFS_ATTRIBUTE_RESIDENT] == 0) + { + /* Read the offset and size of the attribute. */ + curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_RES_OFFSET); + curr += u32at (attr, GRUB_NTFS_ATTRIBUTE_RES_LENGTH); + if (curr > min_size) + min_size = curr; + } + else + { + /* + * If the data is non-resident, the minimum size is 64 which is where + * the data runs start. We already have a minimum size of 24. So, just + * adding 40 to get to the real value. + */ + min_size += 40; + if (min_size > attr_size) + goto fail; + /* If the compression unit size is > 0, +8 bytes*/ + if (u16at (attr, GRUB_NTFS_ATTRIBUTE_COMPRESSION_UNIT_SIZE) > 0) + min_size += 8; + + /* + * Need to consider the data runs now. Each member of the run has byte + * that describes the size of the data length and offset. Each being + * 4 bits in the byte. + */ + curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_DATA_RUNS); + + if (curr + 1 > min_size) + min_size = curr + 1; + + if (min_size > attr_size) + goto fail; + + /* + * Each attribute can store multiple data runs which are stored + * continuously in the attribute. They exist as one header byte + * with up to 14 bytes following it depending on the lengths. + * We stop when we hit a header that is just a NUL byte. + * + * https://flatcap.github.io/linux-ntfs/ntfs/concepts/data_runs.html + */ + while (attr[curr] != 0) + { + /* + * We stop when we hit a header that is just a NUL byte. The data + * run header is stored as a single byte where the top 4 bits refer + * to the number of bytes used to store the total length of the + * data run, and the number of bytes used to store the offset. + * These directly follow the header byte, so we use them to update + * the minimum size. + */ + min_size += (attr[curr] & 0x7) + ((attr[curr] >> 4) & 0x7); + curr += min_size; + min_size++; + if (min_size > attr_size) + goto fail; + } + } + + /* Name offset, doing this after data residence checks. */ + if (u16at (attr, GRUB_NTFS_ATTRIBUTE_NAME_OFFSET) != 0) + { + curr = u16at (attr, GRUB_NTFS_ATTRIBUTE_NAME_OFFSET); + /* + * Multiple the name length by 2 as its UTF-16. Can be zero if this in an + * unamed attribute. + */ + curr += attr[GRUB_NTFS_ATTRIBUTE_NAME_LENGTH] * 2; + if (curr > min_size) + min_size = curr; + } + + /* Padded to 8 bytes. */ + if (min_size % 8 != 0) + min_size += 8 - (min_size % 8); + + /* + * At this point min_size should be exactly attr_size but being flexible + * here to avoid any issues. + */ + if (min_size > attr_size) + goto fail; + + return true; + + fail: + grub_dprintf ("ntfs", "spare=%" PRIuGRUB_SIZE " min_size=%" PRIuGRUB_SIZE " attr_size=%" PRIuGRUB_SIZE "\n", + spare, min_size, attr_size); + return false; +} + +/* Return the next attribute if it exists, otherwise return NULL. */ +static grub_uint8_t * +next_attribute (grub_uint8_t *curr_attribute, void *end) +{ + grub_uint8_t *next = curr_attribute; + + /* + * Need to verify we aren't exceeding the end of the buffer by reading the + * header for the current attribute + */ + if (curr_attribute + GRUB_NTFS_ATTRIBUTE_HEADER_SIZE >= (grub_uint8_t *) end) + return NULL; + + next += u16at (curr_attribute, 4); + if (validate_attribute (next, end) == false) + return NULL; + + return next; +} + + grub_ntfscomp_func_t grub_ntfscomp_func; static grub_err_t -fixup (char *buf, int len, const char *magic) +fixup (grub_uint8_t *buf, grub_size_t len, const grub_uint8_t *magic) { - int ss; - char *pu; + grub_uint16_t ss; + grub_uint8_t *pu; grub_uint16_t us; COMPILE_TIME_ASSERT ((1 << GRUB_NTFS_BLK_SHR) == GRUB_DISK_SECTOR_SIZE); @@ -86,33 +269,35 @@ fixup (char *buf, int len, const char *magic) return 0; } -static grub_err_t read_mft (struct grub_ntfs_data *data, char *buf, - grub_uint32_t mftno); -static grub_err_t read_attr (struct grub_ntfs_attr *at, char *dest, +static grub_err_t read_mft (struct grub_ntfs_data *data, grub_uint8_t *buf, + grub_uint64_t mftno); +static grub_err_t read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs, grub_size_t len, int cached, - void - NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t - sector, - unsigned offset, - unsigned length)); + grub_disk_read_hook_t read_hook, + void *read_hook_data); -static grub_err_t read_data (struct grub_ntfs_attr *at, char *pa, char *dest, +static grub_err_t read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, + grub_uint8_t *dest, grub_disk_addr_t ofs, grub_size_t len, int cached, - void - NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t - sector, - unsigned offset, - unsigned length)); + grub_disk_read_hook_t read_hook, + void *read_hook_data); -static void +static grub_err_t init_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft) { at->mft = mft; at->flags = (mft == &mft->data->mmft) ? GRUB_NTFS_AF_MMFT : 0; - at->attr_nxt = mft->buf + u16at (mft->buf, 0x14); + at->attr_nxt = mft->buf + first_attr_off (mft->buf); + at->end = mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR); + + if (at->attr_nxt > at->end) + return grub_error (GRUB_ERR_BAD_FS, "attributes start outside the MFT"); + at->attr_end = at->emft_buf = at->edat_buf = at->sbuf = NULL; + + return GRUB_ERR_NONE; } static void @@ -123,19 +308,21 @@ free_attr (struct grub_ntfs_attr *at) grub_free (at->sbuf); } -static char * -find_attr (struct grub_ntfs_attr *at, unsigned char attr) +static grub_uint8_t * +find_attr (struct grub_ntfs_attr *at, grub_uint8_t attr) { + grub_uint8_t *mft_end; + if (at->flags & GRUB_NTFS_AF_ALST) { retry: - while (at->attr_nxt < at->attr_end) + while (at->attr_nxt) { at->attr_cur = at->attr_nxt; - at->attr_nxt += u16at (at->attr_cur, 4); - if (((unsigned char) *at->attr_cur == attr) || (attr == 0)) + at->attr_nxt = next_attribute (at->attr_cur, at->attr_end); + if ((*at->attr_cur == attr) || (attr == 0)) { - char *new_pos; + grub_uint8_t *new_pos, *end; if (at->flags & GRUB_NTFS_AF_MMFT) { @@ -148,7 +335,8 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) 512, at->emft_buf + 512))) return NULL; - if (fixup (at->emft_buf, at->mft->data->mft_size, "FILE")) + if (fixup (at->emft_buf, at->mft->data->mft_size, + (const grub_uint8_t *) "FILE")) return NULL; } else @@ -158,16 +346,36 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) return NULL; } - new_pos = &at->emft_buf[u16at (at->emft_buf, 0x14)]; - while ((unsigned char) *new_pos != 0xFF) + /* + * Only time emft_bufs is defined is in this function, with this + * size. + */ + grub_size_t emft_buf_size = + at->mft->data->mft_size << GRUB_NTFS_BLK_SHR; + + /* + * Needs to be enough space for the successful case to even + * bother. + */ + if (first_attr_off (at->emft_buf) >= (emft_buf_size - 0x18 - 2)) { - if (((unsigned char) *new_pos == - (unsigned char) *at->attr_cur) + grub_error (GRUB_ERR_BAD_FS, + "can\'t find 0x%X in attribute list", + (unsigned char) *at->attr_cur); + return NULL; + } + + new_pos = &at->emft_buf[first_attr_off (at->emft_buf)]; + end = &at->emft_buf[emft_buf_size]; + + while (new_pos && *new_pos != 0xFF) + { + if ((*new_pos == *at->attr_cur) && (u16at (new_pos, 0xE) == u16at (at->attr_cur, 0x18))) { return new_pos; } - new_pos += u16at (new_pos, 4); + new_pos = next_attribute (new_pos, end); } grub_error (GRUB_ERR_BAD_FS, "can\'t find 0x%X in attribute list", @@ -178,18 +386,19 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) return NULL; } at->attr_cur = at->attr_nxt; - while ((unsigned char) *at->attr_cur != 0xFF) + mft_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR); + while (at->attr_cur >= at->mft->buf && at->attr_cur < mft_end && *at->attr_cur != 0xFF) { - at->attr_nxt += u16at (at->attr_cur, 4); - if ((unsigned char) *at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST) + at->attr_nxt = next_attribute (at->attr_cur, at->end); + if (*at->attr_cur == GRUB_NTFS_AT_ATTRIBUTE_LIST) at->attr_end = at->attr_cur; - if (((unsigned char) *at->attr_cur == attr) || (attr == 0)) + if ((*at->attr_cur == attr) || (attr == 0)) return at->attr_cur; at->attr_cur = at->attr_nxt; } if (at->attr_end) { - char *pa; + grub_uint8_t *pa, *pa_end; at->emft_buf = grub_malloc (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR); if (at->emft_buf == NULL) @@ -198,7 +407,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) pa = at->attr_end; if (pa[8]) { - int n; + grub_uint32_t n; n = ((u32at (pa, 0x30) + GRUB_DISK_SECTOR_SIZE - 1) & (~(GRUB_DISK_SECTOR_SIZE - 1))); @@ -206,7 +415,7 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) at->edat_buf = grub_malloc (n); if (!at->edat_buf) return NULL; - if (read_data (at, pa, at->edat_buf, 0, n, 0, 0)) + if (read_data (at, pa, at->edat_buf, 0, n, 0, 0, 0)) { grub_error (GRUB_ERR_BAD_FS, "fail to read non-resident attribute list"); @@ -214,20 +423,30 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) } at->attr_nxt = at->edat_buf; at->attr_end = at->edat_buf + u32at (pa, 0x30); + pa_end = at->edat_buf + n; } else { - at->attr_nxt = at->attr_end + u16at (pa, 0x14); + at->attr_nxt = at->attr_end + res_attr_data_off (pa); at->attr_end = at->attr_end + u32at (pa, 4); + pa_end = at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR); } at->flags |= GRUB_NTFS_AF_ALST; - while (at->attr_nxt < at->attr_end) + + /* From this point on pa_end is the end of the buffer */ + at->end = pa_end; + + if (validate_attribute (at->attr_nxt, pa_end) == false) + return NULL; + + while (at->attr_nxt) { - if (((unsigned char) *at->attr_nxt == attr) || (attr == 0)) + if ((*at->attr_nxt == attr) || (attr == 0)) break; - at->attr_nxt += u16at (at->attr_nxt, 4); + at->attr_nxt = next_attribute (at->attr_nxt, pa_end); } - if (at->attr_nxt >= at->attr_end) + + if (at->attr_nxt >= at->attr_end || at->attr_nxt == NULL) return NULL; if ((at->flags & GRUB_NTFS_AF_MMFT) && (attr == GRUB_NTFS_AT_DATA)) @@ -235,22 +454,40 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) at->flags |= GRUB_NTFS_AF_GPOS; at->attr_cur = at->attr_nxt; pa = at->attr_cur; + + if ((pa >= pa_end) || (pa_end - pa < 0x18)) + { + grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list"); + return NULL; + } + grub_set_unaligned32 ((char *) pa + 0x10, grub_cpu_to_le32 (at->mft->data->mft_start)); grub_set_unaligned32 ((char *) pa + 0x14, grub_cpu_to_le32 (at->mft->data->mft_start + 1)); pa = at->attr_nxt + u16at (pa, 4); - while (pa < at->attr_end) + + if (validate_attribute (pa, pa_end) == true) + pa = NULL; + + while (pa) { - if ((unsigned char) *pa != attr) + if (*pa != attr) break; + + if ((pa >= pa_end) || (pa_end - pa < 0x18)) + { + grub_error (GRUB_ERR_BAD_FS, "can\'t parse attribute list"); + return NULL; + } + if (read_attr (at, pa + 0x10, u32at (pa, 0x10) * (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR), - at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0)) + at->mft->data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0)) return NULL; - pa += u16at (pa, 4); + pa = next_attribute (pa, pa_end); } at->attr_nxt = at->attr_cur; at->flags &= ~GRUB_NTFS_AF_GPOS; @@ -260,13 +497,15 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) return NULL; } -static char * +static grub_uint8_t * locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft, - unsigned char attr) + grub_uint8_t attr) { - char *pa; + grub_uint8_t *pa; + + if (init_attr (at, mft) != GRUB_ERR_NONE) + return NULL; - init_attr (at, mft); pa = find_attr (at, attr); if (pa == NULL) return NULL; @@ -282,55 +521,47 @@ locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft, } grub_errno = GRUB_ERR_NONE; free_attr (at); - init_attr (at, mft); + if (init_attr (at, mft) != GRUB_ERR_NONE) + return NULL; pa = find_attr (at, attr); } return pa; } -static char * -read_run_data (char *run, int nn, grub_disk_addr_t * val, int sig) +static grub_disk_addr_t +read_run_data (const grub_uint8_t *run, int nn, int sig) { - grub_disk_addr_t r, v; + grub_uint64_t r = 0; - r = 0; - v = 1; + if (sig && nn && (run[nn - 1] & 0x80)) + r = -1; - while (nn--) - { - r += v * (*(unsigned char *) (run++)); - v <<= 8; - } + grub_memcpy (&r, run, nn); - if ((sig) && (r & (v >> 1))) - r -= v; - - *val = r; - return run; + return grub_le_to_cpu64 (r); } grub_err_t grub_ntfs_read_run_list (struct grub_ntfs_rlst * ctx) { - int c1, c2; + grub_uint8_t c1, c2; grub_disk_addr_t val; - char *run; + grub_uint8_t *run; run = ctx->cur_run; retry: - c1 = ((unsigned char) (*run) & 0xF); - c2 = ((unsigned char) (*run) >> 4); + c1 = ((*run) & 0x7); + c2 = ((*run) >> 4) & 0x7; + run++; if (!c1) { if ((ctx->attr) && (ctx->attr->flags & GRUB_NTFS_AF_ALST)) { - void NESTED_FUNC_ATTR (*save_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length); + grub_disk_read_hook_t save_hook; save_hook = ctx->comp.disk->read_hook; ctx->comp.disk->read_hook = 0; - run = find_attr (ctx->attr, (unsigned char) *ctx->attr->attr_cur); + run = find_attr (ctx->attr, *ctx->attr->attr_cur); ctx->comp.disk->read_hook = save_hook; if (run) { @@ -343,12 +574,13 @@ retry: goto retry; } } - return grub_error (GRUB_ERR_BAD_FS, "run list overflown"); + return grub_error (GRUB_ERR_BAD_FS, "run list overflow"); } - run = read_run_data (run + 1, c1, &val, 0); /* length of current VCN */ ctx->curr_vcn = ctx->next_vcn; - ctx->next_vcn += val; - run = read_run_data (run, c2, &val, 1); /* offset to previous LCN */ + ctx->next_vcn += read_run_data (run, c1, 0); /* length of current VCN */ + run += c1; + val = read_run_data (run, c2, 1); /* offset to previous LCN */ + run += c2; ctx->curr_lcn += val; if (val == 0) ctx->flags |= GRUB_NTFS_RF_BLNK; @@ -376,13 +608,10 @@ grub_ntfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t block) } static grub_err_t -read_data (struct grub_ntfs_attr *at, char *pa, char *dest, +read_data (struct grub_ntfs_attr *at, grub_uint8_t *pa, grub_uint8_t *dest, grub_disk_addr_t ofs, grub_size_t len, int cached, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length)) + grub_disk_read_hook_t read_hook, void *read_hook_data) { - grub_disk_addr_t vcn; struct grub_ntfs_rlst cc, *ctx; if (len == 0) @@ -391,63 +620,48 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, grub_memset (&cc, 0, sizeof (cc)); ctx = &cc; ctx->attr = at; - ctx->comp.spc = at->mft->data->spc; + ctx->comp.log_spc = at->mft->data->log_spc; ctx->comp.disk = at->mft->data->disk; + if (read_hook == grub_file_progress_hook) + ctx->file = read_hook_data; + if (pa[8] == 0) { - if (ofs + len > u32at (pa, 0x10)) + if (ofs + len > res_attr_data_len (pa)) return grub_error (GRUB_ERR_BAD_FS, "read out of range"); - grub_memcpy (dest, pa + u32at (pa, 0x14) + ofs, len); + + if (res_attr_data_len (pa) > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR)) + return grub_error (GRUB_ERR_BAD_FS, "resident attribute too large"); + + if (pa >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR)) + return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range"); + + if (res_attr_data_off (pa) + res_attr_data_len (pa) > + (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) pa) + return grub_error (GRUB_ERR_BAD_FS, "resident attribute out of range"); + + grub_memcpy (dest, pa + res_attr_data_off (pa) + ofs, len); return 0; } - if (u16at (pa, 0xC) & GRUB_NTFS_FLAG_COMPRESSED) - ctx->flags |= GRUB_NTFS_RF_COMP; - else - ctx->flags &= ~GRUB_NTFS_RF_COMP; ctx->cur_run = pa + u16at (pa, 0x20); - if (ctx->flags & GRUB_NTFS_RF_COMP) + ctx->next_vcn = u32at (pa, 0x10); + ctx->curr_lcn = 0; + + if ((pa[0xC] & GRUB_NTFS_FLAG_COMPRESSED) + && !(at->flags & GRUB_NTFS_AF_GPOS)) { if (!cached) return grub_error (GRUB_ERR_BAD_FS, "attribute can\'t be compressed"); - if (at->sbuf) - { - if ((ofs & (~(GRUB_NTFS_COM_LEN - 1))) == at->save_pos) - { - grub_disk_addr_t n; - - n = GRUB_NTFS_COM_LEN - (ofs - at->save_pos); - if (n > len) - n = len; - - grub_memcpy (dest, at->sbuf + ofs - at->save_pos, n); - if (n == len) - return 0; - - dest += n; - len -= n; - ofs += n; - } - } - else - { - at->sbuf = grub_malloc (GRUB_NTFS_COM_LEN); - if (at->sbuf == NULL) - return grub_errno; - at->save_pos = 1; - } - - vcn = ctx->target_vcn = (ofs >> GRUB_NTFS_COM_LOG_LEN) * (GRUB_NTFS_COM_SEC / ctx->comp.spc); - ctx->target_vcn &= ~0xFULL; + return (grub_ntfscomp_func) ? grub_ntfscomp_func (dest, ofs, len, ctx) + : grub_error (GRUB_ERR_BAD_FS, N_("module `%s' isn't loaded"), + "ntfscomp"); } - else - vcn = ctx->target_vcn = grub_divmod64 (ofs >> GRUB_NTFS_BLK_SHR, ctx->comp.spc, 0); - ctx->next_vcn = u32at (pa, 0x10); - ctx->curr_lcn = 0; + ctx->target_vcn = ofs >> (GRUB_NTFS_BLK_SHR + ctx->comp.log_spc); while (ctx->next_vcn <= ctx->target_vcn) { if (grub_ntfs_read_run_list (ctx)) @@ -459,81 +673,74 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, grub_disk_addr_t st0, st1; grub_uint64_t m; - grub_divmod64 (ofs >> GRUB_NTFS_BLK_SHR, ctx->comp.spc, &m); + m = (ofs >> GRUB_NTFS_BLK_SHR) & ((1 << ctx->comp.log_spc) - 1); st0 = - (ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc + m; + ((ctx->target_vcn - ctx->curr_vcn + ctx->curr_lcn) << ctx->comp.log_spc) + m; st1 = st0 + 1; if (st1 == - (ctx->next_vcn - ctx->curr_vcn + ctx->curr_lcn) * ctx->comp.spc) + (ctx->next_vcn - ctx->curr_vcn + ctx->curr_lcn) << ctx->comp.log_spc) { if (grub_ntfs_read_run_list (ctx)) return grub_errno; - st1 = ctx->curr_lcn * ctx->comp.spc; + st1 = ctx->curr_lcn << ctx->comp.log_spc; } grub_set_unaligned32 (dest, grub_cpu_to_le32 (st0)); grub_set_unaligned32 (dest + 4, grub_cpu_to_le32 (st1)); return 0; } - if (!(ctx->flags & GRUB_NTFS_RF_COMP)) - { - unsigned int pow; - - if (!grub_fshelp_log2blksize (ctx->comp.spc, &pow)) - grub_fshelp_read_file (ctx->comp.disk, (grub_fshelp_node_t) ctx, - read_hook, ofs, len, dest, - grub_ntfs_read_block, ofs + len, pow, 0); - return grub_errno; - } - - return (grub_ntfscomp_func) ? grub_ntfscomp_func (at, dest, ofs, len, ctx, - vcn) : - grub_error (GRUB_ERR_BAD_FS, N_("module `%s' isn't loaded"), - "ntfscomp"); + grub_fshelp_read_file (ctx->comp.disk, (grub_fshelp_node_t) ctx, + read_hook, read_hook_data, ofs, len, + (char *) dest, + grub_ntfs_read_block, ofs + len, + ctx->comp.log_spc, 0); + return grub_errno; } static grub_err_t -read_attr (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, +read_attr (struct grub_ntfs_attr *at, grub_uint8_t *dest, grub_disk_addr_t ofs, grub_size_t len, int cached, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length)) + grub_disk_read_hook_t read_hook, void *read_hook_data) { - char *save_cur; - unsigned char attr; - char *pp; + grub_uint8_t *save_cur; + grub_uint8_t attr; + grub_uint8_t *pp; grub_err_t ret; save_cur = at->attr_cur; at->attr_nxt = at->attr_cur; - attr = (unsigned char) *at->attr_nxt; + attr = *at->attr_nxt; if (at->flags & GRUB_NTFS_AF_ALST) { - char *pa; + grub_uint8_t *pa; grub_disk_addr_t vcn; /* If compression is possible make sure that we include possible compressed block size. */ - if (GRUB_NTFS_COM_SEC >= at->mft->data->spc) + if (GRUB_NTFS_LOG_COM_SEC >= at->mft->data->log_spc) vcn = ((ofs >> GRUB_NTFS_COM_LOG_LEN) - * (GRUB_NTFS_COM_SEC / at->mft->data->spc)) & ~0xFULL; + << (GRUB_NTFS_LOG_COM_SEC - at->mft->data->log_spc)) & ~0xFULL; else - vcn = grub_divmod64 (ofs, at->mft->data->spc << GRUB_NTFS_BLK_SHR, 0); + vcn = ofs >> (at->mft->data->log_spc + GRUB_NTFS_BLK_SHR); pa = at->attr_nxt + u16at (at->attr_nxt, 4); - while (pa < at->attr_end) + if (validate_attribute (pa, at->attr_end) == false) + pa = NULL; + + while (pa) { - if ((unsigned char) *pa != attr) + if (*pa != attr) break; if (u32at (pa, 8) > vcn) break; at->attr_nxt = pa; - pa += u16at (pa, 4); + pa = next_attribute (pa, at->attr_end); } } pp = find_attr (at, attr); if (pp) - ret = read_data (at, pp, dest, ofs, len, cached, read_hook); + ret = read_data (at, pp, dest, ofs, len, cached, + read_hook, read_hook_data); else ret = (grub_errno) ? grub_errno : grub_error (GRUB_ERR_BAD_FS, @@ -543,17 +750,17 @@ read_attr (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, } static grub_err_t -read_mft (struct grub_ntfs_data *data, char *buf, grub_uint32_t mftno) +read_mft (struct grub_ntfs_data *data, grub_uint8_t *buf, grub_uint64_t mftno) { if (read_attr (&data->mmft.attr, buf, mftno * ((grub_disk_addr_t) data->mft_size << GRUB_NTFS_BLK_SHR), - data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0)) - return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%X fails", mftno); - return fixup (buf, data->mft_size, "FILE"); + data->mft_size << GRUB_NTFS_BLK_SHR, 0, 0, 0)) + return grub_error (GRUB_ERR_BAD_FS, "read MFT 0x%llx fails", (unsigned long long) mftno); + return fixup (buf, data->mft_size, (const grub_uint8_t *) "FILE"); } static grub_err_t -init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno) +init_file (struct grub_ntfs_file *mft, grub_uint64_t mftno) { unsigned short flag; @@ -568,18 +775,20 @@ init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno) flag = u16at (mft->buf, 0x16); if ((flag & 1) == 0) - return grub_error (GRUB_ERR_BAD_FS, "MFT 0x%X is not in use", mftno); + return grub_error (GRUB_ERR_BAD_FS, "MFT 0x%llx is not in use", + (unsigned long long) mftno); if ((flag & 2) == 0) { - char *pa; + grub_uint8_t *pa; pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_DATA); if (pa == NULL) - return grub_error (GRUB_ERR_BAD_FS, "no $DATA in MFT 0x%X", mftno); + return grub_error (GRUB_ERR_BAD_FS, "no $DATA in MFT 0x%llx", + (unsigned long long) mftno); if (!pa[8]) - mft->size = u32at (pa, 0x10); + mft->size = res_attr_data_len (pa); else mft->size = u64at (pa, 0x30); @@ -587,7 +796,7 @@ init_file (struct grub_ntfs_file *mft, grub_uint32_t mftno) mft->attr.attr_end = 0; /* Don't jump to attribute list */ } else - init_attr (&mft->attr, mft); + return init_attr (&mft->attr, mft); return 0; } @@ -599,27 +808,53 @@ free_file (struct grub_ntfs_file *mft) grub_free (mft->buf); } -static int -list_file (struct grub_ntfs_file *diro, char *pos, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) +static char * +get_utf8 (grub_uint8_t *in, grub_size_t len) { - char *np; + grub_uint8_t *buf; + grub_uint16_t *tmp; + grub_size_t i; + + buf = grub_calloc (len, GRUB_MAX_UTF8_PER_UTF16 + 1); + tmp = grub_calloc (len, sizeof (tmp[0])); + if (!buf || !tmp) + { + grub_free (buf); + grub_free (tmp); + return NULL; + } + for (i = 0; i < len; i++) + tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 (in + 2 * i)); + *grub_utf16_to_utf8 (buf, tmp, len) = '\0'; + grub_free (tmp); + return (char *) buf; +} + +static int +list_file (struct grub_ntfs_file *diro, grub_uint8_t *pos, grub_uint8_t *end_pos, + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) +{ + grub_uint8_t *np; int ns; while (1) { - char *ustr, namespace; + grub_uint8_t namespace; + char *ustr; + + if ((pos >= end_pos) || (end_pos - pos < 0x52)) + break; if (pos[0xC] & 2) /* end signature */ break; np = pos + 0x50; - ns = (unsigned char) *(np++); + ns = *(np++); namespace = *(np++); + if (2 * ns > end_pos - pos - 0x52) + break; + /* * Ignore files in DOS namespace, as they will reappear as Win32 * names. @@ -630,12 +865,6 @@ list_file (struct grub_ntfs_file *diro, char *pos, struct grub_ntfs_file *fdiro; grub_uint32_t attr; - if (u16at (pos, 4)) - { - grub_error (GRUB_ERR_BAD_FS, "64-bit MFT number"); - return 0; - } - attr = u32at (pos, 0x48); if (attr & GRUB_NTFS_ATTR_REPARSE) type = GRUB_FSHELP_SYMLINK; @@ -649,25 +878,19 @@ list_file (struct grub_ntfs_file *diro, char *pos, return 0; fdiro->data = diro->data; - fdiro->ino = u32at (pos, 0); + fdiro->ino = u64at (pos, 0) & 0xffffffffffffULL; fdiro->mtime = u64at (pos, 0x20); - ustr = grub_malloc (ns * GRUB_MAX_UTF8_PER_UTF16 + 1); + ustr = get_utf8 (np, ns); if (ustr == NULL) - return 0; - { - grub_uint16_t tmp[ns]; - int i; - for (i = 0; i < ns; i++) - tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 ((char *) np - + 2 * i)); - - *grub_utf16_to_utf8 ((grub_uint8_t *) ustr, tmp, ns) = '\0'; - } + { + grub_free (fdiro); + return 0; + } if (namespace) type |= GRUB_FSHELP_CASE_INSENSITIVE; - if (hook (ustr, type, fdiro)) + if (hook (ustr, type, fdiro, hook_data)) { grub_free (ustr); return 1; @@ -688,7 +911,7 @@ struct symlink_descriptor grub_uint16_t len1; grub_uint16_t off2; grub_uint16_t len2; -} __attribute__ ((packed)); +} GRUB_PACKED; static char * grub_ntfs_read_symlink (grub_fshelp_node_t node) @@ -696,11 +919,10 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) struct grub_ntfs_file *mft; struct symlink_descriptor symdesc; grub_err_t err; - grub_uint16_t *buf16; + grub_uint8_t *buf16 = NULL; char *buf, *end; grub_size_t len; - grub_size_t i; - char *pa; + grub_uint8_t *pa; grub_size_t off; mft = (struct grub_ntfs_file *) node; @@ -710,19 +932,20 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) return NULL; if (read_mft (mft->data, mft->buf, mft->ino)) - return NULL; + goto fail; pa = locate_attr (&mft->attr, mft, GRUB_NTFS_AT_SYMLINK); if (pa == NULL) { - grub_error (GRUB_ERR_BAD_FS, "no $SYMLINK in MFT 0x%X", mft->ino); - return NULL; + grub_error (GRUB_ERR_BAD_FS, "no $SYMLINK in MFT 0x%llx", + (unsigned long long) mft->ino); + goto fail; } - err = read_attr (&mft->attr, (char *) &symdesc, 0, - sizeof (struct symlink_descriptor), 1, 0); + err = read_attr (&mft->attr, (grub_uint8_t *) &symdesc, 0, + sizeof (struct symlink_descriptor), 1, 0, 0); if (err) - return NULL; + goto fail; switch (grub_cpu_to_le32 (symdesc.type)) { @@ -739,53 +962,50 @@ grub_ntfs_read_symlink (grub_fshelp_node_t node) default: grub_error (GRUB_ERR_BAD_FS, "symlink type invalid (%x)", grub_cpu_to_le32 (symdesc.type)); - return NULL; + goto fail; } buf16 = grub_malloc (len); if (!buf16) - return NULL; + goto fail; - err = read_attr (&mft->attr, (char *) buf16, off, len, 1, 0); + err = read_attr (&mft->attr, buf16, off, len, 1, 0, 0); if (err) - return NULL; + goto fail; - buf = grub_malloc (len * 2 + 1); + buf = get_utf8 (buf16, len / 2); if (!buf) - { - grub_free (buf16); - return NULL; - } + goto fail; - for (i = 0; i < len / 2; i++) - { - buf16[i] = grub_le_to_cpu16 (buf16[i]); - if (buf16[i] == '\\') - buf16[i] = '/'; - } + grub_free (mft->buf); + grub_free (buf16); + + for (end = buf; *end; end++) + if (*end == '\\') + *end = '/'; - end = (char *) grub_utf16_to_utf8 ((grub_uint8_t *) buf, buf16, len / 2); - *end = '\0'; /* Split the sequence to avoid GCC thinking that this is a trigraph. */ if (grub_memcmp (buf, "/?" "?/", 4) == 0 && buf[5] == ':' && buf[6] == '/' && grub_isalpha (buf[4])) { grub_memmove (buf, buf + 6, end - buf + 1 - 6); - end -= 6; + end -= 6; } return buf; + + fail: + grub_free (mft->buf); + grub_free (buf16); + return NULL; } static int grub_ntfs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { - unsigned char *bitmap; + grub_uint8_t *bitmap; struct grub_ntfs_attr attr, *at; - char *cur_pos, *indx, *bmp; + grub_uint8_t *cur_pos, *indx, *bmp; int ret = 0; grub_size_t bitmap_len; struct grub_ntfs_file *mft; @@ -802,7 +1022,9 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, bmp = NULL; at = &attr; - init_attr (at, mft); + if (init_attr (at, mft) != GRUB_ERR_NONE) + return 0; + while (1) { cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ROOT); @@ -817,26 +1039,30 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, (u32at (cur_pos, 0x18) != 0x490024) || (u32at (cur_pos, 0x1C) != 0x300033)) continue; - cur_pos += u16at (cur_pos, 0x14); + cur_pos += res_attr_data_off (cur_pos); if (*cur_pos != 0x30) /* Not filename index */ continue; break; } cur_pos += 0x10; /* Skip index root */ - ret = list_file (mft, cur_pos + u16at (cur_pos, 0), hook); + ret = list_file (mft, cur_pos + u16at (cur_pos, 0), + at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR), + hook, hook_data); if (ret) goto done; bitmap = NULL; bitmap_len = 0; free_attr (at); + /* No need to check errors here, as it will already be fine */ init_attr (at, mft); + while ((cur_pos = find_attr (at, GRUB_NTFS_AT_BITMAP)) != NULL) { int ofs; - ofs = (unsigned char) cur_pos[0xA]; + ofs = cur_pos[0xA]; /* Namelen=4, Name="$I30" */ if ((cur_pos[9] == 4) && (u32at (cur_pos, ofs) == 0x490024) && @@ -844,7 +1070,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, { int is_resident = (cur_pos[8] == 0); - bitmap_len = ((is_resident) ? u32at (cur_pos, 0x10) : + bitmap_len = ((is_resident) ? res_attr_data_len (cur_pos) : u32at (cur_pos, 0x28)); bmp = grub_malloc (bitmap_len); @@ -853,12 +1079,31 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, if (is_resident) { - grub_memcpy (bmp, (char *) (cur_pos + u16at (cur_pos, 0x14)), + if (bitmap_len > (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR)) + { + grub_error (GRUB_ERR_BAD_FS, "resident bitmap too large"); + goto done; + } + + if (cur_pos >= at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR)) + { + grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range"); + goto done; + } + + if (res_attr_data_off (cur_pos) + res_attr_data_len (cur_pos) > + (grub_addr_t) at->mft->buf + (at->mft->data->mft_size << GRUB_NTFS_BLK_SHR) - (grub_addr_t) cur_pos) + { + grub_error (GRUB_ERR_BAD_FS, "resident bitmap out of range"); + goto done; + } + + grub_memcpy (bmp, cur_pos + res_attr_data_off (cur_pos), bitmap_len); } else { - if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0)) + if (read_data (at, cur_pos, bmp, 0, bitmap_len, 0, 0, 0)) { grub_error (GRUB_ERR_BAD_FS, "fails to read non-resident $BITMAP"); @@ -867,7 +1112,7 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, bitmap_len = u32at (cur_pos, 0x30); } - bitmap = (unsigned char *) bmp; + bitmap = bmp; break; } } @@ -892,7 +1137,8 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, if (bitmap) { - grub_disk_addr_t v, i; + grub_disk_addr_t i; + grub_uint8_t v; indx = grub_malloc (mft->data->idx_size << GRUB_NTFS_BLK_SHR); if (indx == NULL) @@ -905,15 +1151,18 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, { if ((read_attr (at, indx, i * (mft->data->idx_size << GRUB_NTFS_BLK_SHR), - (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0)) - || (fixup (indx, mft->data->idx_size, "INDX"))) + (mft->data->idx_size << GRUB_NTFS_BLK_SHR), 0, 0, 0)) + || (fixup (indx, mft->data->idx_size, + (const grub_uint8_t *) "INDX"))) goto done; - ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], hook); + ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], + indx + (mft->data->idx_size << GRUB_NTFS_BLK_SHR), + hook, hook_data); if (ret) goto done; } v <<= 1; - if (v >= 0x100) + if (!v) { v = 1; bitmap++; @@ -934,6 +1183,7 @@ grub_ntfs_mount (grub_disk_t disk) { struct grub_ntfs_bpb bpb; struct grub_ntfs_data *data = 0; + grub_uint32_t spc; if (!disk) goto fail; @@ -955,23 +1205,30 @@ grub_ntfs_mount (grub_disk_t disk) || (bpb.bytes_per_sector & (bpb.bytes_per_sector - 1)) != 0) goto fail; - data->spc = (((grub_uint32_t) bpb.sectors_per_cluster - * (grub_uint32_t) grub_le_to_cpu16 (bpb.bytes_per_sector)) - >> GRUB_NTFS_BLK_SHR); - if (!data->spc) + spc = (((grub_uint32_t) bpb.sectors_per_cluster + * (grub_uint32_t) grub_le_to_cpu16 (bpb.bytes_per_sector)) + >> GRUB_NTFS_BLK_SHR); + if (spc == 0) goto fail; + for (data->log_spc = 0; (1U << data->log_spc) < spc; data->log_spc++); + if (bpb.clusters_per_mft > 0) - data->mft_size = data->spc * bpb.clusters_per_mft; + data->mft_size = ((grub_disk_addr_t) bpb.clusters_per_mft) << data->log_spc; + else if (-bpb.clusters_per_mft < GRUB_NTFS_BLK_SHR || -bpb.clusters_per_mft >= 31) + goto fail; else - data->mft_size = 1 << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR); + data->mft_size = 1ULL << (-bpb.clusters_per_mft - GRUB_NTFS_BLK_SHR); if (bpb.clusters_per_index > 0) - data->idx_size = data->spc * bpb.clusters_per_index; + data->idx_size = (((grub_disk_addr_t) bpb.clusters_per_index) + << data->log_spc); + else if (-bpb.clusters_per_index < GRUB_NTFS_BLK_SHR || -bpb.clusters_per_index >= 31) + goto fail; else - data->idx_size = 1 << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR); + data->idx_size = 1ULL << (-bpb.clusters_per_index - GRUB_NTFS_BLK_SHR); - data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) * data->spc; + data->mft_start = grub_le_to_cpu64 (bpb.mft_lcn) << data->log_spc; if ((data->mft_size > GRUB_NTFS_MAX_MFT) || (data->idx_size > GRUB_NTFS_MAX_IDX)) goto fail; @@ -989,7 +1246,7 @@ grub_ntfs_mount (grub_disk_t disk) data->uuid = grub_le_to_cpu64 (bpb.num_serial); - if (fixup (data->mmft.buf, data->mft_size, "FILE")) + if (fixup (data->mmft.buf, data->mft_size, (const grub_uint8_t *) "FILE")) goto fail; if (!locate_attr (&data->mmft.attr, &data->mmft, GRUB_NTFS_AT_DATA)) @@ -1012,33 +1269,39 @@ fail: return 0; } +/* Context for grub_ntfs_dir. */ +struct grub_ntfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_ntfs_dir. */ +static int +grub_ntfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_ntfs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = grub_divmod64 (node->mtime, 10000000, 0) + - 86400ULL * 365 * (1970 - 1601) + - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_ntfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_ntfs_dir_ctx ctx = { hook, hook_data }; struct grub_ntfs_data *data = 0; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = 1; - info.mtime = grub_divmod64 (node->mtime, 10000000, 0) - - 86400ULL * 365 * (1970 - 1601) - - 86400ULL * ((1970 - 1601) / 4) + 86400ULL * ((1970 - 1601) / 100); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_ntfs_mount (device->disk); @@ -1051,7 +1314,7 @@ grub_ntfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_ntfs_iterate_dir (fdiro, iterate); + grub_ntfs_iterate_dir (fdiro, grub_ntfs_dir_iter, &ctx); fail: if ((fdiro) && (fdiro != &data->cmft)) @@ -1129,7 +1392,8 @@ grub_ntfs_read (grub_file_t file, char *buf, grub_size_t len) if (file->read_hook) mft->attr.save_pos = 1; - read_attr (&mft->attr, buf, file->offset, len, 1, file->read_hook); + read_attr (&mft->attr, (grub_uint8_t *) buf, file->offset, len, 1, + file->read_hook, file->read_hook_data); return (grub_errno) ? -1 : (grub_ssize_t) len; } @@ -1157,7 +1421,8 @@ grub_ntfs_label (grub_device_t device, char **label) { struct grub_ntfs_data *data = 0; struct grub_fshelp_node *mft = 0; - char *pa; + grub_uint8_t *pa; + grub_err_t err; grub_dl_ref (my_mod); @@ -1183,25 +1448,34 @@ grub_ntfs_label (grub_device_t device, char **label) goto fail; } - init_attr (&mft->attr, mft); + err = init_attr (&mft->attr, mft); + if (err != GRUB_ERR_NONE) + return err; + pa = find_attr (&mft->attr, GRUB_NTFS_AT_VOLUME_NAME); - if ((pa) && (pa[8] == 0) && (u32at (pa, 0x10))) + + if (pa >= mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR)) + { + grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label"); + goto fail; + } + + if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa < 0x16) + { + grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label"); + goto fail; + } + + if ((pa) && (pa[8] == 0) && (res_attr_data_len (pa))) { - char *buf; int len; - len = u32at (pa, 0x10) / 2; - buf = grub_malloc (len * 4 + 1); - pa += u16at (pa, 0x14); - { - grub_uint16_t tmp[len]; - int i; - for (i = 0; i < len; i++) - tmp[i] = grub_le_to_cpu16 (grub_get_unaligned16 (pa + 2 * i)); - *grub_utf16_to_utf8 ((grub_uint8_t *) buf, tmp, len) = - '\0'; - } - *label = buf; + len = res_attr_data_len (pa) / 2; + pa += res_attr_data_off (pa); + if (mft->buf + (mft->data->mft_size << GRUB_NTFS_BLK_SHR) - pa >= 2 * len) + *label = get_utf8 (pa, len); + else + grub_error (GRUB_ERR_BAD_FS, "can\'t parse volume label"); } fail: @@ -1253,12 +1527,12 @@ grub_ntfs_uuid (grub_device_t device, char **uuid) static struct grub_fs grub_ntfs_fs = { .name = "ntfs", - .dir = grub_ntfs_dir, - .open = grub_ntfs_open, - .read = grub_ntfs_read, - .close = grub_ntfs_close, - .label = grub_ntfs_label, - .uuid = grub_ntfs_uuid, + .fs_dir = grub_ntfs_dir, + .fs_open = grub_ntfs_open, + .fs_read = grub_ntfs_read, + .fs_close = grub_ntfs_close, + .fs_label = grub_ntfs_label, + .fs_uuid = grub_ntfs_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, @@ -1268,11 +1542,16 @@ static struct grub_fs grub_ntfs_fs = GRUB_MOD_INIT (ntfs) { - grub_fs_register (&grub_ntfs_fs); + if (!grub_is_lockdown ()) + { + grub_ntfs_fs.mod = mod; + grub_fs_register (&grub_ntfs_fs); + } my_mod = mod; } GRUB_MOD_FINI (ntfs) { - grub_fs_unregister (&grub_ntfs_fs); + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_ntfs_fs); } diff --git a/grub-core/fs/ntfscomp.c b/grub-core/fs/ntfscomp.c index ec359fa9d..b68bf5e40 100644 --- a/grub-core/fs/ntfscomp.c +++ b/grub-core/fs/ntfscomp.c @@ -22,6 +22,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -29,12 +30,13 @@ static grub_err_t decomp_nextvcn (struct grub_ntfs_comp *cc) { if (cc->comp_head >= cc->comp_tail) - return grub_error (GRUB_ERR_BAD_FS, "compression block overflown"); + return grub_error (GRUB_ERR_BAD_FS, "compression block overflow"); if (grub_disk_read (cc->disk, (cc->comp_table[cc->comp_head].next_lcn - - (cc->comp_table[cc->comp_head].next_vcn - cc->cbuf_vcn)) * cc->spc, 0, - cc->spc << GRUB_NTFS_BLK_SHR, cc->cbuf)) + (cc->comp_table[cc->comp_head].next_vcn - cc->cbuf_vcn)) << cc->log_spc, + 0, + 1 << (cc->log_spc + GRUB_NTFS_BLK_SHR), cc->cbuf)) return grub_errno; cc->cbuf_vcn++; if ((cc->cbuf_vcn >= cc->comp_table[cc->comp_head].next_vcn)) @@ -44,21 +46,21 @@ decomp_nextvcn (struct grub_ntfs_comp *cc) } static grub_err_t -decomp_getch (struct grub_ntfs_comp *cc, unsigned char *res) +decomp_getch (struct grub_ntfs_comp *cc, grub_uint8_t *res) { - if (cc->cbuf_ofs >= (cc->spc << GRUB_NTFS_BLK_SHR)) + if (cc->cbuf_ofs >= (1U << (cc->log_spc + GRUB_NTFS_BLK_SHR))) { if (decomp_nextvcn (cc)) return grub_errno; } - *res = (unsigned char) cc->cbuf[cc->cbuf_ofs++]; + *res = cc->cbuf[cc->cbuf_ofs++]; return 0; } static grub_err_t decomp_get16 (struct grub_ntfs_comp *cc, grub_uint16_t * res) { - unsigned char c1 = 0, c2 = 0; + grub_uint8_t c1 = 0, c2 = 0; if ((decomp_getch (cc, &c1)) || (decomp_getch (cc, &c2))) return grub_errno; @@ -68,7 +70,7 @@ decomp_get16 (struct grub_ntfs_comp *cc, grub_uint16_t * res) /* Decompress a block (4096 bytes) */ static grub_err_t -decomp_block (struct grub_ntfs_comp *cc, char *dest) +decomp_block (struct grub_ntfs_comp *cc, grub_uint8_t *dest) { grub_uint16_t flg, cnt; @@ -80,7 +82,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) { if (flg & 0x8000) { - unsigned char tag; + grub_uint8_t tag; grub_uint32_t bits, copied; bits = copied = tag = 0; @@ -103,7 +105,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) if (tag & 1) { grub_uint32_t i, len, delta, code, lmask, dshift; - grub_uint16_t word; + grub_uint16_t word = 0; if (decomp_get16 (cc, &word)) return grub_errno; @@ -135,7 +137,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) } else { - unsigned char ch = 0; + grub_uint8_t ch = 0; if (decomp_getch (cc, &ch)) return grub_errno; @@ -159,7 +161,7 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) { int n; - n = (cc->spc << GRUB_NTFS_BLK_SHR) - cc->cbuf_ofs; + n = (1 << (cc->log_spc + GRUB_NTFS_BLK_SHR)) - cc->cbuf_ofs; if (n > cnt) n = cnt; if ((dest) && (n)) @@ -176,9 +178,9 @@ decomp_block (struct grub_ntfs_comp *cc, char *dest) } static grub_err_t -read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) +read_block (struct grub_ntfs_rlst *ctx, grub_uint8_t *buf, grub_size_t num) { - int cpb = GRUB_NTFS_COM_SEC / ctx->comp.spc; + int log_cpb = GRUB_NTFS_LOG_COM_SEC - ctx->comp.log_spc; while (num) { @@ -192,7 +194,7 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) return grub_error (GRUB_ERR_BAD_FS, "invalid compression block"); ctx->comp.comp_head = ctx->comp.comp_tail = 0; ctx->comp.cbuf_vcn = ctx->target_vcn; - ctx->comp.cbuf_ofs = (ctx->comp.spc << GRUB_NTFS_BLK_SHR); + ctx->comp.cbuf_ofs = (1 << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR)); if (ctx->target_vcn >= ctx->next_vcn) { if (grub_ntfs_read_run_list (ctx)) @@ -211,20 +213,23 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) } } - nn = (16 - (unsigned) (ctx->target_vcn & 0xF)) / cpb; + nn = (16 - (unsigned) (ctx->target_vcn & 0xF)) >> log_cpb; if (nn > num) nn = num; num -= nn; if (ctx->flags & GRUB_NTFS_RF_BLNK) { - ctx->target_vcn += nn * cpb; + ctx->target_vcn += nn << log_cpb; if (ctx->comp.comp_tail == 0) { if (buf) { grub_memset (buf, 0, nn * GRUB_NTFS_COM_LEN); buf += nn * GRUB_NTFS_COM_LEN; + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, nn * GRUB_NTFS_COM_LEN, NULL, + ctx->file); } } else @@ -235,13 +240,16 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) return grub_errno; if (buf) buf += GRUB_NTFS_COM_LEN; + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, GRUB_NTFS_COM_LEN, NULL, + ctx->file); nn--; } } } else { - nn *= cpb; + nn <<= log_cpb; while ((ctx->comp.comp_head < ctx->comp.comp_tail) && (nn)) { grub_disk_addr_t tt; @@ -258,10 +266,15 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) (ctx->comp.disk, (ctx->comp.comp_table[ctx->comp.comp_head].next_lcn - (ctx->comp.comp_table[ctx->comp.comp_head].next_vcn - - ctx->target_vcn)) * ctx->comp.spc, 0, - tt * (ctx->comp.spc << GRUB_NTFS_BLK_SHR), buf)) + ctx->target_vcn)) << ctx->comp.log_spc, 0, + tt << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR), buf)) return grub_errno; - buf += tt * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, + tt << (ctx->comp.log_spc + + GRUB_NTFS_BLK_SHR), NULL, + ctx->file); + buf += tt << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR); } nn -= tt; if (ctx->target_vcn >= @@ -275,10 +288,15 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) if (grub_disk_read (ctx->comp.disk, (ctx->target_vcn - ctx->curr_vcn + - ctx->curr_lcn) * ctx->comp.spc, 0, - nn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR), buf)) + ctx->curr_lcn) << ctx->comp.log_spc, 0, + nn << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR), buf)) return grub_errno; - buf += nn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); + buf += nn << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR); + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, + nn << (ctx->comp.log_spc + + GRUB_NTFS_BLK_SHR), NULL, + ctx->file); } ctx->target_vcn += nn; } @@ -288,23 +306,68 @@ read_block (struct grub_ntfs_rlst *ctx, char *buf, grub_size_t num) } static grub_err_t -ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, - grub_size_t len, struct grub_ntfs_rlst *ctx, grub_disk_addr_t vcn) +ntfscomp (grub_uint8_t *dest, grub_disk_addr_t ofs, + grub_size_t len, struct grub_ntfs_rlst *ctx) { grub_err_t ret; + grub_disk_addr_t vcn; + int log_sz; + + if (ctx->attr->sbuf) + { + if ((ofs & (~(GRUB_NTFS_COM_LEN - 1))) == ctx->attr->save_pos) + { + grub_disk_addr_t n; + + n = GRUB_NTFS_COM_LEN - (ofs - ctx->attr->save_pos); + if (n > len) + n = len; + + grub_memcpy (dest, ctx->attr->sbuf + ofs - ctx->attr->save_pos, n); + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, n, NULL, ctx->file); + if (n == len) + return 0; + + dest += n; + len -= n; + ofs += n; + } + } + else + { + ctx->attr->sbuf = grub_malloc (GRUB_NTFS_COM_LEN); + if (ctx->attr->sbuf == NULL) + return grub_errno; + ctx->attr->save_pos = 1; + } + + vcn = ctx->target_vcn = (ofs >> GRUB_NTFS_COM_LOG_LEN) * (GRUB_NTFS_COM_SEC >> ctx->comp.log_spc); + ctx->target_vcn &= ~0xFULL; + while (ctx->next_vcn <= ctx->target_vcn) + { + if (grub_ntfs_read_run_list (ctx)) + return grub_errno; + } ctx->comp.comp_head = ctx->comp.comp_tail = 0; - ctx->comp.cbuf = grub_malloc ((ctx->comp.spc) << GRUB_NTFS_BLK_SHR); + if (grub_add (ctx->comp.log_spc, GRUB_NTFS_BLK_SHR, &log_sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("compression buffer size overflow")); + return 0; + } + ctx->comp.cbuf = grub_malloc (1 << log_sz); if (!ctx->comp.cbuf) return 0; ret = 0; //ctx->comp.disk->read_hook = read_hook; + //ctx->comp.disk->read_hook_data = read_hook_data; if ((vcn > ctx->target_vcn) && (read_block - (ctx, NULL, ((vcn - ctx->target_vcn) * ctx->comp.spc) / GRUB_NTFS_COM_SEC))) + (ctx, NULL, (vcn - ctx->target_vcn) >> (GRUB_NTFS_LOG_COM_SEC - ctx->comp.log_spc)))) { ret = grub_errno; goto quit; @@ -313,21 +376,28 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, if (ofs % GRUB_NTFS_COM_LEN) { grub_uint32_t t, n, o; + void *file = ctx->file; - t = ctx->target_vcn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); - if (read_block (ctx, at->sbuf, 1)) + ctx->file = 0; + + t = ctx->target_vcn << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR); + if (read_block (ctx, ctx->attr->sbuf, 1)) { ret = grub_errno; goto quit; } - at->save_pos = t; + ctx->file = file; + + ctx->attr->save_pos = t; o = ofs % GRUB_NTFS_COM_LEN; n = GRUB_NTFS_COM_LEN - o; if (n > len) n = len; - grub_memcpy (dest, &at->sbuf[o], n); + grub_memcpy (dest, &ctx->attr->sbuf[o], n); + if (grub_file_progress_hook && ctx->file) + grub_file_progress_hook (0, 0, n, NULL, ctx->file); if (n == len) goto quit; dest += n; @@ -345,17 +415,21 @@ ntfscomp (struct grub_ntfs_attr *at, char *dest, grub_disk_addr_t ofs, if (len) { grub_uint32_t t; + void *file = ctx->file; - t = ctx->target_vcn * (ctx->comp.spc << GRUB_NTFS_BLK_SHR); - if (read_block (ctx, at->sbuf, 1)) + ctx->file = 0; + t = ctx->target_vcn << (ctx->comp.log_spc + GRUB_NTFS_BLK_SHR); + if (read_block (ctx, ctx->attr->sbuf, 1)) { ret = grub_errno; goto quit; } - at->save_pos = t; + ctx->attr->save_pos = t; - grub_memcpy (dest, at->sbuf, len); + grub_memcpy (dest, ctx->attr->sbuf, len); + if (grub_file_progress_hook && file) + grub_file_progress_hook (0, 0, len, NULL, file); } quit: diff --git a/grub-core/fs/odc.c b/grub-core/fs/odc.c index 5fa88e3f9..8e4e8aeac 100644 --- a/grub-core/fs/odc.c +++ b/grub-core/fs/odc.c @@ -1,2 +1,62 @@ -#define MODE_ODC 1 -#include "cpio.c" +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#define ALIGN_CPIO(x) x + +#define MAGIC "070707" +struct head +{ + char magic[6]; + char dev[6]; + char ino[6]; + char mode[6]; + char uid[6]; + char gid[6]; + char nlink[6]; + char rdev[6]; + char mtime[11]; + char namesize[6]; + char filesize[11]; +} GRUB_PACKED; + +static inline unsigned long long +read_number (const char *str, grub_size_t size) +{ + unsigned long long ret = 0; + while (size-- && *str >= '0' && *str <= '7') + ret = (ret << 3) | (*str++ & 0xf); + return ret; +} + +#define FSNAME "odc" + +#include "cpio_common.c" + +GRUB_MOD_INIT (odc) +{ + grub_cpio_fs.mod = mod; + grub_fs_register (&grub_cpio_fs); +} + +GRUB_MOD_FINI (odc) +{ + grub_fs_unregister (&grub_cpio_fs); +} diff --git a/grub-core/fs/proc.c b/grub-core/fs/proc.c new file mode 100644 index 000000000..bcde43349 --- /dev/null +++ b/grub-core/fs/proc.c @@ -0,0 +1,204 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_procfs_entry *grub_procfs_entries; + +static int +grub_procdev_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, + grub_disk_pull_t pull) +{ + if (pull != GRUB_DISK_PULL_NONE) + return 0; + + return hook ("proc", hook_data); +} + +static grub_err_t +grub_procdev_open (const char *name, grub_disk_t disk) +{ + if (grub_strcmp (name, "proc")) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a procfs disk"); + + disk->total_sectors = 0; + disk->id = 0; + + disk->data = 0; + + return GRUB_ERR_NONE; +} + +static void +grub_procdev_close (grub_disk_t disk __attribute((unused))) +{ +} + +static grub_err_t +grub_procdev_read (grub_disk_t disk __attribute((unused)), + grub_disk_addr_t sector __attribute((unused)), + grub_size_t size __attribute((unused)), + char *buf __attribute((unused))) +{ + return GRUB_ERR_OUT_OF_RANGE; +} + +static grub_err_t +grub_procdev_write (grub_disk_t disk __attribute ((unused)), + grub_disk_addr_t sector __attribute ((unused)), + grub_size_t size __attribute ((unused)), + const char *buf __attribute ((unused))) +{ + return GRUB_ERR_OUT_OF_RANGE; +} + +struct grub_archelp_data +{ + struct grub_procfs_entry *entry, *next_entry; +}; + +static void +grub_procfs_rewind (struct grub_archelp_data *data) +{ + data->entry = NULL; + data->next_entry = grub_procfs_entries; +} + +static grub_err_t +grub_procfs_find_file (struct grub_archelp_data *data, char **name, + grub_int32_t *mtime, + grub_uint32_t *mode) +{ + data->entry = data->next_entry; + if (!data->entry) + { + *mode = GRUB_ARCHELP_ATTR_END; + return GRUB_ERR_NONE; + } + data->next_entry = data->entry->next; + *mode = GRUB_ARCHELP_ATTR_FILE | GRUB_ARCHELP_ATTR_NOTIME; + *name = grub_strdup (data->entry->name); + *mtime = 0; + if (!*name) + return grub_errno; + return GRUB_ERR_NONE; +} + +static struct grub_archelp_ops arcops = + { + .find_file = grub_procfs_find_file, + .rewind = grub_procfs_rewind + }; + +static grub_ssize_t +grub_procfs_read (grub_file_t file, char *buf, grub_size_t len) +{ + char *data = file->data; + + grub_memcpy (buf, data + file->offset, len); + + return len; +} + +static grub_err_t +grub_procfs_close (grub_file_t file) +{ + char *data; + + data = file->data; + grub_free (data); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_procfs_dir (grub_device_t device, const char *path, + grub_fs_dir_hook_t hook, void *hook_data) +{ + struct grub_archelp_data data; + + /* Check if the disk is our dummy disk. */ + if (grub_strcmp (device->disk->name, "proc")) + return grub_error (GRUB_ERR_BAD_FS, "not a procfs"); + + grub_procfs_rewind (&data); + + return grub_archelp_dir (&data, &arcops, + path, hook, hook_data); +} + +static grub_err_t +grub_procfs_open (struct grub_file *file, const char *path) +{ + grub_err_t err; + struct grub_archelp_data data; + grub_size_t sz; + + grub_procfs_rewind (&data); + + err = grub_archelp_open (&data, &arcops, path); + if (err) + return err; + file->data = data.entry->get_contents (&sz); + if (!file->data) + return grub_errno; + file->size = sz; + return GRUB_ERR_NONE; +} + +static struct grub_disk_dev grub_procfs_dev = { + .name = "proc", + .id = GRUB_DISK_DEVICE_PROCFS_ID, + .disk_iterate = grub_procdev_iterate, + .disk_open = grub_procdev_open, + .disk_close = grub_procdev_close, + .disk_read = grub_procdev_read, + .disk_write = grub_procdev_write, + .next = 0 +}; + +static struct grub_fs grub_procfs_fs = + { + .name = "procfs", + .fs_dir = grub_procfs_dir, + .fs_open = grub_procfs_open, + .fs_read = grub_procfs_read, + .fs_close = grub_procfs_close, + .next = 0 + }; + +GRUB_MOD_INIT (procfs) +{ + grub_procfs_fs.mod = mod; + grub_disk_dev_register (&grub_procfs_dev); + grub_fs_register (&grub_procfs_fs); +} + +GRUB_MOD_FINI (procfs) +{ + grub_disk_dev_unregister (&grub_procfs_dev); + grub_fs_unregister (&grub_procfs_fs); +} diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c index 26adf23c4..5d3c85950 100644 --- a/grub-core/fs/reiserfs.c +++ b/grub-core/fs/reiserfs.c @@ -39,6 +39,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -109,14 +110,14 @@ struct grub_reiserfs_superblock grub_uint8_t unused[4]; grub_uint16_t uuid[8]; char label[16]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_reiserfs_journal_header { grub_uint32_t last_flush_uid; grub_uint32_t unflushed_offset; grub_uint32_t mount_id; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_reiserfs_description_block { @@ -124,14 +125,14 @@ struct grub_reiserfs_description_block grub_uint32_t len; grub_uint32_t mount_id; grub_uint32_t real_blocks[0]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_reiserfs_commit_block { grub_uint32_t id; grub_uint32_t len; grub_uint32_t real_blocks[0]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_reiserfs_stat_item_v1 { @@ -145,7 +146,7 @@ struct grub_reiserfs_stat_item_v1 grub_uint32_t ctime; grub_uint32_t rdev; grub_uint32_t first_direct_byte; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_reiserfs_stat_item_v2 { @@ -160,7 +161,7 @@ struct grub_reiserfs_stat_item_v2 grub_uint32_t ctime; grub_uint32_t blocks; grub_uint32_t first_direct_byte; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_reiserfs_key { @@ -172,13 +173,13 @@ struct grub_reiserfs_key { grub_uint32_t offset; grub_uint32_t type; - } v1 __attribute__ ((packed)); + } GRUB_PACKED v1; struct { grub_uint64_t offset_type; - } v2 __attribute__ ((packed)); + } GRUB_PACKED v2; } u; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_reiserfs_item_header { @@ -187,11 +188,11 @@ struct grub_reiserfs_item_header { grub_uint16_t free_space; grub_uint16_t entry_count; - } u __attribute__ ((packed)); + } GRUB_PACKED u; grub_uint16_t item_size; grub_uint16_t item_location; grub_uint16_t version; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_reiserfs_block_header { @@ -200,14 +201,14 @@ struct grub_reiserfs_block_header grub_uint16_t free_space; grub_uint16_t reserved; struct grub_reiserfs_key block_right_delimiting_key; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_reiserfs_disk_child { grub_uint32_t block_number; grub_uint16_t size; grub_uint16_t reserved; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_reiserfs_directory_header { @@ -216,7 +217,7 @@ struct grub_reiserfs_directory_header grub_uint32_t object_id; grub_uint16_t location; grub_uint16_t state; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_fshelp_node { @@ -240,9 +241,8 @@ struct grub_reiserfs_data static grub_ssize_t grub_reiserfs_read_real (struct grub_fshelp_node *node, grub_off_t off, char *buf, grub_size_t len, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length)); + grub_disk_read_hook_t read_hook, + void *read_hook_data); /* Internal-only functions. Not to be used outside of this file. */ @@ -366,7 +366,7 @@ grub_reiserfs_set_key_offset (struct grub_reiserfs_key *key, key->u.v1.offset = grub_cpu_to_le32 (value); else key->u.v2.offset_type \ - = ((key->u.v2.offset_type & grub_cpu_to_le64 (15ULL << 60)) + = ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (15ULL << 60)) | grub_cpu_to_le64 (value & (~0ULL >> 4))); } @@ -413,7 +413,7 @@ grub_reiserfs_set_key_type (struct grub_reiserfs_key *key, key->u.v1.type = grub_cpu_to_le32 (type); else key->u.v2.offset_type - = ((key->u.v2.offset_type & grub_cpu_to_le64 (~0ULL >> 4)) + = ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (~0ULL >> 4)) | grub_cpu_to_le64 ((grub_uint64_t) type << 60)); assert (grub_reiserfs_get_key_type (key) == grub_type); @@ -674,7 +674,7 @@ grub_reiserfs_read_symlink (grub_fshelp_node_t node) if (! symlink_buffer) return 0; - ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0); + ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0, 0); if (ret < 0) { grub_free (symlink_buffer); @@ -718,10 +718,8 @@ grub_reiserfs_mount (grub_disk_t disk) /* Call HOOK for each file in directory ITEM. */ static int grub_reiserfs_iterate_dir (grub_fshelp_node_t item, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, + void *hook_data) { struct grub_reiserfs_data *data = item->data; struct grub_reiserfs_block_header *block_header = 0; @@ -784,14 +782,32 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, = grub_le_to_cpu16 (directory_header->state); grub_fshelp_node_t entry_item; struct grub_reiserfs_key entry_key; - enum grub_reiserfs_item_type entry_type; + enum grub_fshelp_filetype entry_type; char *entry_name; - + char *entry_name_end = 0; + char c; + if (!(entry_state & GRUB_REISERFS_VISIBLE_MASK)) continue; entry_name = (((char *) directory_headers) + grub_le_to_cpu16 (directory_header->location)); + if (entry_number == 0) + { + entry_name_end = (char *) block_header + + grub_le_to_cpu16 (item_headers[block_position].item_location) + + grub_le_to_cpu16 (item_headers[block_position].item_size); + } + else + { + entry_name_end = (((char *) directory_headers) + + grub_le_to_cpu16 (directory_headers[entry_number - 1].location)); + } + if (entry_name_end < entry_name || entry_name_end > (char *) block_header + block_size) + { + entry_name_end = (char *) block_header + block_size; + } + entry_key.directory_id = directory_header->directory_id; entry_key.object_id = directory_header->object_id; entry_key.u.v2.offset_type = 0; @@ -938,7 +954,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, else { /* Pseudo file ".." never has stat block. */ - if (grub_strcmp (entry_name, "..")) + if (entry_name_end == entry_name + 2 && grub_memcmp (entry_name, "..", 2) != 0) grub_dprintf ("reiserfs", "Warning : %s has no stat block !\n", entry_name); @@ -946,18 +962,21 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, goto next; } } - if (hook (entry_name, entry_type, entry_item)) + + c = *entry_name_end; + *entry_name_end = 0; + if (hook (entry_name, entry_type, entry_item, hook_data)) { + *entry_name_end = c; grub_dprintf ("reiserfs", "Found : %s, type=%d\n", entry_name, entry_type); ret = 1; goto found; } + *entry_name_end = c; next: - *entry_name = 0; /* Make sure next entry name (which is just - before this one in disk order) stops before - the current one. */ + ; } if (next_offset == 0) @@ -1000,8 +1019,8 @@ grub_reiserfs_open (struct grub_file *file, const char *name) data = grub_reiserfs_mount (file->device->disk); if (! data) goto fail; - key.directory_id = grub_cpu_to_le32 (1); - key.object_id = grub_cpu_to_le32 (2); + key.directory_id = grub_cpu_to_le32_compile_time (1); + key.object_id = grub_cpu_to_le32_compile_time (2); key.u.v2.offset_type = 0; grub_reiserfs_set_key_type (&key, GRUB_REISERFS_DIRECTORY, 2); grub_reiserfs_set_key_offset (&key, 1); @@ -1038,9 +1057,7 @@ grub_reiserfs_open (struct grub_file *file, const char *name) static grub_ssize_t grub_reiserfs_read_real (struct grub_fshelp_node *node, grub_off_t off, char *buf, grub_size_t len, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, - unsigned length)) + grub_disk_read_hook_t read_hook, void *read_hook_data) { unsigned int indirect_block, indirect_block_count; struct grub_reiserfs_key key; @@ -1095,7 +1112,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, switch (found.type) { case GRUB_REISERFS_DIRECT: - block = found.block_number * (block_size >> GRUB_DISK_SECTOR_BITS); + block = ((grub_disk_addr_t) found.block_number) * (block_size >> GRUB_DISK_SECTOR_BITS); grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block); if (initial_position < current_position + item_size) { @@ -1107,6 +1124,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, (unsigned) block, (unsigned) offset, (unsigned) (offset + length)); found.data->disk->read_hook = read_hook; + found.data->disk->read_hook_data = read_hook_data; grub_disk_read (found.data->disk, block, offset @@ -1133,6 +1151,7 @@ grub_reiserfs_read_real (struct grub_fshelp_node *node, if (grub_errno) goto fail; found.data->disk->read_hook = read_hook; + found.data->disk->read_hook_data = read_hook_data; for (indirect_block = 0; indirect_block < indirect_block_count && current_position < final_position; @@ -1238,7 +1257,7 @@ static grub_ssize_t grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len) { return grub_reiserfs_read_real (file->data, file->offset, buf, len, - file->read_hook); + file->read_hook, file->read_hook_data); } /* Close the file FILE. */ @@ -1254,38 +1273,46 @@ grub_reiserfs_close (grub_file_t file) return GRUB_ERR_NONE; } +/* Context for grub_reiserfs_dir. */ +struct grub_reiserfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_reiserfs_dir. */ +static int +grub_reiserfs_dir_iter (const char *filename, + enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_reiserfs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = node->mtime; + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + /* Call HOOK with each file under DIR. */ static grub_err_t grub_reiserfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_reiserfs_dir_ctx ctx = { hook, hook_data }; struct grub_reiserfs_data *data = 0; struct grub_fshelp_node root, *found; struct grub_reiserfs_key root_key; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = 1; - info.mtime = node->mtime; - grub_free (node); - return hook (filename, &info); - } grub_dl_ref (my_mod); data = grub_reiserfs_mount (device->disk); if (! data) goto fail; - root_key.directory_id = grub_cpu_to_le32 (1); - root_key.object_id = grub_cpu_to_le32 (2); + root_key.directory_id = grub_cpu_to_le32_compile_time (1); + root_key.object_id = grub_cpu_to_le32_compile_time (2); root_key.u.v2.offset_type = 0; grub_reiserfs_set_key_type (&root_key, GRUB_REISERFS_DIRECTORY, 2); grub_reiserfs_set_key_offset (&root_key, 1); @@ -1300,7 +1327,7 @@ grub_reiserfs_dir (grub_device_t device, const char *path, grub_reiserfs_read_symlink, GRUB_FSHELP_DIR); if (grub_errno) goto fail; - grub_reiserfs_iterate_dir (found, iterate); + grub_reiserfs_iterate_dir (found, grub_reiserfs_dir_iter, &ctx); grub_free (data); grub_dl_unref (my_mod); return GRUB_ERR_NONE; @@ -1376,12 +1403,12 @@ grub_reiserfs_uuid (grub_device_t device, char **uuid) static struct grub_fs grub_reiserfs_fs = { .name = "reiserfs", - .dir = grub_reiserfs_dir, - .open = grub_reiserfs_open, - .read = grub_reiserfs_read, - .close = grub_reiserfs_close, - .label = grub_reiserfs_label, - .uuid = grub_reiserfs_uuid, + .fs_dir = grub_reiserfs_dir, + .fs_open = grub_reiserfs_open, + .fs_read = grub_reiserfs_read, + .fs_close = grub_reiserfs_close, + .fs_label = grub_reiserfs_label, + .fs_uuid = grub_reiserfs_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, @@ -1391,11 +1418,16 @@ static struct grub_fs grub_reiserfs_fs = GRUB_MOD_INIT(reiserfs) { - grub_fs_register (&grub_reiserfs_fs); + if (!grub_is_lockdown ()) + { + grub_reiserfs_fs.mod = mod; + grub_fs_register (&grub_reiserfs_fs); + } my_mod = mod; } GRUB_MOD_FINI(reiserfs) { - grub_fs_unregister (&grub_reiserfs_fs); + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_reiserfs_fs); } diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index b30caef35..eafab03b2 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -112,7 +113,7 @@ grub_romfs_mount (grub_device_t dev) { grub_error (GRUB_ERR_BAD_FS, "not romfs"); return NULL; - } + } err = do_checksum (&sb, sizeof (sb) < grub_be_to_cpu32 (sb.sb.total_size) ? sizeof (sb) : grub_be_to_cpu32 (sb.sb.total_size)); if (err) @@ -171,10 +172,7 @@ grub_romfs_read_symlink (grub_fshelp_node_t node) static int grub_romfs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { grub_disk_addr_t caddr; struct grub_romfs_file_header hdr; @@ -274,7 +272,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, while (1) { char buf[16]; - err = grub_disk_read (dir->data->disk, + err = grub_disk_read (dir->data->disk, laddr >> GRUB_DISK_SECTOR_BITS, laddr & (GRUB_DISK_SECTOR_SIZE - 1), 16, buf); @@ -301,12 +299,12 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, node->data_addr = grub_be_to_cpu32 (node->file.spec); filetype = GRUB_FSHELP_DIR; } - + break; } } - if (hook ((char *) name, filetype, node)) + if (hook ((char *) name, filetype, node, hook_data)) { grub_free (name); return 1; @@ -316,30 +314,36 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, return 0; } +/* Context for grub_romfs_dir. */ +struct grub_romfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_romfs_dir. */ +static int +grub_romfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_romfs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_romfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_romfs_dir_ctx ctx = { hook, hook_data }; struct grub_romfs_data *data = 0; struct grub_fshelp_node *fdiro = 0, start; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - grub_free (node); - return hook (filename, &info); - } - data = grub_romfs_mount (device); if (! data) goto fail; @@ -352,7 +356,7 @@ grub_romfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_romfs_iterate_dir (fdiro, iterate); + grub_romfs_iterate_dir (fdiro, grub_romfs_dir_iter, &ctx); fail: grub_free (data); @@ -396,9 +400,10 @@ grub_romfs_read (grub_file_t file, char *buf, grub_size_t len) /* XXX: The file is stored in as a single extent. */ data->data->disk->read_hook = file->read_hook; + data->data->disk->read_hook_data = file->read_hook_data; grub_disk_read (data->data->disk, (data->data_addr + file->offset) >> GRUB_DISK_SECTOR_BITS, - (data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1), + (data->data_addr + file->offset) & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); data->data->disk->read_hook = NULL; @@ -457,11 +462,11 @@ grub_romfs_label (grub_device_t device, char **label) static struct grub_fs grub_romfs_fs = { .name = "romfs", - .dir = grub_romfs_dir, - .open = grub_romfs_open, - .read = grub_romfs_read, - .close = grub_romfs_close, - .label = grub_romfs_label, + .fs_dir = grub_romfs_dir, + .fs_open = grub_romfs_open, + .fs_read = grub_romfs_read, + .fs_close = grub_romfs_close, + .fs_label = grub_romfs_label, #ifdef GRUB_UTIL .reserved_first_sector = 0, .blocklist_install = 0, @@ -471,10 +476,15 @@ static struct grub_fs grub_romfs_fs = GRUB_MOD_INIT(romfs) { - grub_fs_register (&grub_romfs_fs); + if (!grub_is_lockdown ()) + { + grub_romfs_fs.mod = mod; + grub_fs_register (&grub_romfs_fs); + } } GRUB_MOD_FINI(romfs) { - grub_fs_unregister (&grub_romfs_fs); + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_romfs_fs); } diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index f7cdb0898..bad4ae8d1 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -35,7 +37,7 @@ struct grub_sfs_bheader grub_uint8_t magic[4]; grub_uint32_t chksum; grub_uint32_t ipointtomyself; -} __attribute__ ((packed)); +} GRUB_PACKED; /* The sfs rootblock. */ struct grub_sfs_rblock @@ -50,7 +52,7 @@ struct grub_sfs_rblock grub_uint8_t unused3[8]; grub_uint32_t rootobject; grub_uint32_t btree; -} __attribute__ ((packed)); +} GRUB_PACKED; enum { @@ -69,18 +71,18 @@ struct grub_sfs_obj { grub_uint32_t first_block; grub_uint32_t size; - } file __attribute__ ((packed)); + } GRUB_PACKED file; struct { grub_uint32_t hashtable; grub_uint32_t dir_objc; - } dir __attribute__ ((packed)); + } GRUB_PACKED dir; } file_dir; grub_uint32_t mtime; grub_uint8_t type; grub_uint8_t filename[1]; grub_uint8_t comment[1]; -} __attribute__ ((packed)); +} GRUB_PACKED; #define GRUB_SFS_TYPE_DELETED 32 #define GRUB_SFS_TYPE_SYMLINK 64 @@ -95,13 +97,13 @@ struct grub_sfs_objc grub_uint32_t prev; /* The amount of objects depends on the blocksize. */ struct grub_sfs_obj objects[1]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_sfs_btree_node { grub_uint32_t key; grub_uint32_t data; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_sfs_btree_extent { @@ -109,7 +111,7 @@ struct grub_sfs_btree_extent grub_uint32_t next; grub_uint32_t prev; grub_uint16_t size; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_sfs_btree { @@ -120,7 +122,7 @@ struct grub_sfs_btree /* Normally this can be kind of node, but just extents are supported. */ struct grub_sfs_btree_node node[1]; -} __attribute__ ((packed)); +} GRUB_PACKED; @@ -173,10 +175,11 @@ grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block, struct grub_sfs_btree *tree; int i; grub_uint32_t next; + grub_size_t blocksize = GRUB_DISK_SECTOR_SIZE << data->log_blocksize; - treeblock = grub_malloc (GRUB_DISK_SECTOR_SIZE << data->log_blocksize); - if (!block) - return 0; + treeblock = grub_malloc (blocksize); + if (!treeblock) + return grub_errno; next = grub_be_to_cpu32 (data->rblock.btree); tree = (struct grub_sfs_btree *) treeblock; @@ -184,17 +187,21 @@ grub_sfs_read_extent (struct grub_sfs_data *data, unsigned int block, /* Handle this level in the btree. */ do { + grub_uint16_t nnodes; grub_disk_read (data->disk, ((grub_disk_addr_t) next) << data->log_blocksize, - 0, GRUB_DISK_SECTOR_SIZE << data->log_blocksize, - treeblock); + 0, blocksize, treeblock); if (grub_errno) { grub_free (treeblock); return grub_errno; } - for (i = grub_be_to_cpu16 (tree->nodes) - 1; i >= 0; i--) + nnodes = grub_be_to_cpu16 (tree->nodes); + if (nnodes * (grub_uint32_t) (tree)->nodesize > blocksize) + break; + + for (i = (int) nnodes - 1; i >= 0; i--) { #define EXTNODE(tree, index) \ @@ -261,7 +268,7 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) node->next_extent = node->block; node->cache_size = 0; - node->cache = grub_malloc (sizeof (node->cache[0]) * cache_size); + node->cache = grub_calloc (cache_size, sizeof (node->cache[0])); if (!node->cache) { grub_errno = 0; @@ -302,10 +309,15 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) if (node->cache && node->cache_size >= node->cache_allocated) { struct cache_entry *e = node->cache; - e = grub_realloc (node->cache,node->cache_allocated * 2 - * sizeof (e[0])); + grub_size_t sz; + + if (grub_mul (node->cache_allocated, 2 * sizeof (e[0]), &sz)) + goto fail; + + e = grub_realloc (node->cache, sz); if (!e) { + fail: grub_errno = 0; grub_free (node->cache); node->cache = 0; @@ -345,11 +357,11 @@ grub_sfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_sfs_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { - return grub_fshelp_read_file (node->data->disk, node, read_hook, + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, pos, len, buf, grub_sfs_read_block, node->size, node->data->log_blocksize, 0); } @@ -362,6 +374,7 @@ grub_sfs_mount (grub_disk_t disk) struct grub_sfs_objc *rootobjc; char *rootobjc_data = 0; grub_uint32_t blk; + unsigned int max_len; data = grub_malloc (sizeof (*data)); if (!data) @@ -410,7 +423,16 @@ grub_sfs_mount (grub_disk_t disk) data->diropen.data = data; data->diropen.cache = 0; data->disk = disk; - data->label = grub_strdup ((char *) (rootobjc->objects[0].filename)); + + /* We only read 1 block of data, so truncate the name if needed. */ + max_len = ((GRUB_DISK_SECTOR_SIZE << data->log_blocksize) + - 24 /* offsetof (struct grub_sfs_objc, objects) */ + - 25); /* offsetof (struct grub_sfs_obj, filename) */ + data->label = grub_zalloc (max_len + 1); + if (data->label == NULL) + goto fail; + + grub_strncpy (data->label, (char *) rootobjc->objects[0].filename, max_len); grub_free (rootobjc_data); return data; @@ -460,12 +482,54 @@ grub_sfs_read_symlink (grub_fshelp_node_t node) return symlink; } +/* Helper for grub_sfs_iterate_dir. */ +static int +grub_sfs_create_node (struct grub_fshelp_node **node, + struct grub_sfs_data *data, + const char *name, + grub_uint32_t block, grub_uint32_t size, int type, + grub_uint32_t mtime, + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) +{ + grub_size_t len = grub_strlen (name); + grub_uint8_t *name_u8; + int ret; + grub_size_t sz; + + if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) || + grub_add (sz, 1, &sz)) + return 1; + + *node = grub_malloc (sizeof (**node)); + if (!*node) + return 1; + name_u8 = grub_malloc (sz); + if (!name_u8) + { + grub_free (*node); + return 1; + } + + (*node)->data = data; + (*node)->size = size; + (*node)->block = block; + (*node)->mtime = mtime; + (*node)->cache = 0; + (*node)->cache_off = 0; + (*node)->next_extent = block; + (*node)->cache_size = 0; + (*node)->cache_allocated = 0; + + *grub_latin1_to_utf8 (name_u8, (const grub_uint8_t *) name, len) = '\0'; + + ret = hook ((char *) name_u8, type | data->fshelp_flags, *node, hook_data); + grub_free (name_u8); + return ret; +} + static int grub_sfs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { struct grub_fshelp_node *node = 0; struct grub_sfs_data *data = dir->data; @@ -474,46 +538,6 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, unsigned int next = dir->block; grub_uint32_t pos; - auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, - grub_uint32_t block, - grub_uint32_t size, int type, - grub_uint32_t mtime); - - int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, - grub_uint32_t block, - grub_uint32_t size, int type, - grub_uint32_t mtime) - { - grub_size_t len = grub_strlen (name); - grub_uint8_t *name_u8; - int ret; - node = grub_malloc (sizeof (*node)); - if (!node) - return 1; - name_u8 = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); - if (!name_u8) - { - grub_free (node); - return 1; - } - - node->data = data; - node->size = size; - node->block = block; - node->mtime = mtime; - node->cache = 0; - node->cache_off = 0; - node->next_extent = block; - node->cache_size = 0; - node->cache_allocated = 0; - - *grub_latin1_to_utf8 (name_u8, (const grub_uint8_t *) name, len) = '\0'; - - ret = hook ((char *) name_u8, type | data->fshelp_flags, node); - grub_free (name_u8); - return ret; - } - objc_data = grub_malloc (GRUB_DISK_SECTOR_SIZE << data->log_blocksize); if (!objc_data) goto fail; @@ -570,9 +594,10 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, else block = grub_be_to_cpu32 (obj->file_dir.file.first_block); - if (grub_sfs_create_node (filename, block, + if (grub_sfs_create_node (&node, data, filename, block, grub_be_to_cpu32 (obj->file_dir.file.size), - type, grub_be_to_cpu32 (obj->mtime))) + type, grub_be_to_cpu32 (obj->mtime), + hook, hook_data)) { grub_free (objc_data); return 1; @@ -649,37 +674,44 @@ grub_sfs_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_sfs_data *data = (struct grub_sfs_data *) file->data; - return grub_sfs_read_file (&data->diropen, file->read_hook, + return grub_sfs_read_file (&data->diropen, + file->read_hook, file->read_hook_data, file->offset, len, buf); } +/* Context for grub_sfs_dir. */ +struct grub_sfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_sfs_dir. */ +static int +grub_sfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_sfs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2; + info.mtimeset = 1; + grub_free (node->cache); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_sfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_sfs_dir_ctx ctx = { hook, hook_data }; struct grub_sfs_data *data = 0; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtime = node->mtime + 8 * 365 * 86400 + 86400 * 2; - info.mtimeset = 1; - grub_free (node->cache); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_sfs_mount (device->disk); @@ -691,7 +723,7 @@ grub_sfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_sfs_iterate_dir (fdiro, iterate); + grub_sfs_iterate_dir (fdiro, grub_sfs_dir_iter, &ctx); fail: if (data && fdiro != &data->diropen) @@ -715,8 +747,13 @@ grub_sfs_label (grub_device_t device, char **label) data = grub_sfs_mount (disk); if (data) { - grub_size_t len = grub_strlen (data->label); - *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); + grub_size_t sz, len = grub_strlen (data->label); + + if (grub_mul (len, GRUB_MAX_UTF8_PER_LATIN1, &sz) || + grub_add (sz, 1, &sz)) + return GRUB_ERR_OUT_OF_RANGE; + + *label = grub_malloc (sz); if (*label) *grub_latin1_to_utf8 ((grub_uint8_t *) *label, (const grub_uint8_t *) data->label, @@ -732,11 +769,11 @@ grub_sfs_label (grub_device_t device, char **label) static struct grub_fs grub_sfs_fs = { .name = "sfs", - .dir = grub_sfs_dir, - .open = grub_sfs_open, - .read = grub_sfs_read, - .close = grub_sfs_close, - .label = grub_sfs_label, + .fs_dir = grub_sfs_dir, + .fs_open = grub_sfs_open, + .fs_read = grub_sfs_read, + .fs_close = grub_sfs_close, + .fs_label = grub_sfs_label, #ifdef GRUB_UTIL .reserved_first_sector = 0, .blocklist_install = 1, @@ -746,11 +783,16 @@ static struct grub_fs grub_sfs_fs = GRUB_MOD_INIT(sfs) { - grub_fs_register (&grub_sfs_fs); + if (!grub_is_lockdown ()) + { + grub_sfs_fs.mod = mod; + grub_fs_register (&grub_sfs_fs); + } my_mod = mod; } GRUB_MOD_FINI(sfs) { - grub_fs_unregister (&grub_sfs_fs); + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_sfs_fs); } diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 44af0f82a..cf2bca822 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "xz.h" @@ -71,7 +72,7 @@ struct grub_squash_super grub_uint64_t diroffset; grub_uint64_t unk1offset; grub_uint64_t unk2offset; -} __attribute__ ((packed)); +} GRUB_PACKED; /* Chunk-based */ struct grub_squash_inode @@ -89,7 +90,7 @@ struct grub_squash_inode grub_uint32_t offset; grub_uint32_t size; grub_uint32_t block_size[0]; - } __attribute__ ((packed)) file; + } GRUB_PACKED file; struct { grub_uint64_t chunk; grub_uint64_t size; @@ -98,13 +99,13 @@ struct grub_squash_inode grub_uint32_t offset; grub_uint32_t dummy3; grub_uint32_t block_size[0]; - } __attribute__ ((packed)) long_file; + } GRUB_PACKED long_file; struct { grub_uint32_t chunk; grub_uint32_t dummy; grub_uint16_t size; grub_uint16_t offset; - } __attribute__ ((packed)) dir; + } GRUB_PACKED dir; struct { grub_uint32_t dummy1; grub_uint32_t size; @@ -112,14 +113,14 @@ struct grub_squash_inode grub_uint32_t dummy2; grub_uint16_t dummy3; grub_uint16_t offset; - } __attribute__ ((packed)) long_dir; + } GRUB_PACKED long_dir; struct { grub_uint32_t dummy; grub_uint32_t namelen; char name[0]; - } __attribute__ ((packed)) symlink; - } __attribute__ ((packed)); -} __attribute__ ((packed)); + } GRUB_PACKED symlink; + } GRUB_PACKED; +} GRUB_PACKED; struct grub_squash_cache_inode { @@ -137,7 +138,7 @@ struct grub_squash_dirent_header grub_uint32_t nelems; grub_uint32_t ino_chunk; grub_uint32_t dummy; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_squash_dirent { @@ -147,7 +148,7 @@ struct grub_squash_dirent /* Actually the value is the length of name - 1. */ grub_uint16_t namelen; char name[0]; -} __attribute__ ((packed)); +} GRUB_PACKED; enum { @@ -164,7 +165,7 @@ struct grub_squash_frag_desc grub_uint64_t offset; grub_uint32_t size; grub_uint32_t dummy; -} __attribute__ ((packed)); +} GRUB_PACKED; enum { @@ -209,7 +210,7 @@ struct grub_fshelp_node struct grub_squash_data *data; struct grub_squash_inode ino; grub_size_t stsize; - struct + struct { grub_disk_addr_t ino_chunk; grub_uint16_t ino_offset; @@ -242,7 +243,7 @@ read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len, csize = SQUASH_CHUNK_SIZE - offset; if (csize > len) csize = len; - + if (grub_le_to_cpu16 (d) & SQUASH_CHUNK_UNCOMPRESSED) { grub_disk_addr_t a = chunk_start + 2 + offset; @@ -255,7 +256,7 @@ read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len, else { char *tmp; - grub_size_t bsize = grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS; + grub_size_t bsize = grub_le_to_cpu16 (d) & ~SQUASH_CHUNK_FLAGS; grub_disk_addr_t a = chunk_start + 2; tmp = grub_malloc (bsize); if (!tmp) @@ -338,7 +339,7 @@ xz_decompress (char *inbuf, grub_size_t insize, grub_off_t off, while (len) { enum xz_ret xzret; - + buf.out_pos = 0; xzret = xz_dec_run (data->xzdec, &buf); @@ -398,9 +399,9 @@ squash_mount (grub_disk_t disk) return NULL; } - err = grub_disk_read (disk, + err = grub_disk_read (disk, grub_le_to_cpu64 (sb.unk1offset) - >> GRUB_DISK_SECTOR_BITS, + >> GRUB_DISK_SECTOR_BITS, grub_le_to_cpu64 (sb.unk1offset) & (GRUB_DISK_SECTOR_SIZE - 1), sizeof (frag), &frag); if (grub_errno == GRUB_ERR_OUT_OF_RANGE) @@ -447,7 +448,7 @@ squash_mount (grub_disk_t disk) } data->blksz = grub_le_to_cpu32 (data->sb.block_size); - for (data->log2_blksz = 0; + for (data->log2_blksz = 0; (1U << data->log2_blksz) < data->blksz; data->log2_blksz++); @@ -459,7 +460,17 @@ grub_squash_read_symlink (grub_fshelp_node_t node) { char *ret; grub_err_t err; - ret = grub_malloc (grub_le_to_cpu32 (node->ino.symlink.namelen) + 1); + grub_uint32_t sz; + + if (grub_add (grub_le_to_cpu32 (node->ino.symlink.namelen), 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink name length overflow")); + return NULL; + } + + ret = grub_malloc (sz); + if (!ret) + return NULL; err = read_chunk (node->data, ret, grub_le_to_cpu32 (node->ino.symlink.namelen), @@ -478,10 +489,7 @@ grub_squash_read_symlink (grub_fshelp_node_t node) static int grub_squash_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { grub_uint32_t off; grub_uint32_t endoff; @@ -509,24 +517,32 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, { grub_fshelp_node_t node; - node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); + grub_size_t sz; + + if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) || + grub_add (sz, sizeof (*node), &sz)) + return 0; + + node = grub_malloc (sz); if (!node) return 0; - grub_memcpy (node, dir, - sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); - if (hook (".", GRUB_FSHELP_DIR, node)) + grub_memcpy (node, dir, sz); + if (hook (".", GRUB_FSHELP_DIR, node, hook_data)) return 1; if (dir->stsize != 1) { grub_err_t err; - node = grub_malloc (sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); + if (grub_mul (dir->stsize, sizeof (dir->stack[0]), &sz) || + grub_add (sz, sizeof (*node), &sz)) + return 0; + + node = grub_malloc (sz); if (!node) return 0; - grub_memcpy (node, dir, - sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); + grub_memcpy (node, dir, sz); node->stsize--; err = read_chunk (dir->data, &node->ino, sizeof (node->ino), @@ -534,9 +550,12 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, + node->stack[node->stsize - 1].ino_chunk, node->stack[node->stsize - 1].ino_offset); if (err) - return 0; + { + grub_free (node); + return 0; + } - if (hook ("..", GRUB_FSHELP_DIR, node)) + if (hook ("..", GRUB_FSHELP_DIR, node, hook_data)) return 1; } } @@ -560,6 +579,8 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, enum grub_fshelp_filetype filetype = GRUB_FSHELP_REG; struct grub_squash_dirent di; struct grub_squash_inode ino; + grub_size_t sz; + grub_uint16_t nlen; err = read_chunk (dir->data, &di, sizeof (di), grub_le_to_cpu64 (dir->data->sb.diroffset) @@ -575,7 +596,12 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, if (err) return 0; - buf = grub_malloc (grub_le_to_cpu16 (di.namelen) + 2); + if (grub_add (grub_le_to_cpu16 (di.namelen), 2, &nlen)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("name length overflow")); + return 0; + } + buf = grub_malloc (nlen); if (!buf) return 0; err = read_chunk (dir->data, buf, @@ -583,7 +609,10 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, grub_le_to_cpu64 (dir->data->sb.diroffset) + chunk, off); if (err) - return 0; + { + grub_free (buf); + return 0; + } off += grub_le_to_cpu16 (di.namelen) + 1; buf[grub_le_to_cpu16 (di.namelen) + 1] = 0; @@ -592,19 +621,28 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, if (grub_le_to_cpu16 (di.type) == SQUASH_TYPE_SYMLINK) filetype = GRUB_FSHELP_SYMLINK; - node = grub_malloc (sizeof (*node) - + (dir->stsize + 1) * sizeof (dir->stack[0])); - if (! node) - return 0; + if (grub_add (dir->stsize, 1, &sz) || + grub_mul (sz, sizeof (dir->stack[0]), &sz) || + grub_add (sz, sizeof (*node), &sz)) + { + grub_free (buf); + return 0; + } - grub_memcpy (node, dir, - sizeof (*node) + dir->stsize * sizeof (dir->stack[0])); + node = grub_malloc (sz); + if (! node) + { + grub_free (buf); + return 0; + } + + grub_memcpy (node, dir, sz - sizeof(dir->stack[0])); node->ino = ino; node->stack[node->stsize].ino_chunk = grub_le_to_cpu32 (dh.ino_chunk); node->stack[node->stsize].ino_offset = grub_le_to_cpu16 (di.ino_offset); node->stsize++; - r = hook (buf, filetype, node); + r = hook (buf, filetype, node, hook_data); grub_free (buf); if (r) @@ -623,7 +661,7 @@ make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root) root->stack[0].ino_chunk = grub_le_to_cpu32 (data->sb.root_ino_chunk); root->stack[0].ino_offset = grub_cpu_to_le16 (data->sb.root_ino_offset); return read_chunk (data, &root->ino, sizeof (root->ino), - grub_le_to_cpu64 (data->sb.inodeoffset) + grub_le_to_cpu64 (data->sb.inodeoffset) + root->stack[0].ino_chunk, root->stack[0].ino_offset); } @@ -640,28 +678,34 @@ squash_unmount (struct grub_squash_data *data) } +/* Context for grub_squash_dir. */ +struct grub_squash_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_squash_dir. */ +static int +grub_squash_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_squash_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + info.mtimeset = 1; + info.mtime = grub_le_to_cpu32 (node->ino.mtime); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_squash_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - info.mtimeset = 1; - info.mtime = grub_le_to_cpu32 (node->ino.mtime); - grub_free (node); - return hook (filename, &info); - } - + struct grub_squash_dir_ctx ctx = { hook, hook_data }; struct grub_squash_data *data = 0; struct grub_fshelp_node *fdiro = 0; struct grub_fshelp_node root; @@ -678,7 +722,7 @@ grub_squash_dir (grub_device_t device, const char *path, grub_fshelp_find_file (path, &root, &fdiro, grub_squash_iterate_dir, grub_squash_read_symlink, GRUB_FSHELP_DIR); if (!grub_errno) - grub_squash_iterate_dir (fdiro, iterate); + grub_squash_iterate_dir (fdiro, grub_squash_dir_iter, &ctx); squash_unmount (data); @@ -739,11 +783,11 @@ grub_squash_open (struct grub_file *file, const char *name) } static grub_ssize_t -direct_read (struct grub_squash_data *data, +direct_read (struct grub_squash_data *data, struct grub_squash_cache_inode *ino, grub_off_t off, char *buf, grub_size_t len) { - grub_err_t err; + grub_err_t err = GRUB_ERR_NONE; grub_off_t cumulated_uncompressed_size = 0; grub_uint64_t a = 0; grub_size_t i; @@ -778,10 +822,10 @@ direct_read (struct grub_squash_data *data, break; } total_blocks = ((total_size + data->blksz - 1) >> data->log2_blksz); - ino->block_sizes = grub_malloc (total_blocks - * sizeof (ino->block_sizes[0])); - ino->cumulated_block_sizes = grub_malloc (total_blocks - * sizeof (ino->cumulated_block_sizes[0])); + ino->block_sizes = grub_calloc (total_blocks, + sizeof (ino->block_sizes[0])); + ino->cumulated_block_sizes = grub_calloc (total_blocks, + sizeof (ino->cumulated_block_sizes[0])); if (!ino->block_sizes || !ino->cumulated_block_sizes) { grub_free (ino->block_sizes); @@ -820,7 +864,12 @@ direct_read (struct grub_squash_data *data, curread = data->blksz - boff; if (curread > len) curread = len; - if (!(ino->block_sizes[i] + if (!ino->block_sizes[i]) + { + /* Sparse block */ + grub_memset (buf, '\0', curread); + } + else if (!(ino->block_sizes[i] & grub_cpu_to_le32_compile_time (SQUASH_BLOCK_UNCOMPRESSED))) { char *block; @@ -851,7 +900,7 @@ direct_read (struct grub_squash_data *data, grub_free (block); } else - err = grub_disk_read (data->disk, + err = grub_disk_read (data->disk, (ino->cumulated_block_sizes[i] + a + boff) >> GRUB_DISK_SECTOR_BITS, (ino->cumulated_block_sizes[i] + a + boff) @@ -870,42 +919,63 @@ direct_read (struct grub_squash_data *data, static grub_ssize_t -grub_squash_read_data (struct grub_squash_data *data, - struct grub_squash_cache_inode *ino, - grub_off_t off, char *buf, grub_size_t len) +grub_squash_read (grub_file_t file, char *buf, grub_size_t len) { + struct grub_squash_data *data = file->data; + struct grub_squash_cache_inode *ino = &data->ino; + grub_off_t off = file->offset; grub_err_t err; - grub_uint64_t a = 0, b; + grub_uint64_t a, b; grub_uint32_t fragment = 0; int compressed = 0; struct grub_squash_frag_desc frag; + grub_off_t direct_len; + grub_uint64_t mask = grub_le_to_cpu32 (data->sb.block_size) - 1; + grub_size_t orig_len = len; switch (ino->ino.type) { case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR): - a = grub_le_to_cpu64 (ino->ino.long_file.chunk); fragment = grub_le_to_cpu32 (ino->ino.long_file.fragment); break; case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR): - a = grub_le_to_cpu32 (ino->ino.file.chunk); fragment = grub_le_to_cpu32 (ino->ino.file.fragment); break; } - if (fragment == 0xffffffff) - return direct_read (data, ino, off, buf, len); - + /* Squash may pack file tail as fragment. So read initial part directly and + get tail from fragments */ + direct_len = fragment == 0xffffffff ? file->size : file->size & ~mask; + if (off < direct_len) + { + grub_size_t read_len = direct_len - off; + grub_ssize_t res; + + if (read_len > len) + read_len = len; + res = direct_read (data, ino, off, buf, read_len); + if ((grub_size_t) res != read_len) + return -1; /* FIXME: is short read possible here? */ + len -= read_len; + if (!len) + return read_len; + buf += read_len; + off = 0; + } + else + off -= direct_len; + err = read_chunk (data, &frag, sizeof (frag), data->fragments, sizeof (frag) * fragment); if (err) return -1; - a += grub_le_to_cpu64 (frag.offset); + a = grub_le_to_cpu64 (frag.offset); compressed = !(frag.size & grub_cpu_to_le32_compile_time (SQUASH_BLOCK_UNCOMPRESSED)); if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR)) b = grub_le_to_cpu32 (ino->ino.long_file.offset) + off; else b = grub_le_to_cpu32 (ino->ino.file.offset) + off; - + /* FIXME: cache uncompressed chunks. */ if (compressed) { @@ -940,16 +1010,7 @@ grub_squash_read_data (struct grub_squash_data *data, if (err) return -1; } - return len; -} - -static grub_ssize_t -grub_squash_read (grub_file_t file, char *buf, grub_size_t len) -{ - struct grub_squash_data *data = file->data; - - return grub_squash_read_data (data, &data->ino, - file->offset, buf, len); + return orig_len; } static grub_err_t @@ -960,7 +1021,7 @@ grub_squash_close (grub_file_t file) } static grub_err_t -grub_squash_mtime (grub_device_t dev, grub_int32_t *tm) +grub_squash_mtime (grub_device_t dev, grub_int64_t *tm) { struct grub_squash_data *data = 0; @@ -970,16 +1031,16 @@ grub_squash_mtime (grub_device_t dev, grub_int32_t *tm) *tm = grub_le_to_cpu32 (data->sb.creation_time); squash_unmount (data); return GRUB_ERR_NONE; -} +} static struct grub_fs grub_squash_fs = { .name = "squash4", - .dir = grub_squash_dir, - .open = grub_squash_open, - .read = grub_squash_read, - .close = grub_squash_close, - .mtime = grub_squash_mtime, + .fs_dir = grub_squash_dir, + .fs_open = grub_squash_open, + .fs_read = grub_squash_read, + .fs_close = grub_squash_close, + .fs_mtime = grub_squash_mtime, #ifdef GRUB_UTIL .reserved_first_sector = 0, .blocklist_install = 0, @@ -989,6 +1050,7 @@ static struct grub_fs grub_squash_fs = GRUB_MOD_INIT(squash4) { + grub_squash_fs.mod = mod; grub_fs_register (&grub_squash_fs); } diff --git a/grub-core/fs/tar.c b/grub-core/fs/tar.c index 6ab62bca7..1eaa5349f 100644 --- a/grub-core/fs/tar.c +++ b/grub-core/fs/tar.c @@ -1,2 +1,373 @@ -#define MODE_USTAR 1 -#include "cpio.c" +/* cpio.c - cpio and tar filesystem. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009,2013 Free Software Foundation, 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* tar support */ +#define MAGIC "ustar" +struct head +{ + char name[100]; + char mode[8]; + char uid[8]; + char gid[8]; + char size[12]; + char mtime[12]; + char chksum[8]; + char typeflag; + char linkname[100]; + char magic[6]; + char version[2]; + char uname[32]; + char gname[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; +} GRUB_PACKED; + +static inline unsigned long long +read_number (const char *str, grub_size_t size) +{ + unsigned long long ret = 0; + while (size-- && *str >= '0' && *str <= '7') + ret = (ret << 3) | (*str++ & 0xf); + return ret; +} + +struct grub_archelp_data +{ + grub_disk_t disk; + grub_off_t hofs, next_hofs; + grub_off_t dofs; + grub_off_t size; + char *linkname; + grub_size_t linkname_alloc; +}; + +static grub_err_t +grub_cpio_find_file (struct grub_archelp_data *data, char **name, + grub_int32_t *mtime, + grub_uint32_t *mode) +{ + struct head hd; + int reread = 0, have_longname = 0, have_longlink = 0; + grub_size_t sz; + + data->hofs = data->next_hofs; + *name = NULL; + + for (reread = 0; reread < 3; reread++) + { + if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) + return grub_errno; + + if (!hd.name[0] && !hd.prefix[0]) + { + *mode = GRUB_ARCHELP_ATTR_END; + return GRUB_ERR_NONE; + } + + if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1)) + return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive"); + + if (hd.typeflag == 'L') + { + grub_err_t err; + grub_size_t namesize; + + if (grub_cast (read_number (hd.size, sizeof (hd.size)), &namesize) || + grub_add (namesize, 1, &sz)) + return grub_error (GRUB_ERR_BAD_FS, N_("name size overflow")); + + *name = grub_malloc (sz); + if (*name == NULL) + return grub_errno; + err = grub_disk_read (data->disk, 0, + data->hofs + GRUB_DISK_SECTOR_SIZE, namesize, + *name); + (*name)[namesize] = 0; + if (err) + return err; + data->hofs += GRUB_DISK_SECTOR_SIZE + + ((namesize + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + have_longname = 1; + continue; + } + + if (hd.typeflag == 'K') + { + grub_err_t err; + grub_size_t linksize; + + if (grub_cast (read_number (hd.size, sizeof (hd.size)), &linksize) || + grub_add (linksize, 1, &sz)) + return grub_error (GRUB_ERR_BAD_FS, N_("link size overflow")); + + if (data->linkname_alloc < sz) + { + char *n; + n = grub_calloc (2, sz); + if (!n) + return grub_errno; + grub_free (data->linkname); + data->linkname = n; + data->linkname_alloc = 2 * (sz); + } + + err = grub_disk_read (data->disk, 0, + data->hofs + GRUB_DISK_SECTOR_SIZE, linksize, + data->linkname); + if (err) + return err; + data->linkname[linksize] = 0; + data->hofs += GRUB_DISK_SECTOR_SIZE + + ((linksize + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + have_longlink = 1; + continue; + } + + if (!have_longname) + { + grub_size_t extra_size = 0; + + while (extra_size < sizeof (hd.prefix) + && hd.prefix[extra_size]) + extra_size++; + + if (grub_add (sizeof (hd.name) + 2, extra_size, &sz)) + return grub_error (GRUB_ERR_BAD_FS, N_("long name size overflow")); + *name = grub_malloc (sz); + if (*name == NULL) + return grub_errno; + if (hd.prefix[0]) + { + grub_memcpy (*name, hd.prefix, extra_size); + (*name)[extra_size++] = '/'; + } + grub_memcpy (*name + extra_size, hd.name, sizeof (hd.name)); + (*name)[extra_size + sizeof (hd.name)] = 0; + } + + if (grub_cast (read_number (hd.size, sizeof (hd.size)), &data->size)) + return grub_error (GRUB_ERR_BAD_FS, N_("data size overflow")); + + data->dofs = data->hofs + GRUB_DISK_SECTOR_SIZE; + data->next_hofs = data->dofs + ((data->size + GRUB_DISK_SECTOR_SIZE - 1) & + ~(GRUB_DISK_SECTOR_SIZE - 1)); + if (mtime) + { + if (grub_cast (read_number (hd.mtime, sizeof (hd.mtime)), mtime)) + return grub_error (GRUB_ERR_BAD_FS, N_("mtime overflow")); + } + if (mode) + { + if (grub_cast (read_number (hd.mode, sizeof (hd.mode)), mode)) + return grub_error (GRUB_ERR_BAD_FS, N_("mode overflow")); + + switch (hd.typeflag) + { + /* Hardlink. */ + case '1': + /* Symlink. */ + case '2': + *mode |= GRUB_ARCHELP_ATTR_LNK; + break; + case '0': + *mode |= GRUB_ARCHELP_ATTR_FILE; + break; + case '5': + *mode |= GRUB_ARCHELP_ATTR_DIR; + break; + } + } + if (!have_longlink) + { + if (data->linkname_alloc < 101) + { + char *n; + n = grub_malloc (101); + if (!n) + return grub_errno; + grub_free (data->linkname); + data->linkname = n; + data->linkname_alloc = 101; + } + grub_memcpy (data->linkname, hd.linkname, sizeof (hd.linkname)); + data->linkname[100] = 0; + } + return GRUB_ERR_NONE; + } + + if (*name == NULL) + return grub_error (GRUB_ERR_BAD_FS, "invalid tar archive"); + + return GRUB_ERR_NONE; +} + +static char * +grub_cpio_get_link_target (struct grub_archelp_data *data) +{ + return grub_strdup (data->linkname); +} + +static void +grub_cpio_rewind (struct grub_archelp_data *data) +{ + data->next_hofs = 0; +} + +static struct grub_archelp_ops arcops = + { + .find_file = grub_cpio_find_file, + .get_link_target = grub_cpio_get_link_target, + .rewind = grub_cpio_rewind + }; + +static struct grub_archelp_data * +grub_cpio_mount (grub_disk_t disk) +{ + struct head hd; + struct grub_archelp_data *data; + + if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd)) + goto fail; + + if (grub_memcmp (hd.magic, MAGIC, sizeof (MAGIC) - 1)) + goto fail; + + data = (struct grub_archelp_data *) grub_zalloc (sizeof (*data)); + if (!data) + goto fail; + + data->disk = disk; + + return data; + +fail: + grub_error (GRUB_ERR_BAD_FS, "not a tarfs filesystem"); + return 0; +} + +static grub_err_t +grub_cpio_dir (grub_device_t device, const char *path_in, + grub_fs_dir_hook_t hook, void *hook_data) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cpio_mount (device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_dir (data, &arcops, + path_in, hook, hook_data); + + grub_free (data->linkname); + grub_free (data); + + return err; +} + +static grub_err_t +grub_cpio_open (grub_file_t file, const char *name_in) +{ + struct grub_archelp_data *data; + grub_err_t err; + + data = grub_cpio_mount (file->device->disk); + if (!data) + return grub_errno; + + err = grub_archelp_open (data, &arcops, name_in); + if (err) + { + grub_free (data->linkname); + grub_free (data); + } + else + { + file->data = data; + file->size = data->size; + } + return err; +} + +static grub_ssize_t +grub_cpio_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_archelp_data *data; + grub_ssize_t ret; + + data = file->data; + + data->disk->read_hook = file->read_hook; + data->disk->read_hook_data = file->read_hook_data; + ret = (grub_disk_read (data->disk, 0, data->dofs + file->offset, + len, buf)) ? -1 : (grub_ssize_t) len; + data->disk->read_hook = 0; + + return ret; +} + +static grub_err_t +grub_cpio_close (grub_file_t file) +{ + struct grub_archelp_data *data; + + data = file->data; + grub_free (data->linkname); + grub_free (data); + + return grub_errno; +} + +static struct grub_fs grub_cpio_fs = { + .name = "tarfs", + .fs_dir = grub_cpio_dir, + .fs_open = grub_cpio_open, + .fs_read = grub_cpio_read, + .fs_close = grub_cpio_close, +#ifdef GRUB_UTIL + .reserved_first_sector = 0, + .blocklist_install = 0, +#endif +}; + +GRUB_MOD_INIT (tar) +{ + grub_cpio_fs.mod = mod; + grub_fs_register (&grub_cpio_fs); +} + +GRUB_MOD_FINI (tar) +{ + grub_fs_unregister (&grub_cpio_fs); +} diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index 8e28d41e2..3d5ee5af5 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -112,36 +115,40 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_UDF_PARTMAP_TYPE_1 1 #define GRUB_UDF_PARTMAP_TYPE_2 2 +#define GRUB_UDF_INVALID_STRUCT_PTR(_ptr, _struct) \ + ((char *) (_ptr) >= end_ptr || \ + ((grub_ssize_t) (end_ptr - (char *) (_ptr)) < (grub_ssize_t) sizeof (_struct))) + struct grub_udf_lb_addr { grub_uint32_t block_num; grub_uint16_t part_ref; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_short_ad { grub_uint32_t length; grub_uint32_t position; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_long_ad { grub_uint32_t length; struct grub_udf_lb_addr block; grub_uint8_t imp_use[6]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_extent_ad { grub_uint32_t length; grub_uint32_t start; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_charspec { grub_uint8_t charset_type; grub_uint8_t charset_info[63]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_timestamp { @@ -155,14 +162,14 @@ struct grub_udf_timestamp grub_uint8_t centi_seconds; grub_uint8_t hundreds_of_micro_seconds; grub_uint8_t micro_seconds; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_regid { grub_uint8_t flags; grub_uint8_t ident[23]; grub_uint8_t ident_suffix[8]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_tag { @@ -174,7 +181,7 @@ struct grub_udf_tag grub_uint16_t desc_crc; grub_uint16_t desc_crc_length; grub_uint32_t tag_location; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_fileset { @@ -196,7 +203,7 @@ struct grub_udf_fileset struct grub_udf_regid domain_ident; struct grub_udf_long_ad next_ext; struct grub_udf_long_ad streamdir_icb; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_icbtag { @@ -208,17 +215,18 @@ struct grub_udf_icbtag grub_uint8_t file_type; struct grub_udf_lb_addr parent_idb; grub_uint16_t flags; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_file_ident { struct grub_udf_tag tag; grub_uint16_t version_num; grub_uint8_t characteristics; +#define MAX_FILE_IDENT_LENGTH 256 grub_uint8_t file_ident_length; struct grub_udf_long_ad icb; grub_uint16_t imp_use_length; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_file_entry { @@ -243,7 +251,7 @@ struct grub_udf_file_entry grub_uint32_t ext_attr_length; grub_uint32_t alloc_descs_length; grub_uint8_t ext_attr[0]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_extended_file_entry { @@ -272,20 +280,20 @@ struct grub_udf_extended_file_entry grub_uint32_t ext_attr_length; grub_uint32_t alloc_descs_length; grub_uint8_t ext_attr[0]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_vrs { grub_uint8_t type; grub_uint8_t magic[5]; grub_uint8_t version; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_avdp { struct grub_udf_tag tag; struct grub_udf_extent_ad vds; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_pd { @@ -298,7 +306,7 @@ struct grub_udf_pd grub_uint32_t access_type; grub_uint32_t start; grub_uint32_t length; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_partmap { @@ -317,7 +325,33 @@ struct grub_udf_partmap grub_uint8_t ident[62]; } type2; }; -} __attribute__ ((packed)); +} GRUB_PACKED; + +struct grub_udf_pvd +{ + struct grub_udf_tag tag; + grub_uint32_t seq_num; + grub_uint32_t pvd_num; + grub_uint8_t ident[32]; + grub_uint16_t vol_seq_num; + grub_uint16_t max_vol_seq_num; + grub_uint16_t interchange_level; + grub_uint16_t max_interchange_level; + grub_uint32_t charset_list; + grub_uint32_t max_charset_list; + grub_uint8_t volset_ident[128]; + struct grub_udf_charspec desc_charset; + struct grub_udf_charspec expl_charset; + struct grub_udf_extent_ad vol_abstract; + struct grub_udf_extent_ad vol_copyright; + struct grub_udf_regid app_ident; + struct grub_udf_timestamp recording_time; + struct grub_udf_regid imp_ident; + grub_uint8_t imp_use[64]; + grub_uint32_t pred_vds_loc; + grub_uint16_t flags; + grub_uint8_t reserved[22]; +} GRUB_PACKED; struct grub_udf_lvd { @@ -334,18 +368,19 @@ struct grub_udf_lvd grub_uint8_t imp_use[128]; struct grub_udf_extent_ad integrity_seq_ext; grub_uint8_t part_maps[1608]; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_aed { struct grub_udf_tag tag; grub_uint32_t prev_ae; grub_uint32_t ae_len; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_udf_data { grub_disk_t disk; + struct grub_udf_pvd pvd; struct grub_udf_lvd lvd; struct grub_udf_pd pds[GRUB_UDF_MAX_PDS]; struct grub_udf_partmap *pms[GRUB_UDF_MAX_PMS]; @@ -428,6 +463,7 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) char *ptr; grub_ssize_t len; grub_disk_addr_t filebytes; + char *end_ptr; switch (U16 (node->block.fe.tag.tag_ident)) { @@ -446,9 +482,17 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) return 0; } + end_ptr = (char *) node + get_fshelp_size (node->data); + if ((U16 (node->block.fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK) == GRUB_UDF_ICBTAG_FLAG_AD_SHORT) { + if (GRUB_UDF_INVALID_STRUCT_PTR (ptr, struct grub_udf_short_ad)) + { + grub_error (GRUB_ERR_BAD_FS, "corrupted UDF file system"); + return 0; + } + struct grub_udf_short_ad *ad = (struct grub_udf_short_ad *) ptr; filebytes = fileblock * U32 (node->data->lvd.bsize); @@ -480,6 +524,20 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) } len = U32 (extension->ae_len); + /* + * Ensure AE length is less than block size + * per UDF spec v2.01 section 2.3.11. + * + * node->data->lbshift is initialized by + * grub_udf_mount(). lbshift has a maximum value + * of 3 and it does not cause an overflow here. + */ + if (len < 0 || len > ((grub_ssize_t) 1 << node->data->lbshift)) + { + grub_error (GRUB_ERR_BAD_FS, "invalid ae length"); + goto fail; + } + ad = (struct grub_udf_short_ad *) (buf + sizeof (struct grub_udf_aed)); continue; @@ -498,10 +556,22 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) filebytes -= adlen; ad++; len -= sizeof (struct grub_udf_short_ad); + + if (GRUB_UDF_INVALID_STRUCT_PTR (ad, struct grub_udf_short_ad)) + { + grub_error (GRUB_ERR_BAD_FS, "corrupted UDF file system"); + return 0; + } } } else { + if (GRUB_UDF_INVALID_STRUCT_PTR (ptr, struct grub_udf_long_ad)) + { + grub_error (GRUB_ERR_BAD_FS, "corrupted UDF file system"); + return 0; + } + struct grub_udf_long_ad *ad = (struct grub_udf_long_ad *) ptr; filebytes = fileblock * U32 (node->data->lvd.bsize); @@ -533,11 +603,25 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) } len = U32 (extension->ae_len); + /* + * Ensure AE length is less than block size + * per UDF spec v2.01 section 2.3.11. + * + * node->data->lbshift is initialized by + * grub_udf_mount(). lbshift has a maximum value + * of 3 and it does not cause an overflow here. + */ + if (len < 0 || len > ((grub_ssize_t) 1 << node->data->lbshift)) + { + grub_error (GRUB_ERR_BAD_FS, "invalid ae length"); + goto fail; + } + ad = (struct grub_udf_long_ad *) (buf + sizeof (struct grub_udf_aed)); continue; } - + if (filebytes < adlen) { grub_uint32_t ad_block_num = ad->block.block_num; @@ -553,6 +637,12 @@ grub_udf_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) filebytes -= adlen; ad++; len -= sizeof (struct grub_udf_long_ad); + + if (GRUB_UDF_INVALID_STRUCT_PTR (ad, struct grub_udf_long_ad)) + { + grub_error (GRUB_ERR_BAD_FS, "corrupted UDF file system"); + return 0; + } } } @@ -564,9 +654,7 @@ fail: static grub_ssize_t grub_udf_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR - (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { switch (U16 (node->block.fe.icbtag.flags) & GRUB_UDF_ICBTAG_FLAG_AD_MASK) @@ -574,6 +662,7 @@ grub_udf_read_file (grub_fshelp_node_t node, case GRUB_UDF_ICBTAG_FLAG_AD_IN_ICB: { char *ptr; + char *end_ptr = (char *) node + get_fshelp_size (node->data); ptr = ((U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) ? ((char *) &node->block.fe.ext_attr[0] @@ -581,6 +670,12 @@ grub_udf_read_file (grub_fshelp_node_t node, ((char *) &node->block.efe.ext_attr[0] + U32 (node->block.efe.ext_attr_length))); + if ((ptr + pos + len) > end_ptr) + { + grub_error (GRUB_ERR_BAD_FS, "corrupted UDF file system"); + return 0; + } + grub_memcpy (buf, ptr + pos, len); return len; @@ -591,10 +686,11 @@ grub_udf_read_file (grub_fshelp_node_t node, return 0; } - return grub_fshelp_read_file (node->data->disk, node, read_hook, - pos, len, buf, grub_udf_read_block, - U64 (node->block.fe.file_size), - node->data->lbshift, 0); + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, + pos, len, buf, grub_udf_read_block, + U64 (node->block.fe.file_size), + node->data->lbshift, 0); } static unsigned sblocklist[] = { 256, 512, 0 }; @@ -691,7 +787,17 @@ grub_udf_mount (grub_disk_t disk) } tag.tag_ident = U16 (tag.tag_ident); - if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD) + if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PVD) + { + if (grub_disk_read (disk, block << lbshift, 0, + sizeof (struct grub_udf_pvd), + &data->pvd)) + { + grub_error (GRUB_ERR_BAD_FS, "not an UDF filesystem"); + goto fail; + } + } + else if (tag.tag_ident == GRUB_UDF_TAG_IDENT_PD) { if (data->npd >= GRUB_UDF_MAX_PDS) { @@ -801,6 +907,24 @@ fail: return 0; } +#ifdef GRUB_UTIL +grub_disk_addr_t +grub_udf_get_cluster_sector (grub_disk_t disk, grub_uint64_t *sec_per_lcn) +{ + grub_disk_addr_t ret; + static struct grub_udf_data *data; + + data = grub_udf_mount (disk); + if (!data) + return 0; + + ret = U32 (data->pds[data->pms[0]->type1.part_num].start); + *sec_per_lcn = 1ULL << data->lbshift; + grub_free (data); + return ret; +} +#endif + static char * read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf) { @@ -817,7 +941,7 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf) { unsigned i; utf16len = sz - 1; - utf16 = grub_malloc (utf16len * sizeof (utf16[0])); + utf16 = grub_calloc (utf16len, sizeof (utf16[0])); if (!utf16) return NULL; for (i = 0; i < utf16len; i++) @@ -827,26 +951,52 @@ read_string (const grub_uint8_t *raw, grub_size_t sz, char *outbuf) { unsigned i; utf16len = (sz - 1) / 2; - utf16 = grub_malloc (utf16len * sizeof (utf16[0])); + utf16 = grub_calloc (utf16len, sizeof (utf16[0])); if (!utf16) return NULL; for (i = 0; i < utf16len; i++) utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; } if (!outbuf) - outbuf = grub_malloc (utf16len * GRUB_MAX_UTF8_PER_UTF16 + 1); + { + grub_size_t size; + + if (grub_mul (utf16len, GRUB_MAX_UTF8_PER_UTF16, &size) || + grub_add (size, 1, &size)) + goto fail; + + outbuf = grub_malloc (size); + } if (outbuf) *grub_utf16_to_utf8 ((grub_uint8_t *) outbuf, utf16, utf16len) = '\0'; + + fail: grub_free (utf16); return outbuf; } +static char * +read_dstring (const grub_uint8_t *raw, grub_size_t sz) +{ + grub_size_t len; + + if (raw[0] == 0) { + char *outbuf = grub_malloc (1); + if (!outbuf) + return NULL; + outbuf[0] = 0; + return outbuf; + } + + len = raw[sz - 1]; + if (len > sz - 1) + len = sz - 1; + return read_string (raw, len, NULL); +} + static int grub_udf_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { grub_fshelp_node_t child; struct grub_udf_file_ident dirent; @@ -859,12 +1009,12 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, /* The current directory is not stored. */ grub_memcpy (child, dir, get_fshelp_size (dir->data)); - if (hook (".", GRUB_FSHELP_DIR, child)) + if (hook (".", GRUB_FSHELP_DIR, child, hook_data)) return 1; while (offset < U64 (dir->block.fe.file_size)) { - if (grub_udf_read_file (dir, 0, offset, sizeof (dirent), + if (grub_udf_read_file (dir, 0, 0, offset, sizeof (dirent), (char *) &dirent) != sizeof (dirent)) return 0; @@ -882,36 +1032,45 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, return 0; if (grub_udf_read_icb (dir->data, &dirent.icb, child)) - return 0; - + { + grub_free (child); + return 0; + } if (dirent.characteristics & GRUB_UDF_FID_CHAR_PARENT) { /* This is the parent directory. */ - if (hook ("..", GRUB_FSHELP_DIR, child)) + if (hook ("..", GRUB_FSHELP_DIR, child, hook_data)) return 1; } else { enum grub_fshelp_filetype type; char *filename; - grub_uint8_t raw[dirent.file_ident_length]; + grub_uint8_t raw[MAX_FILE_IDENT_LENGTH]; type = ((dirent.characteristics & GRUB_UDF_FID_CHAR_DIRECTORY) ? (GRUB_FSHELP_DIR) : (GRUB_FSHELP_REG)); if (child->block.fe.icbtag.file_type == GRUB_UDF_ICBTAG_TYPE_SYMLINK) type = GRUB_FSHELP_SYMLINK; - if ((grub_udf_read_file (dir, 0, offset, + if ((grub_udf_read_file (dir, 0, 0, offset, dirent.file_ident_length, (char *) raw)) != dirent.file_ident_length) - return 0; + { + grub_free (child); + return 0; + } filename = read_string (raw, dirent.file_ident_length, 0); if (!filename) - grub_print_error (); + { + /* As the hook won't get called. */ + grub_free (child); + grub_print_error (); + } - if (filename && hook (filename, type, child)) + if (filename && hook (filename, type, child, hook_data)) { grub_free (filename); return 1; @@ -930,25 +1089,35 @@ grub_udf_iterate_dir (grub_fshelp_node_t dir, static char * grub_udf_read_symlink (grub_fshelp_node_t node) { - grub_size_t sz = U64 (node->block.fe.file_size); + grub_size_t s, sz = U64 (node->block.fe.file_size); grub_uint8_t *raw; const grub_uint8_t *ptr; - char *out, *optr; + char *out = NULL, *optr; if (sz < 4) return NULL; raw = grub_malloc (sz); if (!raw) return NULL; - if (grub_udf_read_file (node, NULL, 0, sz, (char *) raw) < 0) - { - grub_free (raw); - return NULL; - } + if (grub_udf_read_file (node, NULL, NULL, 0, sz, (char *) raw) < 0) + goto fail_1; - out = grub_malloc (sz * 2 + 1); + /* + * Local sz is the size of the symlink file data, which contains a sequence + * of path components (ECMA-167 14.16.1) representing the link destination. + * This size is an upper-bound on the number of bytes of a contained and + * potentially compressed UTF-16 character string. Allocate 2*sz for the + * output buffer containing the string converted to UTF-8 because the + * resulting string can not be more than double the size (2-byte unicode + * code points will be converted to a maximum of 3 bytes in UTF-8). + */ + if (grub_mul (sz, 2, &s)) + goto fail_0; + + out = grub_malloc (s); if (!out) { + fail_0: grub_free (raw); return NULL; } @@ -957,19 +1126,19 @@ grub_udf_read_symlink (grub_fshelp_node_t node) for (ptr = raw; ptr < raw + sz; ) { - grub_size_t s; if ((grub_size_t) (ptr - raw + 4) > sz) - goto fail; + goto fail_1; if (!(ptr[2] == 0 && ptr[3] == 0)) - goto fail; + goto fail_1; s = 4 + ptr[1]; if ((grub_size_t) (ptr - raw + s) > sz) - goto fail; + goto fail_1; switch (*ptr) { case 1: if (ptr[1]) - goto fail; + goto fail_1; + /* Fallthrough. */ case 2: /* in 4 bytes. out: 1 byte. */ optr = out; @@ -993,11 +1162,11 @@ grub_udf_read_symlink (grub_fshelp_node_t node) if (optr != out) *optr++ = '/'; if (!read_string (ptr + 4, s - 4, optr)) - goto fail; + goto fail_1; optr += grub_strlen (optr); break; default: - goto fail; + goto fail_1; } ptr += s; } @@ -1005,65 +1174,71 @@ grub_udf_read_symlink (grub_fshelp_node_t node) grub_free (raw); return out; - fail: + fail_1: grub_free (raw); grub_free (out); grub_error (GRUB_ERR_BAD_FS, "invalid symlink"); return NULL; } +/* Context for grub_udf_dir. */ +struct grub_udf_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_udf_dir. */ +static int +grub_udf_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_udf_dir_ctx *ctx = data; + struct grub_dirhook_info info; + const struct grub_udf_timestamp *tstamp = NULL; + + grub_memset (&info, 0, sizeof (info)); + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) + tstamp = &node->block.fe.modification_time; + else if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE) + tstamp = &node->block.efe.modification_time; + + if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000) + { + grub_int16_t tz; + struct grub_datetime datetime; + + datetime.year = U16 (tstamp->year); + datetime.month = tstamp->month; + datetime.day = tstamp->day; + datetime.hour = tstamp->hour; + datetime.minute = tstamp->minute; + datetime.second = tstamp->second; + + tz = U16 (tstamp->type_and_timezone) & 0xfff; + if (tz & 0x800) + tz |= 0xf000; + if (tz == -2047) + tz = 0; + + info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime); + + info.mtime -= 60 * tz; + } + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_udf_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_udf_dir_ctx ctx = { hook, hook_data }; struct grub_udf_data *data = 0; struct grub_fshelp_node *rootnode = 0; struct grub_fshelp_node *foundnode = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - const struct grub_udf_timestamp *tstamp = NULL; - grub_memset (&info, 0, sizeof (info)); - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_FE) - tstamp = &node->block.fe.modification_time; - else if (U16 (node->block.fe.tag.tag_ident) == GRUB_UDF_TAG_IDENT_EFE) - tstamp = &node->block.efe.modification_time; - - if (tstamp && (U16 (tstamp->type_and_timezone) & 0xf000) == 0x1000) - { - grub_int16_t tz; - struct grub_datetime datetime; - - datetime.year = U16 (tstamp->year); - datetime.month = tstamp->month; - datetime.day = tstamp->day; - datetime.hour = tstamp->hour; - datetime.minute = tstamp->minute; - datetime.second = tstamp->second; - - tz = U16 (tstamp->type_and_timezone) & 0xfff; - if (tz & 0x800) - tz |= 0xf000; - if (tz == -2047) - tz = 0; - - info.mtimeset = !!grub_datetime2unixtime (&datetime, &info.mtime); - - info.mtime -= 60 * tz; - } - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_udf_mount (device->disk); @@ -1083,7 +1258,7 @@ grub_udf_dir (grub_device_t device, const char *path, GRUB_FSHELP_DIR)) goto fail; - grub_udf_iterate_dir (foundnode, iterate); + grub_udf_iterate_dir (foundnode, grub_udf_dir_iter, &ctx); if (foundnode != rootnode) grub_free (foundnode); @@ -1146,7 +1321,8 @@ grub_udf_read (grub_file_t file, char *buf, grub_size_t len) { struct grub_fshelp_node *node = (struct grub_fshelp_node *) file->data; - return grub_udf_read_file (node, file->read_hook, file->offset, len, buf); + return grub_udf_read_file (node, file->read_hook, file->read_hook_data, + file->offset, len, buf); } static grub_err_t @@ -1173,7 +1349,7 @@ grub_udf_label (grub_device_t device, char **label) if (data) { - *label = read_string (data->lvd.ident, sizeof (data->lvd.ident), 0); + *label = read_dstring (data->lvd.ident, sizeof (data->lvd.ident)); grub_free (data); } else @@ -1182,13 +1358,95 @@ grub_udf_label (grub_device_t device, char **label) return grub_errno; } +static char * +gen_uuid_from_volset (char *volset_ident) +{ + grub_size_t i; + grub_size_t len; + grub_size_t nonhexpos; + grub_uint8_t buf[17]; + char *uuid; + + len = grub_strlen (volset_ident); + if (len < 8) + return NULL; + + uuid = grub_malloc (17); + if (!uuid) + return NULL; + + if (len > 16) + len = 16; + + grub_memset (buf, 0, sizeof (buf)); + grub_memcpy (buf, volset_ident, len); + + nonhexpos = 16; + for (i = 0; i < 16; ++i) + { + if (!grub_isxdigit (buf[i])) + { + nonhexpos = i; + break; + } + } + + if (nonhexpos < 8) + { + grub_snprintf (uuid, 17, "%02x%02x%02x%02x%02x%02x%02x%02x", + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7]); + } + else if (nonhexpos < 16) + { + for (i = 0; i < 8; ++i) + uuid[i] = grub_tolower (buf[i]); + grub_snprintf (uuid+8, 9, "%02x%02x%02x%02x", + buf[8], buf[9], buf[10], buf[11]); + } + else + { + for (i = 0; i < 16; ++i) + uuid[i] = grub_tolower (buf[i]); + uuid[16] = 0; + } + + return uuid; +} + +static grub_err_t +grub_udf_uuid (grub_device_t device, char **uuid) +{ + char *volset_ident; + struct grub_udf_data *data; + data = grub_udf_mount (device->disk); + + if (data) + { + volset_ident = read_dstring (data->pvd.volset_ident, sizeof (data->pvd.volset_ident)); + if (volset_ident) + { + *uuid = gen_uuid_from_volset (volset_ident); + grub_free (volset_ident); + } + else + *uuid = 0; + grub_free (data); + } + else + *uuid = 0; + + return grub_errno; +} + static struct grub_fs grub_udf_fs = { .name = "udf", - .dir = grub_udf_dir, - .open = grub_udf_open, - .read = grub_udf_read, - .close = grub_udf_close, - .label = grub_udf_label, + .fs_dir = grub_udf_dir, + .fs_open = grub_udf_open, + .fs_read = grub_udf_read, + .fs_close = grub_udf_close, + .fs_label = grub_udf_label, + .fs_uuid = grub_udf_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 1, .blocklist_install = 1, @@ -1198,11 +1456,16 @@ static struct grub_fs grub_udf_fs = { GRUB_MOD_INIT (udf) { - grub_fs_register (&grub_udf_fs); + if (!grub_is_lockdown ()) + { + grub_udf_fs.mod = mod; + grub_fs_register (&grub_udf_fs); + } my_mod = mod; } GRUB_MOD_FINI (udf) { - grub_fs_unregister (&grub_udf_fs); + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_udf_fs); } diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index bd0cd1f49..8b5adbd48 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -25,6 +25,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -49,18 +50,46 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_UFS_VOLNAME_LEN 32 +#ifdef MODE_BIGENDIAN +#define grub_ufs_to_cpu16 grub_be_to_cpu16 +#define grub_ufs_to_cpu32 grub_be_to_cpu32 +#define grub_ufs_to_cpu64 grub_be_to_cpu64 +#define grub_cpu_to_ufs32_compile_time grub_cpu_to_be32_compile_time +#else +#define grub_ufs_to_cpu16 grub_le_to_cpu16 +#define grub_ufs_to_cpu32 grub_le_to_cpu32 +#define grub_ufs_to_cpu64 grub_le_to_cpu64 +#define grub_cpu_to_ufs32_compile_time grub_cpu_to_le32_compile_time +#endif + +#ifdef MODE_UFS2 +typedef grub_uint64_t grub_ufs_blk_t; +static inline grub_disk_addr_t +grub_ufs_to_cpu_blk (grub_ufs_blk_t blk) +{ + return grub_ufs_to_cpu64 (blk); +} +#else +typedef grub_uint32_t grub_ufs_blk_t; +static inline grub_disk_addr_t +grub_ufs_to_cpu_blk (grub_ufs_blk_t blk) +{ + return grub_ufs_to_cpu32 (blk); +} +#endif + /* Calculate in which group the inode can be found. */ -#define UFS_BLKSZ(sblock) (grub_le_to_cpu32 (sblock->bsize)) +#define UFS_BLKSZ(sblock) (grub_ufs_to_cpu32 (sblock->bsize)) #define UFS_LOG_BLKSZ(sblock) (data->log2_blksz) #ifdef MODE_UFS2 -#define INODE_ENDIAN(data,field,bits1,bits2) grub_le_to_cpu##bits2 (data->inode.field) +#define INODE_ENDIAN(data,field,bits1,bits2) grub_ufs_to_cpu##bits2 (data->inode.field) #else -#define INODE_ENDIAN(data,field,bits1,bits2) grub_le_to_cpu##bits1 (data->inode.field) +#define INODE_ENDIAN(data,field,bits1,bits2) grub_ufs_to_cpu##bits1 (data->inode.field) #endif -#define INODE_SIZE(data) grub_le_to_cpu64 (data->inode.size) -#define INODE_MODE(data) grub_le_to_cpu16 (data->inode.mode) +#define INODE_SIZE(data) grub_ufs_to_cpu64 (data->inode.size) +#define INODE_MODE(data) grub_ufs_to_cpu16 (data->inode.mode) #ifdef MODE_UFS2 #define LOG_INODE_BLKSZ 3 #else @@ -139,9 +168,9 @@ struct grub_ufs_inode grub_uint64_t mtime; grub_uint64_t ctime; grub_uint64_t create_time; - grub_uint32_t atime_sec; - grub_uint32_t mtime_sec; - grub_uint32_t ctime_sec; + grub_uint32_t atime_usec; + grub_uint32_t mtime_usec; + grub_uint32_t ctime_usec; grub_uint32_t create_time_sec; grub_uint32_t gen; grub_uint32_t kernel_flags; @@ -159,7 +188,7 @@ struct grub_ufs_inode }; grub_uint8_t unused[24]; -} __attribute__ ((packed)); +} GRUB_PACKED; #else /* UFS inode. */ struct grub_ufs_inode @@ -169,9 +198,12 @@ struct grub_ufs_inode grub_uint16_t uid; grub_uint16_t gid; grub_uint64_t size; - grub_uint64_t atime; - grub_uint64_t mtime; - grub_uint64_t ctime; + grub_uint32_t atime; + grub_uint32_t atime_usec; + grub_uint32_t mtime; + grub_uint32_t mtime_usec; + grub_uint32_t ctime; + grub_uint32_t ctime_usec; union { struct @@ -186,7 +218,7 @@ struct grub_ufs_inode grub_uint32_t gen; grub_uint32_t unused; grub_uint8_t pad[12]; -} __attribute__ ((packed)); +} GRUB_PACKED; #endif /* Directory entry. */ @@ -203,7 +235,7 @@ struct grub_ufs_dirent grub_uint8_t namelen_bsd; }; }; -} __attribute__ ((packed)); +} GRUB_PACKED; /* Information about a "mounted" ufs filesystem. */ struct grub_ufs_data @@ -226,7 +258,6 @@ static grub_err_t grub_ufs_find_file (struct grub_ufs_data *data, static grub_disk_addr_t grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk) { - struct grub_ufs_sblock *sblock = &data->sblock; unsigned long indirsz; int log2_blksz, log_indirsz; @@ -234,47 +265,41 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk) if (blk < GRUB_UFS_DIRBLKS) return INODE_DIRBLOCKS (data, blk); - log2_blksz = grub_le_to_cpu32 (data->sblock.log2_blksz); + log2_blksz = grub_ufs_to_cpu32 (data->sblock.log2_blksz); blk -= GRUB_UFS_DIRBLKS; log_indirsz = data->log2_blksz - LOG_INODE_BLKSZ; indirsz = 1 << log_indirsz; + /* Single indirect block. */ if (blk < indirsz) { -#ifdef MODE_UFS2 - grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)]; -#else - grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)]; -#endif + grub_ufs_blk_t indir; grub_disk_read (data->disk, ((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 0)) << log2_blksz, - 0, sizeof (indir), indir); - return indir[blk]; + blk * sizeof (indir), sizeof (indir), &indir); + return indir; } blk -= indirsz; /* Double indirect block. */ if (blk < (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz) { -#ifdef MODE_UFS2 - grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)]; -#else - grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)]; -#endif + grub_ufs_blk_t indir; grub_disk_read (data->disk, ((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 1)) << log2_blksz, - 0, sizeof (indir), indir); + (blk >> log_indirsz) * sizeof (indir), + sizeof (indir), &indir); grub_disk_read (data->disk, - ((grub_disk_addr_t) indir [blk >> log_indirsz]) - << log2_blksz, - 0, sizeof (indir), indir); + grub_ufs_to_cpu_blk (indir) << log2_blksz, + (blk & ((1 << log_indirsz) - 1)) * sizeof (indir), + sizeof (indir), &indir); - return indir[blk & ((1 << log_indirsz) - 1)]; + return indir; } blk -= (grub_disk_addr_t) indirsz * (grub_disk_addr_t) indirsz; @@ -282,31 +307,28 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk) /* Triple indirect block. */ if (!(blk >> (3 * log_indirsz))) { -#ifdef MODE_UFS2 - grub_uint64_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint64_t)]; -#else - grub_uint32_t indir[UFS_BLKSZ (sblock) / sizeof (grub_uint32_t)]; -#endif + grub_ufs_blk_t indir; grub_disk_read (data->disk, ((grub_disk_addr_t) INODE_INDIRBLOCKS (data, 2)) << log2_blksz, - 0, sizeof (indir), indir); + (blk >> (2 * log_indirsz)) * sizeof (indir), + sizeof (indir), &indir); grub_disk_read (data->disk, - ((grub_disk_addr_t) indir [blk >> (2 * log_indirsz)]) - << log2_blksz, - 0, sizeof (indir), indir); + grub_ufs_to_cpu_blk (indir) << log2_blksz, + ((blk >> log_indirsz) + & ((1 << log_indirsz) - 1)) * sizeof (indir), + sizeof (indir), &indir); grub_disk_read (data->disk, - ((grub_disk_addr_t) indir [(blk >> log_indirsz) - & ((1 << log_indirsz) - 1)]) - << log2_blksz, - 0, sizeof (indir), indir); + grub_ufs_to_cpu_blk (indir) << log2_blksz, + (blk & ((1 << log_indirsz) - 1)) * sizeof (indir), + sizeof (indir), &indir); - return indir[blk & ((1 << log_indirsz) - 1)]; + return indir; } - grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + grub_error (GRUB_ERR_BAD_FS, "ufs does not support quadruple indirect blocks"); return 0; } @@ -316,8 +338,7 @@ grub_ufs_get_file_block (struct grub_ufs_data *data, grub_disk_addr_t blk) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_ufs_read_file (struct grub_ufs_data *data, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), + grub_disk_read_hook_t read_hook, void *read_hook_data, grub_off_t pos, grub_size_t len, char *buf) { struct grub_ufs_sblock *sblock = &data->sblock; @@ -365,15 +386,16 @@ grub_ufs_read_file (struct grub_ufs_data *data, if (blknr) { data->disk->read_hook = read_hook; + data->disk->read_hook_data = read_hook_data; grub_disk_read (data->disk, - blknr << grub_le_to_cpu32 (data->sblock.log2_blksz), + blknr << grub_ufs_to_cpu32 (data->sblock.log2_blksz), skipfirst, blockend, buf); data->disk->read_hook = 0; if (grub_errno) return -1; } else - grub_memset (buf, UFS_BLKSZ (sblock) - skipfirst, 0); + grub_memset (buf, 0, blockend); buf += UFS_BLKSZ (sblock) - skipfirst; } @@ -389,17 +411,17 @@ grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode) struct grub_ufs_sblock *sblock = &data->sblock; /* Determine the group the inode is in. */ - int group = ino / grub_le_to_cpu32 (sblock->ino_per_group); + int group = ino / grub_ufs_to_cpu32 (sblock->ino_per_group); /* Determine the inode within the group. */ - int grpino = ino % grub_le_to_cpu32 (sblock->ino_per_group); + int grpino = ino % grub_ufs_to_cpu32 (sblock->ino_per_group); /* The first block of the group. */ - int grpblk = group * (grub_le_to_cpu32 (sblock->frags_per_group)); + int grpblk = group * (grub_ufs_to_cpu32 (sblock->frags_per_group)); #ifndef MODE_UFS2 - grpblk += grub_le_to_cpu32 (sblock->cylg_offset) - * (group & (~grub_le_to_cpu32 (sblock->cylg_mask))); + grpblk += grub_ufs_to_cpu32 (sblock->cylg_offset) + * (group & (~grub_ufs_to_cpu32 (sblock->cylg_mask))); #endif if (!inode) @@ -409,8 +431,8 @@ grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode) } grub_disk_read (data->disk, - ((grub_le_to_cpu32 (sblock->inoblk_offs) + grpblk) - << grub_le_to_cpu32 (data->sblock.log2_blksz)) + ((grub_ufs_to_cpu32 (sblock->inoblk_offs) + grpblk) + << grub_ufs_to_cpu32 (data->sblock.log2_blksz)) + grpino / UFS_INODE_PER_BLOCK, (grpino % UFS_INODE_PER_BLOCK) * sizeof (struct grub_ufs_inode), @@ -426,11 +448,15 @@ grub_ufs_read_inode (struct grub_ufs_data *data, int ino, char *inode) static grub_err_t grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) { - char symlink[INODE_SIZE (data) + 1]; + char *symlink; + grub_size_t sz = INODE_SIZE (data); if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT) return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks")); + symlink = grub_malloc (sz + 1); + if (!symlink) + return grub_errno; /* Normally we should just check that data->inode.nblocks == 0. However old Linux doesn't maintain nblocks correctly and so it's always 0. If size is bigger than inline space then the symlink is surely not @@ -438,10 +464,16 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) /* Check against zero is paylindromic, no need to swap. */ if (data->inode.nblocks == 0 && INODE_SIZE (data) <= sizeof (data->inode.symlink)) - grub_strcpy (symlink, (char *) data->inode.symlink); + grub_strlcpy (symlink, (char *) data->inode.symlink, sz); else - grub_ufs_read_file (data, 0, 0, INODE_SIZE (data), symlink); - symlink[INODE_SIZE (data)] = '\0'; + { + if (grub_ufs_read_file (data, 0, 0, 0, sz, symlink) < 0) + { + grub_free(symlink); + return grub_errno; + } + } + symlink[sz] = '\0'; /* The symlink is an absolute path, go back to the root inode. */ if (symlink[0] == '/') @@ -449,10 +481,15 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) /* Now load in the old inode. */ if (grub_ufs_read_inode (data, ino, 0)) - return grub_errno; + { + grub_free (symlink); + return grub_errno; + } grub_ufs_find_file (data, symlink); + grub_free (symlink); + return grub_errno; } @@ -462,95 +499,91 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) static grub_err_t grub_ufs_find_file (struct grub_ufs_data *data, const char *path) { - char fpath[grub_strlen (path) + 1]; - char *name = fpath; - char *next; + const char *name; + const char *next = path; unsigned int pos = 0; int dirino; + char *filename; - grub_strcpy (fpath, path); + /* We reject filenames longer than the one we're looking + for without reading, so this allocation is enough. */ + filename = grub_malloc (grub_strlen (path) + 2); + if (!filename) + return grub_errno; - /* Skip the first slash. */ - while (*name == '/') - name++; - if (!*name) - return 0; - - /* Extract the actual part from the pathname. */ - next = grub_strchr (name, '/'); - if (next) - { - next[0] = '\0'; - next++; - while (*next == '/') - next++; - } - - do + while (1) { struct grub_ufs_dirent dirent; - int namelen; - if (grub_strlen (name) == 0) - return GRUB_ERR_NONE; + name = next; + /* Skip the first slash. */ + while (*name == '/') + name++; + if (*name == 0) + { + grub_free (filename); + return GRUB_ERR_NONE; + } - if (grub_ufs_read_file (data, 0, pos, sizeof (dirent), - (char *) &dirent) < 0) - return grub_errno; + if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) + != GRUB_UFS_ATTR_DIR) + { + grub_error (GRUB_ERR_BAD_FILE_TYPE, + N_("not a directory")); + goto fail; + } + + /* Extract the actual part from the pathname. */ + for (next = name; *next && *next != '/'; next++); + for (pos = 0; ; pos += grub_ufs_to_cpu16 (dirent.direntlen)) + { + int namelen; + + if (pos >= INODE_SIZE (data)) + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, + N_("file `%s' not found"), + path); + goto fail; + } + + if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent), + (char *) &dirent) < 0) + goto fail; #ifdef MODE_UFS2 - namelen = dirent.namelen_bsd; + namelen = dirent.namelen_bsd; #else - namelen = grub_le_to_cpu16 (dirent.namelen); + namelen = grub_ufs_to_cpu16 (dirent.namelen); #endif - { - char filename[namelen + 1]; - - if (grub_ufs_read_file (data, 0, pos + sizeof (dirent), - namelen, filename) < 0) - return grub_errno; - - filename[namelen] = '\0'; - - if (!grub_strcmp (name, filename)) - { - dirino = data->ino; - grub_ufs_read_inode (data, grub_le_to_cpu32 (dirent.ino), 0); - - if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) - == GRUB_UFS_ATTR_LNK) - { - grub_ufs_lookup_symlink (data, dirino); - if (grub_errno) - return grub_errno; - } - - if (!next) - return 0; - - pos = 0; - - name = next; - next = grub_strchr (name, '/'); - if (next) - { - next[0] = '\0'; - next++; - while (*next == '/') - next++; - } - - if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) != GRUB_UFS_ATTR_DIR) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); - + if (namelen < next - name) continue; - } - } - pos += grub_le_to_cpu16 (dirent.direntlen); - } while (pos < INODE_SIZE (data)); + if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent), + next - name + (namelen != next - name), + filename) < 0) + goto fail; - grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); + if (grub_strncmp (name, filename, next - name) == 0 + && (namelen == next - name || filename[next - name] == '\0')) + { + dirino = data->ino; + grub_ufs_read_inode (data, grub_ufs_to_cpu32 (dirent.ino), 0); + + if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) + == GRUB_UFS_ATTR_LNK) + { + grub_ufs_lookup_symlink (data, dirino); + if (grub_errno) + goto fail; + } + + break; + } + } + } + fail: + grub_free (filename); return grub_errno; } @@ -576,12 +609,13 @@ grub_ufs_mount (grub_disk_t disk) /* No need to byteswap bsize in this check. It works the same on both endiannesses. */ - if (grub_le_to_cpu32 (data->sblock.magic) == GRUB_UFS_MAGIC + if (data->sblock.magic == grub_cpu_to_ufs32_compile_time (GRUB_UFS_MAGIC) && data->sblock.bsize != 0 - && ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0)) + && ((data->sblock.bsize & (data->sblock.bsize - 1)) == 0) + && data->sblock.ino_per_group != 0) { - for (data->log2_blksz = 0; - (1U << data->log2_blksz) < grub_le_to_cpu32 (data->sblock.bsize); + for (data->log2_blksz = 0; + (1U << data->log2_blksz) < grub_ufs_to_cpu32 (data->sblock.bsize); data->log2_blksz++); data->disk = disk; @@ -610,8 +644,7 @@ grub_ufs_mount (grub_disk_t disk) static grub_err_t grub_ufs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { struct grub_ufs_data *data; unsigned int pos = 0; @@ -645,40 +678,56 @@ grub_ufs_dir (grub_device_t device, const char *path, struct grub_ufs_dirent dirent; int namelen; - if (grub_ufs_read_file (data, 0, pos, sizeof (dirent), + if (grub_ufs_read_file (data, 0, 0, pos, sizeof (dirent), (char *) &dirent) < 0) break; + if (dirent.direntlen == 0) + break; + #ifdef MODE_UFS2 namelen = dirent.namelen_bsd; #else - namelen = grub_le_to_cpu16 (dirent.namelen); + namelen = grub_ufs_to_cpu16 (dirent.namelen); #endif - { - char filename[namelen + 1]; - struct grub_dirhook_info info; - struct grub_ufs_inode inode; + char *filename = grub_malloc (namelen + 1); + if (!filename) + goto fail; + struct grub_dirhook_info info; + struct grub_ufs_inode inode; - grub_memset (&info, 0, sizeof (info)); + grub_memset (&info, 0, sizeof (info)); - if (grub_ufs_read_file (data, 0, pos + sizeof (dirent), - namelen, filename) < 0) + if (grub_ufs_read_file (data, 0, 0, pos + sizeof (dirent), + namelen, filename) < 0) + { + grub_free (filename); break; + } - filename[namelen] = '\0'; - grub_ufs_read_inode (data, dirent.ino, (char *) &inode); + filename[namelen] = '\0'; + grub_ufs_read_inode (data, grub_ufs_to_cpu32 (dirent.ino), + (char *) &inode); - info.dir = ((grub_le_to_cpu16 (inode.mode) & GRUB_UFS_ATTR_TYPE) - == GRUB_UFS_ATTR_DIR); - info.mtime = grub_le_to_cpu64 (inode.mtime); - info.mtimeset = 1; + info.dir = ((grub_ufs_to_cpu16 (inode.mode) & GRUB_UFS_ATTR_TYPE) + == GRUB_UFS_ATTR_DIR); +#ifdef MODE_UFS2 + info.mtime = grub_ufs_to_cpu64 (inode.mtime); +#else + info.mtime = grub_ufs_to_cpu32 (inode.mtime); +#endif + info.mtimeset = 1; - if (hook (filename, &info)) + if (hook (filename, &info, hook_data)) + { + grub_free (filename); break; - } + } - pos += grub_le_to_cpu16 (dirent.direntlen); + grub_free (filename); + + pos += grub_ufs_to_cpu16 (dirent.direntlen); } fail: @@ -730,7 +779,8 @@ grub_ufs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_ufs_data *data = (struct grub_ufs_data *) file->data; - return grub_ufs_read_file (data, file->read_hook, file->offset, len, buf); + return grub_ufs_read_file (data, file->read_hook, file->read_hook_data, + file->offset, len, buf); } @@ -773,8 +823,8 @@ grub_ufs_uuid (grub_device_t device, char **uuid) data = grub_ufs_mount (disk); if (data && (data->sblock.uuidhi != 0 || data->sblock.uuidlow != 0)) *uuid = grub_xasprintf ("%08x%08x", - (unsigned) grub_le_to_cpu32 (data->sblock.uuidhi), - (unsigned) grub_le_to_cpu32 (data->sblock.uuidlow)); + (unsigned) grub_ufs_to_cpu32 (data->sblock.uuidhi), + (unsigned) grub_ufs_to_cpu32 (data->sblock.uuidlow)); else *uuid = NULL; @@ -788,7 +838,7 @@ grub_ufs_uuid (grub_device_t device, char **uuid) /* Get mtime. */ static grub_err_t -grub_ufs_mtime (grub_device_t device, grub_int32_t *tm) +grub_ufs_mtime (grub_device_t device, grub_int64_t *tm) { struct grub_ufs_data *data = 0; @@ -799,10 +849,10 @@ grub_ufs_mtime (grub_device_t device, grub_int32_t *tm) *tm = 0; else { - *tm = grub_le_to_cpu32 (data->sblock.mtime); + *tm = grub_ufs_to_cpu32 (data->sblock.mtime); #ifdef MODE_UFS2 - if (*tm < (grub_int64_t) grub_le_to_cpu64 (data->sblock.mtime2)) - *tm = grub_le_to_cpu64 (data->sblock.mtime2); + if (*tm < (grub_int64_t) grub_ufs_to_cpu64 (data->sblock.mtime2)) + *tm = grub_ufs_to_cpu64 (data->sblock.mtime2); #endif } @@ -819,16 +869,20 @@ static struct grub_fs grub_ufs_fs = { #ifdef MODE_UFS2 .name = "ufs2", +#else +#ifdef MODE_BIGENDIAN + .name = "ufs1_be", #else .name = "ufs1", #endif - .dir = grub_ufs_dir, - .open = grub_ufs_open, - .read = grub_ufs_read, - .close = grub_ufs_close, - .label = grub_ufs_label, - .uuid = grub_ufs_uuid, - .mtime = grub_ufs_mtime, +#endif + .fs_dir = grub_ufs_dir, + .fs_open = grub_ufs_open, + .fs_read = grub_ufs_read, + .fs_close = grub_ufs_close, + .fs_label = grub_ufs_label, + .fs_uuid = grub_ufs_uuid, + .fs_mtime = grub_ufs_mtime, /* FIXME: set reserved_first_sector. */ #ifdef GRUB_UTIL .blocklist_install = 1, @@ -839,19 +893,32 @@ static struct grub_fs grub_ufs_fs = #ifdef MODE_UFS2 GRUB_MOD_INIT(ufs2) #else +#ifdef MODE_BIGENDIAN +GRUB_MOD_INIT(ufs1_be) +#else GRUB_MOD_INIT(ufs1) #endif +#endif { - grub_fs_register (&grub_ufs_fs); + if (!grub_is_lockdown ()) + { + grub_ufs_fs.mod = mod; + grub_fs_register (&grub_ufs_fs); + } my_mod = mod; } #ifdef MODE_UFS2 GRUB_MOD_FINI(ufs2) #else +#ifdef MODE_BIGENDIAN +GRUB_MOD_FINI(ufs1_be) +#else GRUB_MOD_FINI(ufs1) #endif +#endif { - grub_fs_unregister (&grub_ufs_fs); + if (!grub_is_lockdown ()) + grub_fs_unregister (&grub_ufs_fs); } diff --git a/grub-core/fs/ufs_be.c b/grub-core/fs/ufs_be.c new file mode 100644 index 000000000..a58f75a99 --- /dev/null +++ b/grub-core/fs/ufs_be.c @@ -0,0 +1,2 @@ +#define MODE_BIGENDIAN 1 +#include "ufs.c" diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index 2c6b00c2a..1bc4017ca 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -23,8 +23,10 @@ #include #include #include +#include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -34,6 +36,91 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define XFS_INODE_FORMAT_EXT 2 #define XFS_INODE_FORMAT_BTREE 3 +/* Superblock version field flags */ +#define XFS_SB_VERSION_NUMBITS 0x000f +#define XFS_SB_VERSION_ATTRBIT 0x0010 +#define XFS_SB_VERSION_NLINKBIT 0x0020 +#define XFS_SB_VERSION_QUOTABIT 0x0040 +#define XFS_SB_VERSION_ALIGNBIT 0x0080 +#define XFS_SB_VERSION_DALIGNBIT 0x0100 +#define XFS_SB_VERSION_LOGV2BIT 0x0400 +#define XFS_SB_VERSION_SECTORBIT 0x0800 +#define XFS_SB_VERSION_EXTFLGBIT 0x1000 +#define XFS_SB_VERSION_DIRV2BIT 0x2000 +#define XFS_SB_VERSION_MOREBITSBIT 0x8000 +#define XFS_SB_VERSION_BITS_SUPPORTED \ + (XFS_SB_VERSION_NUMBITS | \ + XFS_SB_VERSION_ATTRBIT | \ + XFS_SB_VERSION_NLINKBIT | \ + XFS_SB_VERSION_QUOTABIT | \ + XFS_SB_VERSION_ALIGNBIT | \ + XFS_SB_VERSION_DALIGNBIT | \ + XFS_SB_VERSION_LOGV2BIT | \ + XFS_SB_VERSION_SECTORBIT | \ + XFS_SB_VERSION_EXTFLGBIT | \ + XFS_SB_VERSION_DIRV2BIT | \ + XFS_SB_VERSION_MOREBITSBIT) + +/* Recognized xfs format versions */ +#define XFS_SB_VERSION_4 4 /* Good old XFS filesystem */ +#define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */ + +/* features2 field flags */ +#define XFS_SB_VERSION2_LAZYSBCOUNTBIT 0x00000002 /* Superblk counters */ +#define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */ +#define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32-bit project ids */ +#define XFS_SB_VERSION2_FTYPE 0x00000200 /* inode type in dir */ +#define XFS_SB_VERSION2_BITS_SUPPORTED \ + (XFS_SB_VERSION2_LAZYSBCOUNTBIT | \ + XFS_SB_VERSION2_ATTR2BIT | \ + XFS_SB_VERSION2_PROJID32BIT | \ + XFS_SB_VERSION2_FTYPE) + +/* Inode flags2 flags */ +#define XFS_DIFLAG2_BIGTIME_BIT 3 +#define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT) +#define XFS_DIFLAG2_NREXT64_BIT 4 +#define XFS_DIFLAG2_NREXT64 (1 << XFS_DIFLAG2_NREXT64_BIT) + +/* incompat feature flags */ +#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ +#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ +#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ +#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */ +#define XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR (1 << 4) /* needs xfs_repair */ +#define XFS_SB_FEAT_INCOMPAT_NREXT64 (1 << 5) /* large extent counters */ +#define XFS_SB_FEAT_INCOMPAT_EXCHRANGE (1 << 6) /* exchangerange supported */ +#define XFS_SB_FEAT_INCOMPAT_PARENT (1 << 7) /* parent pointers */ +#define XFS_SB_FEAT_INCOMPAT_METADIR (1 << 8) /* metadata dir tree */ + +/* + * Directory entries with ftype are explicitly handled by GRUB code. + * + * We do not currently read the inode btrees, so it is safe to read filesystems + * with the XFS_SB_FEAT_INCOMPAT_SPINODES feature. + * + * We do not currently verify metadata UUID, so it is safe to read filesystems + * with the XFS_SB_FEAT_INCOMPAT_META_UUID feature. + * + * We do not currently replay the log, so it is safe to read filesystems + * with the XFS_SB_FEAT_INCOMPAT_EXCHRANGE feature. + * + * We do not currently read directory parent pointers, so it is safe to read + * filesystems with the XFS_SB_FEAT_INCOMPAT_PARENT feature. + * + * We do not currently look at realtime or quota metadata, so it is safe to + * read filesystems with the XFS_SB_FEAT_INCOMPAT_METADIR feature. + */ +#define XFS_SB_FEAT_INCOMPAT_SUPPORTED \ + (XFS_SB_FEAT_INCOMPAT_FTYPE | \ + XFS_SB_FEAT_INCOMPAT_SPINODES | \ + XFS_SB_FEAT_INCOMPAT_META_UUID | \ + XFS_SB_FEAT_INCOMPAT_BIGTIME | \ + XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR | \ + XFS_SB_FEAT_INCOMPAT_NREXT64 | \ + XFS_SB_FEAT_INCOMPAT_EXCHRANGE | \ + XFS_SB_FEAT_INCOMPAT_PARENT | \ + XFS_SB_FEAT_INCOMPAT_METADIR) struct grub_xfs_sblock { @@ -45,7 +132,9 @@ struct grub_xfs_sblock grub_uint64_t rootino; grub_uint8_t unused3[20]; grub_uint32_t agsize; - grub_uint8_t unused4[20]; + grub_uint8_t unused4[12]; + grub_uint16_t version; + grub_uint8_t unused5[6]; grub_uint8_t label[12]; grub_uint8_t log2_bsize; grub_uint8_t log2_sect; @@ -54,34 +143,49 @@ struct grub_xfs_sblock grub_uint8_t log2_agblk; grub_uint8_t unused6[67]; grub_uint8_t log2_dirblk; -} __attribute__ ((packed)); + grub_uint8_t unused7[7]; + grub_uint32_t features2; + grub_uint8_t unused8[4]; + grub_uint32_t sb_features_compat; + grub_uint32_t sb_features_ro_compat; + grub_uint32_t sb_features_incompat; + grub_uint32_t sb_features_log_incompat; +} GRUB_PACKED; struct grub_xfs_dir_header { grub_uint8_t count; - grub_uint8_t smallino; + grub_uint8_t largeino; union { grub_uint32_t i4; grub_uint64_t i8; - } parent __attribute__ ((packed)); -} __attribute__ ((packed)); + } GRUB_PACKED parent; +} GRUB_PACKED; +/* Structure for directory entry inlined in the inode */ struct grub_xfs_dir_entry { grub_uint8_t len; grub_uint16_t offset; char name[1]; - /* Inode number follows, 32 bits. */ -} __attribute__ ((packed)); + /* Inode number follows, 32 / 64 bits. */ +} GRUB_PACKED; +/* Structure for directory entry in a block */ struct grub_xfs_dir2_entry { grub_uint64_t inode; grub_uint8_t len; -} __attribute__ ((packed)); +} GRUB_PACKED; -typedef grub_uint32_t grub_xfs_extent[4]; +struct grub_xfs_extent +{ + /* This should be a bitfield but bietfields are unportable, so just have + a raw array and functions extracting useful info from it. + */ + grub_uint32_t raw[4]; +} GRUB_PACKED; struct grub_xfs_btree_node { @@ -90,57 +194,66 @@ struct grub_xfs_btree_node grub_uint16_t numrecs; grub_uint64_t left; grub_uint64_t right; - grub_uint64_t keys[1]; -} __attribute__ ((packed)); + /* In V5 here follow crc, uuid, etc. */ + /* Then follow keys and block pointers */ +} GRUB_PACKED; struct grub_xfs_btree_root { grub_uint16_t level; grub_uint16_t numrecs; grub_uint64_t keys[1]; -} __attribute__ ((packed)); +} GRUB_PACKED; -struct grub_xfs_time +struct grub_xfs_time_legacy { grub_uint32_t sec; grub_uint32_t nanosec; -} __attribute__ ((packed)); +} GRUB_PACKED; +/* + * The struct grub_xfs_inode layout was taken from the + * struct xfs_dinode_core which is described here: + * https://mirrors.edge.kernel.org/pub/linux/utils/fs/xfs/docs/xfs_filesystem_structure.pdf + */ struct grub_xfs_inode { grub_uint8_t magic[2]; grub_uint16_t mode; grub_uint8_t version; grub_uint8_t format; - grub_uint8_t unused2[26]; - struct grub_xfs_time atime; - struct grub_xfs_time mtime; - struct grub_xfs_time ctime; + grub_uint8_t unused2[18]; + grub_uint64_t nextents_big; + grub_uint64_t atime; + grub_uint64_t mtime; + grub_uint64_t ctime; grub_uint64_t size; grub_uint64_t nblocks; grub_uint32_t extsize; grub_uint32_t nextents; grub_uint16_t unused3; grub_uint8_t fork_offset; - grub_uint8_t unused4[17]; - union - { - char raw[156]; - struct dir - { - struct grub_xfs_dir_header dirhead; - struct grub_xfs_dir_entry direntry[1]; - } dir; - grub_xfs_extent extents[XFS_INODE_EXTENTS]; - struct grub_xfs_btree_root btree; - } data __attribute__ ((packed)); -} __attribute__ ((packed)); + grub_uint8_t unused4[17]; /* Last member of inode v2. */ + grub_uint8_t unused5[20]; /* First member of inode v3. */ + grub_uint64_t flags2; + grub_uint8_t unused6[48]; /* Last member of inode v3. */ +} GRUB_PACKED; + +#define XFS_V3_INODE_SIZE sizeof(struct grub_xfs_inode) +/* Size of struct grub_xfs_inode v2, up to unused4 member included. */ +#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 76) + +struct grub_xfs_dir_leaf_entry +{ + grub_uint32_t hashval; + grub_uint32_t address; +} GRUB_PACKED; struct grub_xfs_dirblock_tail { grub_uint32_t leaf_count; grub_uint32_t leaf_stale; -} __attribute__ ((packed)); +} GRUB_PACKED; struct grub_fshelp_node { @@ -152,11 +265,14 @@ struct grub_fshelp_node struct grub_xfs_data { + grub_size_t data_size; struct grub_xfs_sblock sblock; grub_disk_t disk; int pos; int bsize; grub_uint32_t agsize; + unsigned int hasftype:1; + unsigned int hascrc:1; struct grub_fshelp_node diropen; }; @@ -164,6 +280,83 @@ static grub_dl_t my_mod; +static int grub_xfs_sb_hascrc(struct grub_xfs_data *data) +{ + return (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == + grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5); +} + +static int grub_xfs_sb_hasftype(struct grub_xfs_data *data) +{ + if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == + grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5) && + data->sblock.sb_features_incompat & grub_cpu_to_be32_compile_time(XFS_SB_FEAT_INCOMPAT_FTYPE)) + return 1; + if (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_MOREBITSBIT) && + data->sblock.features2 & grub_cpu_to_be32_compile_time(XFS_SB_VERSION2_FTYPE)) + return 1; + return 0; +} + +static int grub_xfs_sb_valid(struct grub_xfs_data *data) +{ + grub_dprintf("xfs", "Validating superblock\n"); + if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4) + || data->sblock.log2_bsize < GRUB_DISK_SECTOR_BITS + || ((int) data->sblock.log2_bsize + + (int) data->sblock.log2_dirblk) >= 27) + { + grub_error (GRUB_ERR_BAD_FS, "not a XFS filesystem"); + return 0; + } + if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == + grub_cpu_to_be16_compile_time(XFS_SB_VERSION_5)) + { + grub_dprintf("xfs", "XFS v5 superblock detected\n"); + if (data->sblock.sb_features_incompat & + grub_cpu_to_be32_compile_time(~XFS_SB_FEAT_INCOMPAT_SUPPORTED)) + { + grub_error (GRUB_ERR_BAD_FS, "XFS filesystem has unsupported " + "incompatible features"); + return 0; + } + return 1; + } + else if ((data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == + grub_cpu_to_be16_compile_time(XFS_SB_VERSION_4)) + { + grub_dprintf("xfs", "XFS v4 superblock detected\n"); + if (!(data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_DIRV2BIT))) + { + grub_error (GRUB_ERR_BAD_FS, "XFS filesystem without V2 directories " + "is unsupported"); + return 0; + } + if (data->sblock.version & grub_cpu_to_be16_compile_time(~XFS_SB_VERSION_BITS_SUPPORTED) || + (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_MOREBITSBIT) && + data->sblock.features2 & grub_cpu_to_be16_compile_time(~XFS_SB_VERSION2_BITS_SUPPORTED))) + { + grub_error (GRUB_ERR_BAD_FS, "XFS filesystem has unsupported version " + "bits"); + return 0; + } + return 1; + } + + grub_error (GRUB_ERR_BAD_FS, "unsupported XFS filesystem version"); + return 0; +} + +static int +grub_xfs_sb_needs_repair (struct grub_xfs_data *data) +{ + return ((data->sblock.version & + grub_cpu_to_be16_compile_time (XFS_SB_VERSION_NUMBITS)) == + grub_cpu_to_be16_compile_time (XFS_SB_VERSION_5) && + (data->sblock.sb_features_incompat & + grub_cpu_to_be32_compile_time (XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR))); +} + /* Filetype information as used in inodes. */ #define FILETYPE_INO_MASK 0170000 #define FILETYPE_INO_REG 0100000 @@ -180,14 +373,14 @@ static inline grub_uint64_t GRUB_XFS_INO_INOINAG (struct grub_xfs_data *data, grub_uint64_t ino) { - return (grub_be_to_cpu64 (ino) & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1)); + return (ino & ((1LL << GRUB_XFS_INO_AGBITS (data)) - 1)); } static inline grub_uint64_t GRUB_XFS_INO_AG (struct grub_xfs_data *data, grub_uint64_t ino) { - return (grub_be_to_cpu64 (ino) >> GRUB_XFS_INO_AGBITS (data)); + return (ino >> GRUB_XFS_INO_AGBITS (data)); } static inline grub_disk_addr_t @@ -198,37 +391,25 @@ GRUB_XFS_FSB_TO_BLOCK (struct grub_xfs_data *data, grub_disk_addr_t fsb) } static inline grub_uint64_t -GRUB_XFS_EXTENT_OFFSET (grub_xfs_extent *exts, int ex) +GRUB_XFS_EXTENT_OFFSET (struct grub_xfs_extent *exts, int ex) { - return ((grub_be_to_cpu32 (exts[ex][0]) & ~(1 << 31)) << 23 - | grub_be_to_cpu32 (exts[ex][1]) >> 9); + return ((grub_be_to_cpu32 (exts[ex].raw[0]) & ~(1 << 31)) << 23 + | grub_be_to_cpu32 (exts[ex].raw[1]) >> 9); } static inline grub_uint64_t -GRUB_XFS_EXTENT_BLOCK (grub_xfs_extent *exts, int ex) +GRUB_XFS_EXTENT_BLOCK (struct grub_xfs_extent *exts, int ex) { - return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex][1]) + return ((grub_uint64_t) (grub_be_to_cpu32 (exts[ex].raw[1]) & (0x1ff)) << 43 - | (grub_uint64_t) grub_be_to_cpu32 (exts[ex][2]) << 11 - | grub_be_to_cpu32 (exts[ex][3]) >> 21); + | (grub_uint64_t) grub_be_to_cpu32 (exts[ex].raw[2]) << 11 + | grub_be_to_cpu32 (exts[ex].raw[3]) >> 21); } static inline grub_uint64_t -GRUB_XFS_EXTENT_SIZE (grub_xfs_extent *exts, int ex) +GRUB_XFS_EXTENT_SIZE (struct grub_xfs_extent *exts, int ex) { - return (grub_be_to_cpu32 (exts[ex][3]) & ((1 << 21) - 1)); -} - -static inline int -GRUB_XFS_ROUND_TO_DIRENT (int pos) -{ - return ((((pos) + 8 - 1) / 8) * 8); -} - -static inline int -GRUB_XFS_NEXT_DIRENT (int pos, int len) -{ - return (pos) + GRUB_XFS_ROUND_TO_DIRENT (8 + 1 + len + 2); + return (grub_be_to_cpu32 (exts[ex].raw[3]) & ((1 << 21) - 1)); } @@ -255,6 +436,109 @@ grub_xfs_inode_offset (struct grub_xfs_data *data, data->sblock.log2_inode); } +static inline grub_size_t +grub_xfs_inode_size(struct grub_xfs_data *data) +{ + return (grub_size_t)1 << data->sblock.log2_inode; +} + +/* + * Returns size occupied by XFS inode stored in memory - we store struct + * grub_fshelp_node there but on disk inode size may be actually larger than + * struct grub_xfs_inode so we need to account for that so that we can read + * from disk directly into in-memory structure. + */ +static inline grub_size_t +grub_xfs_fshelp_size(struct grub_xfs_data *data) +{ + return sizeof (struct grub_fshelp_node) - sizeof (struct grub_xfs_inode) + + grub_xfs_inode_size(data); +} + +/* This should return void * but XFS code is error-prone with alignment, so + return char to retain cast-align. + */ +static char * +grub_xfs_inode_data(struct grub_xfs_inode *inode) +{ + if (inode->version <= 2) + return ((char *)inode) + XFS_V2_INODE_SIZE; + return ((char *)inode) + XFS_V3_INODE_SIZE; +} + +static struct grub_xfs_dir_entry * +grub_xfs_inline_de(struct grub_xfs_dir_header *head) +{ + /* + With small inode numbers the header is 4 bytes smaller because of + smaller parent pointer + */ + return (struct grub_xfs_dir_entry *) + (((char *) head) + sizeof(struct grub_xfs_dir_header) - + (head->largeino ? 0 : sizeof(grub_uint32_t))); +} + +static grub_uint8_t * +grub_xfs_inline_de_inopos(struct grub_xfs_data *data, + struct grub_xfs_dir_entry *de) +{ + return ((grub_uint8_t *)(de + 1)) + de->len - 1 + (data->hasftype ? 1 : 0); +} + +static struct grub_xfs_dir_entry * +grub_xfs_inline_next_de(struct grub_xfs_data *data, + struct grub_xfs_dir_header *head, + struct grub_xfs_dir_entry *de) +{ + char *p = (char *)de + sizeof(struct grub_xfs_dir_entry) - 1 + de->len; + + p += head->largeino ? sizeof(grub_uint64_t) : sizeof(grub_uint32_t); + if (data->hasftype) + p++; + + return (struct grub_xfs_dir_entry *)p; +} + +static struct grub_xfs_dirblock_tail * +grub_xfs_dir_tail(struct grub_xfs_data *data, void *dirblock) +{ + int dirblksize = 1 << (data->sblock.log2_bsize + data->sblock.log2_dirblk); + + return (struct grub_xfs_dirblock_tail *) + ((char *)dirblock + dirblksize - sizeof (struct grub_xfs_dirblock_tail)); +} + +static struct grub_xfs_dir2_entry * +grub_xfs_first_de(struct grub_xfs_data *data, void *dirblock) +{ + if (data->hascrc) + return (struct grub_xfs_dir2_entry *)((char *)dirblock + 64); + return (struct grub_xfs_dir2_entry *)((char *)dirblock + 16); +} + +static struct grub_xfs_dir2_entry * +grub_xfs_next_de(struct grub_xfs_data *data, struct grub_xfs_dir2_entry *de) +{ + int size = sizeof (struct grub_xfs_dir2_entry) + de->len + 2 /* Tag */; + + if (data->hasftype) + size++; /* File type */ + return (struct grub_xfs_dir2_entry *)(((char *)de) + ALIGN_UP(size, 8)); +} + +/* This should return void * but XFS code is error-prone with alignment, so + return char to retain cast-align. + */ +static char * +grub_xfs_btree_keys(struct grub_xfs_data *data, + struct grub_xfs_btree_node *leaf) +{ + char *keys = (char *)(leaf + 1); + + if (data->hascrc) + keys += 48; /* skip crc, uuid, ... */ + return keys; +} static grub_err_t grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, @@ -263,9 +547,11 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, grub_uint64_t block = grub_xfs_inode_block (data, ino); int offset = grub_xfs_inode_offset (data, ino); + grub_dprintf("xfs", "Reading inode (%" PRIuGRUB_UINT64_T ") - %" PRIuGRUB_UINT64_T ", %d\n", + ino, block, offset); /* Read the inode. */ - if (grub_disk_read (data->disk, block, offset, - 1 << data->sblock.log2_inode, inode)) + if (grub_disk_read (data->disk, block, offset, grub_xfs_inode_size(data), + inode)) return grub_errno; if (grub_strncmp ((char *) inode->magic, "IN", 2)) @@ -274,42 +560,73 @@ grub_xfs_read_inode (struct grub_xfs_data *data, grub_uint64_t ino, return 0; } +static grub_uint64_t +get_fsb (const void *keys, int idx) +{ + const char *p = (const char *) keys + sizeof(grub_uint64_t) * idx; + return grub_be_to_cpu64 (grub_get_unaligned64 (p)); +} + +static int +grub_xfs_inode_has_large_extent_counts (const struct grub_xfs_inode *inode) +{ + return inode->version >= 3 && + (inode->flags2 & grub_cpu_to_be64_compile_time (XFS_DIFLAG2_NREXT64)); +} + +static grub_uint64_t +grub_xfs_get_inode_nextents (struct grub_xfs_inode *inode) +{ + return (grub_xfs_inode_has_large_extent_counts (inode)) ? + grub_be_to_cpu64 (inode->nextents_big) : + grub_be_to_cpu32 (inode->nextents); +} static grub_disk_addr_t grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) { struct grub_xfs_btree_node *leaf = 0; - int ex, nrec; - grub_xfs_extent *exts; + grub_uint64_t ex, nrec; + struct grub_xfs_extent *exts; grub_uint64_t ret = 0; if (node->inode.format == XFS_INODE_FORMAT_BTREE) { - grub_uint64_t *keys; + struct grub_xfs_btree_root *root; + const char *keys; int recoffset; leaf = grub_malloc (node->data->bsize); if (leaf == 0) return 0; - nrec = grub_be_to_cpu16 (node->inode.data.btree.numrecs); - keys = &node->inode.data.btree.keys[0]; + root = (struct grub_xfs_btree_root *) grub_xfs_inode_data(&node->inode); + nrec = grub_be_to_cpu16 (root->numrecs); + keys = (char *) &root->keys[0]; if (node->inode.fork_offset) - recoffset = (node->inode.fork_offset - - ((char *) &node->inode.data.btree.keys - (char *) &node->inode)) - / (2 * sizeof (grub_uint64_t)); + recoffset = (node->inode.fork_offset - 1) / 2; else - recoffset = ((1 << node->data->sblock.log2_inode) - - ((char *) &node->inode.data.btree.keys - - (char *) &node->inode)) - / (2 * sizeof (grub_uint64_t)); + recoffset = (grub_xfs_inode_size(node->data) + - ((char *) keys - (char *) &node->inode)) + / (2 * sizeof (grub_uint64_t)); do { - int i; + grub_uint64_t i; + grub_addr_t keys_end, data_end; + + if (grub_mul (sizeof (grub_uint64_t), nrec, &keys_end) || + grub_add ((grub_addr_t) keys, keys_end, &keys_end) || + grub_add ((grub_addr_t) node->data, node->data->data_size, &data_end) || + keys_end > data_end) + { + grub_error (GRUB_ERR_BAD_FS, "invalid number of XFS root keys"); + grub_free (leaf); + return 0; + } for (i = 0; i < nrec; i++) { - if (fileblock < grub_be_to_cpu64 (keys[i])) + if (fileblock < get_fsb(keys, i)) break; } @@ -319,12 +636,19 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) grub_free (leaf); return 0; } - if (grub_disk_read (node->data->disk, - GRUB_XFS_FSB_TO_BLOCK (node->data, grub_be_to_cpu64 (keys[i - 1 + recoffset])) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS), - 0, node->data->bsize, leaf)) - return 0; - if (grub_strncmp ((char *) leaf->magic, "BMAP", 4)) + if (grub_disk_read (node->data->disk, + GRUB_XFS_FSB_TO_BLOCK (node->data, get_fsb (keys, i - 1 + recoffset)) << (node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS), + 0, node->data->bsize, leaf)) + { + grub_free (leaf); + return 0; + } + + if ((!node->data->hascrc && + grub_strncmp ((char *) leaf->magic, "BMAP", 4)) || + (node->data->hascrc && + grub_strncmp ((char *) leaf->magic, "BMA3", 4))) { grub_free (leaf); grub_error (GRUB_ERR_BAD_FS, "not a correct XFS BMAP node"); @@ -332,18 +656,30 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) } nrec = grub_be_to_cpu16 (leaf->numrecs); - keys = &leaf->keys[0]; - recoffset = ((node->data->bsize - ((char *) &leaf->keys + keys = grub_xfs_btree_keys(node->data, leaf); + recoffset = ((node->data->bsize - ((char *) keys - (char *) leaf)) / (2 * sizeof (grub_uint64_t))); } while (leaf->level); - exts = (grub_xfs_extent *) keys; + exts = (struct grub_xfs_extent *) keys; } else if (node->inode.format == XFS_INODE_FORMAT_EXT) { - nrec = grub_be_to_cpu32 (node->inode.nextents); - exts = &node->inode.data.extents[0]; + grub_addr_t exts_end = 0; + grub_addr_t data_end = 0; + + nrec = grub_xfs_get_inode_nextents (&node->inode); + exts = (struct grub_xfs_extent *) grub_xfs_inode_data(&node->inode); + + if (grub_mul (sizeof (struct grub_xfs_extent), nrec, &exts_end) || + grub_add ((grub_addr_t) node->data, exts_end, &exts_end) || + grub_add ((grub_addr_t) node->data, node->data->data_size, &data_end) || + exts_end > data_end) + { + grub_error (GRUB_ERR_BAD_FS, "invalid number of XFS extents"); + return 0; + } } else { @@ -381,13 +717,13 @@ grub_xfs_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) POS. Return the amount of read bytes in READ. */ static grub_ssize_t grub_xfs_read_file (grub_fshelp_node_t node, - void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector, - unsigned offset, unsigned length), - grub_off_t pos, grub_size_t len, char *buf) + grub_disk_read_hook_t read_hook, void *read_hook_data, + grub_off_t pos, grub_size_t len, char *buf, grub_uint32_t header_size) { - return grub_fshelp_read_file (node->data->disk, node, read_hook, + return grub_fshelp_read_file (node->data->disk, node, + read_hook, read_hook_data, pos, len, buf, grub_xfs_read_block, - grub_be_to_cpu64 (node->inode.size), + grub_be_to_cpu64 (node->inode.size) + header_size, node->data->sblock.log2_bsize - GRUB_DISK_SECTOR_BITS, 0); } @@ -396,23 +732,40 @@ grub_xfs_read_file (grub_fshelp_node_t node, static char * grub_xfs_read_symlink (grub_fshelp_node_t node) { - int size = grub_be_to_cpu64 (node->inode.size); + grub_ssize_t size = grub_be_to_cpu64 (node->inode.size); + grub_size_t sz; + + if (size < 0) + { + grub_error (GRUB_ERR_BAD_FS, "invalid symlink"); + return 0; + } switch (node->inode.format) { case XFS_INODE_FORMAT_INO: - return grub_strndup (node->inode.data.raw, size); + return grub_strndup (grub_xfs_inode_data(&node->inode), size); case XFS_INODE_FORMAT_EXT: { char *symlink; grub_ssize_t numread; + int off = 0; - symlink = grub_malloc (size + 1); + if (node->data->hascrc) + off = 56; + + if (grub_add (size, 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("symlink size overflow")); + return 0; + } + symlink = grub_malloc (sz); if (!symlink) return 0; - numread = grub_xfs_read_file (node, 0, 0, size, symlink); + node->inode.size = grub_be_to_cpu64 (size + off); + numread = grub_xfs_read_file (node, 0, 0, off, size, symlink, off); if (numread != size) { grub_free (symlink); @@ -443,84 +796,100 @@ grub_xfs_mode_to_filetype (grub_uint16_t mode) } +/* Context for grub_xfs_iterate_dir. */ +struct grub_xfs_iterate_dir_ctx +{ + grub_fshelp_iterate_dir_hook_t hook; + void *hook_data; + struct grub_fshelp_node *diro; +}; + +/* Helper for grub_xfs_iterate_dir. */ +static int iterate_dir_call_hook (grub_uint64_t ino, const char *filename, + struct grub_xfs_iterate_dir_ctx *ctx) +{ + struct grub_fshelp_node *fdiro; + grub_err_t err; + grub_size_t sz; + + if (grub_add (grub_xfs_fshelp_size(ctx->diro->data), 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("directory data size overflow")); + grub_print_error (); + return 0; + } + fdiro = grub_malloc (sz); + if (!fdiro) + { + grub_print_error (); + return 0; + } + + /* The inode should be read, otherwise the filetype can + not be determined. */ + fdiro->ino = ino; + fdiro->inode_read = 1; + fdiro->data = ctx->diro->data; + err = grub_xfs_read_inode (ctx->diro->data, ino, &fdiro->inode); + if (err) + { + grub_print_error (); + grub_free (fdiro); + return 0; + } + + return ctx->hook (filename, grub_xfs_mode_to_filetype (fdiro->inode.mode), + fdiro, ctx->hook_data); +} + static int grub_xfs_iterate_dir (grub_fshelp_node_t dir, - int NESTED_FUNC_ATTR - (*hook) (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node)) + grub_fshelp_iterate_dir_hook_t hook, void *hook_data) { struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; - auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename); - - int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename) - { - struct grub_fshelp_node *fdiro; - grub_err_t err; - - fdiro = grub_malloc (sizeof (struct grub_fshelp_node) - - sizeof (struct grub_xfs_inode) - + (1 << diro->data->sblock.log2_inode)); - if (!fdiro) - { - grub_print_error (); - return 0; - } - - /* The inode should be read, otherwise the filetype can - not be determined. */ - fdiro->ino = ino; - fdiro->inode_read = 1; - fdiro->data = diro->data; - err = grub_xfs_read_inode (diro->data, ino, &fdiro->inode); - if (err) - { - grub_print_error (); - return 0; - } - - return hook (filename, - grub_xfs_mode_to_filetype (fdiro->inode.mode), - fdiro); - } + struct grub_xfs_iterate_dir_ctx ctx = { + .hook = hook, + .hook_data = hook_data, + .diro = diro + }; switch (diro->inode.format) { case XFS_INODE_FORMAT_INO: { - struct grub_xfs_dir_entry *de = &diro->inode.data.dir.direntry[0]; - int smallino = !diro->inode.data.dir.dirhead.smallino; + struct grub_xfs_dir_header *head = (struct grub_xfs_dir_header *) grub_xfs_inode_data(&diro->inode); + struct grub_xfs_dir_entry *de = grub_xfs_inline_de(head); + int smallino = !head->largeino; int i; grub_uint64_t parent; /* If small inode numbers are used to pack the direntry, the parent inode number is small too. */ if (smallino) - { - parent = grub_be_to_cpu32 (diro->inode.data.dir.dirhead.parent.i4); - parent = grub_cpu_to_be64 (parent); - /* The header is a bit smaller than usual. */ - de = (struct grub_xfs_dir_entry *) ((char *) de - 4); - } + parent = grub_be_to_cpu32 (head->parent.i4); else - { - parent = diro->inode.data.dir.dirhead.parent.i8; - } + parent = grub_be_to_cpu64 (head->parent.i8); /* Synthesize the direntries for `.' and `..'. */ - if (call_hook (diro->ino, ".")) + if (iterate_dir_call_hook (diro->ino, ".", &ctx)) return 1; - if (call_hook (parent, "..")) + if (iterate_dir_call_hook (parent, "..", &ctx)) return 1; - for (i = 0; i < diro->inode.data.dir.dirhead.count; i++) + for (i = 0; i < head->count && + (grub_uint8_t *) de < ((grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data)); i++) { grub_uint64_t ino; - grub_uint8_t *inopos = (((grub_uint8_t *) de) - + sizeof (struct grub_xfs_dir_entry) - + de->len - 1); - char name[de->len + 1]; + grub_uint8_t *inopos = grub_xfs_inline_de_inopos(dir->data, de); + grub_uint8_t c; + + if ((inopos + (smallino ? 4 : 8)) > (grub_uint8_t *) dir + grub_xfs_fshelp_size (dir->data)) + { + grub_error (GRUB_ERR_BAD_FS, "invalid XFS inode"); + return 0; + } + /* inopos might be unaligned. */ if (smallino) @@ -537,17 +906,17 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, | (((grub_uint64_t) inopos[5]) << 16) | (((grub_uint64_t) inopos[6]) << 8) | (((grub_uint64_t) inopos[7]) << 0); - ino = grub_cpu_to_be64 (ino); - grub_memcpy (name, de->name, de->len); - name[de->len] = '\0'; - if (call_hook (ino, name)) - return 1; + c = de->name[de->len]; + de->name[de->len] = '\0'; + if (iterate_dir_call_hook (ino, de->name, &ctx)) + { + de->name[de->len] = c; + return 1; + } + de->name[de->len] = c; - de = ((struct grub_xfs_dir_entry *) - (((char *) de)+ sizeof (struct grub_xfs_dir_entry) + de->len - + ((smallino ? sizeof (grub_uint32_t) - : sizeof (grub_uint64_t))) - 1)); + de = grub_xfs_inline_next_de(dir->data, head, de); } break; } @@ -574,34 +943,55 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, >> dirblk_log2); blk++) { - /* The header is skipped, the first direntry is stored - from byte 16. */ - int pos = 16; - int entries; - int tail_start = (dirblk_size - - sizeof (struct grub_xfs_dirblock_tail)); + struct grub_xfs_dir2_entry *direntry = + grub_xfs_first_de(dir->data, dirblock); + int entries = -1; + char *end = dirblock + dirblk_size; + grub_uint32_t magic; - struct grub_xfs_dirblock_tail *tail; - tail = (struct grub_xfs_dirblock_tail *) &dirblock[tail_start]; - - numread = grub_xfs_read_file (dir, 0, + numread = grub_xfs_read_file (dir, 0, 0, blk << dirblk_log2, - dirblk_size, dirblock); + dirblk_size, dirblock, 0); if (numread != dirblk_size) - return 0; + { + grub_free (dirblock); + return 0; + } - entries = (grub_be_to_cpu32 (tail->leaf_count) - - grub_be_to_cpu32 (tail->leaf_stale)); + /* + * If this data block isn't actually part of the extent list then + * grub_xfs_read_file() returns a block of zeros. So, if the magic + * number field is all zeros then this block should be skipped. + */ + magic = *(grub_uint32_t *)(void *) dirblock; + if (!magic) + continue; + + /* + * Leaf and tail information are only in the data block if the number + * of extents is 1. + */ + if (grub_xfs_get_inode_nextents (&dir->inode) == 1) + { + struct grub_xfs_dirblock_tail *tail = grub_xfs_dir_tail (dir->data, dirblock); + + end = (char *) tail; + + /* Subtract the space used by leaf nodes. */ + end -= grub_be_to_cpu32 (tail->leaf_count) * sizeof (struct grub_xfs_dir_leaf_entry); + + entries = grub_be_to_cpu32 (tail->leaf_count) - grub_be_to_cpu32 (tail->leaf_stale); + + if (!entries) + continue; + } /* Iterate over all entries within this block. */ - while (pos < (dirblk_size - - (int) sizeof (struct grub_xfs_dir2_entry))) + while ((char *) direntry < (char *) end) { - struct grub_xfs_dir2_entry *direntry; grub_uint8_t *freetag; char *filename; - direntry = (struct grub_xfs_dir2_entry *) &dirblock[pos]; freetag = (grub_uint8_t *) direntry; if (grub_get_unaligned16 (freetag) == 0XFFFF) @@ -609,31 +999,45 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, grub_uint8_t *skip = (freetag + sizeof (grub_uint16_t)); /* This entry is not used, go to the next one. */ - pos += grub_be_to_cpu16 (grub_get_unaligned16 (skip)); + direntry = (struct grub_xfs_dir2_entry *) + (((char *)direntry) + + grub_be_to_cpu16 (grub_get_unaligned16 (skip))); continue; } - filename = &dirblock[pos + sizeof (*direntry)]; - /* The byte after the filename is for the tag, which - is not used by GRUB. So it can be overwritten. */ + filename = (char *)(direntry + 1); + if (filename + direntry->len + 1 > (char *) end) + { + grub_error (GRUB_ERR_BAD_FS, "invalid XFS directory entry"); + return 0; + } + + /* The byte after the filename is for the filetype, padding, or + tag, which is not used by GRUB. So it can be overwritten. */ filename[direntry->len] = '\0'; - if (call_hook (direntry->inode, filename)) + if (iterate_dir_call_hook (grub_be_to_cpu64(direntry->inode), + filename, &ctx)) { grub_free (dirblock); return 1; } - /* Check if last direntry in this block is - reached. */ - entries--; - if (!entries) - break; + /* + * The expected number of directory entries is only tracked for the + * single extent case. + */ + if (grub_xfs_get_inode_nextents (&dir->inode) == 1) + { + /* Check if last direntry in this block is reached. */ + entries--; + if (!entries) + break; + } /* Select the next directory entry. */ - pos = GRUB_XFS_NEXT_DIRENT (pos, direntry->len); - pos = GRUB_XFS_ROUND_TO_DIRENT (pos); + direntry = grub_xfs_next_de(dir->data, direntry); } } grub_free (dirblock); @@ -653,48 +1057,55 @@ static struct grub_xfs_data * grub_xfs_mount (grub_disk_t disk) { struct grub_xfs_data *data = 0; + grub_size_t sz; data = grub_zalloc (sizeof (struct grub_xfs_data)); if (!data) return 0; + data->data_size = sizeof (struct grub_xfs_data); + + grub_dprintf("xfs", "Reading sb\n"); /* Read the superblock. */ if (grub_disk_read (disk, 0, 0, sizeof (struct grub_xfs_sblock), &data->sblock)) goto fail; - if (grub_strncmp ((char *) (data->sblock.magic), "XFSB", 4) - || data->sblock.log2_bsize < GRUB_DISK_SECTOR_BITS - || ((int) data->sblock.log2_bsize - + (int) data->sblock.log2_dirblk) >= 27) - { - grub_error (GRUB_ERR_BAD_FS, "not a XFS filesystem"); - goto fail; - } + if (!grub_xfs_sb_valid(data)) + goto fail; - data = grub_realloc (data, - sizeof (struct grub_xfs_data) - - sizeof (struct grub_xfs_inode) - + (1 << data->sblock.log2_inode)); + if (grub_xfs_sb_needs_repair (data)) + grub_dprintf ("xfs", "XFS filesystem needs repair, boot may fail\n"); + + if (grub_add (grub_xfs_inode_size (data), + sizeof (struct grub_xfs_data) - sizeof (struct grub_xfs_inode) + 1, &sz)) + goto fail; + + data = grub_realloc (data, sz); if (! data) goto fail; + data->data_size = sz; data->diropen.data = data; - data->diropen.ino = data->sblock.rootino; + data->diropen.ino = grub_be_to_cpu64(data->sblock.rootino); data->diropen.inode_read = 1; data->bsize = grub_be_to_cpu32 (data->sblock.bsize); data->agsize = grub_be_to_cpu32 (data->sblock.agsize); + data->hasftype = grub_xfs_sb_hasftype(data); + data->hascrc = grub_xfs_sb_hascrc(data); data->disk = disk; data->pos = 0; + grub_dprintf("xfs", "Reading root ino %" PRIuGRUB_UINT64_T "\n", + grub_cpu_to_be64(data->sblock.rootino)); grub_xfs_read_inode (data, data->diropen.ino, &data->diropen.inode); return data; fail: - if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + if (grub_errno == GRUB_ERR_OUT_OF_RANGE || grub_errno == GRUB_ERR_NONE) grub_error (GRUB_ERR_BAD_FS, "not an XFS filesystem"); grub_free (data); @@ -703,34 +1114,61 @@ grub_xfs_mount (grub_disk_t disk) } +/* Context for grub_xfs_dir. */ +struct grub_xfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; +}; + +/* Bigtime inodes helpers. */ +#define XFS_BIGTIME_EPOCH_OFFSET (-(grub_int64_t) GRUB_INT32_MIN) + +static int grub_xfs_inode_has_bigtime (const struct grub_xfs_inode *inode) +{ + return inode->version >= 3 && + (inode->flags2 & grub_cpu_to_be64_compile_time (XFS_DIFLAG2_BIGTIME)); +} + +static grub_int64_t +grub_xfs_get_inode_time (struct grub_xfs_inode *inode) +{ + struct grub_xfs_time_legacy *lts; + + if (grub_xfs_inode_has_bigtime (inode)) + return grub_divmod64 (grub_be_to_cpu64 (inode->mtime), NSEC_PER_SEC, NULL) - XFS_BIGTIME_EPOCH_OFFSET; + + lts = (struct grub_xfs_time_legacy *) &inode->mtime; + return grub_be_to_cpu32 (lts->sec); +} + +/* Helper for grub_xfs_dir. */ +static int +grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + grub_fshelp_node_t node, void *data) +{ + struct grub_xfs_dir_ctx *ctx = data; + struct grub_dirhook_info info; + + grub_memset (&info, 0, sizeof (info)); + if (node->inode_read) + { + info.mtimeset = 1; + info.mtime = grub_xfs_get_inode_time (&node->inode); + } + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); + return ctx->hook (filename, &info, ctx->hook_data); +} + static grub_err_t grub_xfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_xfs_dir_ctx ctx = { hook, hook_data }; struct grub_xfs_data *data = 0; struct grub_fshelp_node *fdiro = 0; - auto int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node); - - int NESTED_FUNC_ATTR iterate (const char *filename, - enum grub_fshelp_filetype filetype, - grub_fshelp_node_t node) - { - struct grub_dirhook_info info; - grub_memset (&info, 0, sizeof (info)); - if (node->inode_read) - { - info.mtimeset = 1; - info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec); - } - info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); - grub_free (node); - return hook (filename, &info); - } - grub_dl_ref (my_mod); data = grub_xfs_mount (device->disk); @@ -742,7 +1180,7 @@ grub_xfs_dir (grub_device_t device, const char *path, if (grub_errno) goto fail; - grub_xfs_iterate_dir (fdiro, iterate); + grub_xfs_iterate_dir (fdiro, grub_xfs_dir_iter, &ctx); fail: if (fdiro != &data->diropen) @@ -784,10 +1222,7 @@ grub_xfs_open (struct grub_file *file, const char *name) if (fdiro != &data->diropen) { - grub_memcpy (&data->diropen, fdiro, - sizeof (struct grub_fshelp_node) - - sizeof (struct grub_xfs_inode) - + (1 << data->sblock.log2_inode)); + grub_memcpy (&data->diropen, fdiro, grub_xfs_fshelp_size(data)); grub_free (fdiro); } @@ -815,8 +1250,9 @@ grub_xfs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_xfs_data *data = (struct grub_xfs_data *) file->data; - return grub_xfs_read_file (&data->diropen, file->read_hook, - file->offset, len, buf); + return grub_xfs_read_file (&data->diropen, + file->read_hook, file->read_hook_data, + file->offset, len, buf, 0); } @@ -888,12 +1324,12 @@ grub_xfs_uuid (grub_device_t device, char **uuid) static struct grub_fs grub_xfs_fs = { .name = "xfs", - .dir = grub_xfs_dir, - .open = grub_xfs_open, - .read = grub_xfs_read, - .close = grub_xfs_close, - .label = grub_xfs_label, - .uuid = grub_xfs_uuid, + .fs_dir = grub_xfs_dir, + .fs_open = grub_xfs_open, + .fs_read = grub_xfs_read, + .fs_close = grub_xfs_close, + .fs_label = grub_xfs_label, + .fs_uuid = grub_xfs_uuid, #ifdef GRUB_UTIL .reserved_first_sector = 0, .blocklist_install = 1, @@ -903,6 +1339,7 @@ static struct grub_fs grub_xfs_fs = GRUB_MOD_INIT(xfs) { + grub_xfs_fs.mod = mod; grub_fs_register (&grub_xfs_fs); my_mod = mod; } diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index ba0554abd..bff9d0208 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -2,6 +2,7 @@ * GRUB -- GRand Unified Bootloader * Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010,2011 Free Software Foundation, Inc. * Copyright 2010 Sun Microsystems, Inc. + * Copyright (c) 2012 by Delphix. All rights reserved. * * GRUB is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,6 +55,9 @@ #include #include #include +#include + +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -71,6 +75,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define DATA_TYPE_NVLIST 19 #define DATA_TYPE_NVLIST_ARRAY 20 +#define DNODE_NUM_MASK 0xffffffffffffULL + #ifndef GRUB_UTIL static grub_dl_t my_mod; #endif @@ -128,7 +134,7 @@ LEAF_HASH (int bs, grub_uint64_t h, zap_leaf_phys_t *l) static inline int ZAP_LEAF_NUMCHUNKS (int bs) { - return (((1 << bs) - 2 * ZAP_LEAF_HASH_NUMENTRIES (bs)) / + return (((1U << bs) - 2 * ZAP_LEAF_HASH_NUMENTRIES (bs)) / ZAP_LEAF_CHUNKSIZE - 2); } @@ -140,7 +146,10 @@ ZAP_LEAF_NUMCHUNKS (int bs) static inline zap_leaf_chunk_t * ZAP_LEAF_CHUNK (zap_leaf_phys_t *l, int bs, int idx) { - return &((zap_leaf_chunk_t *) (l->l_entries + grub_properly_aligned_t *l_entries; + + l_entries = (grub_properly_aligned_t *) ALIGN_UP((grub_addr_t)l->l_hash, sizeof (grub_properly_aligned_t)); + return &((zap_leaf_chunk_t *) (l_entries + (ZAP_LEAF_HASH_NUMENTRIES(bs) * 2) / sizeof (grub_properly_aligned_t)))[idx]; } @@ -153,11 +162,13 @@ ZAP_LEAF_ENTRY(zap_leaf_phys_t *l, int bs, int idx) /* - * Decompression Entry - lzjb + * Decompression Entry - lzjb & lz4 */ extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t); +extern grub_err_t lz4_decompress (void *, void *, grub_size_t, grub_size_t); + typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start, grub_size_t s_len, grub_size_t d_len); typedef struct decomp_entry @@ -169,17 +180,17 @@ typedef struct decomp_entry /* * Signature for checksum functions. */ -typedef void zio_checksum_t(const void *data, grub_uint64_t size, +typedef void zio_checksum_t(const void *data, grub_uint64_t size, grub_zfs_endian_t endian, zio_cksum_t *zcp); /* * Information about each checksum function. */ typedef struct zio_checksum_info { - zio_checksum_t *ci_func; /* checksum function for each byteorder */ - int ci_correctable; /* number of correctable bits */ - int ci_eck; /* uses zio embedded checksum? */ - const char *ci_name; /* descriptive name */ + zio_checksum_t *ci_func; /* checksum function for each byteorder */ + int ci_correctable; /* number of correctable bits */ + int ci_eck; /* uses zio embedded checksum? */ + const char *ci_name; /* descriptive name */ } zio_checksum_info_t; typedef struct dnode_end @@ -249,10 +260,17 @@ struct grub_zfs_data uberblock_t current_uberblock; - int mounted; grub_uint64_t guid; }; +/* Context for grub_zfs_dir. */ +struct grub_zfs_dir_ctx +{ + grub_fs_dir_hook_t hook; + void *hook_data; + struct grub_zfs_data *data; +}; + grub_err_t (*grub_zfs_decrypt) (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, void *nonce, @@ -263,17 +281,77 @@ grub_crypto_cipher_handle_t (*grub_zfs_load_key) (const struct grub_zfs_key *key grub_size_t keysize, grub_uint64_t salt, grub_uint64_t algo) = NULL; +/* + * List of pool features that the grub implementation of ZFS supports for + * read. Note that features that are only required for write do not need + * to be listed here since grub opens pools in read-only mode. + */ +#define MAX_SUPPORTED_FEATURE_STRLEN 50 +static const char *spa_feature_names[] = { + "org.illumos:lz4_compress", + "com.delphix:hole_birth", + "com.delphix:embedded_data", + "com.delphix:extensible_dataset", + "org.open-zfs:large_blocks", + "com.klarasystems:vdev_zaps_v2", + "com.delphix:head_errlog", + "org.freebsd:zstd_compress", + NULL +}; -static grub_err_t +static int +check_feature(const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx); +static grub_err_t +check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ); + +static grub_err_t zlib_decompress (void *s, void *d, grub_size_t slen, grub_size_t dlen) { - if (grub_zlib_decompress (s, slen, 0, d, dlen) < 0) - return grub_errno; + if (grub_zlib_decompress (s, slen, 0, d, dlen) == (grub_ssize_t) dlen) + return GRUB_ERR_NONE; + + if (!grub_errno) + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "premature end of compressed"); + return grub_errno; +} + +static grub_err_t +zstd_decompress (void *ibuf, void *obuf, grub_size_t isize, + grub_size_t osize) +{ + grub_size_t zstd_ret; + grub_uint32_t c_len; + grub_uint8_t *byte_buf = (grub_uint8_t *) ibuf; + + if (isize < 8) + return grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "zstd data too short"); + + c_len = grub_be_to_cpu32 (grub_get_unaligned32 (byte_buf)); + + if (c_len > isize - 8) + return grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "zstd data announced size overflow"); + + /* + * ZFS uses non-stadard magic for zstd streams. Rather than adjusting + * library functions, replace non-standard magic with standard one. + */ + byte_buf[4] = 0x28; + byte_buf[5] = 0xb5; + byte_buf[6] = 0x2f; + byte_buf[7] = 0xfd; + zstd_ret = ZSTD_decompress (obuf, osize, byte_buf + 4, c_len + 4); + + if (ZSTD_isError (zstd_ret)) + return grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "zstd data corrupted (error %d)", (int) zstd_ret); + return GRUB_ERR_NONE; } -static grub_err_t +static grub_err_t zle_decompress (void *s, void *d, grub_size_t slen, grub_size_t dlen) { @@ -322,6 +400,8 @@ static decomp_entry_t decomp_table[ZIO_COMPRESS_FUNCTIONS] = { {"gzip-8", zlib_decompress}, /* ZIO_COMPRESS_GZIP8 */ {"gzip-9", zlib_decompress}, /* ZIO_COMPRESS_GZIP9 */ {"zle", zle_decompress}, /* ZIO_COMPRESS_ZLE */ + {"lz4", lz4_decompress}, /* ZIO_COMPRESS_LZ4 */ + {"zstd", zstd_decompress}, /* ZIO_COMPRESS_ZSTD */ }; static grub_err_t zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, @@ -341,7 +421,7 @@ zfs_log2 (grub_uint64_t num) num = num >> 1; } - return (i); + return i; } /* Checksum Functions */ @@ -377,7 +457,7 @@ static zio_checksum_info_t zio_checksum_table[ZIO_CHECKSUM_FUNCTIONS] = { */ static grub_err_t zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, - grub_zfs_endian_t endian, + grub_zfs_endian_t endian, char *buf, grub_size_t size) { zio_eck_t *zec = (zio_eck_t *) (buf + size) - 1; @@ -387,14 +467,14 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, if (checksum >= ZIO_CHECKSUM_FUNCTIONS || ci->ci_func == NULL) { grub_dprintf ("zfs", "unknown checksum function %d\n", checksum); - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unknown checksum function %d", checksum); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unknown checksum function %d", checksum); } if (ci->ci_eck) { - expected_cksum = zec->zec_cksum; - zec->zec_cksum = zc; + expected_cksum = zec->zec_cksum; + zec->zec_cksum = zc; ci->ci_func (buf, size, endian, &actual_cksum); zec->zec_cksum = expected_cksum; zc = expected_cksum; @@ -407,14 +487,14 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, { grub_dprintf ("zfs", "checksum %s verification failed\n", ci->ci_name); grub_dprintf ("zfs", "actual checksum %016llx %016llx %016llx %016llx\n", - (unsigned long long) actual_cksum.zc_word[0], + (unsigned long long) actual_cksum.zc_word[0], (unsigned long long) actual_cksum.zc_word[1], - (unsigned long long) actual_cksum.zc_word[2], + (unsigned long long) actual_cksum.zc_word[2], (unsigned long long) actual_cksum.zc_word[3]); grub_dprintf ("zfs", "expected checksum %016llx %016llx %016llx %016llx\n", - (unsigned long long) zc.zc_word[0], + (unsigned long long) zc.zc_word[0], (unsigned long long) zc.zc_word[1], - (unsigned long long) zc.zc_word[2], + (unsigned long long) zc.zc_word[2], (unsigned long long) zc.zc_word[3]); return grub_error (GRUB_ERR_BAD_FS, N_("checksum verification failed")); } @@ -447,21 +527,21 @@ vdev_uberblock_compare (uberblock_t * ub1, uberblock_t * ub2) else ub2_endian = GRUB_ZFS_BIG_ENDIAN; - if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) + if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) < grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian)) - return (-1); - if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) + return -1; + if (grub_zfs_to_cpu64 (ub1->ub_txg, ub1_endian) > grub_zfs_to_cpu64 (ub2->ub_txg, ub2_endian)) - return (1); + return 1; - if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) + if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) < grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian)) - return (-1); - if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) + return -1; + if (grub_zfs_to_cpu64 (ub1->ub_timestamp, ub1_endian) > grub_zfs_to_cpu64 (ub2->ub_timestamp, ub2_endian)) - return (1); + return 1; - return (0); + return 0; } /* @@ -482,15 +562,11 @@ uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset, if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC - && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN) > 0 - && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN) - <= SPA_VERSION) + && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_LITTLE_ENDIAN))) endian = GRUB_ZFS_LITTLE_ENDIAN; if (grub_zfs_to_cpu64 (uber->ub_magic, GRUB_ZFS_BIG_ENDIAN) == UBERBLOCK_MAGIC - && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN) > 0 - && grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN) - <= SPA_VERSION) + && SPA_VERSION_IS_SUPPORTED(grub_zfs_to_cpu64 (uber->ub_version, GRUB_ZFS_BIG_ENDIAN))) endian = GRUB_ZFS_BIG_ENDIAN; if (endian == GRUB_ZFS_UNKNOWN_ENDIAN) @@ -533,13 +609,13 @@ find_bestub (uberblock_phys_t * ub_array, ubptr = (uberblock_phys_t *) ((grub_properly_aligned_t *) ub_array + ((i << ub_shift) / sizeof (grub_properly_aligned_t))); - err = uberblock_verify (ubptr, offset, 1 << ub_shift); + err = uberblock_verify (ubptr, offset, (grub_size_t) 1 << ub_shift); if (err) { grub_errno = GRUB_ERR_NONE; continue; } - if (ubbest == NULL + if (ubbest == NULL || vdev_uberblock_compare (&(ubptr->ubp_uberblock), &(ubbest->ubp_uberblock)) > 0) ubbest = ubptr; @@ -547,7 +623,7 @@ find_bestub (uberblock_phys_t * ub_array, if (!ubbest) grub_errno = err; - return (ubbest); + return ubbest; } static inline grub_size_t @@ -560,10 +636,10 @@ get_psize (blkptr_t * bp, grub_zfs_endian_t endian) static grub_uint64_t dva_get_offset (const dva_t *dva, grub_zfs_endian_t endian) { - grub_dprintf ("zfs", "dva=%llx, %llx\n", - (unsigned long long) dva->dva_word[0], + grub_dprintf ("zfs", "dva=%llx, %llx\n", + (unsigned long long) dva->dva_word[0], (unsigned long long) dva->dva_word[1]); - return grub_zfs_to_cpu64 ((dva)->dva_word[1], + return grub_zfs_to_cpu64 ((dva)->dva_word[1], endian) << SPA_MINBLOCKSHIFT; } @@ -578,6 +654,8 @@ zfs_fetch_nvlist (struct grub_zfs_device_desc *diskdesc, char **nvlist) return grub_error (GRUB_ERR_BUG, "member drive unknown"); *nvlist = grub_malloc (VDEV_PHYS_SIZE); + if (!*nvlist) + return grub_errno; /* Read in the vdev name-value pair list (112K). */ err = grub_disk_read (diskdesc->dev->disk, diskdesc->vdev_phys_sector, 0, @@ -686,9 +764,14 @@ fill_vdev_info_real (struct grub_zfs_data *data, if (!fill->children) { fill->n_children = nelm; - - fill->children = grub_zalloc (fill->n_children - * sizeof (fill->children[0])); + + fill->children = grub_calloc (fill->n_children, + sizeof (fill->children[0])); + if (!fill->children) + { + grub_free (type); + return grub_errno; + } } for (i = 0; i < nelm; i++) @@ -743,11 +826,14 @@ fill_vdev_info (struct grub_zfs_data *data, if (data->n_devices_attached > data->n_devices_allocated) { void *tmp; - data->n_devices_allocated = 2 * data->n_devices_attached + 1; - data->devices_attached - = grub_realloc (tmp = data->devices_attached, - data->n_devices_allocated - * sizeof (data->devices_attached[0])); + grub_size_t sz; + + if (grub_mul (data->n_devices_attached, 2, &data->n_devices_allocated) || + grub_add (data->n_devices_allocated, 1, &data->n_devices_allocated) || + grub_mul (data->n_devices_allocated, sizeof (data->devices_attached[0]), &sz)) + return GRUB_ERR_OUT_OF_RANGE; + + data->devices_attached = grub_realloc (tmp = data->devices_attached, sz); if (!data->devices_attached) { data->devices_attached = tmp; @@ -763,6 +849,167 @@ fill_vdev_info (struct grub_zfs_data *data, diskdesc, inserted, 0xffffffff); } +/* + * For a given XDR packed nvlist, verify the first 4 bytes and move on. + * + * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) : + * + * encoding method/host endian (4 bytes) + * nvl_version (4 bytes) + * nvl_nvflag (4 bytes) + * encoded nvpairs: + * encoded size of the nvpair (4 bytes) + * decoded size of the nvpair (4 bytes) + * name string size (4 bytes) + * name string data (sizeof(NV_ALIGN4(string)) + * data type (4 bytes) + * # of elements in the nvpair (4 bytes) + * data + * 2 zero's for the last nvpair + * (end of the entire list) (8 bytes) + * + */ + +/* + * The nvlist_next_nvpair() function returns a handle to the next nvpair in the + * list following nvpair. If nvpair is NULL, the first pair is returned. If + * nvpair is the last pair in the nvlist, NULL is returned. + */ +static const char * +nvlist_next_nvpair (const char *nvl, const char *nvpair) +{ + const char *nvp; + int encode_size; + int name_len; + if (nvl == NULL) + return NULL; + + if (nvpair == NULL) + { + /* skip over header, nvl_version and nvl_nvflag */ + nvpair = nvl + 4 * 3; + } + else + { + /* skip to the next nvpair */ + encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair)); + nvpair += encode_size; + /*If encode_size equals 0 nvlist_next_nvpair would return + * the same pair received in input, leading to an infinite loop. + * If encode_size is less than 0, this will move the pointer + * backwards, *possibly* examinining two times the same nvpair + * and potentially getting into an infinite loop. */ + if(encode_size <= 0) + { + grub_dprintf ("zfs", "nvpair with size <= 0\n"); + grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); + return NULL; + } + } + /* 8 bytes of 0 marks the end of the list */ + if (grub_get_unaligned64 (nvpair) == 0) + return NULL; + /*consistency checks*/ + if (nvpair + 4 * 3 >= nvl + VDEV_PHYS_SIZE) + { + grub_dprintf ("zfs", "nvlist overflow\n"); + grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); + return NULL; + } + encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvpair)); + + nvp = nvpair + 4*2; + name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + nvp += 4; + + nvp = nvp + ((name_len + 3) & ~3); // align + if (nvp + 4 >= nvl + VDEV_PHYS_SIZE + || encode_size < 0 + || nvp + 4 + encode_size > nvl + VDEV_PHYS_SIZE) + { + grub_dprintf ("zfs", "nvlist overflow\n"); + grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); + return NULL; + } + /* end consistency checks */ + + return nvpair; +} + +/* + * This function returns 0 on success and 1 on failure. On success, a string + * containing the name of nvpair is saved in buf. + */ +static int +nvpair_name (const char *nvp, char **buf, grub_size_t *buflen) +{ + /* skip over encode/decode size */ + nvp += 4 * 2; + + *buf = (char *) (nvp + 4); + *buflen = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + + return 0; +} + +/* + * This function retrieves the value of the nvpair in the form of enumerated + * type data_type_t. + */ +static int +nvpair_type (const char *nvp) +{ + int name_len, type; + + /* skip over encode/decode size */ + nvp += 4 * 2; + + /* skip over name_len */ + name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + nvp += 4; + + /* skip over name */ + nvp = nvp + ((name_len + 3) & ~3); /* align */ + + type = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + + return type; +} + +static int +nvpair_value (const char *nvp,char **val, + grub_size_t *size_out, grub_size_t *nelm_out) +{ + int name_len,nelm,encode_size; + + /* skip over encode/decode size */ + encode_size = grub_be_to_cpu32 (grub_get_unaligned32(nvp)); + nvp += 8; + + /* skip over name_len */ + name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + nvp += 4; + + /* skip over name */ + nvp = nvp + ((name_len + 3) & ~3); /* align */ + + /* skip over type */ + nvp += 4; + nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvp)); + nvp +=4; + if (nelm < 1) + { + grub_error (GRUB_ERR_BAD_FS, "empty nvpair"); + return 0; + } + *val = (char *) nvp; + *size_out = encode_size; + if (nelm_out) + *nelm_out = nelm; + + return 1; +} + /* * Check the disk label information and retrieve needed vdev name-value pairs. * @@ -770,10 +1017,10 @@ fill_vdev_info (struct grub_zfs_data *data, static grub_err_t check_pool_label (struct grub_zfs_data *data, struct grub_zfs_device_desc *diskdesc, - int *inserted) + int *inserted, int original) { grub_uint64_t pool_state, txg = 0; - char *nvlist; + char *nvlist,*features; #if 0 char *nv; #endif @@ -781,6 +1028,9 @@ check_pool_label (struct grub_zfs_data *data, grub_uint64_t version; int found; grub_err_t err; + grub_zfs_endian_t endian; + vdev_phys_t *phys; + zio_cksum_t emptycksum; *inserted = 0; @@ -788,6 +1038,30 @@ check_pool_label (struct grub_zfs_data *data, if (err) return err; + phys = (vdev_phys_t*) nvlist; + if (grub_zfs_to_cpu64 (phys->vp_zbt.zec_magic, + GRUB_ZFS_LITTLE_ENDIAN) + == ZEC_MAGIC) + endian = GRUB_ZFS_LITTLE_ENDIAN; + else if (grub_zfs_to_cpu64 (phys->vp_zbt.zec_magic, + GRUB_ZFS_BIG_ENDIAN) + == ZEC_MAGIC) + endian = GRUB_ZFS_BIG_ENDIAN; + else + { + grub_free (nvlist); + return grub_error (GRUB_ERR_BAD_FS, + "bad vdev_phys_t.vp_zbt.zec_magic number"); + } + /* Now check the integrity of the vdev_phys_t structure though checksum. */ + ZIO_SET_CHECKSUM(&emptycksum, diskdesc->vdev_phys_sector << 9, 0, 0, 0); + err = zio_checksum_verify (emptycksum, ZIO_CHECKSUM_LABEL, endian, + nvlist, VDEV_PHYS_SIZE); + if (err) { + grub_free (nvlist); + return err; + } + grub_dprintf ("zfs", "check 2 passed\n"); found = grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_POOL_STATE, @@ -837,13 +1111,13 @@ check_pool_label (struct grub_zfs_data *data, } grub_dprintf ("zfs", "check 8 passed\n"); - if (version > SPA_VERSION) + if (!SPA_VERSION_IS_SUPPORTED(version)) { grub_free (nvlist); return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "too new version %llu > %llu", (unsigned long long) version, - (unsigned long long) SPA_VERSION); + (unsigned long long) SPA_VERSION_BEFORE_FEATURES); } grub_dprintf ("zfs", "check 9 passed\n"); @@ -869,11 +1143,14 @@ check_pool_label (struct grub_zfs_data *data, grub_dprintf ("zfs", "check 11 passed\n"); - if (data->mounted && data->guid != poolguid) - return grub_error (GRUB_ERR_BAD_FS, "another zpool"); - else + if (original) data->guid = poolguid; + if (data->guid != poolguid) { + grub_free (nvlist); + return grub_error (GRUB_ERR_BAD_FS, "another zpool"); + } + { char *nv; nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE); @@ -893,7 +1170,34 @@ check_pool_label (struct grub_zfs_data *data, grub_free (nv); } grub_dprintf ("zfs", "check 10 passed\n"); - + features = grub_zfs_nvlist_lookup_nvlist(nvlist, + ZPOOL_CONFIG_FEATURES_FOR_READ); + if (features) + { + const char *nvp=NULL; + char name[MAX_SUPPORTED_FEATURE_STRLEN + 1]; + char *nameptr; + grub_size_t namelen; + while ((nvp = nvlist_next_nvpair(features, nvp)) != NULL) + { + nvpair_name (nvp, &nameptr, &namelen); + if(namelen > MAX_SUPPORTED_FEATURE_STRLEN) + namelen = MAX_SUPPORTED_FEATURE_STRLEN; + grub_memcpy (name, nameptr, namelen); + name[namelen] = '\0'; + grub_dprintf("zfs","str=%s\n",name); + if (check_feature(name,1, NULL) != 0) + { + grub_dprintf("zfs","feature missing in check_pool_label:%s\n",name); + err= grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET," check_pool_label missing feature '%s' for read",name); + grub_free(features); + grub_free(nvlist); + return err; + } + } + grub_free(features); + } + grub_dprintf ("zfs", "check 12 passed (feature flags)\n"); grub_free (nvlist); return GRUB_ERR_NONE; @@ -927,7 +1231,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, desc.original = original; /* Don't check back labels on CDROM. */ - if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN) + if (grub_disk_native_sectors (dev->disk) == GRUB_DISK_SIZE_UNKNOWN) vdevnum = VDEV_LABELS / 2; for (label = 0; ubbest == NULL && label < vdevnum; label++) @@ -935,8 +1239,8 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, desc.vdev_phys_sector = label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT) + ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT) - + (label < VDEV_LABELS / 2 ? 0 : - ALIGN_DOWN (grub_disk_get_size (dev->disk), sizeof (vdev_label_t)) + + (label < VDEV_LABELS / 2 ? 0 : + ALIGN_DOWN (grub_disk_native_sectors (dev->disk), sizeof (vdev_label_t)) - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)); /* Read in the uberblock ring (128K). */ @@ -950,7 +1254,7 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, } grub_dprintf ("zfs", "label ok %d\n", label); - err = check_pool_label (data, &desc, inserted); + err = check_pool_label (data, &desc, inserted, original); if (err || !*inserted) { grub_errno = GRUB_ERR_NONE; @@ -981,50 +1285,54 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, grub_free (bh); return GRUB_ERR_NONE; } - + grub_free (ub_array); grub_free (bh); return grub_error (GRUB_ERR_BAD_FS, "couldn't find a valid label"); } +/* Helper for scan_devices. */ +static int +scan_devices_iter (const char *name, void *hook_data) +{ + struct grub_zfs_data *data = hook_data; + grub_device_t dev; + grub_err_t err; + int inserted; + + dev = grub_device_open (name); + if (!dev) + return 0; + if (!dev->disk) + { + grub_device_close (dev); + return 0; + } + err = scan_disk (dev, data, 0, &inserted); + if (err == GRUB_ERR_BAD_FS) + { + grub_device_close (dev); + grub_errno = GRUB_ERR_NONE; + return 0; + } + if (err) + { + grub_device_close (dev); + grub_print_error (); + return 0; + } + + if (!inserted) + grub_device_close (dev); + + return 0; +} + static grub_err_t scan_devices (struct grub_zfs_data *data) { - auto int hook (const char *name); - int hook (const char *name) - { - grub_device_t dev; - grub_err_t err; - int inserted; - dev = grub_device_open (name); - if (!dev) - return 0; - if (!dev->disk) - { - grub_device_close (dev); - return 0; - } - err = scan_disk (dev, data, 0, &inserted); - if (err == GRUB_ERR_BAD_FS) - { - grub_device_close (dev); - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (err) - { - grub_device_close (dev); - grub_print_error (); - return 0; - } - - if (!inserted) - grub_device_close (dev); - - return 0; - } - grub_device_iterate (hook); + grub_device_iterate (scan_devices_iter, data); return GRUB_ERR_NONE; } @@ -1037,9 +1345,9 @@ static const grub_uint8_t poly = 0x1d; /* perform the operation a ^= b * (x ** (known_idx * recovery_pow) ) */ static inline void xor_out (grub_uint8_t *a, const grub_uint8_t *b, grub_size_t s, - int known_idx, int recovery_pow) + unsigned known_idx, unsigned recovery_pow) { - int add; + unsigned add; /* Simple xor. */ if (known_idx == 0 || recovery_pow == 0) @@ -1061,10 +1369,12 @@ gf_mul (grub_uint8_t a, grub_uint8_t b) return powx[powx_inv[a] + powx_inv[b]]; } -static inline grub_err_t +#define MAX_NBUFS 4 + +static grub_err_t recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, const unsigned *powers, - const int *idx) + const unsigned *idx) { grub_dprintf ("zfs", "recovering %u buffers\n", nbufs); /* Now we have */ @@ -1115,9 +1425,9 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, return GRUB_ERR_NONE; } /* Otherwise use Gauss. */ - default: + case 3: { - grub_uint8_t matrix1[nbufs][nbufs], matrix2[nbufs][nbufs]; + grub_uint8_t matrix1[MAX_NBUFS][MAX_NBUFS], matrix2[MAX_NBUFS][MAX_NBUFS]; int i, j, k; for (i = 0; i < nbufs; i++) @@ -1127,12 +1437,12 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, for (j = 0; j < nbufs; j++) matrix2[i][j] = 0; for (i = 0; i < nbufs; i++) - matrix2[i][i] = 1; + matrix2[i][i] = 1; for (i = 0; i < nbufs; i++) { grub_uint8_t mul; - for (j = i; j < nbufs; j++) + for (j = i; j < nbufs; j++) if (matrix1[i][j]) break; if (j == nbufs) @@ -1185,7 +1495,7 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, for (i = 0; i < (int) s; i++) { - grub_uint8_t b[nbufs]; + grub_uint8_t b[MAX_NBUFS]; for (j = 0; j < nbufs; j++) b[j] = bufs[j][i]; for (j = 0; j < nbufs; j++) @@ -1197,7 +1507,9 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, } return GRUB_ERR_NONE; } - } + default: + return grub_error (GRUB_ERR_BUG, "too big matrix"); + } } static grub_err_t @@ -1234,7 +1546,9 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, break; grub_errno = GRUB_ERR_NONE; } - return (grub_errno = err); + grub_errno = err; + + return err; } case DEVICE_RAIDZ: { @@ -1247,14 +1561,17 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, grub_size_t orig_len = len; grub_uint8_t *recovery_buf[4]; grub_size_t recovery_len[4]; - int recovery_idx[4]; + unsigned recovery_idx[4]; unsigned failed_devices = 0; int idx, orig_idx; if (desc->nparity < 1 || desc->nparity > 3) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "raidz%d is not supported", desc->nparity); + if (desc->n_children <= desc->nparity || desc->n_children < 1) + return grub_error(GRUB_ERR_BAD_FS, "too little devices for given parity"); + orig_s = (((len + (1 << desc->ashift) - 1) >> desc->ashift) + (desc->n_children - desc->nparity) - 1); s = orig_s; @@ -1285,7 +1602,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, high = grub_divmod64 ((offset >> desc->ashift) + c, desc->n_children, &devn); - csize = bsize << desc->ashift; + csize = (grub_size_t) bsize << desc->ashift; if (csize > len) csize = len; @@ -1377,8 +1694,8 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, while (len > 0) { - grub_size_t csize; - csize = ((s / (desc->n_children - desc->nparity)) + grub_size_t csize = s; + csize = ((csize / (desc->n_children - desc->nparity)) << desc->ashift); if (csize > len) csize = len; @@ -1398,7 +1715,7 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, len -= csize; idx--; } - for (i = 0; i < failed_devices + for (i = 0; i < failed_devices && recovery_len[i] == recovery_len[0]; i++); /* Since the chunks have variable length handle the last block @@ -1502,7 +1819,7 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, for (i = 0; i < SPA_GBH_NBLKPTRS; i++) { - if (zio_gb->zg_blkptr[i].blk_birth == 0) + if (BP_IS_HOLE(&zio_gb->zg_blkptr[i])) continue; err = zio_read_data (&zio_gb->zg_blkptr[i], endian, buf, data); @@ -1521,7 +1838,7 @@ zio_read_gang (blkptr_t * bp, grub_zfs_endian_t endian, dva_t * dva, void *buf, * Read in a block of raw data to buf. */ static grub_err_t -zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, +zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, struct grub_zfs_data *data) { int i, psize; @@ -1551,12 +1868,45 @@ zio_read_data (blkptr_t * bp, grub_zfs_endian_t endian, void *buf, return err; } +/* + * buf must be at least BPE_GET_PSIZE(bp) bytes long (which will never be + * more than BPE_PAYLOAD_SIZE bytes). + */ +static grub_err_t +decode_embedded_bp_compressed(const blkptr_t *bp, void *buf) +{ + grub_size_t psize, i; + grub_uint8_t *buf8 = buf; + grub_uint64_t w = 0; + const grub_uint64_t *bp64 = (const grub_uint64_t *)bp; + + psize = BPE_GET_PSIZE(bp); + + /* + * Decode the words of the block pointer into the byte array. + * Low bits of first word are the first byte (little endian). + */ + for (i = 0; i < psize; i++) + { + if (i % sizeof (w) == 0) + { + /* beginning of a word */ + w = *bp64; + bp64++; + if (!BPE_IS_PAYLOADWORD(bp, bp64)) + bp64++; + } + buf8[i] = BF64_GET(w, (i % sizeof (w)) * 8, 8); + } + return GRUB_ERR_NONE; +} + /* * Read in a block of data, verify its checksum, decompress if needed, * and put the uncompressed data in buf. */ static grub_err_t -zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, +zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, grub_size_t *size, struct grub_zfs_data *data) { grub_size_t lsize, psize; @@ -1569,12 +1919,27 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, *buf = NULL; checksum = (grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 40) & 0xff; - comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0xff; + comp = (grub_zfs_to_cpu64((bp)->blk_prop, endian)>>32) & 0x7f; encrypted = ((grub_zfs_to_cpu64((bp)->blk_prop, endian) >> 60) & 3); - lsize = (BP_IS_HOLE(bp) ? 0 : - (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) - << SPA_MINBLOCKSHIFT)); - psize = get_psize (bp, endian); + if (BP_IS_EMBEDDED(bp)) + { + if (BPE_GET_ETYPE(bp) != BP_EMBEDDED_TYPE_DATA) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported embedded BP (type=%" + PRIuGRUB_UINT64_T ")\n", + BPE_GET_ETYPE (bp)); + lsize = BPE_GET_LSIZE(bp); + psize = BF64_GET_SB(grub_zfs_to_cpu64 ((bp)->blk_prop, endian), 25, 7, 0, 1); + } + else + { + lsize = (BP_IS_HOLE(bp) ? 0 : + (((grub_zfs_to_cpu64 ((bp)->blk_prop, endian) & 0xffff) + 1) + << SPA_MINBLOCKSHIFT)); + psize = get_psize (bp, endian); + } + grub_dprintf("zfs", "zio_read: E %d: size %" PRIdGRUB_SSIZE "/%" + PRIdGRUB_SSIZE "\n", (int)BP_IS_EMBEDDED(bp), lsize, psize); if (size) *size = lsize; @@ -1588,39 +1953,47 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, "compression algorithm %s not supported\n", decomp_table[comp].name); if (comp != ZIO_COMPRESS_OFF) - { - /* It's not really necessary to align to 16, just for safety. */ - compbuf = grub_malloc (ALIGN_UP (psize, 16)); - if (! compbuf) - return grub_errno; - } + /* It's not really necessary to align to 16, just for safety. */ + compbuf = grub_malloc (ALIGN_UP (psize, 16)); else compbuf = *buf = grub_malloc (lsize); + if (! compbuf) + return grub_errno; grub_dprintf ("zfs", "endian = %d\n", endian); - err = zio_read_data (bp, endian, compbuf, data); + if (BP_IS_EMBEDDED(bp)) + err = decode_embedded_bp_compressed(bp, compbuf); + else + { + err = zio_read_data (bp, endian, compbuf, data); + /* FIXME is it really necessary? */ + if (comp != ZIO_COMPRESS_OFF) + grub_memset (compbuf + psize, 0, ALIGN_UP (psize, 16) - psize); + } if (err) { grub_free (compbuf); *buf = NULL; return err; } - grub_memset (compbuf, 0, ALIGN_UP (psize, 16) - psize); - err = zio_checksum_verify (zc, checksum, endian, - compbuf, psize); - if (err) + if (!BP_IS_EMBEDDED(bp)) { - grub_dprintf ("zfs", "incorrect checksum\n"); - grub_free (compbuf); - *buf = NULL; - return err; + err = zio_checksum_verify (zc, checksum, endian, + compbuf, psize); + if (err) + { + grub_dprintf ("zfs", "incorrect checksum\n"); + grub_free (compbuf); + *buf = NULL; + return err; + } } if (encrypted) { if (!grub_zfs_decrypt) - err = grub_error (GRUB_ERR_BAD_FS, + err = grub_error (GRUB_ERR_BAD_FS, N_("module `%s' isn't loaded"), "zfscrypt"); else @@ -1644,7 +2017,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, endian)); return grub_error (GRUB_ERR_BAD_FS, "no key found in keychain"); } - grub_dprintf ("zfs", "using key %u (%" PRIxGRUB_UINT64_T + grub_dprintf ("zfs", "using key %u (%" PRIxGRUB_UINT64_T ", %p) for txg %" PRIxGRUB_UINT64_T "\n", besti, data->subvol.keyring[besti].txg, data->subvol.keyring[besti].cipher, @@ -1653,7 +2026,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, err = grub_zfs_decrypt (data->subvol.keyring[besti].cipher, data->subvol.keyring[besti].algo, &(bp)->blk_dva[encrypted], - compbuf, psize, ((grub_uint32_t *) &zc + 5), + compbuf, psize, zc.zc_mac, endian); } if (err) @@ -1692,7 +2065,7 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, * */ static grub_err_t -dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, +dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, grub_zfs_endian_t *endian_out, struct grub_zfs_data *data) { int level; @@ -1722,11 +2095,11 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, if (BP_IS_HOLE (bp)) { - grub_size_t size = grub_zfs_to_cpu16 (dn->dn.dn_datablkszsec, - dn->endian) + grub_size_t size = grub_zfs_to_cpu16 (dn->dn.dn_datablkszsec, + dn->endian) << SPA_MINBLOCKSHIFT; *buf = grub_malloc (size); - if (*buf) + if (!*buf) { err = grub_errno; break; @@ -1764,12 +2137,14 @@ dmu_read (dnode_end_t * dn, grub_uint64_t blkid, void **buf, */ static grub_err_t mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, - int objsize, const char *name, grub_uint64_t * value, + grub_uint32_t objsize, const char *name, grub_uint64_t * value, int case_insensitive) { - int i, chunks; + grub_uint32_t i, chunks; mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk; + if (objsize < MZAP_ENT_LEN) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name); chunks = objsize / MZAP_ENT_LEN - 1; for (i = 0; i < chunks; i++) { @@ -1785,9 +2160,10 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, } static int -mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, - int NESTED_FUNC_ATTR (*hook) (const char *name, - grub_uint64_t val)) +mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, + int (*hook) (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx), + struct grub_zfs_dir_ctx *ctx) { int i, chunks; mzap_ent_phys_t *mzap_ent = zapobj->mz_chunk; @@ -1798,8 +2174,8 @@ mzap_iterate (mzap_phys_t * zapobj, grub_zfs_endian_t endian, int objsize, grub_dprintf ("zfs", "zap: name = %s, value = %llx, cd = %x\n", mzap_ent[i].mze_name, (long long)mzap_ent[i].mze_value, (int)mzap_ent[i].mze_cd); - if (hook (mzap_ent[i].mze_name, - grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian))) + if (hook (mzap_ent[i].mze_name, + grub_zfs_to_cpu64 (mzap_ent[i].mze_value, endian), ctx)) return 1; } @@ -1841,7 +2217,7 @@ zap_hash (grub_uint64_t salt, const char *name, */ crc &= ~((1ULL << (64 - ZAP_HASHBITS)) - 1); - return (crc); + return crc; } /* @@ -1859,12 +2235,12 @@ name_cmp (const char *s1, const char *s2, grub_size_t n, if (!case_insensitive) return grub_memcmp (t1, t2, n); - + while (n--) { if (grub_toupper (*t1) != grub_toupper (*t2)) - return (int) grub_toupper (*t1) - (int) grub_toupper (*t2); - + return (int) grub_toupper (*t1) - (int) grub_toupper (*t2); + t1++; t2++; } @@ -1902,14 +2278,14 @@ zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, /* XXX */ static grub_err_t -zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, +zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, int chunk, grub_size_t array_len, char *buf) { grub_size_t bseen = 0; while (bseen < array_len) { - struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk)->l_array; + struct zap_leaf_array *la; grub_size_t toread = array_len - bseen; if (toread > ZAP_LEAF_ARRAY_BYTES) @@ -1919,6 +2295,7 @@ zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, /* Don't use grub_error because this error is to be ignored. */ return GRUB_ERR_BAD_FS; + la = &ZAP_LEAF_CHUNK (l, blksft, chunk)->l_array; grub_memcpy (buf + bseen,la->la_array, toread); chunk = grub_zfs_to_cpu16 (la->la_next, endian); bseen += toread; @@ -1966,7 +2343,7 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, grub_dprintf ("zfs", "fzap: length %d\n", (int) le->le_name_length); - if (zap_leaf_array_equal (l, endian, blksft, + if (zap_leaf_array_equal (l, endian, blksft, grub_zfs_to_cpu16 (le->le_name_chunk,endian), grub_zfs_to_cpu16 (le->le_name_length, endian), name, case_insensitive)) @@ -2015,7 +2392,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, { void *l; grub_uint64_t hash, idx, blkid; - int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, + int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << DNODE_SHIFT); grub_err_t err; grub_zfs_endian_t leafendian; @@ -2028,7 +2405,7 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, /* get block id from index */ if (zap->zap_ptrtbl.zt_numblks != 0) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "external pointer tables not supported"); idx = ZAP_HASH_IDX (hash, zap->zap_ptrtbl.zt_shift); blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))], zap_dnode->endian); @@ -2050,21 +2427,21 @@ fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, static int fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, grub_size_t name_elem_length, - int NESTED_FUNC_ATTR (*hook) (const void *name, - grub_size_t name_length, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize), - struct grub_zfs_data *data) + int (*hook) (const void *name, grub_size_t name_length, + const void *val_in, + grub_size_t nelem, grub_size_t elemsize, + void *data), + void *hook_data, struct grub_zfs_data *data) { zap_leaf_phys_t *l; void *l_in; grub_uint64_t idx, idx2, blkid; grub_uint16_t chunk; - int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, + int blksft = zfs_log2 (grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << DNODE_SHIFT); grub_err_t err; grub_zfs_endian_t endian; + grub_size_t sz; if (zap_verify (zap, zap_dnode->endian)) return 0; @@ -2072,7 +2449,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, /* get block id from index */ if (zap->zap_ptrtbl.zt_numblks != 0) { - grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "external pointer tables not supported"); return 0; } @@ -2085,11 +2462,11 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, for (idx = 0; idx < (1ULL << zap->zap_ptrtbl.zt_shift); idx++) { blkid = grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx + (1 << (blksft - 3 - 1))], - zap_dnode->endian); + zap_dnode->endian); for (idx2 = 0; idx2 < idx; idx2++) if (blkid == grub_zfs_to_cpu64 (((grub_uint64_t *) zap)[idx2 + (1 << (blksft - 3 - 1))], - zap_dnode->endian)) + zap_dnode->endian)) break; if (idx2 != idx) continue; @@ -2115,53 +2492,70 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, } for (chunk = 0; chunk < ZAP_LEAF_NUMCHUNKS (blksft); chunk++) - { - char *buf; - struct zap_leaf_entry *le; - char *val; - grub_size_t val_length; - le = ZAP_LEAF_ENTRY (l, blksft, chunk); + { + char *buf; + struct zap_leaf_entry *le; + char *val; + grub_size_t val_length; + le = ZAP_LEAF_ENTRY (l, blksft, chunk); - /* Verify the chunk entry */ - if (le->le_type != ZAP_CHUNK_ENTRY) + /* Verify the chunk entry */ + if (le->le_type != ZAP_CHUNK_ENTRY) + continue; + + if (grub_mul (grub_zfs_to_cpu16 (le->le_name_length, endian), name_elem_length, &sz) || + grub_add (sz, 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("buffer size overflow")); + grub_free (l); + return grub_errno; + } + buf = grub_malloc (sz); + if (!buf) + { + grub_free (l); + return grub_errno; + } + if (zap_leaf_array_get (l, endian, blksft, + grub_zfs_to_cpu16 (le->le_name_chunk, + endian), + grub_zfs_to_cpu16 (le->le_name_length, + endian) + * name_elem_length, buf)) + { + grub_free (buf); continue; + } + buf[le->le_name_length * name_elem_length] = 0; - buf = grub_malloc (grub_zfs_to_cpu16 (le->le_name_length, endian) - * name_elem_length + 1); - if (zap_leaf_array_get (l, endian, blksft, - grub_zfs_to_cpu16 (le->le_name_chunk, - endian), - grub_zfs_to_cpu16 (le->le_name_length, - endian) - * name_elem_length, buf)) - { - grub_free (buf); - continue; - } - buf[le->le_name_length * name_elem_length] = 0; + val_length = ((int) le->le_value_length + * (int) le->le_int_size); + val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian)); + if (!val) + { + grub_free (l); + grub_free (buf); + return grub_errno; + } + if (zap_leaf_array_get (l, endian, blksft, + grub_zfs_to_cpu16 (le->le_value_chunk, + endian), + val_length, val)) + { + grub_free (buf); + grub_free (val); + continue; + } - val_length = ((int) le->le_value_length - * (int) le->le_int_size); - val = grub_malloc (grub_zfs_to_cpu16 (val_length, endian)); - if (zap_leaf_array_get (l, endian, blksft, - grub_zfs_to_cpu16 (le->le_value_chunk, - endian), - val_length, val)) - { - grub_free (buf); - grub_free (val); - continue; - } - - if (hook (buf, le->le_name_length, - val, le->le_value_length, le->le_int_size)) - { - grub_free (l); - return 1; - } - grub_free (buf); - grub_free (val); - } + if (hook (buf, le->le_name_length, + val, le->le_value_length, le->le_int_size, hook_data)) + { + grub_free (l); + return 1; + } + grub_free (buf); + grub_free (val); + } grub_free (l); } return 0; @@ -2177,7 +2571,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, struct grub_zfs_data *data, int case_insensitive) { grub_uint64_t block_type; - int size; + grub_uint32_t size; void *zapbuf; grub_err_t err; grub_zfs_endian_t endian; @@ -2185,7 +2579,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, grub_dprintf ("zfs", "looking for '%s'\n", name); /* Read in the first block of the zap object data. */ - size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, + size = (grub_uint32_t) grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT; err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data); if (err) @@ -2199,7 +2593,7 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, grub_dprintf ("zfs", "micro zap\n"); err = mzap_lookup (zapbuf, endian, size, name, val, case_insensitive); - grub_dprintf ("zfs", "returned %d\n", err); + grub_dprintf ("zfs", "returned %d\n", err); grub_free (zapbuf); return err; } @@ -2209,19 +2603,44 @@ zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, /* this is a fat zap */ err = fzap_lookup (zap_dnode, zapbuf, name, val, data, case_insensitive); - grub_dprintf ("zfs", "returned %d\n", err); + grub_dprintf ("zfs", "returned %d\n", err); grub_free (zapbuf); return err; } + grub_free (zapbuf); return grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type"); } +/* Context for zap_iterate_u64. */ +struct zap_iterate_u64_ctx +{ + int (*hook) (const char *, grub_uint64_t, struct grub_zfs_dir_ctx *); + struct grub_zfs_dir_ctx *dir_ctx; +}; + +/* Helper for zap_iterate_u64. */ static int -zap_iterate_u64 (dnode_end_t * zap_dnode, - int NESTED_FUNC_ATTR (*hook) (const char *name, - grub_uint64_t val), - struct grub_zfs_data *data) +zap_iterate_u64_transform (const void *name, + grub_size_t namelen __attribute__ ((unused)), + const void *val_in, + grub_size_t nelem, + grub_size_t elemsize, + void *data) +{ + struct zap_iterate_u64_ctx *ctx = data; + + if (elemsize != sizeof (grub_uint64_t) || nelem != 1) + return 0; + return ctx->hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in), + ctx->dir_ctx); +} + +static int +zap_iterate_u64 (dnode_end_t * zap_dnode, + int (*hook) (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx), + struct grub_zfs_data *data, struct grub_zfs_dir_ctx *ctx) { grub_uint64_t block_type; int size; @@ -2230,23 +2649,6 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, int ret; grub_zfs_endian_t endian; - auto int NESTED_FUNC_ATTR transform (const void *name, - grub_size_t namelen, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize); - - int NESTED_FUNC_ATTR transform (const void *name, - grub_size_t namelen __attribute__ ((unused)), - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize) - { - if (elemsize != sizeof (grub_uint64_t) || nelem != 1) - return 0; - return hook (name, grub_be_to_cpu64 (*(const grub_uint64_t *) val_in)); - } - /* Read in the first block of the zap object data. */ size = grub_zfs_to_cpu16 (zap_dnode->dn.dn_datablkszsec, zap_dnode->endian) << SPA_MINBLOCKSHIFT; err = dmu_read (zap_dnode, 0, &zapbuf, &endian, data); @@ -2259,31 +2661,37 @@ zap_iterate_u64 (dnode_end_t * zap_dnode, if (block_type == ZBT_MICRO) { grub_dprintf ("zfs", "micro zap\n"); - ret = mzap_iterate (zapbuf, endian, size, hook); + ret = mzap_iterate (zapbuf, endian, size, hook, ctx); grub_free (zapbuf); return ret; } else if (block_type == ZBT_HEADER) { + struct zap_iterate_u64_ctx transform_ctx = { + .hook = hook, + .dir_ctx = ctx + }; + grub_dprintf ("zfs", "fat zap\n"); /* this is a fat zap */ - ret = fzap_iterate (zap_dnode, zapbuf, 1, transform, data); + ret = fzap_iterate (zap_dnode, zapbuf, 1, + zap_iterate_u64_transform, &transform_ctx, data); grub_free (zapbuf); return ret; } + grub_free (zapbuf); grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type"); return 0; } static int -zap_iterate (dnode_end_t * zap_dnode, +zap_iterate (dnode_end_t * zap_dnode, grub_size_t nameelemlen, - int NESTED_FUNC_ATTR (*hook) (const void *name, - grub_size_t namelen, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize), - struct grub_zfs_data *data) + int (*hook) (const void *name, grub_size_t namelen, + const void *val_in, + grub_size_t nelem, grub_size_t elemsize, + void *data), + void *hook_data, struct grub_zfs_data *data) { grub_uint64_t block_type; void *zapbuf; @@ -2302,16 +2710,19 @@ zap_iterate (dnode_end_t * zap_dnode, if (block_type == ZBT_MICRO) { grub_error (GRUB_ERR_BAD_FS, "micro ZAP where FAT ZAP expected"); + grub_free (zapbuf); return 0; } if (block_type == ZBT_HEADER) { grub_dprintf ("zfs", "fat zap\n"); /* this is a fat zap */ - ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, data); + ret = fzap_iterate (zap_dnode, zapbuf, nameelemlen, hook, hook_data, + data); grub_free (zapbuf); return ret; } + grub_free (zapbuf); grub_error (GRUB_ERR_BAD_FS, "unknown ZAP type"); return 0; } @@ -2336,24 +2747,31 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, grub_err_t err; grub_zfs_endian_t endian; - blksz = grub_zfs_to_cpu16 (mdn->dn.dn_datablkszsec, + objnum &= DNODE_NUM_MASK; + + blksz = grub_zfs_to_cpu16 (mdn->dn.dn_datablkszsec, mdn->endian) << SPA_MINBLOCKSHIFT; epbs = zfs_log2 (blksz) - DNODE_SHIFT; + + /* While this should never happen, we should check that epbs is not negative. */ + if (epbs < 0) + epbs = 0; + blkid = objnum >> epbs; idx = objnum & ((1 << epbs) - 1); - if (data->dnode_buf != NULL && grub_memcmp (data->dnode_mdn, mdn, - sizeof (*mdn)) == 0 + if (data->dnode_buf != NULL && grub_memcmp (data->dnode_mdn, &mdn->dn, + sizeof (mdn->dn)) == 0 && objnum >= data->dnode_start && objnum < data->dnode_end) { grub_memmove (&(buf->dn), &(data->dnode_buf)[idx], DNODE_SIZE); buf->endian = data->dnode_endian; - if (type && buf->dn.dn_type != type) - return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); + if (type && buf->dn.dn_type != type) + return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); return GRUB_ERR_NONE; } - grub_dprintf ("zfs", "endian = %d, blkid=%llx\n", mdn->endian, + grub_dprintf ("zfs", "endian = %d, blkid=%llx\n", mdn->endian, (unsigned long long) blkid); err = dmu_read (mdn, blkid, &dnbuf, &endian, data); if (err) @@ -2378,9 +2796,12 @@ dnode_get (dnode_end_t * mdn, grub_uint64_t objnum, grub_uint8_t type, } grub_memmove (&(buf->dn), (dnode_phys_t *) dnbuf + idx, DNODE_SIZE); + if (data->dnode_buf == 0) + /* dnbuf not used anymore if data->dnode_mdn malloc failed */ + grub_free (dnbuf); buf->endian = endian; - if (type && buf->dn.dn_type != type) - return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); + if (type && buf->dn.dn_type != type) + return grub_error(GRUB_ERR_BAD_FS, "incorrect dnode type"); return GRUB_ERR_NONE; } @@ -2404,7 +2825,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, struct dnode_chain { struct dnode_chain *next; - dnode_end_t dn; + dnode_end_t dn; }; struct dnode_chain *dnode_path = 0, *dn_new, *root; @@ -2414,7 +2835,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, dn_new->next = 0; dnode_path = root = dn_new; - err = dnode_get (&subvol->mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, + err = dnode_get (&subvol->mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, &(dnode_path->dn), data); if (err) { @@ -2465,7 +2886,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, grub_free (dn_new); return grub_errno; } - + while (1) { /* skip leading slashes */ @@ -2491,7 +2912,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, } else { - err = grub_error (GRUB_ERR_FILE_NOT_FOUND, + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "can't resolve .."); break; } @@ -2503,8 +2924,8 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, if (dnode_path->dn.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS) { - grub_free (path_buf); - return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); + break; } err = zap_lookup (&(dnode_path->dn), cname, &objnum, data, subvol->case_insensitive); @@ -2530,6 +2951,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, && ((grub_zfs_to_cpu64(((znode_phys_t *) DN_BONUS (&dnode_path->dn.dn))->zp_mode, dnode_path->dn.endian) >> 12) & 0xf) == 0xa) { char *sym_value; + grub_size_t sz; grub_size_t sym_sz; int free_symval = 0; char *oldpath = path, *oldpathbuf = path_buf; @@ -2541,13 +2963,23 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, { grub_size_t block; grub_size_t blksz; - blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, - dnode_path->dn.endian) + blksz = (grub_zfs_to_cpu16 (dnode_path->dn.dn.dn_datablkszsec, + dnode_path->dn.endian) << SPA_MINBLOCKSHIFT); + if (blksz == 0) + { + err = grub_error (GRUB_ERR_BAD_FS, "0-sized block"); + break; + } + sym_value = grub_malloc (sym_sz); if (!sym_value) - return grub_errno; + { + err = grub_errno; + break; + } + for (block = 0; block < (sym_sz + blksz - 1) / blksz; block++) { void *t; @@ -2555,7 +2987,10 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, err = dmu_read (&(dnode_path->dn), block, &t, 0, data); if (err) - return err; + { + grub_free (sym_value); + break; + } movesize = sym_sz - block * blksz; if (movesize > blksz) @@ -2564,22 +2999,40 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, grub_memcpy (sym_value + block * blksz, t, movesize); grub_free (t); } + if (err) + break; free_symval = 1; - } - path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1); + } + + if (grub_add (sym_sz, grub_strlen (oldpath), &sz) || + grub_add (sz, 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("path buffer size overflow")); + grub_free (oldpathbuf); + if (free_symval) + grub_free (sym_value); + err = grub_errno; + break; + } + path = path_buf = grub_malloc (sz); if (!path_buf) { grub_free (oldpathbuf); - return grub_errno; + if (free_symval) + grub_free (sym_value); + err = grub_errno; + break; } grub_memcpy (path, sym_value, sym_sz); if (free_symval) grub_free (sym_value); path [sym_sz] = 0; - grub_memcpy (path + grub_strlen (path), oldpath, + grub_memcpy (path + grub_strlen (path), oldpath, grub_strlen (oldpath) + 1); - + grub_free (oldpathbuf); + + /* Restart dnode walk using path of symlink. */ if (path[0] != '/') { dn_new = dnode_path; @@ -2587,17 +3040,19 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, grub_free (dn_new); } else while (dnode_path != root) - { - dn_new = dnode_path; - dnode_path = dn_new->next; - grub_free (dn_new); - } + { + dn_new = dnode_path; + dnode_path = dn_new->next; + grub_free (dn_new); + } + dn_new = dnode_path; } if (dnode_path->dn.dn.dn_bonustype == DMU_OT_SA) { void *sahdrp; int hdrsize; - + grub_size_t sz; + if (dnode_path->dn.dn.dn_bonuslen != 0) { sahdrp = DN_BONUS (&dnode_path->dn.dn); @@ -2605,14 +3060,15 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, else if (dnode_path->dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) { blkptr_t *bp = &dnode_path->dn.dn.dn_spill; - + err = zio_read (bp, dnode_path->dn.endian, &sahdrp, NULL, data); if (err) - return err; + break; } else { - return grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); + err = grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); + break; } hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); @@ -2623,24 +3079,35 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, dnode_path->dn.endian) >> 12) & 0xf) == 0xa) { char *sym_value = (char *) sahdrp + hdrsize + SA_SYMLINK_OFFSET; - grub_size_t sym_sz = + grub_size_t sym_sz = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), dnode_path->dn.endian); char *oldpath = path, *oldpathbuf = path_buf; - path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1); + if (grub_add (sym_sz, grub_strlen (oldpath), &sz) || + grub_add (sz, 1, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("path buffer size overflow")); + grub_free (oldpathbuf); + err = grub_errno; + break; + } + path = path_buf = grub_malloc (sz); if (!path_buf) { grub_free (oldpathbuf); - return grub_errno; + err = grub_errno; + break; } grub_memcpy (path, sym_value, sym_sz); path [sym_sz] = 0; - grub_memcpy (path + grub_strlen (path), oldpath, + grub_memcpy (path + grub_strlen (path), oldpath, grub_strlen (oldpath) + 1); - + grub_free (oldpathbuf); + + /* Restart dnode walk using path of symlink. */ if (path[0] != '/') { dn_new = dnode_path; @@ -2648,11 +3115,12 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, grub_free (dn_new); } else while (dnode_path != root) - { - dn_new = dnode_path; - dnode_path = dn_new->next; - grub_free (dn_new); - } + { + dn_new = dnode_path; + dnode_path = dn_new->next; + grub_free (dn_new); + } + dn_new = dnode_path; } } } @@ -2740,7 +3208,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, grub_dprintf ("zfs", "endian = %d\n", mosmdn->endian); - err = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT, + err = dnode_get (mosmdn, DMU_POOL_DIRECTORY_OBJECT, DMU_OT_OBJECT_DIRECTORY, mdn, data); if (err) return err; @@ -2753,7 +3221,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, grub_dprintf ("zfs", "alive\n"); - err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data); + err = dnode_get (mosmdn, objnum, 0, mdn, data); if (err) return err; @@ -2763,7 +3231,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, { grub_uint64_t childobj; char *cname, ch; - + while (*fsname == '/') fsname++; @@ -2786,7 +3254,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, if (err) return err; - err = dnode_get (mosmdn, objnum, DMU_OT_DSL_DIR, mdn, data); + err = dnode_get (mosmdn, objnum, 0, mdn, data); if (err) return err; @@ -2798,15 +3266,15 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, static grub_err_t make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data) { - void *osp; + objset_phys_t *osp; blkptr_t *bp; - grub_size_t ospsize; + grub_size_t ospsize = 0; grub_err_t err; grub_dprintf ("zfs", "endian = %d\n", mdn->endian); bp = &(((dsl_dataset_phys_t *) DN_BONUS (&mdn->dn))->ds_bp); - err = zio_read (bp, mdn->endian, &osp, &ospsize, data); + err = zio_read (bp, mdn->endian, (void **) &osp, &ospsize, data); if (err) return err; if (ospsize < OBJSET_PHYS_SIZE_V14) @@ -2817,11 +3285,66 @@ make_mdn (dnode_end_t * mdn, struct grub_zfs_data *data) mdn->endian = (grub_zfs_to_cpu64 (bp->blk_prop, mdn->endian)>>63) & 1; grub_memmove ((char *) &(mdn->dn), - (char *) &((objset_phys_t *) osp)->os_meta_dnode, DNODE_SIZE); + (char *) &(osp)->os_meta_dnode, DNODE_SIZE); grub_free (osp); return GRUB_ERR_NONE; } +/* Context for dnode_get_fullpath. */ +struct dnode_get_fullpath_ctx +{ + struct subvolume *subvol; + grub_uint64_t salt; + int keyn; +}; + +/* Helper for dnode_get_fullpath. */ +static int +count_zap_keys (const void *name __attribute__ ((unused)), + grub_size_t namelen __attribute__ ((unused)), + const void *val_in __attribute__ ((unused)), + grub_size_t nelem __attribute__ ((unused)), + grub_size_t elemsize __attribute__ ((unused)), + void *data) +{ + struct dnode_get_fullpath_ctx *ctx = data; + + ctx->subvol->nkeys++; + return 0; +} + +/* Helper for dnode_get_fullpath. */ +static int +load_zap_key (const void *name, grub_size_t namelen, const void *val_in, + grub_size_t nelem, grub_size_t elemsize, void *data) +{ + struct dnode_get_fullpath_ctx *ctx = data; + + if (namelen != 1) + { + grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n", + namelen); + return 0; + } + + if (elemsize != 1) + { + grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n", + elemsize); + return 0; + } + + ctx->subvol->keyring[ctx->keyn].txg = + grub_be_to_cpu64 (*(grub_uint64_t *) name); + ctx->subvol->keyring[ctx->keyn].algo = + grub_le_to_cpu64 (*(grub_uint64_t *) val_in); + ctx->subvol->keyring[ctx->keyn].cipher = + grub_zfs_load_key (val_in, nelem, ctx->salt, + ctx->subvol->keyring[ctx->keyn].algo); + ctx->keyn++; + return 0; +} + static grub_err_t dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, dnode_end_t * dn, int *isfs, @@ -2831,57 +3354,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, const char *ptr_at, *filename; grub_uint64_t headobj; grub_uint64_t keychainobj; - grub_uint64_t salt; grub_err_t err; - int keyn = 0; - - auto int NESTED_FUNC_ATTR count_zap_keys (const void *name, - grub_size_t namelen, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize); - int NESTED_FUNC_ATTR count_zap_keys (const void *name __attribute__ ((unused)), - grub_size_t namelen __attribute__ ((unused)), - const void *val_in __attribute__ ((unused)), - grub_size_t nelem __attribute__ ((unused)), - grub_size_t elemsize __attribute__ ((unused))) - { - subvol->nkeys++; - return 0; - } - - auto int NESTED_FUNC_ATTR load_zap_key (const void *name, - grub_size_t namelen, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize); - int NESTED_FUNC_ATTR load_zap_key (const void *name, - grub_size_t namelen, - const void *val_in, - grub_size_t nelem, - grub_size_t elemsize) - { - if (namelen != 1) - { - grub_dprintf ("zfs", "Unexpected key index size %" PRIuGRUB_SIZE "\n", - namelen); - return 0; - } - - if (elemsize != 1) - { - grub_dprintf ("zfs", "Unexpected key element size %" PRIuGRUB_SIZE "\n", - elemsize); - return 0; - } - - subvol->keyring[keyn].txg = grub_be_to_cpu64 (*(grub_uint64_t *) name); - subvol->keyring[keyn].algo = grub_le_to_cpu64 (*(grub_uint64_t *) val_in); - subvol->keyring[keyn].cipher = grub_zfs_load_key (val_in, nelem, salt, - subvol->keyring[keyn].algo); - keyn++; - return 0; - } ptr_at = grub_strchr (fullpath, '@'); if (! ptr_at) @@ -2890,6 +3363,8 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, filename = 0; snapname = 0; fsname = grub_strdup (fullpath); + if (!fsname) + return grub_errno; } else { @@ -2918,7 +3393,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, filename = ptr_slash; else filename = "/"; - grub_dprintf ("zfs", "fsname = '%s' snapname='%s' filename = '%s'\n", + grub_dprintf ("zfs", "fsname = '%s' snapname='%s' filename = '%s'\n", fsname, snapname, filename); } grub_dprintf ("zfs", "alive\n"); @@ -2936,8 +3411,7 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); - err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &subvol->mdn, - data); + err = dnode_get (&(data->mos), headobj, 0, &subvol->mdn, data); if (err) { grub_free (fsname); @@ -2949,6 +3423,10 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, keychainobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->keychain, dn->endian); if (grub_zfs_load_key && keychainobj) { + struct dnode_get_fullpath_ctx ctx = { + .subvol = subvol, + .keyn = 0 + }; dnode_end_t keychain_dn, props_dn; grub_uint64_t propsobj; propsobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&dn->dn))->dd_props_zapobj, dn->endian); @@ -2962,16 +3440,18 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, return err; } - err = zap_lookup (&props_dn, "salt", &salt, data, 0); + err = zap_lookup (&props_dn, "salt", &ctx.salt, data, 0); if (err == GRUB_ERR_FILE_NOT_FOUND) { err = 0; grub_errno = 0; - salt = 0; + ctx.salt = 0; } if (err) { grub_dprintf ("zfs", "failed here\n"); + grub_free (fsname); + grub_free (snapname); return err; } @@ -2984,15 +3464,15 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, return err; } subvol->nkeys = 0; - zap_iterate (&keychain_dn, 8, count_zap_keys, data); - subvol->keyring = grub_zalloc (subvol->nkeys * sizeof (subvol->keyring[0])); + zap_iterate (&keychain_dn, 8, count_zap_keys, &ctx, data); + subvol->keyring = grub_calloc (subvol->nkeys, sizeof (subvol->keyring[0])); if (!subvol->keyring) { grub_free (fsname); grub_free (snapname); return err; } - zap_iterate (&keychain_dn, 8, load_zap_key, data); + zap_iterate (&keychain_dn, 8, load_zap_key, &ctx, data); } if (snapname) @@ -3001,13 +3481,19 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, snapobj = grub_zfs_to_cpu64 (((dsl_dataset_phys_t *) DN_BONUS (&subvol->mdn.dn))->ds_snapnames_zapobj, subvol->mdn.endian); - err = dnode_get (&(data->mos), snapobj, + err = dnode_get (&(data->mos), snapobj, DMU_OT_DSL_DS_SNAP_MAP, &subvol->mdn, data); if (!err) err = zap_lookup (&subvol->mdn, snapname, &headobj, data, 0); if (!err) - err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, + err = dnode_get (&(data->mos), headobj, 0, &subvol->mdn, data); + if (!err && subvol->mdn.dn.dn_type != DMU_OT_DSL_DATASET && subvol->mdn.dn.dn_bonustype != DMU_OT_DSL_DATASET) { + grub_free (fsname); + grub_free (snapname); + return grub_error(GRUB_ERR_BAD_FS, "incorrect dataset dnode type"); + } + if (err) { grub_free (fsname); @@ -3019,13 +3505,13 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, subvol->obj = headobj; make_mdn (&subvol->mdn, data); - + grub_dprintf ("zfs", "endian = %d\n", subvol->mdn.endian); if (*isfs) { grub_free (fsname); - grub_free (snapname); + grub_free (snapname); return GRUB_ERR_NONE; } err = dnode_get_path (subvol, filename, dn, data); @@ -3034,39 +3520,20 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, return err; } -/* - * For a given XDR packed nvlist, verify the first 4 bytes and move on. - * - * An XDR packed nvlist is encoded as (comments from nvs_xdr_create) : - * - * encoding method/host endian (4 bytes) - * nvl_version (4 bytes) - * nvl_nvflag (4 bytes) - * encoded nvpairs: - * encoded size of the nvpair (4 bytes) - * decoded size of the nvpair (4 bytes) - * name string size (4 bytes) - * name string data (sizeof(NV_ALIGN4(string)) - * data type (4 bytes) - * # of elements in the nvpair (4 bytes) - * data - * 2 zero's for the last nvpair - * (end of the entire list) (8 bytes) - * - */ - static int nvlist_find_value (const char *nvlist_in, const char *name, int valtype, char **val, grub_size_t *size_out, grub_size_t *nelm_out) { - int name_len, type, encode_size; - const char *nvpair, *nvp_name, *nvlist = nvlist_in; + grub_size_t nvp_name_len, name_len = grub_strlen(name); + int type; + const char *nvpair=NULL,*nvlist=nvlist_in; + char *nvp_name; /* Verify if the 1st and 2nd byte in the nvlist are valid. */ - /* NOTE: independently of what endianness header announces all + /* NOTE: independently of what endianness header announces all subsequent values are big-endian. */ - if (nvlist[0] != NV_ENCODE_XDR || (nvlist[1] != NV_LITTLE_ENDIAN + if (nvlist[0] != NV_ENCODE_XDR || (nvlist[1] != NV_LITTLE_ENDIAN && nvlist[1] != NV_BIG_ENDIAN)) { grub_dprintf ("zfs", "incorrect nvlist header\n"); @@ -3074,62 +3541,21 @@ nvlist_find_value (const char *nvlist_in, const char *name, return 0; } - /* skip the header, nvl_version, and nvl_nvflag */ - nvlist = nvlist + 4 * 3; /* * Loop thru the nvpair list * The XDR representation of an integer is in big-endian byte order. */ - while ((encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (nvlist)))) + while ((nvpair=nvlist_next_nvpair(nvlist,nvpair))) { - int nelm; - - if (nvlist + 4 * 4 >= nvlist_in + VDEV_PHYS_SIZE) + nvpair_name(nvpair,&nvp_name, &nvp_name_len); + type = nvpair_type(nvpair); + if (type == valtype + && (nvp_name_len == name_len + || (nvp_name_len > name_len && nvp_name[name_len] == '\0')) + && grub_memcmp (nvp_name, name, name_len) == 0) { - grub_dprintf ("zfs", "nvlist overflow\n"); - grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); - return 0; + return nvpair_value(nvpair,val,size_out,nelm_out); } - - nvpair = nvlist + 4 * 2; /* skip the encode/decode size */ - - name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); - nvpair += 4; - - nvp_name = nvpair; - nvpair = nvpair + ((name_len + 3) & ~3); /* align */ - - if (nvpair + 8 >= nvlist_in + VDEV_PHYS_SIZE - || encode_size < 0 - || nvpair + 8 + encode_size > nvlist_in + VDEV_PHYS_SIZE) - { - grub_dprintf ("zfs", "nvlist overflow\n"); - grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); - return 0; - } - - type = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); - nvpair += 4; - - nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); - if (nelm < 1) - { - grub_error (GRUB_ERR_BAD_FS, "empty nvpair"); - return 0; - } - - nvpair += 4; - - if ((grub_strncmp (nvp_name, name, name_len) == 0) && type == valtype) - { - *val = (char *) nvpair; - *size_out = encode_size; - if (nelm_out) - *nelm_out = nelm; - return 1; - } - - nvlist += encode_size; /* goto the next nvpair */ } return 0; } @@ -3188,14 +3614,18 @@ grub_zfs_nvlist_lookup_nvlist (const char *nvlist, const char *name) { char *nvpair; char *ret; - grub_size_t size; + grub_size_t size, sz; int found; found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST, &nvpair, &size, 0); if (!found) return 0; - ret = grub_zalloc (size + 3 * sizeof (grub_uint32_t)); + + if (grub_add (size, 3 * sizeof (grub_uint32_t), &sz)) + return 0; + + ret = grub_zalloc (sz); if (!ret) return 0; grub_memcpy (ret, nvlist, sizeof (grub_uint32_t)); @@ -3224,13 +3654,13 @@ get_nvlist_size (const char *beg, const char *limit) { const char *ptr; grub_uint32_t encode_size; - + ptr = beg + 8; while (ptr < limit && (encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (ptr)))) ptr += encode_size; /* goto the next nvpair */ - ptr += 8; + ptr += 8; return (ptr > limit) ? -1 : (ptr - beg); } @@ -3245,6 +3675,7 @@ grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, const char *name, unsigned i; grub_size_t nelm; int elemsize = 0; + int sz; found = nvlist_find_value (nvlist, name, DATA_TYPE_NVLIST_ARRAY, &nvpair, &size, &nelm); @@ -3279,7 +3710,12 @@ grub_zfs_nvlist_lookup_nvlist_array (const char *nvlist, const char *name, return 0; } - ret = grub_zalloc (elemsize + sizeof (grub_uint32_t)); + if (grub_add (elemsize, sizeof (grub_uint32_t), &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("elemsize overflow")); + return 0; + } + ret = grub_zalloc (sz); if (!ret) return 0; grub_memcpy (ret, nvlist, sizeof (grub_uint32_t)); @@ -3333,7 +3769,7 @@ zfs_mount (grub_device_t dev) { struct grub_zfs_data *data = 0; grub_err_t err; - void *osp = 0; + objset_phys_t *osp = 0; grub_size_t ospsize; grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN; uberblock_t *ub; @@ -3355,8 +3791,13 @@ zfs_mount (grub_device_t dev) #endif data->n_devices_allocated = 16; - data->devices_attached = grub_malloc (sizeof (data->devices_attached[0]) - * data->n_devices_allocated); + data->devices_attached = grub_calloc (data->n_devices_allocated, + sizeof (data->devices_attached[0])); + if (!data->devices_attached) + { + grub_free (data); + return NULL; + } data->n_devices_attached = 0; err = scan_disk (dev, data, 1, &inserted); if (err) @@ -3366,12 +3807,12 @@ zfs_mount (grub_device_t dev) } ub = &(data->current_uberblock); - ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, - GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC + ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, + GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN); err = zio_read (&ub->ub_rootbp, ub_endian, - &osp, &ospsize, data); + (void **) &osp, &ospsize, data); if (err) { zfs_unmount (data); @@ -3386,15 +3827,21 @@ zfs_mount (grub_device_t dev) return NULL; } + if (ub->ub_version >= SPA_VERSION_FEATURES && + check_mos_features(&osp->os_meta_dnode, ub_endian, data) != 0) + { + grub_error (GRUB_ERR_BAD_FS, "Unsupported features in pool"); + grub_free (osp); + zfs_unmount (data); + return NULL; + } + /* Got the MOS. Save it at the memory addr MOS. */ - grub_memmove (&(data->mos.dn), &((objset_phys_t *) osp)->os_meta_dnode, - DNODE_SIZE); + grub_memmove (&(data->mos.dn), &osp->os_meta_dnode, DNODE_SIZE); data->mos.endian = (grub_zfs_to_cpu64 (ub->ub_rootbp.blk_prop, ub_endian) >> 63) & 1; grub_free (osp); - data->mounted = 1; - return data; } @@ -3412,7 +3859,7 @@ grub_zfs_fetch_nvlist (grub_device_t dev, char **nvlist) return err; } -static grub_err_t +static grub_err_t zfs_label (grub_device_t device, char **label) { char *nvlist; @@ -3424,7 +3871,7 @@ zfs_label (grub_device_t device, char **label) return grub_errno; err = zfs_fetch_nvlist (data->device_original, &nvlist); - if (err) + if (err) { zfs_unmount (data); return err; @@ -3436,7 +3883,7 @@ zfs_label (grub_device_t device, char **label) return grub_errno; } -static grub_err_t +static grub_err_t zfs_uuid (grub_device_t device, char **uuid) { struct grub_zfs_data *data; @@ -3454,8 +3901,8 @@ zfs_uuid (grub_device_t device, char **uuid) return GRUB_ERR_NONE; } -static grub_err_t -zfs_mtime (grub_device_t device, grub_int32_t *mt) +static grub_err_t +zfs_mtime (grub_device_t device, grub_int64_t *mt) { struct grub_zfs_data *data; grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN; @@ -3468,8 +3915,8 @@ zfs_mtime (grub_device_t device, grub_int32_t *mt) return grub_errno; ub = &(data->current_uberblock); - ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, - GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC + ub_endian = (grub_zfs_to_cpu64 (ub->ub_magic, + GRUB_ZFS_LITTLE_ENDIAN) == UBERBLOCK_MAGIC ? GRUB_ZFS_LITTLE_ENDIAN : GRUB_ZFS_BIG_ENDIAN); *mt = grub_zfs_to_cpu64 (ub->ub_timestamp, ub_endian); @@ -3507,7 +3954,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) } /* We found the dnode for this file. Verify if it is a plain file. */ - if (data->dnode.dn.dn_type != DMU_OT_PLAIN_FILE_CONTENTS) + if (data->dnode.dn.dn_type != DMU_OT_PLAIN_FILE_CONTENTS) { zfs_unmount (data); return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); @@ -3524,6 +3971,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) { void *sahdrp; int hdrsize; + bool free_sahdrp = false; if (data->dnode.dn.dn_bonuslen != 0) { @@ -3536,6 +3984,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) err = zio_read (bp, data->dnode.endian, &sahdrp, NULL, data); if (err) return err; + free_sahdrp = true; } else { @@ -3544,6 +3993,8 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); file->size = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), data->dnode.endian); + if (free_sahdrp) + grub_free(sahdrp); } else if (data->dnode.dn.dn_bonustype == DMU_OT_ZNODE) { @@ -3582,9 +4033,15 @@ grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) return len; } - blksz = grub_zfs_to_cpu16 (data->dnode.dn.dn_datablkszsec, + blksz = grub_zfs_to_cpu16 (data->dnode.dn.dn_datablkszsec, data->dnode.endian) << SPA_MINBLOCKSHIFT; + if (blksz == 0) + { + grub_error (GRUB_ERR_BAD_FS, "0-sized block"); + return -1; + } + /* * Entire Dnode is too big to fit into the space available. We * will need to read it in chunks. This could be optimized to @@ -3661,57 +4118,69 @@ grub_zfs_getmdnobj (grub_device_t dev, const char *fsfilename, return err; } -static void +/* + * Note: fill_fs_info() uses functions such as make_mdn() that modify + * the input dnode_end_t parameter. However, we should not allow it. + * Therefore, we are making mdn_in constant - fill_fs_info() makes + * a local copy of it. + */ +static grub_err_t fill_fs_info (struct grub_dirhook_info *info, - dnode_end_t mdn, struct grub_zfs_data *data) + const dnode_end_t *mdn_in, struct grub_zfs_data *data) { grub_err_t err; dnode_end_t dn; grub_uint64_t objnum; grub_uint64_t headobj; - + dnode_end_t mdn; + + grub_memcpy (&mdn, mdn_in, sizeof (*mdn_in)); + grub_memset (info, 0, sizeof (*info)); - + info->dir = 1; - - if (mdn.dn.dn_type == DMU_OT_DSL_DIR) + + if (mdn.dn.dn_type == DMU_OT_DSL_DIR || mdn.dn.dn_bonustype == DMU_OT_DSL_DIR) { headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&mdn.dn))->dd_head_dataset_obj, mdn.endian); - err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &mdn, data); + err = dnode_get (&(data->mos), headobj, 0, &mdn, data); if (err) { grub_dprintf ("zfs", "failed here\n"); - return; + return err; } } - make_mdn (&mdn, data); - err = dnode_get (&mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, + err = make_mdn (&mdn, data); + if (err) + return err; + err = dnode_get (&mdn, MASTER_NODE_OBJ, DMU_OT_MASTER_NODE, &dn, data); if (err) { grub_dprintf ("zfs", "failed here\n"); - return; + return err; } - + err = zap_lookup (&dn, ZFS_ROOT_OBJ, &objnum, data, 0); if (err) { grub_dprintf ("zfs", "failed here\n"); - return; + return err; } - + err = dnode_get (&mdn, objnum, 0, &dn, data); if (err) { grub_dprintf ("zfs", "failed here\n"); - return; + return err; } - + if (dn.dn.dn_bonustype == DMU_OT_SA) { void *sahdrp; int hdrsize; + bool free_sahdrp = false; if (dn.dn.dn_bonuslen != 0) { @@ -3723,17 +4192,20 @@ fill_fs_info (struct grub_dirhook_info *info, err = zio_read (bp, dn.endian, &sahdrp, NULL, data); if (err) - return; + return err; + free_sahdrp = true; } else { grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); - return; + return grub_errno; } hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); info->mtimeset = 1; info->mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + if (free_sahdrp) + grub_free (sahdrp); } if (dn.dn.dn_bonustype == DMU_OT_ZNODE) @@ -3741,111 +4213,162 @@ fill_fs_info (struct grub_dirhook_info *info, info->mtimeset = 1; info->mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], dn.endian); } - return; + return 0; +} + +/* Helper for grub_zfs_dir. */ +static int +iterate_zap (const char *name, grub_uint64_t val, struct grub_zfs_dir_ctx *ctx) +{ + grub_err_t err; + struct grub_dirhook_info info; + + dnode_end_t dn; + grub_memset (&info, 0, sizeof (info)); + + err = dnode_get (&(ctx->data->subvol.mdn), val, 0, &dn, ctx->data); + if (err) + { + grub_print_error (); + return 0; + } + + if (dn.dn.dn_bonustype == DMU_OT_SA) + { + void *sahdrp; + int hdrsize; + bool free_sahdrp = false; + + if (dn.dn.dn_bonuslen != 0) + { + sahdrp = (sa_hdr_phys_t *) DN_BONUS (&ctx->data->dnode.dn); + } + else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) + { + blkptr_t *bp = &dn.dn.dn_spill; + + err = zio_read (bp, dn.endian, &sahdrp, NULL, ctx->data); + if (err) + { + grub_print_error (); + return 0; + } + free_sahdrp = true; + } + else + { + grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); + grub_print_error (); + return 0; + } + + hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); + info.mtimeset = 1; + info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + info.case_insensitive = ctx->data->subvol.case_insensitive; + if (free_sahdrp) + grub_free (sahdrp); + } + + if (dn.dn.dn_bonustype == DMU_OT_ZNODE) + { + info.mtimeset = 1; + info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], + dn.endian); + } + info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); + grub_dprintf ("zfs", "type=%d, name=%s\n", + (int)dn.dn.dn_type, (char *)name); + return ctx->hook (name, &info, ctx->hook_data); +} + +/* Helper for grub_zfs_dir. */ +static int +iterate_zap_fs (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx) +{ + grub_err_t err; + struct grub_dirhook_info info; + + if (name[0] == 0 && val == 0) + return 0; + + dnode_end_t mdn; + err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data); + if (err) + { + grub_errno = 0; + return 0; + } + if (mdn.dn.dn_type != DMU_OT_DSL_DIR && mdn.dn.dn_bonustype != DMU_OT_DSL_DIR) { + grub_dprintf ("zfs", "type = 0x%x, val = 0x%llx\n", mdn.dn.dn_type, (long long)val); + return 0; + } + + err = fill_fs_info (&info, &mdn, ctx->data); + if (err) + { + grub_errno = 0; + return 0; + } + return ctx->hook (name, &info, ctx->hook_data); +} + +/* Helper for grub_zfs_dir. */ +static int +iterate_zap_snap (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx) +{ + grub_err_t err; + struct grub_dirhook_info info; + char *name2; + int ret; + grub_size_t sz; + + dnode_end_t mdn; + + err = dnode_get (&(ctx->data->mos), val, 0, &mdn, ctx->data); + if (err) + { + grub_errno = 0; + return 0; + } + + if (mdn.dn.dn_type != DMU_OT_DSL_DATASET && mdn.dn.dn_bonustype != DMU_OT_DSL_DATASET) + return 0; + + err = fill_fs_info (&info, &mdn, ctx->data); + if (err) + { + grub_errno = 0; + return 0; + } + + if (grub_add (grub_strlen (name), 2, &sz)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("name length overflow")); + + name2 = grub_malloc (sz); + if (!name2) + return grub_errno; + + name2[0] = '@'; + grub_memcpy (name2 + 1, name, grub_strlen (name) + 1); + ret = ctx->hook (name2, &info, ctx->hook_data); + grub_free (name2); + return ret; } static grub_err_t grub_zfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *, const struct grub_dirhook_info *)) + grub_fs_dir_hook_t hook, void *hook_data) { + struct grub_zfs_dir_ctx ctx = { + .hook = hook, + .hook_data = hook_data + }; struct grub_zfs_data *data; grub_err_t err; int isfs; - auto int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val); - auto int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, - grub_uint64_t val); - auto int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, - grub_uint64_t val); - - int NESTED_FUNC_ATTR iterate_zap (const char *name, grub_uint64_t val) - { - struct grub_dirhook_info info; - dnode_end_t dn; - grub_memset (&info, 0, sizeof (info)); - - dnode_get (&(data->subvol.mdn), val, 0, &dn, data); - - if (dn.dn.dn_bonustype == DMU_OT_SA) - { - void *sahdrp; - int hdrsize; - - if (dn.dn.dn_bonuslen != 0) - { - sahdrp = (sa_hdr_phys_t *) DN_BONUS (&data->dnode.dn); - } - else if (dn.dn.dn_flags & DNODE_FLAG_SPILL_BLKPTR) - { - blkptr_t *bp = &dn.dn.dn_spill; - - err = zio_read (bp, dn.endian, &sahdrp, NULL, data); - if (err) - { - grub_print_error (); - return 0; - } - } - else - { - grub_error (GRUB_ERR_BAD_FS, "filesystem is corrupt"); - grub_print_error (); - return 0; - } - - hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); - info.mtimeset = 1; - info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); - info.case_insensitive = data->subvol.case_insensitive; - } - - if (dn.dn.dn_bonustype == DMU_OT_ZNODE) - { - info.mtimeset = 1; - info.mtime = grub_zfs_to_cpu64 (((znode_phys_t *) DN_BONUS (&dn.dn))->zp_mtime[0], - dn.endian); - } - info.dir = (dn.dn.dn_type == DMU_OT_DIRECTORY_CONTENTS); - grub_dprintf ("zfs", "type=%d, name=%s\n", - (int)dn.dn.dn_type, (char *)name); - return hook (name, &info); - } - - int NESTED_FUNC_ATTR iterate_zap_fs (const char *name, grub_uint64_t val) - { - struct grub_dirhook_info info; - dnode_end_t mdn; - err = dnode_get (&(data->mos), val, 0, &mdn, data); - if (err) - return 0; - if (mdn.dn.dn_type != DMU_OT_DSL_DIR) - return 0; - - fill_fs_info (&info, mdn, data); - return hook (name, &info); - } - int NESTED_FUNC_ATTR iterate_zap_snap (const char *name, grub_uint64_t val) - { - struct grub_dirhook_info info; - char *name2; - int ret; - dnode_end_t mdn; - - err = dnode_get (&(data->mos), val, 0, &mdn, data); - if (err) - return 0; - - if (mdn.dn.dn_type != DMU_OT_DSL_DATASET) - return 0; - - fill_fs_info (&info, mdn, data); - - name2 = grub_malloc (grub_strlen (name) + 2); - name2[0] = '@'; - grub_memcpy (name2 + 1, name, grub_strlen (name) + 1); - ret = hook (name2, &info); - grub_free (name2); - return ret; - } data = zfs_mount (device); if (! data) @@ -3856,16 +4379,27 @@ grub_zfs_dir (grub_device_t device, const char *path, zfs_unmount (data); return err; } + ctx.data = data; + if (isfs) { - grub_uint64_t childobj, headobj; + grub_uint64_t childobj, headobj; grub_uint64_t snapobj; dnode_end_t dn; struct grub_dirhook_info info; - fill_fs_info (&info, data->dnode, data); - hook ("@", &info); - + err = fill_fs_info (&info, &data->dnode, data); + if (err) + { + zfs_unmount (data); + return err; + } + if (hook ("@", &info, hook_data)) + { + zfs_unmount (data); + return GRUB_ERR_NONE; + } + childobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_child_dir_zapobj, data->dnode.endian); headobj = grub_zfs_to_cpu64 (((dsl_dir_phys_t *) DN_BONUS (&data->dnode.dn))->dd_head_dataset_obj, data->dnode.endian); err = dnode_get (&(data->mos), childobj, @@ -3876,9 +4410,12 @@ grub_zfs_dir (grub_device_t device, const char *path, return err; } - zap_iterate_u64 (&dn, iterate_zap_fs, data); - - err = dnode_get (&(data->mos), headobj, DMU_OT_DSL_DATASET, &dn, data); + zap_iterate_u64 (&dn, iterate_zap_fs, data, &ctx); + + err = dnode_get (&(data->mos), headobj, 0, &dn, data); + if (!err && dn.dn.dn_type != DMU_OT_DSL_DATASET && dn.dn.dn_bonustype != DMU_OT_DSL_DATASET) + return grub_error(GRUB_ERR_BAD_FS, "incorrect dataset dnode type"); + if (err) { zfs_unmount (data); @@ -3895,7 +4432,7 @@ grub_zfs_dir (grub_device_t device, const char *path, return err; } - zap_iterate_u64 (&dn, iterate_zap_snap, data); + zap_iterate_u64 (&dn, iterate_zap_snap, data, &ctx); } else { @@ -3904,12 +4441,76 @@ grub_zfs_dir (grub_device_t device, const char *path, zfs_unmount (data); return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); } - zap_iterate_u64 (&(data->dnode), iterate_zap, data); + zap_iterate_u64 (&(data->dnode), iterate_zap, data, &ctx); } zfs_unmount (data); return grub_errno; } +static int +check_feature (const char *name, grub_uint64_t val, + struct grub_zfs_dir_ctx *ctx __attribute__((unused))) +{ + int i; + if (val == 0) + return 0; + if (name[0] == 0) + return 0; + for (i = 0; spa_feature_names[i] != NULL; i++) + if (grub_strcmp (name, spa_feature_names[i]) == 0) + return 0; + return 1; +} + +/* + * Checks whether the MOS features that are active are supported by this + * (GRUB's) implementation of ZFS. + * + * Return: + * 0: Success. + * errnum: Failure. + */ + +static grub_err_t +check_mos_features(dnode_phys_t *mosmdn_phys,grub_zfs_endian_t endian,struct grub_zfs_data* data ) +{ + grub_uint64_t objnum; + grub_err_t errnum = 0; + dnode_end_t dn,mosmdn; + mzap_phys_t* mzp; + grub_zfs_endian_t endianzap; + int size, ret; + grub_memmove(&(mosmdn.dn),mosmdn_phys,sizeof(dnode_phys_t)); + mosmdn.endian=endian; + errnum = dnode_get(&mosmdn, DMU_POOL_DIRECTORY_OBJECT, + DMU_OT_OBJECT_DIRECTORY, &dn,data); + if (errnum != 0) + return errnum; + + /* + * Find the object number for 'features_for_read' and retrieve its + * corresponding dnode. Note that we don't check features_for_write + * because GRUB is not opening the pool for write. + */ + errnum = zap_lookup(&dn, DMU_POOL_FEATURES_FOR_READ, &objnum, data,0); + if (errnum != 0) + return errnum; + + errnum = dnode_get(&mosmdn, objnum, DMU_OTN_ZAP_METADATA, &dn, data); + if (errnum != 0) + return errnum; + + errnum = dmu_read(&dn, 0, (void**)&mzp, &endianzap,data); + if (errnum != 0) + return errnum; + + size = grub_zfs_to_cpu16 (dn.dn.dn_datablkszsec, dn.endian) << SPA_MINBLOCKSHIFT; + ret = mzap_iterate (mzp,endianzap, size, check_feature,NULL); + grub_free(mzp); + return ret; +} + + #ifdef GRUB_UTIL static grub_err_t grub_zfs_embed (grub_device_t device __attribute__ ((unused)), @@ -3924,7 +4525,7 @@ grub_zfs_embed (grub_device_t device __attribute__ ((unused)), return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ZFS currently supports only PC-BIOS embedding"); - if ((VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS) < *nsectors) + if ((VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS) < *nsectors) return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("your core.img is unusually large. " "It won't fit in the embedding area")); @@ -3932,7 +4533,7 @@ grub_zfs_embed (grub_device_t device __attribute__ ((unused)), *nsectors = (VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS); if (*nsectors > max_nsectors) *nsectors = max_nsectors; - *sectors = grub_malloc (*nsectors * sizeof (**sectors)); + *sectors = grub_calloc (*nsectors, sizeof (**sectors)); if (!*sectors) return grub_errno; for (i = 0; i < *nsectors; i++) @@ -3944,15 +4545,15 @@ grub_zfs_embed (grub_device_t device __attribute__ ((unused)), static struct grub_fs grub_zfs_fs = { .name = "zfs", - .dir = grub_zfs_dir, - .open = grub_zfs_open, - .read = grub_zfs_read, - .close = grub_zfs_close, - .label = zfs_label, - .uuid = zfs_uuid, - .mtime = zfs_mtime, + .fs_dir = grub_zfs_dir, + .fs_open = grub_zfs_open, + .fs_read = grub_zfs_read, + .fs_close = grub_zfs_close, + .fs_label = zfs_label, + .fs_uuid = zfs_uuid, + .fs_mtime = zfs_mtime, #ifdef GRUB_UTIL - .embed = grub_zfs_embed, + .fs_embed = grub_zfs_embed, .reserved_first_sector = 1, .blocklist_install = 0, #endif @@ -3962,6 +4563,7 @@ static struct grub_fs grub_zfs_fs = { GRUB_MOD_INIT (zfs) { COMPILE_TIME_ASSERT (sizeof (zap_leaf_chunk_t) == ZAP_LEAF_CHUNKSIZE); + grub_zfs_fs.mod = mod; grub_fs_register (&grub_zfs_fs); #ifndef GRUB_UTIL my_mod = mod; diff --git a/grub-core/fs/zfs/zfs_fletcher.c b/grub-core/fs/zfs/zfs_fletcher.c index 7d27b053d..ad3be6705 100644 --- a/grub-core/fs/zfs/zfs_fletcher.c +++ b/grub-core/fs/zfs/zfs_fletcher.c @@ -39,14 +39,14 @@ #include void -fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, +fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, zio_cksum_t *zcp) { const grub_uint64_t *ip = buf; const grub_uint64_t *ipend = ip + (size / sizeof (grub_uint64_t)); grub_uint64_t a0, b0, a1, b1; - - for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2) + + for (a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2) { a0 += grub_zfs_to_cpu64 (ip[0], endian); a1 += grub_zfs_to_cpu64 (ip[1], endian); @@ -61,14 +61,14 @@ fletcher_2(const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, } void -fletcher_4 (const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, +fletcher_4 (const void *buf, grub_uint64_t size, grub_zfs_endian_t endian, zio_cksum_t *zcp) { const grub_uint32_t *ip = buf; const grub_uint32_t *ipend = ip + (size / sizeof (grub_uint32_t)); grub_uint64_t a, b, c, d; - - for (a = b = c = d = 0; ip < ipend; ip++) + + for (a = b = c = d = 0; ip < ipend; ip++) { a += grub_zfs_to_cpu32 (ip[0], endian);; b += a; diff --git a/grub-core/fs/zfs/zfs_lz4.c b/grub-core/fs/zfs/zfs_lz4.c new file mode 100644 index 000000000..5453822d0 --- /dev/null +++ b/grub-core/fs/zfs/zfs_lz4.c @@ -0,0 +1,285 @@ +/* + * LZ4 - Fast LZ compression algorithm + * Header File + * Copyright (C) 2011-2013, Yann Collet. + * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at : + * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html + * - LZ4 source repository : http://code.google.com/p/lz4/ + */ + +#include +#include +#include +#include + +static int LZ4_uncompress_unknownOutputSize(const char *source, char *dest, + int isize, int maxOutputSize); + +/* + * CPU Feature Detection + */ + +/* 32 or 64 bits ? */ +#if (GRUB_CPU_SIZEOF_VOID_P == 8) +#define LZ4_ARCH64 1 +#else +#define LZ4_ARCH64 0 +#endif + +/* + * Compiler Options + */ + + +#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +#if (GCC_VERSION >= 302) || (defined (__INTEL_COMPILER) && __INTEL_COMPILER >= 800) || defined(__clang__) +#define expect(expr, value) (__builtin_expect((expr), (value))) +#else +#define expect(expr, value) (expr) +#endif + +#define likely(expr) expect((expr) != 0, 1) +#define unlikely(expr) expect((expr) != 0, 0) + +/* Basic types */ +#define BYTE grub_uint8_t +#define U16 grub_uint16_t +#define U32 grub_uint32_t +#define S32 grub_int32_t +#define U64 grub_uint64_t + +typedef struct _U16_S { + U16 v; +} GRUB_PACKED U16_S; +typedef struct _U32_S { + U32 v; +} GRUB_PACKED U32_S; +typedef struct _U64_S { + U64 v; +} GRUB_PACKED U64_S; + +#define A64(x) (((U64_S *)(x))->v) +#define A32(x) (((U32_S *)(x))->v) +#define A16(x) (((U16_S *)(x))->v) + +/* + * Constants + */ +#define MINMATCH 4 + +#define COPYLENGTH 8 +#define LASTLITERALS 5 + +#define ML_BITS 4 +#define ML_MASK ((1U< s_len) + return grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed."); + + /* + * Returns 0 on success (decompression function returned non-negative) + * and appropriate error on failure (decompression function returned negative). + */ + return (LZ4_uncompress_unknownOutputSize((char*)s_start + 4, d_start, bufsiz, + d_len) < 0)?grub_error(GRUB_ERR_BAD_FS,"lz4 decompression failed."):0; +} + +static int +LZ4_uncompress_unknownOutputSize(const char *source, + char *dest, int isize, int maxOutputSize) +{ + /* Local Variables */ + const BYTE * ip = (const BYTE *) source; + const BYTE *const iend = ip + isize; + const BYTE * ref; + + BYTE * op = (BYTE *) dest; + BYTE *const oend = op + maxOutputSize; + BYTE *cpy; + + grub_size_t dec[] = { 0, 3, 2, 3, 0, 0, 0, 0 }; + + /* Main Loop */ + while (ip < iend) { + BYTE token; + int length; + + /* get runlength */ + token = *ip++; + if ((length = (token >> ML_BITS)) == RUN_MASK) { + int s = 255; + while ((ip < iend) && (s == 255)) { + s = *ip++; + length += s; + } + } + /* copy literals */ + if ((grub_addr_t) length > ~(grub_addr_t)op) + goto _output_error; + cpy = op + length; + if ((cpy > oend - COPYLENGTH) || + (ip + length > iend - COPYLENGTH)) { + if (cpy > oend) + /* + * Error: request to write beyond destination + * buffer. + */ + goto _output_error; + if (ip + length > iend) + /* + * Error : request to read beyond source + * buffer. + */ + goto _output_error; + grub_memcpy(op, ip, length); + op += length; + ip += length; + if (ip < iend) + /* Error : LZ4 format violation */ + goto _output_error; + /* Necessarily EOF, due to parsing restrictions. */ + break; + } + LZ4_WILDCOPY(ip, op, cpy); + ip -= (op - cpy); + op = cpy; + + /* get offset */ + LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip); + ip += 2; + if (ref < (BYTE * const) dest) + /* + * Error: offset creates reference outside of + * destination buffer. + */ + goto _output_error; + + /* get matchlength */ + if ((length = (token & ML_MASK)) == ML_MASK) { + while (ip < iend) { + int s = *ip++; + length += s; + if (s == 255) + continue; + break; + } + } + /* copy repeated sequence */ + if unlikely(op - ref < STEPSIZE) { +#if LZ4_ARCH64 + grub_size_t dec2table[] = { 0, 0, 0, -1, 0, 1, 2, 3 }; + grub_size_t dec2 = dec2table[op - ref]; +#else + const int dec2 = 0; +#endif + *op++ = *ref++; + *op++ = *ref++; + *op++ = *ref++; + *op++ = *ref++; + ref -= dec[op - ref]; + A32(op) = A32(ref); + op += STEPSIZE - 4; + ref -= dec2; + } else { + LZ4_COPYSTEP(ref, op); + } + cpy = op + length - (STEPSIZE - 4); + if (cpy > oend - COPYLENGTH) { + if (cpy > oend) + /* + * Error: request to write outside of + * destination buffer. + */ + goto _output_error; + LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); + while (op < cpy) + *op++ = *ref++; + op = cpy; + if (op == oend) + /* + * Check EOF (should never happen, since last + * 5 bytes are supposed to be literals). + */ + break; + continue; + } + LZ4_SECURECOPY(ref, op, cpy); + op = cpy; /* correction */ + } + + /* end of decoding */ + return (int)(((char *)op) - dest); + + /* write overflow error detected */ + _output_error: + return (int)(-(((char *)ip) - source)); +} diff --git a/grub-core/fs/zfs/zfs_sha256.c b/grub-core/fs/zfs/zfs_sha256.c index a181f076c..f042fa61a 100644 --- a/grub-core/fs/zfs/zfs_sha256.c +++ b/grub-core/fs/zfs/zfs_sha256.c @@ -116,23 +116,23 @@ zio_checksum_SHA256(const void *buf, grub_uint64_t size, grub_uint8_t pad[128]; unsigned padsize = size & 63; unsigned i; - + for (i = 0; i < size - padsize; i += 64) SHA256Transform(H, (grub_uint8_t *)buf + i); - + for (i = 0; i < padsize; i++) pad[i] = ((grub_uint8_t *)buf)[i]; - + for (pad[padsize++] = 0x80; (padsize & 63) != 56; padsize++) pad[padsize] = 0; - + for (i = 0; i < 8; i++) pad[padsize++] = (size << 3) >> (56 - 8 * i); - + for (i = 0; i < padsize && i <= 64; i += 64) SHA256Transform(H, pad + i); - - zcp->zc_word[0] = grub_cpu_to_zfs64 ((grub_uint64_t)H[0] << 32 | H[1], + + zcp->zc_word[0] = grub_cpu_to_zfs64 ((grub_uint64_t)H[0] << 32 | H[1], endian); zcp->zc_word[1] = grub_cpu_to_zfs64 ((grub_uint64_t)H[2] << 32 | H[3], endian); diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c index 4ea53b863..da30e9ab3 100644 --- a/grub-core/fs/zfs/zfscrypt.c +++ b/grub-core/fs/zfs/zfscrypt.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -45,7 +46,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* - Mostly based on following article: + Mostly based on following article: https://blogs.oracle.com/darren/entry/zfs_encryption_what_is_on */ @@ -82,9 +83,13 @@ grub_zfs_add_key (grub_uint8_t *key_in, int passphrase) { struct grub_zfs_wrap_key *key; + grub_size_t sz; + if (!passphrase && keylen > 32) keylen = 32; - key = grub_malloc (sizeof (*key) + keylen); + if (grub_add (sizeof (*key), keylen, &sz)) + return GRUB_ERR_OUT_OF_RANGE; + key = grub_malloc (sz); if (!key) return grub_errno; key->is_passphrase = passphrase; @@ -143,7 +148,7 @@ grub_ccm_decrypt (grub_crypto_cipher_handle_t cipher, return err; if (mac_out) grub_crypto_xor (mac_out, mac, mul, m); - return GRUB_ERR_NONE; + return GPG_ERR_NO_ERROR; } static void @@ -174,7 +179,7 @@ grub_gcm_mul (grub_uint8_t *a, const grub_uint8_t *b) grub_crypto_xor (res, res, bs, 16); grub_gcm_mul_x (bs); } - + grub_memcpy (a, res, 16); } @@ -238,13 +243,13 @@ grub_gcm_decrypt (grub_crypto_cipher_handle_t cipher, grub_crypto_xor (out + 16 * i, in + 16 * i, mul, csize); } for (j = 0; j < 8; j++) - mac[15 - j] ^= ((psize * 8) >> (8 * j)); + mac[15 - j] ^= ((((grub_uint64_t) psize) * 8) >> (8 * j)); grub_gcm_mul (mac, h); if (mac_out) grub_crypto_xor (mac_out, mac, mac_xor, m); - return GRUB_ERR_NONE; + return GPG_ERR_NO_ERROR; } @@ -258,18 +263,19 @@ algo_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, switch (algo) { case 0: - return grub_ccm_decrypt (cipher, out, in, psize, mac_out, nonce, l, m); + return grub_ccm_decrypt (cipher, out, in, psize, + mac_out, nonce, l, m); case 1: - return grub_gcm_decrypt (cipher, out, in, psize, mac_out, nonce, + return grub_gcm_decrypt (cipher, out, in, psize, + mac_out, nonce, 15 - l, m); default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "algorithm %" - PRIuGRUB_UINT64_T " is not supported yet", algo); + return GPG_ERR_CIPHER_ALGO; } } static grub_err_t -grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, +grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo, void *nonce, char *buf, grub_size_t size, @@ -279,8 +285,8 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, grub_uint32_t mac[4]; unsigned i; grub_uint32_t sw[4]; - grub_err_t err; - + gcry_err_code_t err; + grub_memcpy (sw, nonce, 16); if (endian != GRUB_ZFS_BIG_ENDIAN) for (i = 0; i < 4; i++) @@ -295,8 +301,8 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, size, mac, sw + 1, 3, 12); if (err) - return err; - + return grub_crypto_gcry_error (err); + for (i = 0; i < 3; i++) if (grub_zfs_to_cpu32 (expected_mac[i], endian) != grub_be_to_cpu32 (mac[i])) @@ -353,17 +359,19 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, if (err) { grub_errno = GRUB_ERR_NONE; + grub_crypto_cipher_close (cipher); continue; } - + err = grub_crypto_cipher_set_key (cipher, wrap_key_real, keylen); if (err) { grub_errno = GRUB_ERR_NONE; + grub_crypto_cipher_close (cipher); continue; } - + err = algo_decrypt (cipher, algo, decrypted, key->unknown_purpose_key, 32, mac, key->unknown_purpose_nonce, 2, 16); if (err || (grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16) @@ -371,6 +379,7 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, { grub_dprintf ("zfs", "key loading failed\n"); grub_errno = GRUB_ERR_NONE; + grub_crypto_cipher_close (cipher); continue; } @@ -380,21 +389,25 @@ grub_zfs_load_key_real (const struct grub_zfs_key *key, { grub_dprintf ("zfs", "key loading failed\n"); grub_errno = GRUB_ERR_NONE; + grub_crypto_cipher_close (cipher); continue; } ret = grub_crypto_cipher_open (GRUB_CIPHER_AES); if (!ret) { grub_errno = GRUB_ERR_NONE; + grub_crypto_cipher_close (cipher); continue; } err = grub_crypto_cipher_set_key (ret, decrypted, keylen); if (err) { - grub_errno = GRUB_ERR_NONE; - grub_crypto_cipher_close (ret); - continue; - } + grub_errno = GRUB_ERR_NONE; + grub_crypto_cipher_close (ret); + grub_crypto_cipher_close (cipher); + continue; + } + grub_crypto_cipher_close (cipher); return ret; } return NULL; @@ -417,7 +430,7 @@ grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args) if (argc > 0) { grub_file_t file; - file = grub_file_open (args[0]); + file = grub_file_open (args[0], GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY); if (!file) return grub_errno; real_size = grub_file_read (file, buf, 1024); diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c index fdb587a4c..31d767bbd 100644 --- a/grub-core/fs/zfs/zfsinfo.c +++ b/grub-core/fs/zfs/zfsinfo.c @@ -130,23 +130,35 @@ print_vdev_info (char *nvlist, int tab) grub_free (bootpath); grub_free (devid); grub_free (path); + grub_free (type); return GRUB_ERR_NONE; } + char is_mirror=(grub_strcmp(type,VDEV_TYPE_MIRROR) == 0); + char is_raidz=(grub_strcmp(type,VDEV_TYPE_RAIDZ) == 0); + grub_free (type); - if (grub_strcmp (type, VDEV_TYPE_MIRROR) == 0) + if (is_mirror || is_raidz) { int nelm, i; nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm (nvlist, ZPOOL_CONFIG_CHILDREN); + if(is_mirror){ + grub_puts_ (N_("This VDEV is a mirror")); + } + else if(is_raidz){ + grub_uint64_t parity; + grub_zfs_nvlist_lookup_uint64(nvlist,"nparity",&parity); + grub_printf_ (N_("This VDEV is a RAIDZ%llu\n"),(unsigned long long)parity); + } print_tabs (tab); if (nelm <= 0) { - grub_puts_ (N_("Incorrect mirror")); + grub_puts_ (N_("Incorrect VDEV")); return GRUB_ERR_NONE; } - grub_printf_ (N_("Mirror with %d children\n"), nelm); + grub_printf_ (N_("VDEV with %d children\n"), nelm); print_state (nvlist, tab); for (i = 0; i < nelm; i++) { @@ -162,14 +174,14 @@ print_vdev_info (char *nvlist, int tab) total element number. And the number itself is fine, only the element isn't. */ - grub_printf_ (N_("Mirror element number %d isn't correct\n"), i); + grub_printf_ (N_("VDEV element number %d isn't correct\n"), i); continue; } /* TRANSLATORS: it's the element carying the number %d, not total element number. This is used in enumeration "Element number 1", "Element number 2", ... */ - grub_printf_ (N_("Mirror element number %d:\n"), i); + grub_printf_ (N_("VDEV element number %d:\n"), i); print_vdev_info (child, tab + 1); grub_free (child); @@ -367,14 +379,17 @@ grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc, grub_device_close (dev); - if (err) + if (err) { + grub_free (nvlist); return err; + } poolname = grub_zfs_nvlist_lookup_string (nvlist, ZPOOL_CONFIG_POOL_NAME); if (!poolname) { if (!grub_errno) grub_error (GRUB_ERR_BAD_FS, "No poolname found"); + grub_free (nvlist); return grub_errno; } diff --git a/grub-core/gdb/cstub.c b/grub-core/gdb/cstub.c index a5c0c4316..b64acd70f 100644 --- a/grub-core/gdb/cstub.c +++ b/grub-core/gdb/cstub.c @@ -201,10 +201,10 @@ grub_gdb_hex2int (char **ptr, grub_uint64_t *int_value) } /* This function does all command procesing for interfacing to gdb. */ -void +void __attribute__ ((regparm(3))) grub_gdb_trap (int trap_no) { - int sig_no; + unsigned int sig_no; int stepping; grub_uint64_t addr; grub_uint64_t length; @@ -216,7 +216,7 @@ grub_gdb_trap (int trap_no) grub_backtrace_print_address ((void *) grub_gdb_regs[PC]); grub_printf ("\n"); grub_backtrace_pointer ((void *) grub_gdb_regs[EBP]); - grub_abort (); + grub_fatal ("Unhandled exception"); } sig_no = grub_gdb_trap2sig (trap_no); @@ -264,7 +264,7 @@ grub_gdb_trap (int trap_no) case '?': grub_gdb_outbuf[0] = 'S'; grub_gdb_outbuf[1] = hexchars[sig_no >> 4]; - grub_gdb_outbuf[2] = hexchars[sig_no % 16]; + grub_gdb_outbuf[2] = hexchars[sig_no & 0xf]; grub_gdb_outbuf[3] = 0; break; @@ -336,6 +336,7 @@ grub_gdb_trap (int trap_no) /* sAA..AA: Step one instruction from AA..AA(optional). */ case 's': stepping = 1; + /* FALLTHROUGH */ /* cAA..AA: Continue at address AA..AA(optional). */ case 'c': diff --git a/grub-core/gdb/gdb.c b/grub-core/gdb/gdb.c index 847a1e1e3..9e091ee1b 100644 --- a/grub-core/gdb/gdb.c +++ b/grub-core/gdb/gdb.c @@ -75,25 +75,30 @@ static grub_command_t cmd, cmd_stop, cmd_break; GRUB_MOD_INIT (gdb) { grub_gdb_idtinit (); - cmd = grub_register_command ("gdbstub", grub_cmd_gdbstub, - N_("PORT"), - /* TRANSLATORS: GDB stub is a small part of - GDB functionality running on local host - which allows remote debugger to - connect to it. */ - N_("Start GDB stub on given port")); - cmd_break = grub_register_command ("gdbstub_break", grub_cmd_gdb_break, - /* TRANSLATORS: this refers to triggering - a breakpoint so that the user will land - into GDB. */ - 0, N_("Break into GDB")); - cmd_stop = grub_register_command ("gdbstub_stop", grub_cmd_gdbstop, - 0, N_("Stop GDB stub")); + cmd = grub_register_command_lockdown ("gdbstub", grub_cmd_gdbstub, + N_("PORT"), + /* + * TRANSLATORS: GDB stub is a small part of + * GDB functionality running on local host + * which allows remote debugger to + * connect to it. + */ + N_("Start GDB stub on given port")); + cmd_break = grub_register_command_lockdown ("gdbstub_break", grub_cmd_gdb_break, + /* + * TRANSLATORS: this refers to triggering + * a breakpoint so that the user will land + * into GDB. + */ + 0, N_("Break into GDB")); + cmd_stop = grub_register_command_lockdown ("gdbstub_stop", grub_cmd_gdbstop, + 0, N_("Stop GDB stub")); } GRUB_MOD_FINI (gdb) { grub_unregister_command (cmd); + grub_unregister_command (cmd_break); grub_unregister_command (cmd_stop); grub_gdb_idtrestore (); } diff --git a/grub-core/gdb/i386/idt.c b/grub-core/gdb/i386/idt.c index 69bfcb089..43bde51a0 100644 --- a/grub-core/gdb/i386/idt.c +++ b/grub-core/gdb/i386/idt.c @@ -1,4 +1,4 @@ -/* idt.c - routines for constructing IDT fot the GDB stub */ +/* idt.c - routines for constructing IDT for the GDB stub */ /* * Copyright (C) 2006 Lubomir Kundrak * diff --git a/grub-core/gdb/i386/machdep.S b/grub-core/gdb/i386/machdep.S index 1615b0c9f..f96d2b9c4 100644 --- a/grub-core/gdb/i386/machdep.S +++ b/grub-core/gdb/i386/machdep.S @@ -71,11 +71,7 @@ VARIABLE(grub_gdb_stack) #define REG \reg #define NDX \ndx #endif -#ifdef __APPLE__ xorl %eax, %eax -#else - movl $0, %eax -#endif movw REG, EXT_C(grub_gdb_regs)+(NDX * 4) movw %ax, EXT_C(grub_gdb_regs)+(NDX * 4 + 2) movl EXT_C(grub_gdb_regs)+(EAX * 4), %eax @@ -190,11 +186,7 @@ VARIABLE(grub_gdb_stack) .text 1: .if EC -#ifdef __APPLE__ - add $$4, %esp -#else - add $4, %esp -#endif + add MACRO_DOLLAR(4), %esp .endif save_context diff --git a/grub-core/gdb/i386/signal.c b/grub-core/gdb/i386/signal.c index 23b7c3506..b169c6b23 100644 --- a/grub-core/gdb/i386/signal.c +++ b/grub-core/gdb/i386/signal.c @@ -1,4 +1,4 @@ -/* idt.c - routines for constructing IDT fot the GDB stub */ +/* idt.c - routines for constructing IDT for the GDB stub */ /* * Copyright (C) 2006 Lubomir Kundrak * @@ -24,7 +24,7 @@ /* Converting CPU trap number to UNIX signal number as described in System V ABI i386 Processor Supplement, 3-25. */ -int +unsigned int grub_gdb_trap2sig (int trap_no) { const int signals[] = { diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in index 01ef3e15b..f188a842a 100644 --- a/grub-core/gdb_grub.in +++ b/grub-core/gdb_grub.in @@ -1,6 +1,6 @@ ### ### Load debuging information about GNU GRUB 2 modules into GDB -### automatically. Needs readelf, Perl and gmodule.pl script +### automatically. Needs readelf, objdump, Python and gdb_helper.py script ### ### Has to be launched from the writable and trusted ### directory containing *.image and *.module @@ -9,77 +9,128 @@ ### Lubomir Kundrak ### -# Add section numbers and addresses to .segments.tmp -define dump_module_sections - set $mod = $arg0 +source gdb_helper.py - # FIXME: save logging status - set logging file .segments.tmp - set logging redirect on - set logging overwrite off - set logging on - printf "%s", $mod->name - set $segment = $mod->segment - while ($segment) - printf " %i 0x%x", $segment->section, $segment->addr - set $segment = $segment->next +define dynamic_load_symbols + dynamic_load_kernel_exec_symbols $arg0 + + run_on_start + + # We may have been very late to loading the kernel.exec symbols and + # and modules may already be loaded. So load symbols for any already + # loaded. + load_all_modules + + if $is_grub_loaded() + runtime_load_module end - printf "\n" - - set logging off - # FIXME: restore logging status end -document dump_module_sections - Gather information about module whose mod structure was - given for use with match_and_load_symbols -end - -# Generate and execute GDB commands and delete temporary files -# afterwards -define match_and_load_symbols - shell perl gmodule.pl <.segments.tmp >.loadsym.gdb - source .loadsym.gdb - shell rm -f .segments.tmp .loadsym.gdb -end -document match_and_load_symbols - Launch script, that matches section names with information - generated by dump_module_sections and load debugging info - apropriately -end - -### - -define load_module - dump_module_sections $arg0 - match_and_load_symbols -end -document load_module - Load debugging information for module given as argument. +document dynamic_load_symbols + Load debugging symbols from kernel.exec and any loaded modules given + the address of the .text segment of the UEFI binary in memory. Also + setup session to automatically load module symbols for modules loaded + in the future. end define load_all_modules set $this = grub_dl_head while ($this != 0) - dump_module_sections $this->mod + load_module $this set $this = $this->next end - match_and_load_symbols end document load_all_modules Load debugging information for all loaded modules. end +define runtime_load_module + break grub_dl_add + commands + silent + load_module mod + cont + end +end +document runtime_load_module + Load module symbols at runtime as they are loaded. +end + +define run_on_start + # TODO: Add check to see if _start symbol is defined, if not, then + # the symbols have not yet been loaded and this command will not work. + watch *_start + set $break_efi_start_bpnum = $bpnum + commands + silent + delete $break_efi_start_bpnum + + # Save the breakpoints here before the GRUB image is loaded + # into memory, then delete them. Later they will be reloaded + # once the GRUB image has been loaded. This avoids the issue + # where the loading of the GRUB image overwrites the software + # breakpoints, thus confusing GDB and effectively clearing + # those breakpoints. + save breakpoints .early-breakpoints.gdb + delete breakpoints + + tbreak _start + commands + silent + + # Reload the breakpoints now that the GRUB image has + # finished being loaded into memory. + source .early-breakpoints.gdb + + runtime_load_module + + if $is_user_command("onstart") + onstart + end + continue + end + continue + end +end +document run_on_start + On some targets, such as x86_64-efi, even if you know where the + firmware will load the GRUB image, you can not simply set a break + point before the image is loaded because loading the image + overwrites the break point in memory. So setup a hardware watch + point, which does not have that problem, and if that gets triggered, + then reset the break point. If a user-defined command named + "onstart" exists it will be run after the start is hit. + NOTE: This assumes symbols have already been correctly loaded for + the EFI application. +end + ### set confirm off -file kernel.exec -target remote :1234 -# inform when module is loaded -break grub_dl_add -commands - silent - load_module mod - cont +# Note: On EFI and other platforms that load GRUB to an address that is +# determined at runtime, the symbols in kernel.exec will be wrong. +# However, we must start by loading some executable file or GDB will +# fail. + +set $platform_efi = $_streq("@platform@", "efi") +set $target = "@target_cpu@-@platform@" + +if ! $runonce + if $platform_efi + # Only load the executable file, not the symbols + exec-file kernel.exec + else + if $_streq($target, "i386-pc") + add-symbol-file boot.image + add-symbol-file diskboot.image + add-symbol-file lzma_decompress.image + end + file kernel.exec + run_on_start + runtime_load_module + end + + target remote :1234 + set $runonce = 1 end diff --git a/grub-core/gdb_helper.py.in b/grub-core/gdb_helper.py.in new file mode 100644 index 000000000..a2cab416a --- /dev/null +++ b/grub-core/gdb_helper.py.in @@ -0,0 +1,173 @@ +import os +import re +import subprocess + +def prompt_hook (current_prompt): + return "(grub gdb) " +gdb.prompt_hook = prompt_hook + +##### Convenience functions ##### + +class IsGrubLoaded (gdb.Function): + """Return 1 if GRUB has been loaded in memory, otherwise 0. +The heuristic used is checking if the first 4 bytes of the memory pointed +to by the _start symbol are not 0. This is true for QEMU on the first run +of GRUB. This may not be true on physical hardware, where memory is not +necessarily cleared on soft reset. This may not also be true in QEMU on +soft resets. Also this many not be true when chainloading GRUB. +""" + + def __init__ (self): + super (IsGrubLoaded, self).__init__ ("is_grub_loaded") + + def invoke (self): + return int (gdb.parse_and_eval ("*(int *) _start")) != 0 + +is_grub_loaded = IsGrubLoaded () + +class IsUserCommand (gdb.Function): + """Set the second argument to true value if first argument is the name +of a user-defined command. +""" + + def __init__ (self): + super (IsUserCommand, self).__init__ ("is_user_command") + + def invoke (self, fmt, *args): + name = fmt.string () % tuple(a.string () for a in args) + for line in gdb.execute ("help user-defined", to_string=True).splitlines (): + line_parts = line.split(' -- ', 1) + if len (line_parts) > 1 and line_parts[0] == name: + return True + return False + +is_user_command = IsUserCommand () + +##### Commands ##### + +# Loading symbols is complicated by the fact that kernel.exec is an ELF +# ELF binary, but the UEFI runtime is PE32+. All the data sections of +# the ELF binary are concatenated (accounting for ELF section alignment) +# and put into one .data section of the PE32+ runtime image. So given +# the load address of the .data PE32+ section we can determine the +# addresses each ELF data section maps to. The UEFI application is +# loaded into memory just as it is laid out in the file. It is not +# assumed that the binary is available, but it is known that the .text +# section directly precedes the .data section and that .data is EFI +# page aligned. Using this, the .data offset can be found from the .text +# address. +class GrubLoadKernelExecSymbols (gdb.Command): + """Load debugging symbols from kernel.exec given the address of the +.text segment of the UEFI binary in memory.""" + + PE_SECTION_ALIGN = 12 + + def __init__ (self): + super (GrubLoadKernelExecSymbols, self).__init__ ("dynamic_load_kernel_exec_symbols", + gdb.COMMAND_USER, + gdb.COMPLETE_EXPRESSION) + + def invoke (self, arg, from_tty): + self.dont_repeat () + args = gdb.string_to_argv (arg) + + if len (args) != 1: + raise RuntimeError ("dynamic_load_kernel_exec_symbols expects exactly one argument") + + sections = self.parse_objdump_sections ("kernel.exec") + pe_text = args[0] + text_size = [s['size'] for s in sections if s['name'] == '.text'][0] + pe_data_offset = self.alignup (text_size, self.PE_SECTION_ALIGN) + + sym_load_cmd_parts = ["add-symbol-file", "kernel.exec", pe_text] + offset = 0 + for section in sections: + if 'DATA' in section["flags"] or section["name"] == ".bss": + offset = self.alignup (offset, section["align"]) + sym_load_cmd_parts.extend (["-s", section["name"], "(%s+0x%x+0x%x)" % (pe_text, pe_data_offset, offset)]) + offset += section["size"] + gdb.execute (' '.join (sym_load_cmd_parts)) + + @staticmethod + def parse_objdump_sections (filename): + fields = ("idx", "name", "size", "vma", "lma", "fileoff", "align") + re_section = re.compile ("^\s*" + "\s+".join(["(?P<%s>\S+)" % f for f in fields])) + c = subprocess.run (["objdump", "-h", filename], text=True, capture_output=True) + section_lines = c.stdout.splitlines ()[5:] + sections = [] + + for i in range (len (section_lines) >> 1): + m = re_section.match (section_lines[i * 2]) + s = dict (m.groupdict ()) + for f in ("size", "vma", "lma", "fileoff"): + s[f] = int (s[f], 16) + s["idx"] = int (s["idx"]) + s["align"] = int (s["align"].split ("**", 1)[1]) + s["flags"] = section_lines[(i * 2) + 1].strip ().split (", ") + sections.append (s) + return sections + + @staticmethod + def alignup (addr, align): + pad = (addr % (1 << align)) and 1 or 0 + return ((addr >> align) + pad) << align + +dynamic_load_kernel_exec_symbols = GrubLoadKernelExecSymbols () + + +class GrubLoadModuleSymbols (gdb.Command): + """Load module symbols at correct locations. +Takes one argument which is a pointer to a grub_dl_t struct.""" + + def __init__ (self): + super (GrubLoadModuleSymbols, self).__init__ ("load_module", + gdb.COMMAND_USER, + gdb.COMPLETE_EXPRESSION) + + def invoke (self, arg, from_tty): + self.dont_repeat () + args = gdb.string_to_argv (arg) + self.mod = gdb.parse_and_eval (args[0]) + sections = self.get_section_offsets () + section_names = self.get_section_names () + + sym_load_cmd_parts = ["add-symbol-file", + "%s.module" % (self.mod['name'].string (),)] + for idx, addr in sections: + section_name = section_names[idx] + if section_name == ".text": + sym_load_cmd_parts.append (addr) + else: + sym_load_cmd_parts.extend (["-s", section_name, addr]) + gdb.execute (' '.join (sym_load_cmd_parts)) + + if is_user_command.invoke (gdb.Value ("onload_%s"), self.mod['name']): + gdb.execute ("onload_%s (grub_dl_t)%s" % (self.mod['name'].string (), + self.mod.format_string (format='x'))) + + def get_section_offsets (self): + sections = [] + segment = self.mod['segment'] + while segment: + sections.append ((int (segment['section']), segment['addr'].format_string (format='x'))) + segment = segment['next'] + return sections + + def get_section_names (self): + re_index = re.compile ("^\s+\[\s*(\d+)\] (\S*)") + names = {} + modfilename = "%s.mod" % (self.mod['name'].string (),) + + if not os.path.exists (modfilename): + raise RuntimeError ("%s not found in current directory" % (modfilename,)) + + c = subprocess.run (["readelf", "-SW", modfilename], text=True, capture_output=True) + for line in c.stdout.splitlines ()[4:]: + m = re_index.match (line) + if not m: + continue + idx, name = m.groups () + names[int (idx)] = name + return names + +grub_load_module = GrubLoadModuleSymbols () diff --git a/grub-core/genemuinit.sh b/grub-core/genemuinit.sh index 45c15ecb9..8c6bb1c18 100644 --- a/grub-core/genemuinit.sh +++ b/grub-core/genemuinit.sh @@ -47,7 +47,7 @@ EOF read mods for line in $mods; do if ${nm} --defined-only -P -p ${line} | grep grub_mod_init > /dev/null; then - echo "grub_${line}_init ();" | sed 's,\.mod,,g;' + echo "grub_${line%%.*}_init ();" fi done @@ -63,7 +63,7 @@ EOF for line in $mods; do if ${nm} --defined-only -P -p ${line} | grep grub_mod_fini > /dev/null; then - echo "grub_${line}_fini ();" | sed 's,\.mod,,g;' + echo "grub_${line%%.*}_fini ();" fi done diff --git a/grub-core/genemuinitheader.sh b/grub-core/genemuinitheader.sh index 6b83f5993..a99a15d06 100644 --- a/grub-core/genemuinitheader.sh +++ b/grub-core/genemuinitheader.sh @@ -44,9 +44,9 @@ EOF read mods for line in $mods; do if ${nm} --defined-only -P -p ${line} | grep grub_mod_init > /dev/null; then - echo "void grub_${line}_init (void);" | sed 's,\.mod,,g;' + echo "void grub_${line%%.*}_init (void);" fi if ${nm} --defined-only -P -p ${line} | grep grub_mod_fini > /dev/null; then - echo "void grub_${line}_fini (void);" | sed 's,\.mod,,g;' + echo "void grub_${line%%.*}_fini (void);" fi done diff --git a/grub-core/genmod.sh.in b/grub-core/genmod.sh.in index 76df0bbb4..337753c57 100644 --- a/grub-core/genmod.sh.in +++ b/grub-core/genmod.sh.in @@ -1,4 +1,4 @@ -#! /bin/sh +#! @BUILD_SHEBANG@ set -e # Copyright (C) 2010 Free Software Foundation, Inc. @@ -15,12 +15,12 @@ set -e # # Example: # -# genmod.sh moddep.lst normal.module normal.mod +# genmod.sh moddep.lst normal.module build-grub-module-verifier normal.mod # moddep=$1 infile=$2 -outfile=$3 +outfile=$4 tmpfile=${outfile}.tmp modname=`echo $infile | sed -e 's@\.module.*$@@'` @@ -35,9 +35,9 @@ deps=`grep ^$modname: $moddep | sed s@^.*:@@` # remove old files if any rm -f $tmpfile $outfile -if test x@TARGET_APPLE_CC@ != x1; then +if test x@TARGET_APPLE_LINKER@ != x1; then # stripout .modname and .moddeps sections from input module - @OBJCOPY@ -R .modname -R .moddeps $infile $tmpfile + @TARGET_OBJCOPY@ -R .modname -R .moddeps $infile $tmpfile # Attach .modname and .moddeps sections t1=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 @@ -47,21 +47,28 @@ if test x@TARGET_APPLE_CC@ != x1; then for dep in $deps; do printf "$dep\0" >> $t2; done if test -n "$deps"; then - @OBJCOPY@ --add-section .modname=$t1 --add-section .moddeps=$t2 $tmpfile + @TARGET_OBJCOPY@ --add-section .modname=$t1 --add-section .moddeps=$t2 $tmpfile else - @OBJCOPY@ --add-section .modname=$t1 $tmpfile + @TARGET_OBJCOPY@ --add-section .modname=$t1 $tmpfile fi rm -f $t1 $t2 - if ! test -z "${TARGET_OBJ2ELF}"; then - ./${TARGET_OBJ2ELF} $tmpfile || exit 1 - fi if test x@platform@ != xemu; then - @STRIP@ --strip-unneeded \ + @TARGET_STRIP@ --strip-unneeded \ -K grub_mod_init -K grub_mod_fini \ -K _grub_mod_init -K _grub_mod_fini \ - -R .note.gnu.gold-version -R .note.GNU-stack \ - -R .note -R .comment $tmpfile || exit 1 + -R .note.GNU-stack \ + -R .note.gnu.gold-version \ + -R .note.gnu.property \ + -R .gnu.build.attributes \ + -R '.llvm*' \ + -R .rel.gnu.build.attributes \ + -R .rela.gnu.build.attributes \ + -R .eh_frame -R .rela.eh_frame -R .rel.eh_frame \ + -R .note -R .comment -R .ARM.exidx $tmpfile || exit 1 + fi + if ! test -z "${TARGET_OBJ2ELF}"; then + "${TARGET_OBJ2ELF}" $tmpfile || exit 1 fi else tmpfile2=${outfile}.tmp2 @@ -79,18 +86,21 @@ else for dep in $deps; do echo "char moddep_$dep[] __attribute__ ((section(\"_moddeps, _moddeps\"))) = \"$dep\";" >>$t2; done if test -n "$deps"; then - @TARGET_CC@ @TARGET_LDFLAGS@ -ffreestanding -nostdlib -o $tmpfile2 $t1 $t2 $tmpfile -Wl,-r,-d + @TARGET_CC@ @TARGET_LDFLAGS@ -ffreestanding -nostdlib -o $tmpfile2 $t1 $t2 $tmpfile -Wl,-r else - @TARGET_CC@ @TARGET_LDFLAGS@ -ffreestanding -nostdlib -o $tmpfile2 $t1 $tmpfile -Wl,-r,-d + @TARGET_CC@ @TARGET_LDFLAGS@ -ffreestanding -nostdlib -o $tmpfile2 $t1 $tmpfile -Wl,-r fi rm -f $t1 $t2 $tmpfile mv $tmpfile2 $tmpfile cp $tmpfile $tmpfile.bin - @OBJCONV@ -f@TARGET_MODULE_FORMAT@ \ + @TARGET_OBJCONV@ -f@TARGET_MODULE_FORMAT@ \ -nr:_grub_mod_init:grub_mod_init \ -nr:_grub_mod_fini:grub_mod_fini \ -wd1106 -nu -nd $tmpfile.bin $tmpfile || exit 1 - rm -f $name.bin + rm -f $tmpfile.bin +fi +if test x@platform@ != xemu; then + ./build-grub-module-verifier@BUILD_EXEEXT@ $tmpfile @target_cpu@ @platform@ fi mv $tmpfile $outfile diff --git a/grub-core/genmoddep.awk b/grub-core/genmoddep.awk index 9ffea7309..ab457cb2b 100644 --- a/grub-core/genmoddep.awk +++ b/grub-core/genmoddep.awk @@ -14,25 +14,31 @@ # Read symbols' info from stdin. BEGIN { error = 0 - lineno = 0; - while (getline <"/dev/stdin") { - lineno++; - if ($1 == "defined") { - symtab[$3] = $2; - modtab[$2] = "" modtab[$2] - } else if ($1 == "undefined") { - if ($3 in symtab) - modtab[$2] = modtab[$2] " " symtab[$3]; - else if ($3 != "__gnu_local_gp") { - printf "%s in %s is not defined\n", $3, $2 >"/dev/stderr"; - error++; - } - } - else { - printf "error: %u: unrecognized input format\n", lineno; +} + +{ + if ($1 == "defined") { + if ($3 !~ /^\.refptr\./ && $3 in symtab) { + printf "%s in %s is duplicated in %s\n", $3, $2, symtab[$3] >"/dev/stderr"; error++; - break; } + symtab[$3] = $2; + modtab[$2] = "" modtab[$2] + } else if ($1 == "undefined") { + if ($3 in symtab) + modtab[$2] = modtab[$2] " " symtab[$3]; + else if ($3 != "__gnu_local_gp" && $3 != "_gp_disp") { + printf "%s in %s is not defined\n", $3, $2 >"/dev/stderr"; + error++; + } + } else if ($1 == "depends") { + for (i = 3; i <= NF; i++) { + modtab[$2] = modtab[$2] " " $i; + } + } else if ($1 == "") {} #Skip empty lines + else { + printf "error: %u: unrecognized input format\n", NR >"/dev/stderr"; + error++; } } @@ -41,6 +47,8 @@ END { if (error >= 1) exit 1; + total_depcount = 0 + for (mod in modtab) { # Remove duplications. split(modtab[mod], depmods, " "); @@ -54,14 +62,44 @@ END { uniqmods[depmod] = 1; } modlist = "" - for (depmod in uniqmods) { + depcount[mod] = 0 + n = asorti(uniqmods, w) + for (i = 1; i <= n; i++) { + depmod = w[i] modlist = modlist " " depmod; + inverse_dependencies[depmod] = inverse_dependencies[depmod] " " mod + depcount[mod]++ + total_depcount++ } if (mod == "all_video") { continue; } printf "%s:%s\n", mod, modlist; } + + # Check that we have no dependency circles + while (total_depcount != 0) { + something_done = 0 + for (mod in depcount) { + if (depcount[mod] == 0) { + delete depcount[mod] + split(inverse_dependencies[mod], inv_depmods, " "); + for (ctr in inv_depmods) { + depcount[inv_depmods[ctr]]-- + total_depcount-- + } + delete inverse_dependencies[mod] + something_done = 1 + } + } + if (something_done == 0) { + for (mod in depcount) { + circle = circle " " mod + } + printf "error: modules %s form a dependency circle\n", circle >"/dev/stderr"; + exit 1 + } + } modlist = "" while (getline <"video.lst") { modlist = modlist " " $1; diff --git a/grub-core/gensyminfo.sh.in b/grub-core/gensyminfo.sh.in index d383f2640..9bc767532 100644 --- a/grub-core/gensyminfo.sh.in +++ b/grub-core/gensyminfo.sh.in @@ -1,4 +1,4 @@ -#! /bin/sh +#! @BUILD_SHEBANG@ set -e # Copyright (C) 2010 Free Software Foundation, Inc. @@ -22,14 +22,16 @@ module=$1 modname=`echo $module | sed -e 's@\.module.*$@@'` # Print all symbols defined by module -if test x@TARGET_APPLE_CC@ = x1; then - @NM@ -g -P -p $module | \ - grep -E '^[a-zA-Z0-9_]* [TDS]' | \ - sed "s@^\([^ ]*\).*@defined $modname \1@g" +if test x"@TARGET_NMFLAGS_DEFINED_ONLY@" = x && test x"@TARGET_NMFLAGS_MINUS_P@" = x; then + @TARGET_NM@ -g -p $module | \ + sed -n "s@^\([0-9a-fA-F]*\) *[TBRDS] *\([^ ]*\).*@defined $modname \2@p" +elif test x"@TARGET_NMFLAGS_DEFINED_ONLY@" = x; then + @TARGET_NM@ -g @TARGET_NMFLAGS_MINUS_P@ -p $module | \ + sed -n "s@^\([^ ]*\) *[TBRDS] *\([0-9a-fA-F]*\).*@defined $modname \1@p" else - @NM@ -g --defined-only -P -p $module | \ + @TARGET_NM@ -g --defined-only @TARGET_NMFLAGS_MINUS_P@ -p $module | \ sed "s@^\([^ ]*\).*@defined $modname \1@g" fi # Print all undefined symbols used by module -@NM@ -u -P -p $module | sed "s@^\([^ ]*\).*@undefined $modname \1@g" +@TARGET_NM@ -u @TARGET_NMFLAGS_MINUS_P@ -p $module | sed "s@^\([^ ]*\).*@undefined $modname \1@g" diff --git a/grub-core/gensymlist.sh b/grub-core/gensymlist.sh index a13d7cc38..5074ef6aa 100644 --- a/grub-core/gensymlist.sh +++ b/grub-core/gensymlist.sh @@ -31,6 +31,7 @@ cat <. */ +#include <../config-util.h> EOF for i in $*; do @@ -59,7 +60,7 @@ EOF | grep -v '^#' \ | sed -n \ -e '/EXPORT_FUNC *([a-zA-Z0-9_]*)/{s/.*EXPORT_FUNC *(\([a-zA-Z0-9_]*\)).*/ {"\1", \1, 1},/;p;}' \ - -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/ {"\1", \&\1, 0},/;p;}' \ + -e '/EXPORT_VAR *([a-zA-Z0-9_]*)/{s/.*EXPORT_VAR *(\([a-zA-Z0-9_]*\)).*/ {"\1", (void *) \&\1, 0},/;p;}' \ | sort -u cat < #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -34,8 +35,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); http://www.gnu.org/software/autoconf/manual/gettext/MO-Files.html . */ -static struct grub_gettext_context main_context, secondary_context; - static const char *(*grub_gettext_original) (const char *s); struct grub_gettext_msg @@ -53,7 +52,7 @@ struct header grub_uint32_t offset_translation; }; -struct string_descriptor +struct string_descriptor { grub_uint32_t length; grub_uint32_t offset; @@ -69,6 +68,8 @@ struct grub_gettext_context struct grub_gettext_msg *grub_gettext_msg_list; }; +static struct grub_gettext_context main_context, secondary_context; + #define MO_MAGIC_NUMBER 0x950412de static grub_err_t @@ -99,6 +100,7 @@ grub_gettext_getstr_from_position (struct grub_gettext_context *ctx, char *translation; struct string_descriptor desc; grub_err_t err; + grub_size_t alloc_sz; internal_position = (off + position * sizeof (desc)); @@ -109,7 +111,10 @@ grub_gettext_getstr_from_position (struct grub_gettext_context *ctx, length = grub_cpu_to_le32 (desc.length); offset = grub_cpu_to_le32 (desc.offset); - translation = grub_malloc (length + 1); + if (grub_add (length, 1, &alloc_sz)) + return NULL; + + translation = grub_malloc (alloc_sz); if (!translation) return NULL; @@ -206,7 +211,7 @@ grub_gettext_translate_real (struct grub_gettext_context *ctx, } grub_error_pop (); depth--; - return ret; + return ret; } } @@ -235,7 +240,7 @@ grub_gettext_translate_real (struct grub_gettext_context *ctx, } grub_error_pop (); depth--; - return ret; + return ret; } } @@ -291,7 +296,7 @@ grub_mofile_open (struct grub_gettext_context *ctx, /* Using fd_mo and not another variable because it's needed for grub_gettext_get_info. */ - fd = grub_file_open (filename); + fd = grub_file_open (filename, GRUB_FILE_TYPE_GETTEXT_CATALOG); if (!fd) return grub_errno; @@ -323,8 +328,8 @@ grub_mofile_open (struct grub_gettext_context *ctx, for (ctx->grub_gettext_max_log = 0; ctx->grub_gettext_max >> ctx->grub_gettext_max_log; ctx->grub_gettext_max_log++); - ctx->grub_gettext_msg_list = grub_zalloc (ctx->grub_gettext_max - * sizeof (ctx->grub_gettext_msg_list[0])); + ctx->grub_gettext_msg_list = grub_calloc (ctx->grub_gettext_max, + sizeof (ctx->grub_gettext_msg_list[0])); if (!ctx->grub_gettext_msg_list) { grub_file_close (fd); @@ -355,19 +360,30 @@ grub_mofile_open_lang (struct grub_gettext_context *ctx, return grub_errno; err = grub_mofile_open (ctx, mo_file); + grub_free (mo_file); /* Will try adding .gz as well. */ if (err) { - char *mo_file_old; grub_errno = GRUB_ERR_NONE; - mo_file_old = mo_file; - mo_file = grub_xasprintf ("%s.gz", mo_file); - grub_free (mo_file_old); + mo_file = grub_xasprintf ("%s%s/%s.mo.gz", part1, part2, locale); if (!mo_file) return grub_errno; err = grub_mofile_open (ctx, mo_file); + grub_free (mo_file); } + + /* Will try adding .gmo as well. */ + if (err) + { + grub_errno = GRUB_ERR_NONE; + mo_file = grub_xasprintf ("%s%s/%s.gmo", part1, part2, locale); + if (!mo_file) + return grub_errno; + err = grub_mofile_open (ctx, mo_file); + grub_free (mo_file); + } + return err; } @@ -412,6 +428,10 @@ grub_gettext_init_ext (struct grub_gettext_context *ctx, grub_free (lang); } + + if (locale[0] == 'e' && locale[1] == 'n' + && (locale[2] == '\0' || locale[2] == '_')) + grub_errno = err = GRUB_ERR_NONE; return err; } @@ -437,7 +457,7 @@ void grub_gettext_reread_prefix (const char *val) { grub_err_t err; - err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"), + err = grub_gettext_init_ext (&main_context, grub_env_get ("lang"), grub_env_get ("locale_dir"), val); if (err) @@ -504,7 +524,7 @@ GRUB_MOD_INIT (gettext) grub_register_command_p1 ("gettext", grub_cmd_translate, N_("STRING"), /* TRANSLATORS: It refers to passing the string through gettext. - So it's "translate" in the same meaning as in what you're + So it's "translate" in the same meaning as in what you're doing now. */ N_("Translates the string with the current settings.")); @@ -520,6 +540,10 @@ GRUB_MOD_INIT (gettext) GRUB_MOD_FINI (gettext) { + grub_register_variable_hook ("locale_dir", NULL, NULL); + grub_register_variable_hook ("secondary_locale_dir", NULL, NULL); + grub_register_variable_hook ("lang", NULL, NULL); + grub_gettext_delete_list (&main_context); grub_gettext_delete_list (&secondary_context); diff --git a/grub-core/gfxmenu/font.c b/grub-core/gfxmenu/font.c index 3c15e19fa..756c24f20 100644 --- a/grub-core/gfxmenu/font.c +++ b/grub-core/gfxmenu/font.c @@ -42,37 +42,43 @@ grub_font_draw_string (const char *str, grub_font_t font, int left_x, int baseline_y) { int x; - struct grub_font_glyph *glyph; grub_uint32_t *logical; grub_ssize_t logical_len, visual_len; struct grub_unicode_glyph *visual, *ptr; + grub_err_t err; logical_len = grub_utf8_to_ucs4_alloc (str, &logical, 0); if (logical_len < 0) return grub_errno; visual_len = grub_bidi_logical_to_visual (logical, logical_len, &visual, - 0, 0, 0); + 0, 0, 0, 0, 0, 0, 0); grub_free (logical); if (visual_len < 0) return grub_errno; + err = GRUB_ERR_NONE; for (ptr = visual, x = left_x; ptr < visual + visual_len; ptr++) { - grub_err_t err; + struct grub_font_glyph *glyph; glyph = grub_font_construct_glyph (font, ptr); if (!glyph) - return grub_errno; + { + err = grub_errno; + goto out; + } err = grub_font_draw_glyph (glyph, color, x, baseline_y); - x += glyph->device_width; - grub_free (glyph); if (err) - return err; + goto out; + x += glyph->device_width; } +out: + for (ptr = visual; ptr < visual + visual_len; ptr++) + grub_unicode_destroy_glyph (ptr); grub_free (visual); - return GRUB_ERR_NONE; + return err; } /* Get the width in pixels of the specified UTF-8 string, when rendered in @@ -102,8 +108,9 @@ grub_font_get_string_width (grub_font_t font, const char *str) &glyph); width += grub_font_get_constructed_device_width (font, &glyph); - grub_free (glyph.combining); + grub_unicode_destroy_glyph (&glyph); } + grub_free (logical); return width; } diff --git a/grub-core/gfxmenu/gfxmenu.c b/grub-core/gfxmenu/gfxmenu.c index 09e86213f..72b39f90f 100644 --- a/grub-core/gfxmenu/gfxmenu.c +++ b/grub-core/gfxmenu/gfxmenu.c @@ -42,7 +42,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); static grub_gfxmenu_view_t cached_view; -static void +static void grub_gfxmenu_viewer_fini (void *data __attribute__ ((unused))) { } @@ -53,6 +53,7 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) { grub_gfxmenu_view_t view = NULL; const char *theme_path; + char *full_theme_path = 0; struct grub_menu_viewer *instance; grub_err_t err; struct grub_video_mode_info mode_info; @@ -62,23 +63,35 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "theme"); - instance = grub_zalloc (sizeof (*instance)); - if (!instance) - return grub_errno; - err = grub_video_get_info (&mode_info); if (err) return err; - if (!cached_view || grub_strcmp (cached_view->theme_path, theme_path) != 0 + instance = grub_zalloc (sizeof (*instance)); + if (!instance) + return grub_errno; + + if (theme_path[0] != '/' && theme_path[0] != '(') + { + const char *prefix; + prefix = grub_env_get ("prefix"); + full_theme_path = grub_xasprintf ("%s/themes/%s", + prefix, + theme_path); + } + + if (!cached_view || grub_strcmp (cached_view->theme_path, + full_theme_path ? : theme_path) != 0 || cached_view->screen.width != mode_info.width || cached_view->screen.height != mode_info.height) { - grub_free (cached_view); + grub_gfxmenu_view_destroy (cached_view); /* Create the view. */ - cached_view = grub_gfxmenu_view_new (theme_path, mode_info.width, + cached_view = grub_gfxmenu_view_new (full_theme_path ? : theme_path, + mode_info.width, mode_info.height); } + grub_free (full_theme_path); if (! cached_view) { diff --git a/grub-core/gfxmenu/gui_box.c b/grub-core/gfxmenu/gui_box.c index 38b15f96d..37bab3fbb 100644 --- a/grub-core/gfxmenu/gui_box.c +++ b/grub-core/gfxmenu/gui_box.c @@ -234,14 +234,30 @@ static void box_paint (void *vself, const grub_video_rect_t *region) { grub_gui_box_t self = vself; + struct component_node *cur; grub_video_rect_t vpsave; + grub_video_area_status_t box_area_status; + grub_video_get_area_status (&box_area_status); + grub_gui_set_viewport (&self->bounds, &vpsave); for (cur = self->chead.next; cur != &self->ctail; cur = cur->next) { grub_gui_component_t comp = cur->component; + grub_video_rect_t r; + comp->ops->get_bounds(comp, &r); + + if (!grub_video_have_common_points (region, &r)) + continue; + + /* Paint the child. */ + if (box_area_status == GRUB_VIDEO_AREA_ENABLED + && grub_video_bounds_inside_region (&r, region)) + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); comp->ops->paint (comp, region); + if (box_area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); } grub_gui_restore_viewport (&vpsave); } diff --git a/grub-core/gfxmenu/gui_canvas.c b/grub-core/gfxmenu/gui_canvas.c index b3919c2d3..a05491242 100644 --- a/grub-core/gfxmenu/gui_canvas.c +++ b/grub-core/gfxmenu/gui_canvas.c @@ -80,9 +80,13 @@ static void canvas_paint (void *vself, const grub_video_rect_t *region) { grub_gui_canvas_t self = vself; + struct component_node *cur; grub_video_rect_t vpsave; + grub_video_area_status_t canvas_area_status; + grub_video_get_area_status (&canvas_area_status); + grub_gui_set_viewport (&self->bounds, &vpsave); for (cur = self->components.next; cur; cur = cur->next) { @@ -135,9 +139,16 @@ canvas_paint (void *vself, const grub_video_rect_t *region) r.height = h; comp->ops->set_bounds (comp, &r); + if (!grub_video_have_common_points (region, &r)) + continue; + /* Paint the child. */ - if (grub_video_have_common_points (region, &r)) - comp->ops->paint (comp, region); + if (canvas_area_status == GRUB_VIDEO_AREA_ENABLED + && grub_video_bounds_inside_region (&r, region)) + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); + comp->ops->paint (comp, region); + if (canvas_area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); } grub_gui_restore_viewport (&vpsave); } diff --git a/grub-core/gfxmenu/gui_circular_progress.c b/grub-core/gfxmenu/gui_circular_progress.c index 098ae1c92..db1edb8f4 100644 --- a/grub-core/gfxmenu/gui_circular_progress.c +++ b/grub-core/gfxmenu/gui_circular_progress.c @@ -37,7 +37,7 @@ struct grub_gui_circular_progress int start; int end; int value; - int num_ticks; + unsigned num_ticks; int start_angle; int ticks_disappear; char *theme_dir; @@ -138,49 +138,53 @@ circprog_paint (void *vself, const grub_video_rect_t *region) (height - center_height) / 2, 0, 0, center_width, center_height); - int radius = width / 2 - tick_width / 2 - 1; - int nticks; - int tick_begin; - int tick_end; - if (self->end == self->start) - nticks = 0; - else - nticks = (self->num_ticks - * (self->value - self->start) - / (self->end - self->start)); - /* Do ticks appear or disappear as the value approached the end? */ - if (self->ticks_disappear) + if (self->num_ticks) { - tick_begin = nticks; - tick_end = self->num_ticks - 1; + int radius = grub_min (height, width) / 2 - grub_max (tick_height, tick_width) / 2 - 1; + unsigned nticks; + unsigned tick_begin; + unsigned tick_end; + if (self->end <= self->start + || self->value <= self->start) + nticks = 0; + else + nticks = ((unsigned) (self->num_ticks + * (self->value - self->start))) + / ((unsigned) (self->end - self->start)); + /* Do ticks appear or disappear as the value approached the end? */ + if (self->ticks_disappear) + { + tick_begin = nticks; + tick_end = self->num_ticks; + } + else + { + tick_begin = 0; + tick_end = nticks; + } + + unsigned i; + for (i = tick_begin; i < tick_end; i++) + { + int x; + int y; + int angle; + + /* Calculate the location of the tick. */ + angle = self->start_angle + + i * GRUB_TRIG_ANGLE_MAX / self->num_ticks; + x = width / 2 + (grub_cos (angle) * radius / GRUB_TRIG_FRACTION_SCALE); + y = height / 2 + (grub_sin (angle) * radius / GRUB_TRIG_FRACTION_SCALE); + + /* Adjust (x,y) so the tick is centered. */ + x -= tick_width / 2; + y -= tick_height / 2; + + /* Draw the tick. */ + grub_video_blit_bitmap (self->tick_bitmap, GRUB_VIDEO_BLIT_BLEND, + x, y, 0, 0, tick_width, tick_height); + } } - else - { - tick_begin = 0; - tick_end = nticks - 1; - } - - int i; - for (i = tick_begin; i < tick_end; i++) - { - int x; - int y; - int angle; - - /* Calculate the location of the tick. */ - angle = self->start_angle + i * GRUB_TRIG_ANGLE_MAX / self->num_ticks; - x = width / 2 + (grub_cos (angle) * radius / GRUB_TRIG_FRACTION_SCALE); - y = height / 2 + (grub_sin (angle) * radius / GRUB_TRIG_FRACTION_SCALE); - - /* Adjust (x,y) so the tick is centered. */ - x -= tick_width / 2; - y -= tick_height / 2; - - /* Draw the tick. */ - grub_video_blit_bitmap (self->tick_bitmap, GRUB_VIDEO_BLIT_BLEND, - x, y, 0, 0, tick_width, tick_height); - } - grub_gui_restore_viewport (&vpsave); } @@ -216,24 +220,43 @@ static void circprog_set_state (void *vself, int visible, int start, int current, int end) { - circular_progress_t self = vself; + circular_progress_t self = vself; self->visible = visible; self->start = start; self->value = current; self->end = end; } +static int +parse_angle (const char *value) +{ + const char *ptr; + int angle; + + angle = grub_strtol (value, &ptr, 10); + if (grub_errno) + return 0; + while (grub_isspace (*ptr)) + ptr++; + if (grub_strcmp (ptr, "deg") == 0 + /* Unicode symbol of degrees (a circle, U+b0). Put here in UTF-8 to + avoid potential problem with text file reesncoding */ + || grub_strcmp (ptr, "\xc2\xb0") == 0) + angle = grub_divide_round (angle * 64, 90); + return angle; +} + static grub_err_t circprog_set_property (void *vself, const char *name, const char *value) { circular_progress_t self = vself; if (grub_strcmp (name, "num_ticks") == 0) { - self->num_ticks = grub_strtol (value, 0, 10); + self->num_ticks = grub_strtoul (value, 0, 10); } else if (grub_strcmp (name, "start_angle") == 0) { - self->start_angle = grub_strtol (value, 0, 10); + self->start_angle = parse_angle (value); } else if (grub_strcmp (name, "ticks_disappear") == 0) { diff --git a/grub-core/gfxmenu/gui_image.c b/grub-core/gfxmenu/gui_image.c index 29784ed2d..eed4b6b87 100644 --- a/grub-core/gfxmenu/gui_image.c +++ b/grub-core/gfxmenu/gui_image.c @@ -199,6 +199,12 @@ load_image (grub_gui_image_t self, const char *path) if (self->raw_bitmap) grub_video_bitmap_destroy (self->raw_bitmap); + /* + * Either self->bitmap is being freed or it shares memory with + * self->raw_bitmap which is being freed. To ensure self->bitmap doesn't + * point to memory that has been freed, we can set it to NULL. + */ + self->bitmap = NULL; self->raw_bitmap = bitmap; return rescale_image (self); } diff --git a/grub-core/gfxmenu/gui_label.c b/grub-core/gfxmenu/gui_label.c index 637578f77..ffd50223c 100644 --- a/grub-core/gfxmenu/gui_label.c +++ b/grub-core/gfxmenu/gui_label.c @@ -23,6 +23,7 @@ #include #include #include +#include static const char *align_options[] = { @@ -153,11 +154,13 @@ label_get_minimal_size (void *vself, unsigned *width, unsigned *height) + grub_font_get_descent (self->font)); } +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + static void label_set_state (void *vself, int visible, int start __attribute__ ((unused)), int current, int end __attribute__ ((unused))) { - grub_gui_label_t self = vself; + grub_gui_label_t self = vself; self->value = -current; self->visible = visible; grub_free (self->text); @@ -190,6 +193,10 @@ label_set_property (void *vself, const char *name, const char *value) else if (grub_strcmp (value, "@KEYMAP_SHORT@") == 0) value = _("enter: boot, `e': options, `c': cmd-line"); /* FIXME: Add more templates here if needed. */ + + if (grub_printf_fmt_check(value, "%d") != GRUB_ERR_NONE) + value = ""; /* Unsupported format. */ + self->template = grub_strdup (value); self->text = grub_xasprintf (value, self->value); } @@ -234,6 +241,8 @@ label_set_property (void *vself, const char *name, const char *value) return GRUB_ERR_NONE; } +#pragma GCC diagnostic error "-Wformat-nonliteral" + static struct grub_gui_component_ops label_ops = { .destroy = label_destroy, diff --git a/grub-core/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c index 1982d9a40..2ccd4345f 100644 --- a/grub-core/gfxmenu/gui_list.c +++ b/grub-core/gfxmenu/gui_list.c @@ -23,6 +23,13 @@ #include #include #include +#include + +enum scrollbar_slice_mode { + SCROLLBAR_SLICE_WEST, + SCROLLBAR_SLICE_CENTER, + SCROLLBAR_SLICE_EAST +}; struct grub_gui_list_impl { @@ -40,9 +47,10 @@ struct grub_gui_list_impl int item_icon_space; int item_spacing; grub_font_t item_font; + int selected_item_font_inherit; grub_font_t selected_item_font; grub_video_rgba_color_t item_color; - int selected_item_color_set; + int selected_item_color_inherit; grub_video_rgba_color_t selected_item_color; int draw_scrollbar; @@ -51,16 +59,25 @@ struct grub_gui_list_impl char *scrollbar_thumb_pattern; grub_gfxmenu_box_t scrollbar_frame; grub_gfxmenu_box_t scrollbar_thumb; + int scrollbar_thumb_overlay; int scrollbar_width; + enum scrollbar_slice_mode scrollbar_slice; + int scrollbar_left_pad; + int scrollbar_right_pad; + int scrollbar_top_pad; + int scrollbar_bottom_pad; int first_shown_index; int need_to_recreate_boxes; char *theme_dir; char *menu_box_pattern; + char *item_box_pattern; + int selected_item_box_pattern_inherit; char *selected_item_box_pattern; grub_gfxmenu_box_t menu_box; grub_gfxmenu_box_t selected_item_box; + grub_gfxmenu_box_t item_box; grub_gfxmenu_icon_manager_t icon_manager; @@ -76,14 +93,22 @@ list_destroy (void *vself) grub_free (self->theme_dir); grub_free (self->menu_box_pattern); + grub_free (self->item_box_pattern); grub_free (self->selected_item_box_pattern); if (self->menu_box) self->menu_box->destroy (self->menu_box); + if (self->item_box) + self->item_box->destroy (self->item_box); if (self->selected_item_box) self->selected_item_box->destroy (self->selected_item_box); if (self->icon_manager) grub_gfxmenu_icon_manager_destroy (self->icon_manager); - + if (self->scrollbar_thumb) + self->scrollbar_thumb->destroy (self->scrollbar_thumb); + if (self->scrollbar_frame) + self->scrollbar_frame->destroy (self->scrollbar_frame); + grub_free (self->scrollbar_thumb_pattern); + grub_free (self->scrollbar_frame_pattern); grub_free (self); } @@ -93,13 +118,25 @@ get_num_shown_items (list_impl_t self) int boxpad = self->item_padding; int item_vspace = self->item_spacing; int item_height = self->item_height; - + grub_gfxmenu_box_t box = self->menu_box; int box_top_pad = box->get_top_pad (box); int box_bottom_pad = box->get_bottom_pad (box); - + grub_gfxmenu_box_t itembox = self->item_box; + grub_gfxmenu_box_t selbox = self->selected_item_box; + int item_top_pad = itembox->get_top_pad (itembox); + int item_bottom_pad = itembox->get_bottom_pad (itembox); + int sel_top_pad = selbox->get_top_pad (selbox); + int sel_bottom_pad = selbox->get_bottom_pad (selbox); + int max_top_pad = grub_max (item_top_pad, sel_top_pad); + int max_bottom_pad = grub_max (item_bottom_pad, sel_bottom_pad); + + if (item_height + item_vspace <= 0) + return 1; + return (self->bounds.height + item_vspace - 2 * boxpad - - box_top_pad - box_bottom_pad) / (item_height + item_vspace); + - max_top_pad - max_bottom_pad + - box_top_pad - box_bottom_pad) / (item_height + item_vspace); } static int @@ -111,6 +148,10 @@ check_boxes (list_impl_t self) self->menu_box_pattern, self->theme_dir); + grub_gui_recreate_box (&self->item_box, + self->item_box_pattern, + self->theme_dir); + grub_gui_recreate_box (&self->selected_item_box, self->selected_item_box_pattern, self->theme_dir); @@ -118,7 +159,8 @@ check_boxes (list_impl_t self) self->need_to_recreate_boxes = 0; } - return (self->menu_box != 0 && self->selected_item_box != 0); + return (self->menu_box != 0 && self->selected_item_box != 0 + && self->item_box != 0); } static int @@ -137,7 +179,34 @@ check_scrollbar (list_impl_t self) self->need_to_recreate_scrollbar = 0; } - return (self->scrollbar_frame != 0 && self->scrollbar_thumb != 0); + if (self->scrollbar_frame == 0 || self->scrollbar_thumb == 0) + return 0; + + /* Sanity checks. */ + grub_gfxmenu_box_t frame = self->scrollbar_frame; + grub_gfxmenu_box_t thumb = self->scrollbar_thumb; + grub_gfxmenu_box_t menu = self->menu_box; + int min_width = frame->get_left_pad (frame) + + frame->get_right_pad (frame); + int min_height = frame->get_top_pad (frame) + + frame->get_bottom_pad (frame) + + self->scrollbar_top_pad + self->scrollbar_bottom_pad + + menu->get_top_pad (menu) + + menu->get_bottom_pad (menu); + if (!self->scrollbar_thumb_overlay) + { + min_width += thumb->get_left_pad (thumb) + + thumb->get_right_pad (thumb); + min_height += thumb->get_top_pad (thumb) + + thumb->get_bottom_pad (thumb); + } + if (min_width <= self->scrollbar_width + && min_height <= (int) self->bounds.height) + return 1; + + /* Unprintable dimenstions. */ + self->draw_scrollbar = 0; + return 0; } static const char * @@ -183,36 +252,73 @@ make_selected_item_visible (list_impl_t self) static void draw_scrollbar (list_impl_t self, int value, int extent, int min, int max, - int rightx, int topy, int height) + int scrollbar_width, int scrollbar_height) { + unsigned thumby, thumbheight; + grub_gfxmenu_box_t frame = self->scrollbar_frame; grub_gfxmenu_box_t thumb = self->scrollbar_thumb; int frame_vertical_pad = (frame->get_top_pad (frame) + frame->get_bottom_pad (frame)); int frame_horizontal_pad = (frame->get_left_pad (frame) + frame->get_right_pad (frame)); - int tracktop = topy + frame->get_top_pad (frame); - int tracklen = height - frame_vertical_pad; - frame->set_content_size (frame, self->scrollbar_width, tracklen); - int thumby = tracktop + tracklen * (value - min) / (max - min); - int thumbheight = tracklen * extent / (max - min) + 1; - thumb->set_content_size (thumb, - self->scrollbar_width - frame_horizontal_pad, - thumbheight - (thumb->get_top_pad (thumb) - + thumb->get_bottom_pad (thumb))); - frame->draw (frame, - rightx - (self->scrollbar_width + frame_horizontal_pad), - topy); - thumb->draw (thumb, - rightx - (self->scrollbar_width - frame->get_right_pad (frame)), - thumby); + unsigned thumb_vertical_pad = (thumb->get_top_pad (thumb) + + thumb->get_bottom_pad (thumb)); + int thumb_horizontal_pad = (thumb->get_left_pad (thumb) + + thumb->get_right_pad (thumb)); + int tracktop = frame->get_top_pad (frame); + unsigned tracklen; + if (scrollbar_height <= frame_vertical_pad) + tracklen = 0; + else + tracklen = scrollbar_height - frame_vertical_pad; + frame->set_content_size (frame, + scrollbar_width - frame_horizontal_pad, + tracklen); + if (self->scrollbar_thumb_overlay) + { + tracklen += thumb_vertical_pad; + tracktop -= thumb->get_top_pad (thumb); + } + if (value <= min || max <= min) + thumby = 0; + else + thumby = ((unsigned) tracklen * (value - min)) + / ((unsigned) (max - min)); + if (max <= min) + thumbheight = 1; + else + thumbheight = ((unsigned) (tracklen * extent) + / ((unsigned) (max - min))) + 1; + /* Rare occasion: too many entries or too low height. */ + if (thumbheight < thumb_vertical_pad) + { + thumbheight = thumb_vertical_pad; + if (value <= min || max <= extent + || tracklen <= thumb_vertical_pad) + thumby = 0; + else + thumby = ((unsigned) ((tracklen - thumb_vertical_pad) * (value - min)) + / ((unsigned)(max - extent))); + } + thumby += tracktop; + int thumbx = frame->get_left_pad (frame); + int thumbwidth = scrollbar_width - frame_horizontal_pad; + if (!self->scrollbar_thumb_overlay) + thumbwidth -= thumb_horizontal_pad; + else + thumbx -= thumb->get_left_pad (thumb); + thumb->set_content_size (thumb, thumbwidth, + thumbheight - thumb_vertical_pad); + frame->draw (frame, 0, 0); + thumb->draw (thumb, thumbx, thumby); } /* Draw the list of items. */ static void draw_menu (list_impl_t self, int num_shown_items) { - if (! self->menu_box || ! self->selected_item_box) + if (! self->menu_box || ! self->selected_item_box || ! self->item_box) return; int boxpad = self->item_padding; @@ -221,67 +327,123 @@ draw_menu (list_impl_t self, int num_shown_items) int ascent = grub_font_get_ascent (self->item_font); int descent = grub_font_get_descent (self->item_font); - int item_height = self->item_height; + int selected_ascent = grub_font_get_ascent (self->selected_item_font); + int selected_descent = grub_font_get_descent (self->selected_item_font); + int text_box_height = self->item_height; make_selected_item_visible (self); + grub_gfxmenu_box_t itembox = self->item_box; grub_gfxmenu_box_t selbox = self->selected_item_box; + int item_leftpad = itembox->get_left_pad (itembox); + int item_rightpad = itembox->get_right_pad (itembox); + int item_border_width = item_leftpad + item_rightpad; + int item_toppad = itembox->get_top_pad (itembox); int sel_leftpad = selbox->get_left_pad (selbox); + int sel_rightpad = selbox->get_right_pad (selbox); + int sel_border_width = sel_leftpad + sel_rightpad; int sel_toppad = selbox->get_top_pad (selbox); - int item_top = sel_toppad; + + int max_leftpad = grub_max (item_leftpad, sel_leftpad); + int max_toppad = grub_max (item_toppad, sel_toppad); + int item_top = 0; int menu_index; int visible_index; struct grub_video_rect oviewport; grub_video_get_viewport (&oviewport.x, &oviewport.y, &oviewport.width, &oviewport.height); - grub_video_set_viewport (oviewport.x + boxpad, + grub_video_set_viewport (oviewport.x + boxpad, oviewport.y + boxpad, oviewport.width - 2 * boxpad, oviewport.height - 2 * boxpad); + int cwidth = oviewport.width - 2 * boxpad; + + itembox->set_content_size (itembox, cwidth - item_border_width, + text_box_height); + selbox->set_content_size (selbox, cwidth - sel_border_width, + text_box_height); + + int text_left_offset = self->icon_width + icon_text_space; + int item_text_top_offset = (text_box_height - (ascent + descent)) / 2 + ascent; + int sel_text_top_offset = (text_box_height - (selected_ascent + + selected_descent)) / 2 + + selected_ascent; + + grub_video_rect_t svpsave, sviewport; + sviewport.x = max_leftpad + text_left_offset; + int text_viewport_width = cwidth - sviewport.x; + sviewport.height = text_box_height; + + grub_video_color_t item_color; + grub_video_color_t sel_color; + item_color = grub_video_map_rgba_color (self->item_color); + sel_color = grub_video_map_rgba_color (self->selected_item_color); + + int item_box_top_offset = max_toppad - item_toppad; + int sel_box_top_offset = max_toppad - sel_toppad; + int item_viewport_width = text_viewport_width - item_rightpad; + int sel_viewport_width = text_viewport_width - sel_rightpad; + int tmp_icon_top_offset = (text_box_height - self->icon_height) / 2; + int item_icon_top_offset = item_toppad + tmp_icon_top_offset; + int sel_icon_top_offset = sel_toppad + tmp_icon_top_offset; + for (visible_index = 0, menu_index = self->first_shown_index; visible_index < num_shown_items && menu_index < self->view->menu->size; visible_index++, menu_index++) { int is_selected = (menu_index == self->view->selected); struct grub_video_bitmap *icon; + grub_font_t font; + grub_video_color_t color; + int text_top_offset; + int top_pad; + int icon_top_offset; + int viewport_width; if (is_selected) { - int cwidth = oviewport.width - 2 * boxpad - 2; - if (selbox->get_border_width) - cwidth -= selbox->get_border_width (selbox); - selbox->set_content_size (selbox, cwidth, item_height - 1); - selbox->draw (selbox, 0, - item_top - sel_toppad); + selbox->draw (selbox, 0, item_top + sel_box_top_offset); + font = self->selected_item_font; + color = sel_color; + text_top_offset = sel_text_top_offset; + top_pad = sel_toppad; + icon_top_offset = sel_icon_top_offset; + viewport_width = sel_viewport_width; + } + else + { + itembox->draw (itembox, 0, item_top + item_box_top_offset); + font = self->item_font; + color = item_color; + text_top_offset = item_text_top_offset; + top_pad = item_toppad; + icon_top_offset = item_icon_top_offset; + viewport_width = item_viewport_width; } icon = get_item_icon (self, menu_index); if (icon != 0) grub_video_blit_bitmap (icon, GRUB_VIDEO_BLIT_BLEND, - sel_leftpad, - item_top + (item_height - self->icon_height) / 2, + max_leftpad, + item_top + icon_top_offset, 0, 0, self->icon_width, self->icon_height); const char *item_title = grub_menu_get_entry (self->view->menu, menu_index)->title; - grub_font_t font = - (is_selected && self->selected_item_font - ? self->selected_item_font - : self->item_font); - grub_video_rgba_color_t text_color = - ((is_selected && self->selected_item_color_set) - ? self->selected_item_color - : self->item_color); + + sviewport.y = item_top + top_pad; + sviewport.width = viewport_width; + grub_gui_set_viewport (&sviewport, &svpsave); grub_font_draw_string (item_title, font, - grub_video_map_rgba_color (text_color), - sel_leftpad + self->icon_width + icon_text_space, - (item_top + (item_height - (ascent + descent)) - / 2 + ascent)); + color, + 0, + text_top_offset); + grub_gui_restore_viewport (&svpsave); - item_top += item_height + item_vspace; + item_top += text_box_height + item_vspace; } grub_video_set_viewport (oviewport.x, oviewport.y, @@ -302,7 +464,7 @@ list_paint (void *vself, const grub_video_rect_t *region) check_boxes (self); - if (! self->menu_box || ! self->selected_item_box) + if (! self->menu_box || ! self->selected_item_box || ! self->item_box) return; grub_gui_set_viewport (&self->bounds, &vpsave); @@ -317,6 +479,7 @@ list_paint (void *vself, const grub_video_rect_t *region) int drawing_scrollbar = (self->draw_scrollbar && (num_shown_items < self->view->menu->size) && check_scrollbar (self)); + int scrollbar_width = self->scrollbar_width; content_rect.x = box_left_pad; content_rect.y = box_top_pad; @@ -327,18 +490,65 @@ list_paint (void *vself, const grub_video_rect_t *region) box->draw (box, 0, 0); + switch (self->scrollbar_slice) + { + case SCROLLBAR_SLICE_WEST: + content_rect.x += self->scrollbar_right_pad; + content_rect.width -= self->scrollbar_right_pad; + break; + case SCROLLBAR_SLICE_CENTER: + if (drawing_scrollbar) + content_rect.width -= scrollbar_width + self->scrollbar_left_pad + + self->scrollbar_right_pad; + break; + case SCROLLBAR_SLICE_EAST: + content_rect.width -= self->scrollbar_left_pad; + break; + } + grub_gui_set_viewport (&content_rect, &vpsave2); draw_menu (self, num_shown_items); grub_gui_restore_viewport (&vpsave2); if (drawing_scrollbar) - draw_scrollbar (self, - self->first_shown_index, num_shown_items, - 0, self->view->menu->size, - self->bounds.width - box_right_pad - + self->scrollbar_width, - box_top_pad, - self->bounds.height - box_top_pad - box_bottom_pad); + { + content_rect.y += self->scrollbar_top_pad; + content_rect.height -= self->scrollbar_top_pad + + self->scrollbar_bottom_pad; + content_rect.width = scrollbar_width; + switch (self->scrollbar_slice) + { + case SCROLLBAR_SLICE_WEST: + if (box_left_pad > scrollbar_width) + { + content_rect.x = box_left_pad - scrollbar_width; + content_rect.width = scrollbar_width; + } + else + { + content_rect.x = 0; + content_rect.width = box_left_pad; + } + break; + case SCROLLBAR_SLICE_CENTER: + content_rect.x = self->bounds.width - box_right_pad + - scrollbar_width - self->scrollbar_right_pad; + content_rect.width = scrollbar_width; + break; + case SCROLLBAR_SLICE_EAST: + content_rect.x = self->bounds.width - box_right_pad; + content_rect.width = box_right_pad; + break; + } + + grub_gui_set_viewport (&content_rect, &vpsave2); + draw_scrollbar (self, + self->first_shown_index, num_shown_items, + 0, self->view->menu->size, + scrollbar_width, + content_rect.height); + grub_gui_restore_viewport (&vpsave2); + } } grub_gui_restore_viewport (&vpsave); @@ -392,21 +602,52 @@ list_get_minimal_size (void *vself, unsigned *width, unsigned *height) unsigned width_s; grub_gfxmenu_box_t selbox = self->selected_item_box; - int sel_toppad = selbox->get_top_pad (selbox); - + int sel_top_pad = selbox->get_top_pad (selbox); + int sel_bottom_pad = selbox->get_bottom_pad (selbox); + int sel_left_pad = selbox->get_left_pad (selbox); + int sel_right_pad = selbox->get_right_pad (selbox); + + grub_gfxmenu_box_t itembox = self->item_box; + int item_top_pad = itembox->get_top_pad (itembox); + int item_bottom_pad = itembox->get_bottom_pad (itembox); + int item_left_pad = itembox->get_left_pad (itembox); + int item_right_pad = itembox->get_right_pad (itembox); + + int max_left_pad = grub_max (item_left_pad, sel_left_pad); + int max_right_pad = grub_max (item_right_pad, sel_right_pad); + int max_top_pad = grub_max (item_top_pad, sel_top_pad); + int max_bottom_pad = grub_max (item_bottom_pad, sel_bottom_pad); + *width = grub_font_get_string_width (self->item_font, "Typical OS"); width_s = grub_font_get_string_width (self->selected_item_font, "Typical OS"); if (*width < width_s) *width = width_s; - *width += 2 * boxpad + box_left_pad + box_right_pad; + *width += 2 * boxpad + box_left_pad + box_right_pad + + max_left_pad + max_right_pad + + self->item_icon_space + self->icon_width; + + switch (self->scrollbar_slice) + { + case SCROLLBAR_SLICE_WEST: + *width += self->scrollbar_right_pad; + break; + case SCROLLBAR_SLICE_CENTER: + *width += self->scrollbar_width + self->scrollbar_left_pad + + self->scrollbar_right_pad; + break; + case SCROLLBAR_SLICE_EAST: + *width += self->scrollbar_left_pad; + break; + } /* Set the menu box height to fit the items. */ *height = (item_height * num_items + item_vspace * (num_items - 1) + 2 * boxpad - + box_top_pad + box_bottom_pad + sel_toppad); + + box_top_pad + box_bottom_pad + + max_top_pad + max_bottom_pad); } else { @@ -422,29 +663,48 @@ list_set_property (void *vself, const char *name, const char *value) if (grub_strcmp (name, "item_font") == 0) { self->item_font = grub_font_get (value); + if (self->selected_item_font_inherit) + self->selected_item_font = self->item_font; } else if (grub_strcmp (name, "selected_item_font") == 0) { if (! value || grub_strcmp (value, "inherit") == 0) - self->selected_item_font = 0; + { + self->selected_item_font = self->item_font; + self->selected_item_font_inherit = 1; + } else - self->selected_item_font = grub_font_get (value); + { + self->selected_item_font = grub_font_get (value); + self->selected_item_font_inherit = 0; + } } else if (grub_strcmp (name, "item_color") == 0) { - grub_video_parse_color (value, &self->item_color); + grub_video_rgba_color_t color; + if (grub_video_parse_color (value, &color) == GRUB_ERR_NONE) + { + self->item_color = color; + if (self->selected_item_color_inherit) + self->selected_item_color = self->item_color; + } } else if (grub_strcmp (name, "selected_item_color") == 0) { if (! value || grub_strcmp (value, "inherit") == 0) { - self->selected_item_color_set = 0; + self->selected_item_color = self->item_color; + self->selected_item_color_inherit = 1; } else { - if (grub_video_parse_color (value, &self->selected_item_color) + grub_video_rgba_color_t color; + if (grub_video_parse_color (value, &color) == GRUB_ERR_NONE) - self->selected_item_color_set = 1; + { + self->selected_item_color = color; + self->selected_item_color_inherit = 0; + } } } else if (grub_strcmp (name, "icon_width") == 0) @@ -487,11 +747,33 @@ list_set_property (void *vself, const char *name, const char *value) grub_free (self->menu_box_pattern); self->menu_box_pattern = value ? grub_strdup (value) : 0; } - else if (grub_strcmp (name, "selected_item_pixmap_style") == 0) + else if (grub_strcmp (name, "item_pixmap_style") == 0) { self->need_to_recreate_boxes = 1; - grub_free (self->selected_item_box_pattern); - self->selected_item_box_pattern = value ? grub_strdup (value) : 0; + grub_free (self->item_box_pattern); + self->item_box_pattern = value ? grub_strdup (value) : 0; + if (self->selected_item_box_pattern_inherit) + { + grub_free (self->selected_item_box_pattern); + self->selected_item_box_pattern = value ? grub_strdup (value) : 0; + } + } + else if (grub_strcmp (name, "selected_item_pixmap_style") == 0) + { + if (!value || grub_strcmp (value, "inherit") == 0) + { + grub_free (self->selected_item_box_pattern); + char *tmp = self->item_box_pattern; + self->selected_item_box_pattern = tmp ? grub_strdup (tmp) : 0; + self->selected_item_box_pattern_inherit = 1; + } + else + { + self->need_to_recreate_boxes = 1; + grub_free (self->selected_item_box_pattern); + self->selected_item_box_pattern = grub_strdup (value); + self->selected_item_box_pattern_inherit = 0; + } } else if (grub_strcmp (name, "scrollbar_frame") == 0) { @@ -505,10 +787,39 @@ list_set_property (void *vself, const char *name, const char *value) grub_free (self->scrollbar_thumb_pattern); self->scrollbar_thumb_pattern = value ? grub_strdup (value) : 0; } + else if (grub_strcmp (name, "scrollbar_thumb_overlay") == 0) + { + self->scrollbar_thumb_overlay = grub_strcmp (value, "true") == 0; + } else if (grub_strcmp (name, "scrollbar_width") == 0) { self->scrollbar_width = grub_strtol (value, 0, 10); } + else if (grub_strcmp (name, "scrollbar_slice") == 0) + { + if (grub_strcmp (value, "west") == 0) + self->scrollbar_slice = SCROLLBAR_SLICE_WEST; + else if (grub_strcmp (value, "center") == 0) + self->scrollbar_slice = SCROLLBAR_SLICE_CENTER; + else if (grub_strcmp (value, "east") == 0) + self->scrollbar_slice = SCROLLBAR_SLICE_EAST; + } + else if (grub_strcmp (name, "scrollbar_left_pad") == 0) + { + self->scrollbar_left_pad = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "scrollbar_right_pad") == 0) + { + self->scrollbar_right_pad = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "scrollbar_top_pad") == 0) + { + self->scrollbar_top_pad = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "scrollbar_bottom_pad") == 0) + { + self->scrollbar_bottom_pad = grub_strtol (value, 0, 10); + } else if (grub_strcmp (name, "scrollbar") == 0) { self->draw_scrollbar = grub_strcmp (value, "false") != 0; @@ -541,6 +852,16 @@ list_set_view_info (void *vself, self->view = view; } +/* Refresh list variables */ +static void +list_refresh_info (void *vself, + grub_gfxmenu_view_t view) +{ + list_impl_t self = vself; + if (view->nested) + self->first_shown_index = 0; +} + static struct grub_gui_component_ops list_comp_ops = { .destroy = list_destroy, @@ -557,7 +878,8 @@ static struct grub_gui_component_ops list_comp_ops = static struct grub_gui_list_ops list_ops = { - .set_view_info = list_set_view_info + .set_view_info = list_set_view_info, + .refresh_list = list_refresh_info }; grub_gui_component_t @@ -586,9 +908,10 @@ grub_gui_list_new (void) self->item_icon_space = 4; self->item_spacing = 16; self->item_font = default_font; - self->selected_item_font = 0; /* Default to using the item_font. */ + self->selected_item_font_inherit = 1; /* Default to using the item_font. */ + self->selected_item_font = default_font; self->item_color = default_fg_color; - self->selected_item_color_set = 0; /* Default to using the item_color. */ + self->selected_item_color_inherit = 1; /* Default to using the item_color. */ self->selected_item_color = default_fg_color; self->draw_scrollbar = 1; @@ -597,15 +920,24 @@ grub_gui_list_new (void) self->scrollbar_thumb = 0; self->scrollbar_frame_pattern = 0; self->scrollbar_thumb_pattern = 0; + self->scrollbar_thumb_overlay = 0; self->scrollbar_width = 16; + self->scrollbar_slice = SCROLLBAR_SLICE_EAST; + self->scrollbar_left_pad = 2; + self->scrollbar_right_pad = 0; + self->scrollbar_top_pad = 0; + self->scrollbar_bottom_pad = 0; self->first_shown_index = 0; self->need_to_recreate_boxes = 0; self->theme_dir = 0; self->menu_box_pattern = 0; + self->item_box_pattern = 0; + self->selected_item_box_pattern_inherit = 1;/*Default to using the item_box.*/ self->selected_item_box_pattern = 0; self->menu_box = grub_gfxmenu_create_box (0, 0); + self->item_box = grub_gfxmenu_create_box (0, 0); self->selected_item_box = grub_gfxmenu_create_box (0, 0); self->icon_manager = grub_gfxmenu_icon_manager_new (); diff --git a/grub-core/gfxmenu/gui_progress_bar.c b/grub-core/gfxmenu/gui_progress_bar.c index 7b005f400..c4cd1859b 100644 --- a/grub-core/gfxmenu/gui_progress_bar.c +++ b/grub-core/gfxmenu/gui_progress_bar.c @@ -25,6 +25,7 @@ #include #include #include +#include struct grub_gui_progress_bar { @@ -51,6 +52,7 @@ struct grub_gui_progress_bar char *highlight_pattern; grub_gfxmenu_box_t bar_box; grub_gfxmenu_box_t highlight_box; + int highlight_overlay; }; typedef struct grub_gui_progress_bar *grub_gui_progress_bar_t; @@ -59,6 +61,9 @@ static void progress_bar_destroy (void *vself) { grub_gui_progress_bar_t self = vself; + grub_free (self->theme_dir); + grub_free (self->template); + grub_free (self->id); grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self); grub_free (self); } @@ -113,9 +118,15 @@ draw_filled_rect_bar (grub_gui_progress_bar_t self) f.width + 2, f.height + 2); /* Bar background. */ - int barwidth = (f.width - * (self->value - self->start) - / (self->end - self->start)); + unsigned barwidth; + + if (self->end <= self->start + || self->value <= self->start) + barwidth = 0; + else + barwidth = (f.width + * (self->value - self->start) + / (self->end - self->start)); grub_video_fill_rect (grub_video_map_rgba_color (self->bg_color), f.x + barwidth, f.y, f.width - barwidth, f.height); @@ -139,21 +150,47 @@ draw_pixmap_bar (grub_gui_progress_bar_t self) int bar_b_pad = bar->get_bottom_pad (bar); int bar_h_pad = bar_l_pad + bar_r_pad; int bar_v_pad = bar_t_pad + bar_b_pad; + int hl_l_pad = hl->get_left_pad (hl); + int hl_r_pad = hl->get_right_pad (hl); + int hl_t_pad = hl->get_top_pad (hl); + int hl_b_pad = hl->get_bottom_pad (hl); + int hl_h_pad = hl_l_pad + hl_r_pad; + int hl_v_pad = hl_t_pad + hl_b_pad; int tracklen = w - bar_h_pad; int trackheight = h - bar_v_pad; int barwidth; + int hlheight = trackheight; + int hlx = bar_l_pad; + int hly = bar_t_pad; bar->set_content_size (bar, tracklen, trackheight); - - barwidth = (tracklen * (self->value - self->start) - / (self->end - self->start)); - - hl->set_content_size (hl, barwidth, h - bar_v_pad); - bar->draw (bar, 0, 0); - hl->draw (hl, bar_l_pad, bar_t_pad); + + if (self->highlight_overlay) + { + tracklen += hl_h_pad; + hlx -= hl_l_pad; + hly -= hl_t_pad; + } + else + hlheight -= hl_v_pad; + + if (self->value <= self->start + || self->end <= self->start) + barwidth = 0; + else + barwidth = ((unsigned) (tracklen * (self->value - self->start)) + / ((unsigned) (self->end - self->start))); + + if (barwidth >= hl_h_pad) + { + hl->set_content_size (hl, barwidth - hl_h_pad, hlheight); + hl->draw (hl, hlx, hly); + } } +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + static void draw_text (grub_gui_progress_bar_t self) { @@ -179,9 +216,12 @@ draw_text (grub_gui_progress_bar_t self) int y = ((height - grub_font_get_descent (font)) / 2 + grub_font_get_ascent (font) / 2); grub_font_draw_string (text, font, text_color, x, y); + grub_free (text); } } +#pragma GCC diagnostic error "-Wformat-nonliteral" + static void progress_bar_paint (void *vself, const grub_video_rect_t *region) { @@ -240,29 +280,47 @@ static void progress_bar_get_minimal_size (void *vself, unsigned *width, unsigned *height) { - unsigned text_width = 0, text_height = 0; + unsigned min_width = 0; + unsigned min_height = 0; grub_gui_progress_bar_t self = vself; if (self->template) { - text_width = grub_font_get_string_width (self->font, self->template); - text_width += grub_font_get_string_width (self->font, "XXXXXXXXXX"); - text_height = grub_font_get_descent (self->font) - + grub_font_get_ascent (self->font); + min_width = grub_font_get_string_width (self->font, self->template); + min_width += grub_font_get_string_width (self->font, "XXXXXXXXXX"); + min_height = grub_font_get_descent (self->font) + + grub_font_get_ascent (self->font); + } + if (check_pixmaps (self)) + { + grub_gfxmenu_box_t bar = self->bar_box; + grub_gfxmenu_box_t hl = self->highlight_box; + min_width += bar->get_left_pad (bar) + bar->get_right_pad (bar); + min_height += bar->get_top_pad (bar) + bar->get_bottom_pad (bar); + if (!self->highlight_overlay) + { + min_width += hl->get_left_pad (hl) + hl->get_right_pad (hl); + min_height += hl->get_top_pad (hl) + hl->get_bottom_pad (hl); + } + } + else + { + min_height += 2; + min_width += 2; } *width = 200; - if (*width < text_width) - *width = text_width; + if (*width < min_width) + *width = min_width; *height = 28; - if (*height < text_height) - *height = text_height; + if (*height < min_height) + *height = min_height; } static void progress_bar_set_state (void *vself, int visible, int start, int current, int end) { - grub_gui_progress_bar_t self = vself; + grub_gui_progress_bar_t self = vself; self->visible = visible; self->start = start; self->value = current; @@ -277,7 +335,7 @@ progress_bar_set_property (void *vself, const char *name, const char *value) { grub_free (self->template); if (grub_strcmp (value, "@TIMEOUT_NOTIFICATION_LONG@") == 0) - value + value = _("The highlighted entry will be executed automatically in %ds."); else if (grub_strcmp (value, "@TIMEOUT_NOTIFICATION_MIDDLE@") == 0) /* TRANSLATORS: 's' stands for seconds. @@ -290,6 +348,9 @@ progress_bar_set_property (void *vself, const char *name, const char *value) Please use the shortest form available in you language. */ value = _("%ds"); + if (grub_printf_fmt_check(value, "%d") != GRUB_ERR_NONE) + value = ""; /* Unsupported format. */ + self->template = grub_strdup (value); } else if (grub_strcmp (name, "font") == 0) @@ -326,6 +387,10 @@ progress_bar_set_property (void *vself, const char *name, const char *value) grub_free (self->highlight_pattern); self->highlight_pattern = value ? grub_strdup (value) : 0; } + else if (grub_strcmp (name, "highlight_overlay") == 0) + { + self->highlight_overlay = grub_strcmp (value, "true") == 0; + } else if (grub_strcmp (name, "theme_dir") == 0) { self->need_to_recreate_pixmaps = 1; @@ -386,6 +451,7 @@ grub_gui_progress_bar_new (void) self->border_color = black; self->bg_color = gray; self->fg_color = lightgray; + self->highlight_overlay = 0; return (grub_gui_component_t) self; } diff --git a/grub-core/gfxmenu/gui_string_util.c b/grub-core/gfxmenu/gui_string_util.c index a9a415e31..ba1e1eab3 100644 --- a/grub-core/gfxmenu/gui_string_util.c +++ b/grub-core/gfxmenu/gui_string_util.c @@ -55,7 +55,7 @@ canonicalize_path (const char *path) if (*p == '/') components++; - char **path_array = grub_malloc (components * sizeof (*path_array)); + char **path_array = grub_calloc (components, sizeof (*path_array)); if (! path_array) return 0; diff --git a/grub-core/gfxmenu/icon_manager.c b/grub-core/gfxmenu/icon_manager.c index 45e8f7dea..1894682ef 100644 --- a/grub-core/gfxmenu/icon_manager.c +++ b/grub-core/gfxmenu/icon_manager.c @@ -106,8 +106,10 @@ grub_gfxmenu_icon_manager_set_theme_path (grub_gfxmenu_icon_manager_t mgr, const char *path) { /* Clear the cache if the theme path has changed. */ - if (((mgr->theme_path == 0) != (path == 0)) - || (grub_strcmp (mgr->theme_path, path) != 0)) + if (mgr->theme_path == 0 && path == 0) + return; + if (mgr->theme_path == 0 || path == 0 + || grub_strcmp (mgr->theme_path, path) != 0) grub_gfxmenu_icon_manager_clear_cache (mgr); grub_free (mgr->theme_path); @@ -137,23 +139,19 @@ static struct grub_video_bitmap * try_loading_icon (grub_gfxmenu_icon_manager_t mgr, const char *dir, const char *class_name) { - char *path; - int l; + char *path, *ptr; path = grub_malloc (grub_strlen (dir) + grub_strlen (class_name) + grub_strlen (icon_extension) + 3); if (! path) return 0; - grub_strcpy (path, dir); - l = grub_strlen (path); - if (path[l-1] != '/') - { - path[l] = '/'; - path[l+1] = 0; - } - grub_strcat (path, class_name); - grub_strcat (path, icon_extension); + ptr = grub_stpcpy (path, dir); + if (path == ptr || ptr[-1] != '/') + *ptr++ = '/'; + ptr = grub_stpcpy (ptr, class_name); + ptr = grub_stpcpy (ptr, icon_extension); + *ptr = '\0'; struct grub_video_bitmap *raw_bitmap; grub_video_bitmap_load (&raw_bitmap, path); diff --git a/grub-core/gfxmenu/theme_loader.c b/grub-core/gfxmenu/theme_loader.c index f9c711d3e..9eabf501a 100644 --- a/grub-core/gfxmenu/theme_loader.c +++ b/grub-core/gfxmenu/theme_loader.c @@ -30,6 +30,10 @@ #include #include #include +#include + +static grub_err_t +parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop); /* Construct a new box widget using ABSPATTERN to find the pixmap files for it, storing the new box instance at *BOXPTR. @@ -112,6 +116,24 @@ grub_gui_recreate_box (grub_gfxmenu_box_t *boxptr, return grub_errno; } +static grub_err_t +theme_get_unsigned_int_from_proportional (const char *value, + unsigned absolute_value, + unsigned int *parsed_value) +{ + grub_err_t err; + grub_fixed_signed_t frac; + signed pixels; + err = parse_proportional_spec (value, &pixels, &frac); + if (err != GRUB_ERR_NONE) + return err; + int result = grub_fixed_sfs_multiply (absolute_value, frac) + pixels; + if (result < 0) + result = 0; + *parsed_value = result; + return GRUB_ERR_NONE; +} + /* Set the specified property NAME on the view to the given string VALUE. The caller is responsible for the lifetimes of NAME and VALUE. */ static grub_err_t @@ -143,7 +165,6 @@ theme_set_string (grub_gfxmenu_view_t view, else if (! grub_strcmp ("desktop-image", name)) { struct grub_video_bitmap *raw_bitmap; - struct grub_video_bitmap *scaled_bitmap; char *path; path = grub_resolve_relative_path (theme_dir, value); if (! path) @@ -154,20 +175,56 @@ theme_set_string (grub_gfxmenu_view_t view, return grub_errno; } grub_free(path); - grub_video_bitmap_create_scaled (&scaled_bitmap, - view->screen.width, - view->screen.height, - raw_bitmap, - GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); - grub_video_bitmap_destroy (raw_bitmap); - if (! scaled_bitmap) - { - grub_error_push (); - return grub_error (grub_errno, "error scaling desktop image"); - } - - grub_video_bitmap_destroy (view->desktop_image); - view->desktop_image = scaled_bitmap; + grub_video_bitmap_destroy (view->raw_desktop_image); + view->raw_desktop_image = raw_bitmap; + } + else if (! grub_strcmp ("desktop-image-scale-method", name)) + { + if (! value || ! grub_strcmp ("stretch", value)) + view->desktop_image_scale_method = + GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH; + else if (! grub_strcmp ("crop", value)) + view->desktop_image_scale_method = + GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP; + else if (! grub_strcmp ("padding", value)) + view->desktop_image_scale_method = + GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING; + else if (! grub_strcmp ("fitwidth", value)) + view->desktop_image_scale_method = + GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH; + else if (! grub_strcmp ("fitheight", value)) + view->desktop_image_scale_method = + GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT; + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unsupported scale method: %s", + value); + } + else if (! grub_strcmp ("desktop-image-h-align", name)) + { + if (! grub_strcmp ("left", value)) + view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_LEFT; + else if (! grub_strcmp ("center", value)) + view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER; + else if (! grub_strcmp ("right", value)) + view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_RIGHT; + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unsupported horizontal align method: %s", + value); + } + else if (! grub_strcmp ("desktop-image-v-align", name)) + { + if (! grub_strcmp ("top", value)) + view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_TOP; + else if (! grub_strcmp ("center", value)) + view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER; + else if (! grub_strcmp ("bottom", value)) + view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_BOTTOM; + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unsupported vertical align method: %s", + value); } else if (! grub_strcmp ("desktop-color", name)) grub_video_parse_color (value, &view->desktop_color); @@ -178,6 +235,52 @@ theme_set_string (grub_gfxmenu_view_t view, if (err != GRUB_ERR_NONE) return err; } + else if (! grub_strcmp ("terminal-border", name)) + { + view->terminal_border = grub_strtoul (value, 0, 10); + if (grub_errno) + return grub_errno; + } + else if (! grub_strcmp ("terminal-left", name)) + { + unsigned int tmp; + int err = theme_get_unsigned_int_from_proportional (value, + view->screen.width, + &tmp); + if (err != GRUB_ERR_NONE) + return err; + view->terminal_rect.x = tmp; + } + else if (! grub_strcmp ("terminal-top", name)) + { + unsigned int tmp; + int err = theme_get_unsigned_int_from_proportional (value, + view->screen.height, + &tmp); + if (err != GRUB_ERR_NONE) + return err; + view->terminal_rect.y = tmp; + } + else if (! grub_strcmp ("terminal-width", name)) + { + unsigned int tmp; + int err = theme_get_unsigned_int_from_proportional (value, + view->screen.width, + &tmp); + if (err != GRUB_ERR_NONE) + return err; + view->terminal_rect.width = tmp; + } + else if (! grub_strcmp ("terminal-height", name)) + { + unsigned int tmp; + int err = theme_get_unsigned_int_from_proportional (value, + view->screen.height, + &tmp); + if (err != GRUB_ERR_NONE) + return err; + view->terminal_rect.height = tmp; + } else if (! grub_strcmp ("title-text", name)) { grub_free (view->title_text); @@ -316,7 +419,7 @@ read_expression (struct parsebuf *p) skip_whitespace (p); if (peek_char (p) == '"') { - /* Read as a quoted string. + /* Read as a quoted string. The quotation marks are not included in the expression value. */ /* Skip opening quotation mark. */ read_char (p); @@ -362,10 +465,10 @@ read_expression (struct parsebuf *p) } static grub_err_t -parse_proportional_spec (char *value, signed *abs, grub_fixed_signed_t *prop) +parse_proportional_spec (const char *value, signed *abs, grub_fixed_signed_t *prop) { signed num; - char *ptr; + const char *ptr; int sig = 0; *abs = 0; *prop = 0; @@ -640,7 +743,7 @@ grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path) p.view = view; p.theme_dir = grub_get_dirname (theme_path); - file = grub_file_open (theme_path); + file = grub_file_open (theme_path, GRUB_FILE_TYPE_THEME); if (! file) { grub_free (p.theme_dir); @@ -671,6 +774,8 @@ grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path) view->canvas->component.ops->destroy (view->canvas); view->canvas = grub_gui_canvas_new (); + if (!view->canvas) + goto fail; ((grub_gui_component_t) view->canvas) ->ops->set_bounds ((grub_gui_component_t) view->canvas, &view->screen); diff --git a/grub-core/gfxmenu/view.c b/grub-core/gfxmenu/view.c index 9023fd3c4..e02eba8b0 100644 --- a/grub-core/gfxmenu/view.c +++ b/grub-core/gfxmenu/view.c @@ -40,7 +40,8 @@ static void init_terminal (grub_gfxmenu_view_t view); -static grub_video_rect_t term_rect; +static void +init_background (grub_gfxmenu_view_t view); static grub_gfxmenu_view_t term_view; /* Create a new view object, loading the theme specified by THEME_PATH and @@ -58,11 +59,28 @@ grub_gfxmenu_view_new (const char *theme_path, if (! view) return 0; + while (grub_gfxmenu_timeout_notifications) + { + struct grub_gfxmenu_timeout_notify *p; + p = grub_gfxmenu_timeout_notifications; + grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next; + grub_free (p); + } + view->screen.x = 0; view->screen.y = 0; view->screen.width = width; view->screen.height = height; + view->need_to_check_sanity = 1; + view->terminal_border = 3; + view->terminal_rect.width = view->screen.width * 7 / 10; + view->terminal_rect.height = view->screen.height * 7 / 10; + view->terminal_rect.x = view->screen.x + (view->screen.width + - view->terminal_rect.width) / 2; + view->terminal_rect.y = view->screen.y + (view->screen.height + - view->terminal_rect.height) / 2; + default_font = grub_font_get ("Unknown Regular 16"); default_fg_color = grub_video_rgba_color_rgb (0, 0, 0); default_bg_color = grub_video_rgba_color_rgb (255, 255, 255); @@ -75,7 +93,11 @@ grub_gfxmenu_view_new (const char *theme_path, view->title_color = default_fg_color; view->message_color = default_bg_color; view->message_bg_color = default_fg_color; - view->desktop_image = 0; + view->raw_desktop_image = 0; + view->scaled_desktop_image = 0; + view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH; + view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER; + view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER; view->desktop_color = default_bg_color; view->terminal_box = grub_gfxmenu_create_box (0, 0); view->title_text = grub_strdup (_("GRUB Boot Menu")); @@ -105,7 +127,15 @@ grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view) { if (!view) return; - grub_video_bitmap_destroy (view->desktop_image); + while (grub_gfxmenu_timeout_notifications) + { + struct grub_gfxmenu_timeout_notify *p; + p = grub_gfxmenu_timeout_notifications; + grub_gfxmenu_timeout_notifications = grub_gfxmenu_timeout_notifications->next; + grub_free (p); + } + grub_video_bitmap_destroy (view->raw_desktop_image); + grub_video_bitmap_destroy (view->scaled_desktop_image); if (view->terminal_box) view->terminal_box->destroy (view->terminal_box); grub_free (view->terminal_font_name); @@ -121,9 +151,9 @@ static void redraw_background (grub_gfxmenu_view_t view, const grub_video_rect_t *bounds) { - if (view->desktop_image) + if (view->scaled_desktop_image) { - struct grub_video_bitmap *img = view->desktop_image; + struct grub_video_bitmap *img = view->scaled_desktop_image; grub_video_blit_bitmap (img, GRUB_VIDEO_BLIT_REPLACE, bounds->x, bounds->y, bounds->x - view->screen.x, @@ -183,11 +213,12 @@ redraw_timeouts (struct grub_gfxmenu_view *view) { grub_video_rect_t bounds; cur->self->ops->get_bounds (cur->self, &bounds); + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); grub_gfxmenu_view_redraw (view, &bounds); } } -void +void grub_gfxmenu_print_timeout (int timeout, void *data) { struct grub_gfxmenu_view *view = data; @@ -195,14 +226,14 @@ grub_gfxmenu_print_timeout (int timeout, void *data) if (view->first_timeout == -1) view->first_timeout = timeout; - update_timeouts (1, -(view->first_timeout + 1), -timeout, 0); + update_timeouts (1, -view->first_timeout, -timeout, 0); redraw_timeouts (view); grub_video_swap_buffers (); if (view->double_repaint) redraw_timeouts (view); } -void +void grub_gfxmenu_clear_timeout (void *data) { struct grub_gfxmenu_view *view = data; @@ -236,6 +267,27 @@ update_menu_components (grub_gfxmenu_view_t view) update_menu_visit, view); } +static void +refresh_menu_visit (grub_gui_component_t component, + void *userdata) +{ + grub_gfxmenu_view_t view; + view = userdata; + if (component->ops->is_instance (component, "list")) + { + grub_gui_list_t list = (grub_gui_list_t) component; + list->ops->refresh_list (list, view); + } +} + +/* Refresh list information (useful for submenus) */ +static void +refresh_menu_components (grub_gfxmenu_view_t view) +{ + grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas, + refresh_menu_visit, view); +} + static void draw_message (grub_gfxmenu_view_t view) { @@ -266,10 +318,15 @@ void grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, const grub_video_rect_t *region) { - if (grub_video_have_common_points (&term_rect, region)) + if (grub_video_have_common_points (&view->terminal_rect, region)) grub_gfxterm_schedule_repaint (); grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + grub_video_area_status_t area_status; + grub_video_get_area_status (&area_status); + if (area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_region (region->x, region->y, + region->width, region->height); redraw_background (view, region); if (view->canvas) @@ -277,6 +334,9 @@ grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, draw_title (view); if (grub_video_have_common_points (&view->progress_message_frame, region)) draw_message (view); + + if (area_status == GRUB_VIDEO_AREA_ENABLED) + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); } void @@ -284,6 +344,8 @@ grub_gfxmenu_view_draw (grub_gfxmenu_view_t view) { init_terminal (view); + init_background (view); + /* Clear the screen; there may be garbage left over in video memory. */ grub_video_fill_rect (grub_video_map_rgb (0, 0, 0), view->screen.x, view->screen.y, @@ -294,12 +356,18 @@ grub_gfxmenu_view_draw (grub_gfxmenu_view_t view) view->screen.x, view->screen.y, view->screen.width, view->screen.height); + refresh_menu_components (view); update_menu_components (view); + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); grub_gfxmenu_view_redraw (view, &view->screen); grub_video_swap_buffers (); if (view->double_repaint) - grub_gfxmenu_view_redraw (view, &view->screen); + { + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); + grub_gfxmenu_view_redraw (view, &view->screen); + } + } static void @@ -313,6 +381,7 @@ redraw_menu_visit (grub_gui_component_t component, grub_video_rect_t bounds; component->ops->get_bounds (component, &bounds); + grub_video_set_area_status (GRUB_VIDEO_AREA_ENABLED); grub_gfxmenu_view_redraw (view, &bounds); } } @@ -332,7 +401,7 @@ grub_gfxmenu_redraw_menu (grub_gfxmenu_view_t view) } } -void +void grub_gfxmenu_set_chosen_entry (int entry, void *data) { grub_gfxmenu_view_t view = data; @@ -349,36 +418,175 @@ grub_gfxmenu_draw_terminal_box (void) term_box = term_view->terminal_box; if (!term_box) return; - - term_box->set_content_size (term_box, term_rect.width, - term_rect.height); - + + grub_video_set_area_status (GRUB_VIDEO_AREA_DISABLED); + + term_box->set_content_size (term_box, term_view->terminal_rect.width, + term_view->terminal_rect.height); + term_box->draw (term_box, - term_rect.x - term_box->get_left_pad (term_box), - term_rect.y - term_box->get_top_pad (term_box)); + term_view->terminal_rect.x - term_box->get_left_pad (term_box), + term_view->terminal_rect.y - term_box->get_top_pad (term_box)); +} + +static void +get_min_terminal (grub_font_t terminal_font, + unsigned int border_width, + unsigned int *min_terminal_width, + unsigned int *min_terminal_height) +{ + struct grub_font_glyph *glyph; + glyph = grub_font_get_glyph (terminal_font, 'M'); + *min_terminal_width = (glyph? glyph->device_width : 8) * 80 + + 2 * border_width; + *min_terminal_height = grub_font_get_max_char_height (terminal_font) * 24 + + 2 * border_width; +} + +static void +terminal_sanity_check (grub_gfxmenu_view_t view) +{ + if (!view->need_to_check_sanity) + return; + + /* terminal_font was checked before in the init_terminal function. */ + grub_font_t terminal_font = grub_font_get (view->terminal_font_name); + + /* Non-negative numbers below. */ + int scr_x = view->screen.x; + int scr_y = view->screen.y; + int scr_width = view->screen.width; + int scr_height = view->screen.height; + int term_x = view->terminal_rect.x; + int term_y = view->terminal_rect.y; + int term_width = view->terminal_rect.width; + int term_height = view->terminal_rect.height; + + /* Check that border_width isn't too big. */ + unsigned int border_width = view->terminal_border; + unsigned int min_terminal_width; + unsigned int min_terminal_height; + get_min_terminal (terminal_font, border_width, + &min_terminal_width, &min_terminal_height); + if (border_width > 3 && ((int) min_terminal_width >= scr_width + || (int) min_terminal_height >= scr_height)) + { + border_width = 3; + get_min_terminal (terminal_font, border_width, + &min_terminal_width, &min_terminal_height); + } + + /* Sanity checks. */ + if (term_width > scr_width) + term_width = scr_width; + if (term_height > scr_height) + term_height = scr_height; + + if (scr_width <= (int) min_terminal_width + || scr_height <= (int) min_terminal_height) + { + /* The screen resulution is too low. Use all space, except a small border + to show the user, that it is a window. Then center the window. */ + term_width = scr_width - 6 * border_width; + term_height = scr_height - 6 * border_width; + term_x = scr_x + (scr_width - term_width) / 2; + term_y = scr_y + (scr_height - term_height) / 2; + } + else if (term_width < (int) min_terminal_width + || term_height < (int) min_terminal_height) + { + /* The screen resolution is big enough. Make sure, that terminal screen + dimensions aren't less than minimal values. Then center the window. */ + term_width = (int) min_terminal_width; + term_height = (int) min_terminal_height; + term_x = scr_x + (scr_width - term_width) / 2; + term_y = scr_y + (scr_height - term_height) / 2; + } + + /* At this point w and h are satisfying. */ + if (term_x + term_width > scr_width) + term_x = scr_width - term_width; + if (term_y + term_height > scr_height) + term_y = scr_height - term_height; + + /* Write down corrected data. */ + view->terminal_rect.x = (unsigned int) term_x; + view->terminal_rect.y = (unsigned int) term_y; + view->terminal_rect.width = (unsigned int) term_width; + view->terminal_rect.height = (unsigned int) term_height; + view->terminal_border = border_width; + + view->need_to_check_sanity = 0; } static void init_terminal (grub_gfxmenu_view_t view) { - term_rect.width = view->screen.width * 7 / 10; - term_rect.height = view->screen.height * 7 / 10; + grub_font_t terminal_font; - term_rect.x = view->screen.x + view->screen.width * (10 - 7) / 10 / 2; - term_rect.y = view->screen.y + view->screen.height * (10 - 7) / 10 / 2; + terminal_font = grub_font_get (view->terminal_font_name); + if (!terminal_font) + { + grub_error (GRUB_ERR_BAD_FONT, "no font loaded"); + return; + } + + /* Check that terminal window size and position are sane. */ + terminal_sanity_check (view); term_view = view; /* Note: currently there is no API for changing the gfxterm font on the fly, so whatever font the initially loaded theme specifies will be permanent. */ - grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY, term_rect.x, - term_rect.y, - term_rect.width, term_rect.height, - view->double_repaint, view->terminal_font_name, 3); + grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY, + view->terminal_rect.x, + view->terminal_rect.y, + view->terminal_rect.width, + view->terminal_rect.height, + view->double_repaint, + terminal_font, + view->terminal_border); grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box; } +static void +init_background (grub_gfxmenu_view_t view) +{ + struct grub_video_bitmap *scaled_bitmap; + + /* + * You don't have to scale a raw image if it's not present. This prevents + * setting grub_errno and disrupting a command execution. + */ + if (view->raw_desktop_image == NULL) + return; + + if (view->scaled_desktop_image) + return; + + if (view->desktop_image_scale_method == + GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH) + grub_video_bitmap_create_scaled (&scaled_bitmap, + view->screen.width, + view->screen.height, + view->raw_desktop_image, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + else + grub_video_bitmap_scale_proportional (&scaled_bitmap, + view->screen.width, + view->screen.height, + view->raw_desktop_image, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST, + view->desktop_image_scale_method, + view->desktop_image_v_align, + view->desktop_image_h_align); + if (! scaled_bitmap) + return; + view->scaled_desktop_image = scaled_bitmap; + +} + /* FIXME: previously notifications were displayed in special case. Is it necessary? */ diff --git a/grub-core/gfxmenu/widget-box.c b/grub-core/gfxmenu/widget-box.c index 18e2ef469..470597ded 100644 --- a/grub-core/gfxmenu/widget-box.c +++ b/grub-core/gfxmenu/widget-box.c @@ -80,9 +80,25 @@ draw (grub_gfxmenu_box_t self, int x, int y) { int height_n; int width_w; + int tmp; - height_n = get_height (self->scaled_pixmaps[BOX_PIXMAP_N]); - width_w = get_width (self->scaled_pixmaps[BOX_PIXMAP_W]); + /* Count maximum height of NW, N, NE. */ + height_n = get_height (self->scaled_pixmaps[BOX_PIXMAP_NW]); + tmp = get_height (self->scaled_pixmaps[BOX_PIXMAP_N]); + if (tmp > height_n) + height_n = tmp; + tmp = get_height (self->scaled_pixmaps[BOX_PIXMAP_NE]); + if (tmp > height_n) + height_n = tmp; + + /* Count maximum width of NW, W, SW. */ + width_w = get_width (self->scaled_pixmaps[BOX_PIXMAP_NW]); + tmp = get_width (self->scaled_pixmaps[BOX_PIXMAP_W]); + if (tmp > width_w) + width_w = tmp; + tmp = get_width (self->scaled_pixmaps[BOX_PIXMAP_SW]); + if (tmp > width_w) + width_w = tmp; /* Draw sides. */ blit (self, BOX_PIXMAP_N, x + width_w, y); @@ -287,10 +303,10 @@ grub_gfxmenu_create_box (const char *pixmaps_prefix, box->content_height = 0; box->raw_pixmaps = (struct grub_video_bitmap **) - grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *)); + grub_calloc (BOX_NUM_PIXMAPS, sizeof (struct grub_video_bitmap *)); box->scaled_pixmaps = (struct grub_video_bitmap **) - grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *)); + grub_calloc (BOX_NUM_PIXMAPS, sizeof (struct grub_video_bitmap *)); /* Initialize all pixmap pointers to NULL so that proper destruction can be performed if an error is encountered partway through construction. */ diff --git a/grub-core/gmodule.pl.in b/grub-core/gmodule.pl.in deleted file mode 100644 index 6739a6f1c..000000000 --- a/grub-core/gmodule.pl.in +++ /dev/null @@ -1,30 +0,0 @@ -### -### Generate GDB commands, that load symbols for specified module, -### with proper section relocations. See .gdbinit -### -### $Id: gmodule.pl,v 1.2 2006/05/14 11:38:42 lkundrak Exp lkundrak $ -### Lubomir Kundrak -### - -use strict; - -while (<>) { - my ($name, %sections) = split; - - print "add-symbol-file $name.module"; - - open (READELF, "readelf -S $name.mod |") or die; - while () { - /\[\s*(\d+)\]\s+(\.\S+)/ or next; - - if ($2 eq '.text') { - print " $sections{$1}"; - next; - } - - print " -s $2 $sections{$1}" - if ($sections{$1} ne '0x0'); - }; - close (READELF); - print "\n"; -} diff --git a/grub-core/gnulib/Makefile.am b/grub-core/gnulib/Makefile.am deleted file mode 100644 index fb1525f00..000000000 --- a/grub-core/gnulib/Makefile.am +++ /dev/null @@ -1,1359 +0,0 @@ -## DO NOT EDIT! GENERATED AUTOMATICALLY! -## Process this file with automake to produce Makefile.in. -# Copyright (C) 2002-2010 Free Software Foundation, Inc. -# -# This file is free software, distributed under the terms of the GNU -# General Public License. As a special exception to the GNU General -# Public License, this file may be distributed as part of a program -# that contains a configuration script generated by Autoconf, under -# the same distribution terms as the rest of that program. -# -# Generated by gnulib-tool. -# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=grub-core/gnulib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --no-libtool --macro-prefix=gl --no-vc-files argp error fnmatch getdelim getline gettext progname regex - -AUTOMAKE_OPTIONS = 1.5 gnits - -SUBDIRS = -noinst_HEADERS = -noinst_LIBRARIES = -noinst_LTLIBRARIES = -EXTRA_DIST = -BUILT_SOURCES = -SUFFIXES = -MOSTLYCLEANFILES = core *.stackdump -MOSTLYCLEANDIRS = -CLEANFILES = -DISTCLEANFILES = -MAINTAINERCLEANFILES = - -AM_CPPFLAGS = -AM_CFLAGS = - -noinst_LIBRARIES += libgnu.a - -libgnu_a_SOURCES = -libgnu_a_LIBADD = $(gl_LIBOBJS) -libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) -EXTRA_libgnu_a_SOURCES = - -## begin gnulib module alloca - - -EXTRA_DIST += alloca.c - -EXTRA_libgnu_a_SOURCES += alloca.c - -libgnu_a_LIBADD += @ALLOCA@ -libgnu_a_DEPENDENCIES += @ALLOCA@ -## end gnulib module alloca - -## begin gnulib module alloca-opt - -BUILT_SOURCES += $(ALLOCA_H) - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -alloca.h: alloca.in.h - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - cat $(srcdir)/alloca.in.h; \ - } > $@-t && \ - mv -f $@-t $@ -MOSTLYCLEANFILES += alloca.h alloca.h-t - -EXTRA_DIST += alloca.in.h - -## end gnulib module alloca-opt - -## begin gnulib module arg-nonnull - -# The BUILT_SOURCES created by this Makefile snippet are not used via #include -# statements but through direct file reference. Therefore this snippet must be -# present in all Makefile.am that need it. This is ensured by the applicability -# 'all' defined above. - -BUILT_SOURCES += arg-nonnull.h -# The arg-nonnull.h that gets inserted into generated .h files is the same as -# build-aux/arg-nonnull.h, except that it has the copyright header cut off. -arg-nonnull.h: $(top_srcdir)/build-aux/arg-nonnull.h - $(AM_V_GEN)rm -f $@-t $@ && \ - sed -n -e '/GL_ARG_NONNULL/,$$p' \ - < $(top_srcdir)/build-aux/arg-nonnull.h \ - > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += arg-nonnull.h arg-nonnull.h-t - -ARG_NONNULL_H=arg-nonnull.h - -EXTRA_DIST += $(top_srcdir)/build-aux/arg-nonnull.h - -## end gnulib module arg-nonnull - -## begin gnulib module argp - -libgnu_a_SOURCES += argp.h argp-ba.c argp-eexst.c \ - argp-fmtstream.c argp-fmtstream.h argp-fs-xinl.c argp-help.c \ - argp-namefrob.h argp-parse.c argp-pin.c argp-pv.c argp-pvh.c \ - argp-xinl.c - -## end gnulib module argp - -## begin gnulib module btowc - - -EXTRA_DIST += btowc.c - -EXTRA_libgnu_a_SOURCES += btowc.c - -## end gnulib module btowc - -## begin gnulib module c++defs - -# The BUILT_SOURCES created by this Makefile snippet are not used via #include -# statements but through direct file reference. Therefore this snippet must be -# present in all Makefile.am that need it. This is ensured by the applicability -# 'all' defined above. - -BUILT_SOURCES += c++defs.h -# The c++defs.h that gets inserted into generated .h files is the same as -# build-aux/c++defs.h, except that it has the copyright header cut off. -c++defs.h: $(top_srcdir)/build-aux/c++defs.h - $(AM_V_GEN)rm -f $@-t $@ && \ - sed -n -e '/_GL_CXXDEFS/,$$p' \ - < $(top_srcdir)/build-aux/c++defs.h \ - > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += c++defs.h c++defs.h-t - -CXXDEFS_H=c++defs.h - -EXTRA_DIST += $(top_srcdir)/build-aux/c++defs.h - -## end gnulib module c++defs - -## begin gnulib module configmake - -# Retrieve values of the variables through 'configure' followed by -# 'make', not directly through 'configure', so that a user who -# sets some of these variables consistently on the 'make' command -# line gets correct results. -# -# One advantage of this approach, compared to the classical -# approach of adding -DLIBDIR=\"$(libdir)\" etc. to AM_CPPFLAGS, -# is that it protects against the use of undefined variables. -# If, say, $(libdir) is not set in the Makefile, LIBDIR is not -# defined by this module, and code using LIBDIR gives a -# compilation error. -# -# Another advantage is that 'make' output is shorter. -# -# Listed in the same order as the GNU makefile conventions. -# The Automake-defined pkg* macros are appended, in the order -# listed in the Automake 1.10a+ documentation. -configmake.h: Makefile - $(AM_V_GEN)rm -f $@-t && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - echo '#define PREFIX "$(prefix)"'; \ - echo '#define EXEC_PREFIX "$(exec_prefix)"'; \ - echo '#define BINDIR "$(bindir)"'; \ - echo '#define SBINDIR "$(sbindir)"'; \ - echo '#define LIBEXECDIR "$(libexecdir)"'; \ - echo '#define DATAROOTDIR "$(datarootdir)"'; \ - echo '#define DATADIR "$(datadir)"'; \ - echo '#define SYSCONFDIR "$(sysconfdir)"'; \ - echo '#define SHAREDSTATEDIR "$(sharedstatedir)"'; \ - echo '#define LOCALSTATEDIR "$(localstatedir)"'; \ - echo '#define INCLUDEDIR "$(includedir)"'; \ - echo '#define OLDINCLUDEDIR "$(oldincludedir)"'; \ - echo '#define DOCDIR "$(docdir)"'; \ - echo '#define INFODIR "$(infodir)"'; \ - echo '#define HTMLDIR "$(htmldir)"'; \ - echo '#define DVIDIR "$(dvidir)"'; \ - echo '#define PDFDIR "$(pdfdir)"'; \ - echo '#define PSDIR "$(psdir)"'; \ - echo '#define LIBDIR "$(libdir)"'; \ - echo '#define LISPDIR "$(lispdir)"'; \ - echo '#define LOCALEDIR "$(localedir)"'; \ - echo '#define MANDIR "$(mandir)"'; \ - echo '#define MANEXT "$(manext)"'; \ - echo '#define PKGDATADIR "$(pkgdatadir)"'; \ - echo '#define PKGINCLUDEDIR "$(pkgincludedir)"'; \ - echo '#define PKGLIBDIR "$(pkglibdir)"'; \ - echo '#define PKGLIBEXECDIR "$(pkglibexecdir)"'; \ - } | sed '/""/d' > $@-t && \ - if test -f $@ && cmp $@-t $@ > /dev/null; then \ - rm -f $@-t; \ - else \ - rm -f $@; mv $@-t $@; \ - fi - -BUILT_SOURCES += configmake.h -CLEANFILES += configmake.h configmake.h-t - -## end gnulib module configmake - -## begin gnulib module dirname-lgpl - - -EXTRA_DIST += basename-lgpl.c dirname-lgpl.c dirname.h stripslash.c - -EXTRA_libgnu_a_SOURCES += basename-lgpl.c dirname-lgpl.c stripslash.c - -## end gnulib module dirname-lgpl - -## begin gnulib module errno - -BUILT_SOURCES += $(ERRNO_H) - -# We need the following in order to create when the system -# doesn't have one that is POSIX compliant. -errno.h: errno.in.h - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_ERRNO_H''@|$(NEXT_ERRNO_H)|g' \ - -e 's|@''EMULTIHOP_HIDDEN''@|$(EMULTIHOP_HIDDEN)|g' \ - -e 's|@''EMULTIHOP_VALUE''@|$(EMULTIHOP_VALUE)|g' \ - -e 's|@''ENOLINK_HIDDEN''@|$(ENOLINK_HIDDEN)|g' \ - -e 's|@''ENOLINK_VALUE''@|$(ENOLINK_VALUE)|g' \ - -e 's|@''EOVERFLOW_HIDDEN''@|$(EOVERFLOW_HIDDEN)|g' \ - -e 's|@''EOVERFLOW_VALUE''@|$(EOVERFLOW_VALUE)|g' \ - < $(srcdir)/errno.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += errno.h errno.h-t - -EXTRA_DIST += errno.in.h - -## end gnulib module errno - -## begin gnulib module error - - -EXTRA_DIST += error.c error.h - -EXTRA_libgnu_a_SOURCES += error.c - -## end gnulib module error - -## begin gnulib module float - -BUILT_SOURCES += $(FLOAT_H) - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -float.h: float.in.h - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_FLOAT_H''@|$(NEXT_FLOAT_H)|g' \ - < $(srcdir)/float.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += float.h float.h-t - -EXTRA_DIST += float.in.h - -## end gnulib module float - -## begin gnulib module fnmatch - -BUILT_SOURCES += $(FNMATCH_H) - -# We need the following in order to create when the system -# doesn't have one that supports the required API. -fnmatch.h: fnmatch.in.h $(ARG_NONNULL_H) - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ - < $(srcdir)/fnmatch.in.h; \ - } > $@-t && \ - mv -f $@-t $@ -MOSTLYCLEANFILES += fnmatch.h fnmatch.h-t - -EXTRA_DIST += fnmatch.c fnmatch.in.h fnmatch_loop.c - -EXTRA_libgnu_a_SOURCES += fnmatch.c fnmatch_loop.c - -## end gnulib module fnmatch - -## begin gnulib module getdelim - - -EXTRA_DIST += getdelim.c - -EXTRA_libgnu_a_SOURCES += getdelim.c - -## end gnulib module getdelim - -## begin gnulib module getline - - -EXTRA_DIST += getline.c - -EXTRA_libgnu_a_SOURCES += getline.c - -## end gnulib module getline - -## begin gnulib module getopt-posix - -BUILT_SOURCES += $(GETOPT_H) - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -getopt.h: getopt.in.h $(ARG_NONNULL_H) - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's|@''HAVE_GETOPT_H''@|$(HAVE_GETOPT_H)|g' \ - -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_GETOPT_H''@|$(NEXT_GETOPT_H)|g' \ - -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ - < $(srcdir)/getopt.in.h; \ - } > $@-t && \ - mv -f $@-t $@ -MOSTLYCLEANFILES += getopt.h getopt.h-t - -EXTRA_DIST += getopt.c getopt.in.h getopt1.c getopt_int.h - -EXTRA_libgnu_a_SOURCES += getopt.c getopt1.c - -## end gnulib module getopt-posix - -## begin gnulib module gettext - -# This is for those projects which use "gettextize --intl" to put a source-code -# copy of libintl into their package. In such projects, every Makefile.am needs -# -I$(top_builddir)/intl, so that can be found in this directory. -# For the Makefile.ams in other directories it is the maintainer's -# responsibility; for the one from gnulib we do it here. -# This option has no effect when the user disables NLS (because then the intl -# directory contains no libintl.h file) or when the project does not use -# "gettextize --intl". -AM_CPPFLAGS += -I$(top_builddir)/intl - -EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath - -## end gnulib module gettext - -## begin gnulib module gettext-h - -libgnu_a_SOURCES += gettext.h - -## end gnulib module gettext-h - -## begin gnulib module havelib - - -EXTRA_DIST += $(top_srcdir)/build-aux/config.rpath - -## end gnulib module havelib - -## begin gnulib module intprops - - -EXTRA_DIST += intprops.h - -## end gnulib module intprops - -## begin gnulib module langinfo - -BUILT_SOURCES += langinfo.h - -# We need the following in order to create an empty placeholder for -# when the system doesn't have one. -langinfo.h: langinfo.in.h $(CXXDEFS_H) $(WARN_ON_USE_H) - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's|@''HAVE_LANGINFO_H''@|$(HAVE_LANGINFO_H)|g' \ - -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_LANGINFO_H''@|$(NEXT_LANGINFO_H)|g' \ - -e 's|@''GNULIB_NL_LANGINFO''@|$(GNULIB_NL_LANGINFO)|g' \ - -e 's|@''HAVE_LANGINFO_CODESET''@|$(HAVE_LANGINFO_CODESET)|g' \ - -e 's|@''HAVE_LANGINFO_T_FMT_AMPM''@|$(HAVE_LANGINFO_T_FMT_AMPM)|g' \ - -e 's|@''HAVE_LANGINFO_ERA''@|$(HAVE_LANGINFO_ERA)|g' \ - -e 's|@''HAVE_LANGINFO_YESEXPR''@|$(HAVE_LANGINFO_YESEXPR)|g' \ - -e 's|@''HAVE_NL_LANGINFO''@|$(HAVE_NL_LANGINFO)|g' \ - -e 's|@''REPLACE_NL_LANGINFO''@|$(REPLACE_NL_LANGINFO)|g' \ - -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ - -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ - < $(srcdir)/langinfo.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += langinfo.h langinfo.h-t - -EXTRA_DIST += langinfo.in.h - -## end gnulib module langinfo - -## begin gnulib module localcharset - -libgnu_a_SOURCES += localcharset.h localcharset.c - -# We need the following in order to install a simple file in $(libdir) -# which is shared with other installed packages. We use a list of referencing -# packages so that "make uninstall" will remove the file if and only if it -# is not used by another installed package. -# On systems with glibc-2.1 or newer, the file is redundant, therefore we -# avoid installing it. - -all-local: charset.alias ref-add.sed ref-del.sed - -charset_alias = $(DESTDIR)$(libdir)/charset.alias -charset_tmp = $(DESTDIR)$(libdir)/charset.tmp -install-exec-local: install-exec-localcharset -install-exec-localcharset: all-local - if test $(GLIBC21) = no; then \ - case '$(host_os)' in \ - darwin[56]*) \ - need_charset_alias=true ;; \ - darwin* | cygwin* | mingw* | pw32* | cegcc*) \ - need_charset_alias=false ;; \ - *) \ - need_charset_alias=true ;; \ - esac ; \ - else \ - need_charset_alias=false ; \ - fi ; \ - if $$need_charset_alias; then \ - $(mkinstalldirs) $(DESTDIR)$(libdir) ; \ - fi ; \ - if test -f $(charset_alias); then \ - sed -f ref-add.sed $(charset_alias) > $(charset_tmp) ; \ - $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \ - rm -f $(charset_tmp) ; \ - else \ - if $$need_charset_alias; then \ - sed -f ref-add.sed charset.alias > $(charset_tmp) ; \ - $(INSTALL_DATA) $(charset_tmp) $(charset_alias) ; \ - rm -f $(charset_tmp) ; \ - fi ; \ - fi - -uninstall-local: uninstall-localcharset -uninstall-localcharset: all-local - if test -f $(charset_alias); then \ - sed -f ref-del.sed $(charset_alias) > $(charset_tmp); \ - if grep '^# Packages using this file: $$' $(charset_tmp) \ - > /dev/null; then \ - rm -f $(charset_alias); \ - else \ - $(INSTALL_DATA) $(charset_tmp) $(charset_alias); \ - fi; \ - rm -f $(charset_tmp); \ - fi - -charset.alias: config.charset - $(AM_V_GEN)rm -f t-$@ $@ && \ - $(SHELL) $(srcdir)/config.charset '$(host)' > t-$@ && \ - mv t-$@ $@ - -SUFFIXES += .sed .sin -.sin.sed: - $(AM_V_GEN)rm -f t-$@ $@ && \ - sed -e '/^#/d' -e 's/@''PACKAGE''@/$(PACKAGE)/g' $< > t-$@ && \ - mv t-$@ $@ - -CLEANFILES += charset.alias ref-add.sed ref-del.sed - -EXTRA_DIST += config.charset ref-add.sin ref-del.sin - -## end gnulib module localcharset - -## begin gnulib module malloc-gnu - - -EXTRA_DIST += malloc.c - -EXTRA_libgnu_a_SOURCES += malloc.c - -## end gnulib module malloc-gnu - -## begin gnulib module malloc-posix - - -EXTRA_DIST += malloc.c - -EXTRA_libgnu_a_SOURCES += malloc.c - -## end gnulib module malloc-posix - -## begin gnulib module mbrtowc - - -EXTRA_DIST += mbrtowc.c - -EXTRA_libgnu_a_SOURCES += mbrtowc.c - -## end gnulib module mbrtowc - -## begin gnulib module mbsinit - - -EXTRA_DIST += mbsinit.c - -EXTRA_libgnu_a_SOURCES += mbsinit.c - -## end gnulib module mbsinit - -## begin gnulib module mbsrtowcs - - -EXTRA_DIST += mbsrtowcs-state.c mbsrtowcs.c - -EXTRA_libgnu_a_SOURCES += mbsrtowcs-state.c mbsrtowcs.c - -## end gnulib module mbsrtowcs - -## begin gnulib module memchr - - -EXTRA_DIST += memchr.c memchr.valgrind - -EXTRA_libgnu_a_SOURCES += memchr.c - -## end gnulib module memchr - -## begin gnulib module mempcpy - - -EXTRA_DIST += mempcpy.c - -EXTRA_libgnu_a_SOURCES += mempcpy.c - -## end gnulib module mempcpy - -## begin gnulib module nl_langinfo - - -EXTRA_DIST += nl_langinfo.c - -EXTRA_libgnu_a_SOURCES += nl_langinfo.c - -## end gnulib module nl_langinfo - -## begin gnulib module progname - -libgnu_a_SOURCES += progname.h progname.c - -## end gnulib module progname - -## begin gnulib module rawmemchr - - -EXTRA_DIST += rawmemchr.c rawmemchr.valgrind - -EXTRA_libgnu_a_SOURCES += rawmemchr.c - -## end gnulib module rawmemchr - -## begin gnulib module realloc-posix - - -EXTRA_DIST += realloc.c - -EXTRA_libgnu_a_SOURCES += realloc.c - -## end gnulib module realloc-posix - -## begin gnulib module regex - - -EXTRA_DIST += regcomp.c regex.c regex.h regex_internal.c regex_internal.h regexec.c - -EXTRA_libgnu_a_SOURCES += regcomp.c regex.c regex_internal.c regexec.c - -## end gnulib module regex - -## begin gnulib module size_max - -libgnu_a_SOURCES += size_max.h - -## end gnulib module size_max - -## begin gnulib module sleep - - -EXTRA_DIST += sleep.c - -EXTRA_libgnu_a_SOURCES += sleep.c - -## end gnulib module sleep - -## begin gnulib module stdbool - -BUILT_SOURCES += $(STDBOOL_H) - -# We need the following in order to create when the system -# doesn't have one that works. -stdbool.h: stdbool.in.h - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's/@''HAVE__BOOL''@/$(HAVE__BOOL)/g' < $(srcdir)/stdbool.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += stdbool.h stdbool.h-t - -EXTRA_DIST += stdbool.in.h - -## end gnulib module stdbool - -## begin gnulib module stddef - -BUILT_SOURCES += $(STDDEF_H) - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -stddef.h: stddef.in.h - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_STDDEF_H''@|$(NEXT_STDDEF_H)|g' \ - -e 's|@''HAVE_WCHAR_T''@|$(HAVE_WCHAR_T)|g' \ - -e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \ - < $(srcdir)/stddef.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += stddef.h stddef.h-t - -EXTRA_DIST += stddef.in.h - -## end gnulib module stddef - -## begin gnulib module stdint - -BUILT_SOURCES += $(STDINT_H) - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -stdint.h: stdint.in.h - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's/@''HAVE_STDINT_H''@/$(HAVE_STDINT_H)/g' \ - -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_STDINT_H''@|$(NEXT_STDINT_H)|g' \ - -e 's/@''HAVE_SYS_TYPES_H''@/$(HAVE_SYS_TYPES_H)/g' \ - -e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \ - -e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \ - -e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \ - -e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \ - -e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \ - -e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \ - -e 's/@''BITSIZEOF_PTRDIFF_T''@/$(BITSIZEOF_PTRDIFF_T)/g' \ - -e 's/@''PTRDIFF_T_SUFFIX''@/$(PTRDIFF_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_SIG_ATOMIC_T''@/$(BITSIZEOF_SIG_ATOMIC_T)/g' \ - -e 's/@''HAVE_SIGNED_SIG_ATOMIC_T''@/$(HAVE_SIGNED_SIG_ATOMIC_T)/g' \ - -e 's/@''SIG_ATOMIC_T_SUFFIX''@/$(SIG_ATOMIC_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_SIZE_T''@/$(BITSIZEOF_SIZE_T)/g' \ - -e 's/@''SIZE_T_SUFFIX''@/$(SIZE_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_WCHAR_T''@/$(BITSIZEOF_WCHAR_T)/g' \ - -e 's/@''HAVE_SIGNED_WCHAR_T''@/$(HAVE_SIGNED_WCHAR_T)/g' \ - -e 's/@''WCHAR_T_SUFFIX''@/$(WCHAR_T_SUFFIX)/g' \ - -e 's/@''BITSIZEOF_WINT_T''@/$(BITSIZEOF_WINT_T)/g' \ - -e 's/@''HAVE_SIGNED_WINT_T''@/$(HAVE_SIGNED_WINT_T)/g' \ - -e 's/@''WINT_T_SUFFIX''@/$(WINT_T_SUFFIX)/g' \ - < $(srcdir)/stdint.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += stdint.h stdint.h-t - -EXTRA_DIST += stdint.in.h - -## end gnulib module stdint - -## begin gnulib module stdio - -BUILT_SOURCES += stdio.h - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -stdio.h: stdio.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_STDIO_H''@|$(NEXT_STDIO_H)|g' \ - -e 's|@''GNULIB_DPRINTF''@|$(GNULIB_DPRINTF)|g' \ - -e 's|@''GNULIB_FCLOSE''@|$(GNULIB_FCLOSE)|g' \ - -e 's|@''GNULIB_FFLUSH''@|$(GNULIB_FFLUSH)|g' \ - -e 's|@''GNULIB_FOPEN''@|$(GNULIB_FOPEN)|g' \ - -e 's|@''GNULIB_FPRINTF''@|$(GNULIB_FPRINTF)|g' \ - -e 's|@''GNULIB_FPRINTF_POSIX''@|$(GNULIB_FPRINTF_POSIX)|g' \ - -e 's|@''GNULIB_FPURGE''@|$(GNULIB_FPURGE)|g' \ - -e 's|@''GNULIB_FPUTC''@|$(GNULIB_FPUTC)|g' \ - -e 's|@''GNULIB_FPUTS''@|$(GNULIB_FPUTS)|g' \ - -e 's|@''GNULIB_FREOPEN''@|$(GNULIB_FREOPEN)|g' \ - -e 's|@''GNULIB_FSEEK''@|$(GNULIB_FSEEK)|g' \ - -e 's|@''GNULIB_FSEEKO''@|$(GNULIB_FSEEKO)|g' \ - -e 's|@''GNULIB_FTELL''@|$(GNULIB_FTELL)|g' \ - -e 's|@''GNULIB_FTELLO''@|$(GNULIB_FTELLO)|g' \ - -e 's|@''GNULIB_FWRITE''@|$(GNULIB_FWRITE)|g' \ - -e 's|@''GNULIB_GETDELIM''@|$(GNULIB_GETDELIM)|g' \ - -e 's|@''GNULIB_GETLINE''@|$(GNULIB_GETLINE)|g' \ - -e 's|@''GNULIB_OBSTACK_PRINTF''@|$(GNULIB_OBSTACK_PRINTF)|g' \ - -e 's|@''GNULIB_OBSTACK_PRINTF_POSIX''@|$(GNULIB_OBSTACK_PRINTF_POSIX)|g' \ - -e 's|@''GNULIB_PERROR''@|$(GNULIB_PERROR)|g' \ - -e 's|@''GNULIB_POPEN''@|$(GNULIB_POPEN)|g' \ - -e 's|@''GNULIB_PRINTF''@|$(GNULIB_PRINTF)|g' \ - -e 's|@''GNULIB_PRINTF_POSIX''@|$(GNULIB_PRINTF_POSIX)|g' \ - -e 's|@''GNULIB_PUTC''@|$(GNULIB_PUTC)|g' \ - -e 's|@''GNULIB_PUTCHAR''@|$(GNULIB_PUTCHAR)|g' \ - -e 's|@''GNULIB_PUTS''@|$(GNULIB_PUTS)|g' \ - -e 's|@''GNULIB_REMOVE''@|$(GNULIB_REMOVE)|g' \ - -e 's|@''GNULIB_RENAME''@|$(GNULIB_RENAME)|g' \ - -e 's|@''GNULIB_RENAMEAT''@|$(GNULIB_RENAMEAT)|g' \ - -e 's|@''GNULIB_SNPRINTF''@|$(GNULIB_SNPRINTF)|g' \ - -e 's|@''GNULIB_SPRINTF_POSIX''@|$(GNULIB_SPRINTF_POSIX)|g' \ - -e 's|@''GNULIB_STDIO_H_SIGPIPE''@|$(GNULIB_STDIO_H_SIGPIPE)|g' \ - -e 's|@''GNULIB_TMPFILE''@|$(GNULIB_TMPFILE)|g' \ - -e 's|@''GNULIB_VASPRINTF''@|$(GNULIB_VASPRINTF)|g' \ - -e 's|@''GNULIB_VDPRINTF''@|$(GNULIB_VDPRINTF)|g' \ - -e 's|@''GNULIB_VFPRINTF''@|$(GNULIB_VFPRINTF)|g' \ - -e 's|@''GNULIB_VFPRINTF_POSIX''@|$(GNULIB_VFPRINTF_POSIX)|g' \ - -e 's|@''GNULIB_VPRINTF''@|$(GNULIB_VPRINTF)|g' \ - -e 's|@''GNULIB_VPRINTF_POSIX''@|$(GNULIB_VPRINTF_POSIX)|g' \ - -e 's|@''GNULIB_VSNPRINTF''@|$(GNULIB_VSNPRINTF)|g' \ - -e 's|@''GNULIB_VSPRINTF_POSIX''@|$(GNULIB_VSPRINTF_POSIX)|g' \ - < $(srcdir)/stdio.in.h | \ - sed -e 's|@''HAVE_DECL_FPURGE''@|$(HAVE_DECL_FPURGE)|g' \ - -e 's|@''HAVE_DECL_GETDELIM''@|$(HAVE_DECL_GETDELIM)|g' \ - -e 's|@''HAVE_DECL_GETLINE''@|$(HAVE_DECL_GETLINE)|g' \ - -e 's|@''HAVE_DECL_OBSTACK_PRINTF''@|$(HAVE_DECL_OBSTACK_PRINTF)|g' \ - -e 's|@''HAVE_DECL_SNPRINTF''@|$(HAVE_DECL_SNPRINTF)|g' \ - -e 's|@''HAVE_DECL_VSNPRINTF''@|$(HAVE_DECL_VSNPRINTF)|g' \ - -e 's|@''HAVE_DPRINTF''@|$(HAVE_DPRINTF)|g' \ - -e 's|@''HAVE_FSEEKO''@|$(HAVE_FSEEKO)|g' \ - -e 's|@''HAVE_FTELLO''@|$(HAVE_FTELLO)|g' \ - -e 's|@''HAVE_RENAMEAT''@|$(HAVE_RENAMEAT)|g' \ - -e 's|@''HAVE_VASPRINTF''@|$(HAVE_VASPRINTF)|g' \ - -e 's|@''HAVE_VDPRINTF''@|$(HAVE_VDPRINTF)|g' \ - -e 's|@''REPLACE_DPRINTF''@|$(REPLACE_DPRINTF)|g' \ - -e 's|@''REPLACE_FCLOSE''@|$(REPLACE_FCLOSE)|g' \ - -e 's|@''REPLACE_FFLUSH''@|$(REPLACE_FFLUSH)|g' \ - -e 's|@''REPLACE_FOPEN''@|$(REPLACE_FOPEN)|g' \ - -e 's|@''REPLACE_FPRINTF''@|$(REPLACE_FPRINTF)|g' \ - -e 's|@''REPLACE_FPURGE''@|$(REPLACE_FPURGE)|g' \ - -e 's|@''REPLACE_FREOPEN''@|$(REPLACE_FREOPEN)|g' \ - -e 's|@''REPLACE_FSEEK''@|$(REPLACE_FSEEK)|g' \ - -e 's|@''REPLACE_FSEEKO''@|$(REPLACE_FSEEKO)|g' \ - -e 's|@''REPLACE_FTELL''@|$(REPLACE_FTELL)|g' \ - -e 's|@''REPLACE_FTELLO''@|$(REPLACE_FTELLO)|g' \ - -e 's|@''REPLACE_GETDELIM''@|$(REPLACE_GETDELIM)|g' \ - -e 's|@''REPLACE_GETLINE''@|$(REPLACE_GETLINE)|g' \ - -e 's|@''REPLACE_OBSTACK_PRINTF''@|$(REPLACE_OBSTACK_PRINTF)|g' \ - -e 's|@''REPLACE_PERROR''@|$(REPLACE_PERROR)|g' \ - -e 's|@''REPLACE_POPEN''@|$(REPLACE_POPEN)|g' \ - -e 's|@''REPLACE_PRINTF''@|$(REPLACE_PRINTF)|g' \ - -e 's|@''REPLACE_REMOVE''@|$(REPLACE_REMOVE)|g' \ - -e 's|@''REPLACE_RENAME''@|$(REPLACE_RENAME)|g' \ - -e 's|@''REPLACE_RENAMEAT''@|$(REPLACE_RENAMEAT)|g' \ - -e 's|@''REPLACE_SNPRINTF''@|$(REPLACE_SNPRINTF)|g' \ - -e 's|@''REPLACE_SPRINTF''@|$(REPLACE_SPRINTF)|g' \ - -e 's|@''REPLACE_STDIO_WRITE_FUNCS''@|$(REPLACE_STDIO_WRITE_FUNCS)|g' \ - -e 's|@''REPLACE_TMPFILE''@|$(REPLACE_TMPFILE)|g' \ - -e 's|@''REPLACE_VASPRINTF''@|$(REPLACE_VASPRINTF)|g' \ - -e 's|@''REPLACE_VDPRINTF''@|$(REPLACE_VDPRINTF)|g' \ - -e 's|@''REPLACE_VFPRINTF''@|$(REPLACE_VFPRINTF)|g' \ - -e 's|@''REPLACE_VPRINTF''@|$(REPLACE_VPRINTF)|g' \ - -e 's|@''REPLACE_VSNPRINTF''@|$(REPLACE_VSNPRINTF)|g' \ - -e 's|@''REPLACE_VSPRINTF''@|$(REPLACE_VSPRINTF)|g' \ - -e 's|@''ASM_SYMBOL_PREFIX''@|$(ASM_SYMBOL_PREFIX)|g' \ - -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ - -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ - -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += stdio.h stdio.h-t - -EXTRA_DIST += stdio-write.c stdio.in.h - -EXTRA_libgnu_a_SOURCES += stdio-write.c - -## end gnulib module stdio - -## begin gnulib module stdlib - -BUILT_SOURCES += stdlib.h - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -stdlib.h: stdlib.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_STDLIB_H''@|$(NEXT_STDLIB_H)|g' \ - -e 's|@''GNULIB__EXIT''@|$(GNULIB__EXIT)|g' \ - -e 's|@''GNULIB_ATOLL''@|$(GNULIB_ATOLL)|g' \ - -e 's|@''GNULIB_CALLOC_POSIX''@|$(GNULIB_CALLOC_POSIX)|g' \ - -e 's|@''GNULIB_CANONICALIZE_FILE_NAME''@|$(GNULIB_CANONICALIZE_FILE_NAME)|g' \ - -e 's|@''GNULIB_GETLOADAVG''@|$(GNULIB_GETLOADAVG)|g' \ - -e 's|@''GNULIB_GETSUBOPT''@|$(GNULIB_GETSUBOPT)|g' \ - -e 's|@''GNULIB_GRANTPT''@|$(GNULIB_GRANTPT)|g' \ - -e 's|@''GNULIB_MALLOC_POSIX''@|$(GNULIB_MALLOC_POSIX)|g' \ - -e 's|@''GNULIB_MKDTEMP''@|$(GNULIB_MKDTEMP)|g' \ - -e 's|@''GNULIB_MKOSTEMP''@|$(GNULIB_MKOSTEMP)|g' \ - -e 's|@''GNULIB_MKOSTEMPS''@|$(GNULIB_MKOSTEMPS)|g' \ - -e 's|@''GNULIB_MKSTEMP''@|$(GNULIB_MKSTEMP)|g' \ - -e 's|@''GNULIB_MKSTEMPS''@|$(GNULIB_MKSTEMPS)|g' \ - -e 's|@''GNULIB_PTSNAME''@|$(GNULIB_PTSNAME)|g' \ - -e 's|@''GNULIB_PUTENV''@|$(GNULIB_PUTENV)|g' \ - -e 's|@''GNULIB_RANDOM_R''@|$(GNULIB_RANDOM_R)|g' \ - -e 's|@''GNULIB_REALLOC_POSIX''@|$(GNULIB_REALLOC_POSIX)|g' \ - -e 's|@''GNULIB_REALPATH''@|$(GNULIB_REALPATH)|g' \ - -e 's|@''GNULIB_RPMATCH''@|$(GNULIB_RPMATCH)|g' \ - -e 's|@''GNULIB_SETENV''@|$(GNULIB_SETENV)|g' \ - -e 's|@''GNULIB_STRTOD''@|$(GNULIB_STRTOD)|g' \ - -e 's|@''GNULIB_STRTOLL''@|$(GNULIB_STRTOLL)|g' \ - -e 's|@''GNULIB_STRTOULL''@|$(GNULIB_STRTOULL)|g' \ - -e 's|@''GNULIB_UNLOCKPT''@|$(GNULIB_UNLOCKPT)|g' \ - -e 's|@''GNULIB_UNSETENV''@|$(GNULIB_UNSETENV)|g' \ - -e 's|@''HAVE__EXIT''@|$(HAVE__EXIT)|g' \ - -e 's|@''HAVE_ATOLL''@|$(HAVE_ATOLL)|g' \ - -e 's|@''HAVE_CANONICALIZE_FILE_NAME''@|$(HAVE_CANONICALIZE_FILE_NAME)|g' \ - -e 's|@''HAVE_DECL_GETLOADAVG''@|$(HAVE_DECL_GETLOADAVG)|g' \ - -e 's|@''HAVE_GETSUBOPT''@|$(HAVE_GETSUBOPT)|g' \ - -e 's|@''HAVE_GRANTPT''@|$(HAVE_GRANTPT)|g' \ - -e 's|@''HAVE_MKDTEMP''@|$(HAVE_MKDTEMP)|g' \ - -e 's|@''HAVE_MKOSTEMP''@|$(HAVE_MKOSTEMP)|g' \ - -e 's|@''HAVE_MKOSTEMPS''@|$(HAVE_MKOSTEMPS)|g' \ - -e 's|@''HAVE_MKSTEMP''@|$(HAVE_MKSTEMP)|g' \ - -e 's|@''HAVE_MKSTEMPS''@|$(HAVE_MKSTEMPS)|g' \ - -e 's|@''HAVE_PTSNAME''@|$(HAVE_PTSNAME)|g' \ - -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \ - -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \ - -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \ - -e 's|@''HAVE_RPMATCH''@|$(HAVE_RPMATCH)|g' \ - -e 's|@''HAVE_SETENV''@|$(HAVE_SETENV)|g' \ - -e 's|@''HAVE_STRTOD''@|$(HAVE_STRTOD)|g' \ - -e 's|@''HAVE_STRTOLL''@|$(HAVE_STRTOLL)|g' \ - -e 's|@''HAVE_STRTOULL''@|$(HAVE_STRTOULL)|g' \ - -e 's|@''HAVE_STRUCT_RANDOM_DATA''@|$(HAVE_STRUCT_RANDOM_DATA)|g' \ - -e 's|@''HAVE_SYS_LOADAVG_H''@|$(HAVE_SYS_LOADAVG_H)|g' \ - -e 's|@''HAVE_UNLOCKPT''@|$(HAVE_UNLOCKPT)|g' \ - -e 's|@''HAVE_UNSETENV''@|$(HAVE_UNSETENV)|g' \ - -e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \ - -e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \ - -e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \ - -e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \ - -e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \ - -e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \ - -e 's|@''REPLACE_REALPATH''@|$(REPLACE_REALPATH)|g' \ - -e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \ - -e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \ - -e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \ - -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ - -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ - -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ - < $(srcdir)/stdlib.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += stdlib.h stdlib.h-t - -EXTRA_DIST += stdlib.in.h - -## end gnulib module stdlib - -## begin gnulib module strcase - - -EXTRA_DIST += strcasecmp.c strncasecmp.c - -EXTRA_libgnu_a_SOURCES += strcasecmp.c strncasecmp.c - -## end gnulib module strcase - -## begin gnulib module strchrnul - - -EXTRA_DIST += strchrnul.c strchrnul.valgrind - -EXTRA_libgnu_a_SOURCES += strchrnul.c - -## end gnulib module strchrnul - -## begin gnulib module streq - - -EXTRA_DIST += streq.h - -## end gnulib module streq - -## begin gnulib module strerror - - -EXTRA_DIST += strerror.c - -EXTRA_libgnu_a_SOURCES += strerror.c - -## end gnulib module strerror - -## begin gnulib module string - -BUILT_SOURCES += string.h - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -string.h: string.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_STRING_H''@|$(NEXT_STRING_H)|g' \ - -e 's|@''GNULIB_MBSLEN''@|$(GNULIB_MBSLEN)|g' \ - -e 's|@''GNULIB_MBSNLEN''@|$(GNULIB_MBSNLEN)|g' \ - -e 's|@''GNULIB_MBSCHR''@|$(GNULIB_MBSCHR)|g' \ - -e 's|@''GNULIB_MBSRCHR''@|$(GNULIB_MBSRCHR)|g' \ - -e 's|@''GNULIB_MBSSTR''@|$(GNULIB_MBSSTR)|g' \ - -e 's|@''GNULIB_MBSCASECMP''@|$(GNULIB_MBSCASECMP)|g' \ - -e 's|@''GNULIB_MBSNCASECMP''@|$(GNULIB_MBSNCASECMP)|g' \ - -e 's|@''GNULIB_MBSPCASECMP''@|$(GNULIB_MBSPCASECMP)|g' \ - -e 's|@''GNULIB_MBSCASESTR''@|$(GNULIB_MBSCASESTR)|g' \ - -e 's|@''GNULIB_MBSCSPN''@|$(GNULIB_MBSCSPN)|g' \ - -e 's|@''GNULIB_MBSPBRK''@|$(GNULIB_MBSPBRK)|g' \ - -e 's|@''GNULIB_MBSSPN''@|$(GNULIB_MBSSPN)|g' \ - -e 's|@''GNULIB_MBSSEP''@|$(GNULIB_MBSSEP)|g' \ - -e 's|@''GNULIB_MBSTOK_R''@|$(GNULIB_MBSTOK_R)|g' \ - -e 's|@''GNULIB_MEMCHR''@|$(GNULIB_MEMCHR)|g' \ - -e 's|@''GNULIB_MEMMEM''@|$(GNULIB_MEMMEM)|g' \ - -e 's|@''GNULIB_MEMPCPY''@|$(GNULIB_MEMPCPY)|g' \ - -e 's|@''GNULIB_MEMRCHR''@|$(GNULIB_MEMRCHR)|g' \ - -e 's|@''GNULIB_RAWMEMCHR''@|$(GNULIB_RAWMEMCHR)|g' \ - -e 's|@''GNULIB_STPCPY''@|$(GNULIB_STPCPY)|g' \ - -e 's|@''GNULIB_STPNCPY''@|$(GNULIB_STPNCPY)|g' \ - -e 's|@''GNULIB_STRCHRNUL''@|$(GNULIB_STRCHRNUL)|g' \ - -e 's|@''GNULIB_STRDUP''@|$(GNULIB_STRDUP)|g' \ - -e 's|@''GNULIB_STRNCAT''@|$(GNULIB_STRNCAT)|g' \ - -e 's|@''GNULIB_STRNDUP''@|$(GNULIB_STRNDUP)|g' \ - -e 's|@''GNULIB_STRNLEN''@|$(GNULIB_STRNLEN)|g' \ - -e 's|@''GNULIB_STRPBRK''@|$(GNULIB_STRPBRK)|g' \ - -e 's|@''GNULIB_STRSEP''@|$(GNULIB_STRSEP)|g' \ - -e 's|@''GNULIB_STRSTR''@|$(GNULIB_STRSTR)|g' \ - -e 's|@''GNULIB_STRCASESTR''@|$(GNULIB_STRCASESTR)|g' \ - -e 's|@''GNULIB_STRTOK_R''@|$(GNULIB_STRTOK_R)|g' \ - -e 's|@''GNULIB_STRERROR''@|$(GNULIB_STRERROR)|g' \ - -e 's|@''GNULIB_STRSIGNAL''@|$(GNULIB_STRSIGNAL)|g' \ - -e 's|@''GNULIB_STRVERSCMP''@|$(GNULIB_STRVERSCMP)|g' \ - < $(srcdir)/string.in.h | \ - sed -e 's|@''HAVE_MBSLEN''@|$(HAVE_MBSLEN)|g' \ - -e 's|@''HAVE_MEMCHR''@|$(HAVE_MEMCHR)|g' \ - -e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \ - -e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \ - -e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \ - -e 's|@''HAVE_RAWMEMCHR''@|$(HAVE_RAWMEMCHR)|g' \ - -e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \ - -e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \ - -e 's|@''HAVE_STRCHRNUL''@|$(HAVE_STRCHRNUL)|g' \ - -e 's|@''HAVE_DECL_STRDUP''@|$(HAVE_DECL_STRDUP)|g' \ - -e 's|@''HAVE_DECL_STRNDUP''@|$(HAVE_DECL_STRNDUP)|g' \ - -e 's|@''HAVE_DECL_STRNLEN''@|$(HAVE_DECL_STRNLEN)|g' \ - -e 's|@''HAVE_STRPBRK''@|$(HAVE_STRPBRK)|g' \ - -e 's|@''HAVE_STRSEP''@|$(HAVE_STRSEP)|g' \ - -e 's|@''HAVE_STRCASESTR''@|$(HAVE_STRCASESTR)|g' \ - -e 's|@''HAVE_DECL_STRTOK_R''@|$(HAVE_DECL_STRTOK_R)|g' \ - -e 's|@''HAVE_DECL_STRSIGNAL''@|$(HAVE_DECL_STRSIGNAL)|g' \ - -e 's|@''HAVE_STRVERSCMP''@|$(HAVE_STRVERSCMP)|g' \ - -e 's|@''REPLACE_STPNCPY''@|$(REPLACE_STPNCPY)|g' \ - -e 's|@''REPLACE_MEMCHR''@|$(REPLACE_MEMCHR)|g' \ - -e 's|@''REPLACE_MEMMEM''@|$(REPLACE_MEMMEM)|g' \ - -e 's|@''REPLACE_STRCASESTR''@|$(REPLACE_STRCASESTR)|g' \ - -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \ - -e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \ - -e 's|@''REPLACE_STRERROR''@|$(REPLACE_STRERROR)|g' \ - -e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \ - -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \ - -e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \ - -e 's|@''REPLACE_STRSIGNAL''@|$(REPLACE_STRSIGNAL)|g' \ - -e 's|@''REPLACE_STRTOK_R''@|$(REPLACE_STRTOK_R)|g' \ - -e 's|@''UNDEFINE_STRTOK_R''@|$(UNDEFINE_STRTOK_R)|g' \ - -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ - -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ - -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ - < $(srcdir)/string.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += string.h string.h-t - -EXTRA_DIST += string.in.h - -## end gnulib module string - -## begin gnulib module strings - -BUILT_SOURCES += strings.h - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -strings.h: strings.in.h $(WARN_ON_USE_H) $(ARG_NONNULL_H) - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */' && \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_STRINGS_H''@|$(NEXT_STRINGS_H)|g' \ - -e 's|@''HAVE_STRCASECMP''@|$(HAVE_STRCASECMP)|g' \ - -e 's|@''HAVE_DECL_STRNCASECMP''@|$(HAVE_DECL_STRNCASECMP)|g' \ - -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ - -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ - < $(srcdir)/strings.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += strings.h strings.h-t - -EXTRA_DIST += strings.in.h - -## end gnulib module strings - -## begin gnulib module strndup - - -EXTRA_DIST += strndup.c - -EXTRA_libgnu_a_SOURCES += strndup.c - -## end gnulib module strndup - -## begin gnulib module strnlen - - -EXTRA_DIST += strnlen.c - -EXTRA_libgnu_a_SOURCES += strnlen.c - -## end gnulib module strnlen - -## begin gnulib module strnlen1 - -libgnu_a_SOURCES += strnlen1.h strnlen1.c - -## end gnulib module strnlen1 - -## begin gnulib module sys_wait - -BUILT_SOURCES += sys/wait.h - -# We need the following in order to create when the system -# has one that is incomplete. -sys/wait.h: sys_wait.in.h - $(AM_V_at)$(MKDIR_P) sys - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_SYS_WAIT_H''@|$(NEXT_SYS_WAIT_H)|g' \ - < $(srcdir)/sys_wait.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += sys/wait.h sys/wait.h-t -MOSTLYCLEANDIRS += sys - -EXTRA_DIST += sys_wait.in.h - -## end gnulib module sys_wait - -## begin gnulib module sysexits - -BUILT_SOURCES += $(SYSEXITS_H) - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -sysexits.h: sysexits.in.h - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's|@''HAVE_SYSEXITS_H''@|$(HAVE_SYSEXITS_H)|g' \ - -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_SYSEXITS_H''@|$(NEXT_SYSEXITS_H)|g' \ - < $(srcdir)/sysexits.in.h; \ - } > $@-t && \ - mv -f $@-t $@ -MOSTLYCLEANFILES += sysexits.h sysexits.h-t - -EXTRA_DIST += sysexits.in.h - -## end gnulib module sysexits - -## begin gnulib module unistd - -BUILT_SOURCES += unistd.h - -# We need the following in order to create an empty placeholder for -# when the system doesn't have one. -unistd.h: unistd.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's|@''HAVE_UNISTD_H''@|$(HAVE_UNISTD_H)|g' \ - -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_UNISTD_H''@|$(NEXT_UNISTD_H)|g' \ - -e 's|@''GNULIB_CHOWN''@|$(GNULIB_CHOWN)|g' \ - -e 's|@''GNULIB_CLOSE''@|$(GNULIB_CLOSE)|g' \ - -e 's|@''GNULIB_DUP2''@|$(GNULIB_DUP2)|g' \ - -e 's|@''GNULIB_DUP3''@|$(GNULIB_DUP3)|g' \ - -e 's|@''GNULIB_ENVIRON''@|$(GNULIB_ENVIRON)|g' \ - -e 's|@''GNULIB_EUIDACCESS''@|$(GNULIB_EUIDACCESS)|g' \ - -e 's|@''GNULIB_FACCESSAT''@|$(GNULIB_FACCESSAT)|g' \ - -e 's|@''GNULIB_FCHDIR''@|$(GNULIB_FCHDIR)|g' \ - -e 's|@''GNULIB_FCHOWNAT''@|$(GNULIB_FCHOWNAT)|g' \ - -e 's|@''GNULIB_FSYNC''@|$(GNULIB_FSYNC)|g' \ - -e 's|@''GNULIB_FTRUNCATE''@|$(GNULIB_FTRUNCATE)|g' \ - -e 's|@''GNULIB_GETCWD''@|$(GNULIB_GETCWD)|g' \ - -e 's|@''GNULIB_GETDOMAINNAME''@|$(GNULIB_GETDOMAINNAME)|g' \ - -e 's|@''GNULIB_GETDTABLESIZE''@|$(GNULIB_GETDTABLESIZE)|g' \ - -e 's|@''GNULIB_GETGROUPS''@|$(GNULIB_GETGROUPS)|g' \ - -e 's|@''GNULIB_GETHOSTNAME''@|$(GNULIB_GETHOSTNAME)|g' \ - -e 's|@''GNULIB_GETLOGIN''@|$(GNULIB_GETLOGIN)|g' \ - -e 's|@''GNULIB_GETLOGIN_R''@|$(GNULIB_GETLOGIN_R)|g' \ - -e 's|@''GNULIB_GETPAGESIZE''@|$(GNULIB_GETPAGESIZE)|g' \ - -e 's|@''GNULIB_GETUSERSHELL''@|$(GNULIB_GETUSERSHELL)|g' \ - -e 's|@''GNULIB_LCHOWN''@|$(GNULIB_LCHOWN)|g' \ - -e 's|@''GNULIB_LINK''@|$(GNULIB_LINK)|g' \ - -e 's|@''GNULIB_LINKAT''@|$(GNULIB_LINKAT)|g' \ - -e 's|@''GNULIB_LSEEK''@|$(GNULIB_LSEEK)|g' \ - -e 's|@''GNULIB_PIPE2''@|$(GNULIB_PIPE2)|g' \ - -e 's|@''GNULIB_PREAD''@|$(GNULIB_PREAD)|g' \ - -e 's|@''GNULIB_PWRITE''@|$(GNULIB_PWRITE)|g' \ - -e 's|@''GNULIB_READLINK''@|$(GNULIB_READLINK)|g' \ - -e 's|@''GNULIB_READLINKAT''@|$(GNULIB_READLINKAT)|g' \ - -e 's|@''GNULIB_RMDIR''@|$(GNULIB_RMDIR)|g' \ - -e 's|@''GNULIB_SLEEP''@|$(GNULIB_SLEEP)|g' \ - -e 's|@''GNULIB_SYMLINK''@|$(GNULIB_SYMLINK)|g' \ - -e 's|@''GNULIB_SYMLINKAT''@|$(GNULIB_SYMLINKAT)|g' \ - -e 's|@''GNULIB_TTYNAME_R''@|$(GNULIB_TTYNAME_R)|g' \ - -e 's|@''GNULIB_UNISTD_H_GETOPT''@|$(GNULIB_UNISTD_H_GETOPT)|g' \ - -e 's|@''GNULIB_UNISTD_H_SIGPIPE''@|$(GNULIB_UNISTD_H_SIGPIPE)|g' \ - -e 's|@''GNULIB_UNLINK''@|$(GNULIB_UNLINK)|g' \ - -e 's|@''GNULIB_UNLINKAT''@|$(GNULIB_UNLINKAT)|g' \ - -e 's|@''GNULIB_USLEEP''@|$(GNULIB_USLEEP)|g' \ - -e 's|@''GNULIB_WRITE''@|$(GNULIB_WRITE)|g' \ - < $(srcdir)/unistd.in.h | \ - sed -e 's|@''HAVE_CHOWN''@|$(HAVE_CHOWN)|g' \ - -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \ - -e 's|@''HAVE_DUP3''@|$(HAVE_DUP3)|g' \ - -e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \ - -e 's|@''HAVE_FACCESSAT''@|$(HAVE_FACCESSAT)|g' \ - -e 's|@''HAVE_FCHDIR''@|$(HAVE_FCHDIR)|g' \ - -e 's|@''HAVE_FCHOWNAT''@|$(HAVE_FCHOWNAT)|g' \ - -e 's|@''HAVE_FSYNC''@|$(HAVE_FSYNC)|g' \ - -e 's|@''HAVE_FTRUNCATE''@|$(HAVE_FTRUNCATE)|g' \ - -e 's|@''HAVE_GETDOMAINNAME''@|$(HAVE_GETDOMAINNAME)|g' \ - -e 's|@''HAVE_GETDTABLESIZE''@|$(HAVE_GETDTABLESIZE)|g' \ - -e 's|@''HAVE_GETGROUPS''@|$(HAVE_GETGROUPS)|g' \ - -e 's|@''HAVE_GETHOSTNAME''@|$(HAVE_GETHOSTNAME)|g' \ - -e 's|@''HAVE_GETLOGIN''@|$(HAVE_GETLOGIN)|g' \ - -e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \ - -e 's|@''HAVE_LCHOWN''@|$(HAVE_LCHOWN)|g' \ - -e 's|@''HAVE_LINK''@|$(HAVE_LINK)|g' \ - -e 's|@''HAVE_LINKAT''@|$(HAVE_LINKAT)|g' \ - -e 's|@''HAVE_PIPE2''@|$(HAVE_PIPE2)|g' \ - -e 's|@''HAVE_PREAD''@|$(HAVE_PREAD)|g' \ - -e 's|@''HAVE_PWRITE''@|$(HAVE_PWRITE)|g' \ - -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \ - -e 's|@''HAVE_READLINKAT''@|$(HAVE_READLINKAT)|g' \ - -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \ - -e 's|@''HAVE_SYMLINK''@|$(HAVE_SYMLINK)|g' \ - -e 's|@''HAVE_SYMLINKAT''@|$(HAVE_SYMLINKAT)|g' \ - -e 's|@''HAVE_TTYNAME_R''@|$(HAVE_TTYNAME_R)|g' \ - -e 's|@''HAVE_UNLINKAT''@|$(HAVE_UNLINKAT)|g' \ - -e 's|@''HAVE_USLEEP''@|$(HAVE_USLEEP)|g' \ - -e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \ - -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \ - -e 's|@''HAVE_DECL_GETPAGESIZE''@|$(HAVE_DECL_GETPAGESIZE)|g' \ - -e 's|@''HAVE_DECL_GETUSERSHELL''@|$(HAVE_DECL_GETUSERSHELL)|g' \ - -e 's|@''HAVE_OS_H''@|$(HAVE_OS_H)|g' \ - -e 's|@''HAVE_SYS_PARAM_H''@|$(HAVE_SYS_PARAM_H)|g' \ - -e 's|@''REPLACE_CHOWN''@|$(REPLACE_CHOWN)|g' \ - -e 's|@''REPLACE_CLOSE''@|$(REPLACE_CLOSE)|g' \ - -e 's|@''REPLACE_DUP''@|$(REPLACE_DUP)|g' \ - -e 's|@''REPLACE_DUP2''@|$(REPLACE_DUP2)|g' \ - -e 's|@''REPLACE_FCHOWNAT''@|$(REPLACE_FCHOWNAT)|g' \ - -e 's|@''REPLACE_GETCWD''@|$(REPLACE_GETCWD)|g' \ - -e 's|@''REPLACE_GETGROUPS''@|$(REPLACE_GETGROUPS)|g' \ - -e 's|@''REPLACE_GETPAGESIZE''@|$(REPLACE_GETPAGESIZE)|g' \ - -e 's|@''REPLACE_LCHOWN''@|$(REPLACE_LCHOWN)|g' \ - -e 's|@''REPLACE_LINK''@|$(REPLACE_LINK)|g' \ - -e 's|@''REPLACE_LINKAT''@|$(REPLACE_LINKAT)|g' \ - -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \ - -e 's|@''REPLACE_PREAD''@|$(REPLACE_PREAD)|g' \ - -e 's|@''REPLACE_PWRITE''@|$(REPLACE_PWRITE)|g' \ - -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \ - -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \ - -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \ - -e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \ - -e 's|@''REPLACE_TTYNAME_R''@|$(REPLACE_TTYNAME_R)|g' \ - -e 's|@''REPLACE_UNLINK''@|$(REPLACE_UNLINK)|g' \ - -e 's|@''REPLACE_UNLINKAT''@|$(REPLACE_UNLINKAT)|g' \ - -e 's|@''REPLACE_USLEEP''@|$(REPLACE_USLEEP)|g' \ - -e 's|@''REPLACE_WRITE''@|$(REPLACE_WRITE)|g' \ - -e 's|@''UNISTD_H_HAVE_WINSOCK2_H''@|$(UNISTD_H_HAVE_WINSOCK2_H)|g' \ - -e 's|@''UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS''@|$(UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS)|g' \ - -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ - -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ - -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += unistd.h unistd.h-t - -EXTRA_DIST += unistd.in.h - -## end gnulib module unistd - -## begin gnulib module vasnprintf - - -EXTRA_DIST += asnprintf.c float+.h printf-args.c printf-args.h printf-parse.c printf-parse.h vasnprintf.c vasnprintf.h - -EXTRA_libgnu_a_SOURCES += asnprintf.c printf-args.c printf-parse.c vasnprintf.c - -## end gnulib module vasnprintf - -## begin gnulib module verify - -libgnu_a_SOURCES += verify.h - -## end gnulib module verify - -## begin gnulib module vsnprintf - - -EXTRA_DIST += vsnprintf.c - -EXTRA_libgnu_a_SOURCES += vsnprintf.c - -## end gnulib module vsnprintf - -## begin gnulib module warn-on-use - -BUILT_SOURCES += warn-on-use.h -# The warn-on-use.h that gets inserted into generated .h files is the same as -# build-aux/warn-on-use.h, except that it has the copyright header cut off. -warn-on-use.h: $(top_srcdir)/build-aux/warn-on-use.h - $(AM_V_GEN)rm -f $@-t $@ && \ - sed -n -e '/^.ifndef/,$$p' \ - < $(top_srcdir)/build-aux/warn-on-use.h \ - > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += warn-on-use.h warn-on-use.h-t - -WARN_ON_USE_H=warn-on-use.h - -EXTRA_DIST += $(top_srcdir)/build-aux/warn-on-use.h - -## end gnulib module warn-on-use - -## begin gnulib module wchar - -BUILT_SOURCES += wchar.h - -# We need the following in order to create when the system -# version does not work standalone. -wchar.h: wchar.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H) - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_WCHAR_H''@|$(NEXT_WCHAR_H)|g' \ - -e 's|@''HAVE_WCHAR_H''@|$(HAVE_WCHAR_H)|g' \ - -e 's|@''GNULIB_BTOWC''@|$(GNULIB_BTOWC)|g' \ - -e 's|@''GNULIB_WCTOB''@|$(GNULIB_WCTOB)|g' \ - -e 's|@''GNULIB_MBSINIT''@|$(GNULIB_MBSINIT)|g' \ - -e 's|@''GNULIB_MBRTOWC''@|$(GNULIB_MBRTOWC)|g' \ - -e 's|@''GNULIB_MBRLEN''@|$(GNULIB_MBRLEN)|g' \ - -e 's|@''GNULIB_MBSRTOWCS''@|$(GNULIB_MBSRTOWCS)|g' \ - -e 's|@''GNULIB_MBSNRTOWCS''@|$(GNULIB_MBSNRTOWCS)|g' \ - -e 's|@''GNULIB_WCRTOMB''@|$(GNULIB_WCRTOMB)|g' \ - -e 's|@''GNULIB_WCSRTOMBS''@|$(GNULIB_WCSRTOMBS)|g' \ - -e 's|@''GNULIB_WCSNRTOMBS''@|$(GNULIB_WCSNRTOMBS)|g' \ - -e 's|@''GNULIB_WCWIDTH''@|$(GNULIB_WCWIDTH)|g' \ - -e 's|@''HAVE_WINT_T''@|$(HAVE_WINT_T)|g' \ - -e 's|@''HAVE_BTOWC''@|$(HAVE_BTOWC)|g' \ - -e 's|@''HAVE_MBSINIT''@|$(HAVE_MBSINIT)|g' \ - -e 's|@''HAVE_MBRTOWC''@|$(HAVE_MBRTOWC)|g' \ - -e 's|@''HAVE_MBRLEN''@|$(HAVE_MBRLEN)|g' \ - -e 's|@''HAVE_MBSRTOWCS''@|$(HAVE_MBSRTOWCS)|g' \ - -e 's|@''HAVE_MBSNRTOWCS''@|$(HAVE_MBSNRTOWCS)|g' \ - -e 's|@''HAVE_WCRTOMB''@|$(HAVE_WCRTOMB)|g' \ - -e 's|@''HAVE_WCSRTOMBS''@|$(HAVE_WCSRTOMBS)|g' \ - -e 's|@''HAVE_WCSNRTOMBS''@|$(HAVE_WCSNRTOMBS)|g' \ - -e 's|@''HAVE_DECL_WCTOB''@|$(HAVE_DECL_WCTOB)|g' \ - -e 's|@''HAVE_DECL_WCWIDTH''@|$(HAVE_DECL_WCWIDTH)|g' \ - -e 's|@''REPLACE_MBSTATE_T''@|$(REPLACE_MBSTATE_T)|g' \ - -e 's|@''REPLACE_BTOWC''@|$(REPLACE_BTOWC)|g' \ - -e 's|@''REPLACE_WCTOB''@|$(REPLACE_WCTOB)|g' \ - -e 's|@''REPLACE_MBSINIT''@|$(REPLACE_MBSINIT)|g' \ - -e 's|@''REPLACE_MBRTOWC''@|$(REPLACE_MBRTOWC)|g' \ - -e 's|@''REPLACE_MBRLEN''@|$(REPLACE_MBRLEN)|g' \ - -e 's|@''REPLACE_MBSRTOWCS''@|$(REPLACE_MBSRTOWCS)|g' \ - -e 's|@''REPLACE_MBSNRTOWCS''@|$(REPLACE_MBSNRTOWCS)|g' \ - -e 's|@''REPLACE_WCRTOMB''@|$(REPLACE_WCRTOMB)|g' \ - -e 's|@''REPLACE_WCSRTOMBS''@|$(REPLACE_WCSRTOMBS)|g' \ - -e 's|@''REPLACE_WCSNRTOMBS''@|$(REPLACE_WCSNRTOMBS)|g' \ - -e 's|@''REPLACE_WCWIDTH''@|$(REPLACE_WCWIDTH)|g' \ - -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ - -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ - -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ - < $(srcdir)/wchar.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += wchar.h wchar.h-t - -EXTRA_DIST += wchar.in.h - -## end gnulib module wchar - -## begin gnulib module wcrtomb - - -EXTRA_DIST += wcrtomb.c - -EXTRA_libgnu_a_SOURCES += wcrtomb.c - -## end gnulib module wcrtomb - -## begin gnulib module wctype - -BUILT_SOURCES += wctype.h - -# We need the following in order to create when the system -# doesn't have one that works with the given compiler. -wctype.h: wctype.in.h $(CXXDEFS_H) $(WARN_ON_USE_H) - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's/@''HAVE_WCTYPE_H''@/$(HAVE_WCTYPE_H)/g' \ - -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_WCTYPE_H''@|$(NEXT_WCTYPE_H)|g' \ - -e 's/@''HAVE_ISWBLANK''@/$(HAVE_ISWBLANK)/g' \ - -e 's/@''HAVE_ISWCNTRL''@/$(HAVE_ISWCNTRL)/g' \ - -e 's/@''HAVE_WINT_T''@/$(HAVE_WINT_T)/g' \ - -e 's/@''REPLACE_ISWBLANK''@/$(REPLACE_ISWBLANK)/g' \ - -e 's/@''REPLACE_ISWCNTRL''@/$(REPLACE_ISWCNTRL)/g' \ - -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ - -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ - < $(srcdir)/wctype.in.h; \ - } > $@-t && \ - mv $@-t $@ -MOSTLYCLEANFILES += wctype.h wctype.h-t - -EXTRA_DIST += wctype.in.h - -## end gnulib module wctype - -## begin gnulib module xsize - -libgnu_a_SOURCES += xsize.h - -## end gnulib module xsize - - -mostlyclean-local: mostlyclean-generic - @for dir in '' $(MOSTLYCLEANDIRS); do \ - if test -n "$$dir" && test -d $$dir; then \ - echo "rmdir $$dir"; rmdir $$dir; \ - fi; \ - done; \ - : diff --git a/grub-core/gnulib/alloca.c b/grub-core/gnulib/alloca.c deleted file mode 100644 index 75afdb960..000000000 --- a/grub-core/gnulib/alloca.c +++ /dev/null @@ -1,489 +0,0 @@ -/* alloca.c -- allocate automatically reclaimed memory - (Mostly) portable public-domain implementation -- D A Gwyn - - This implementation of the PWB library alloca function, - which is used to allocate space off the run-time stack so - that it is automatically reclaimed upon procedure exit, - was inspired by discussions with J. Q. Johnson of Cornell. - J.Otto Tennant contributed the Cray support. - - There are some preprocessor constants that can - be defined when compiling for your specific system, for - improved efficiency; however, the defaults should be okay. - - The general concept of this implementation is to keep - track of all alloca-allocated blocks, and reclaim any - that are found to be deeper in the stack than the current - invocation. This heuristic does not reclaim storage as - soon as it becomes invalid, but it will do so eventually. - - As a special case, alloca(0) reclaims storage without - allocating any. It is a good idea to use alloca(0) in - your main control loop, etc. to force garbage collection. */ - -#include - -#include - -#include -#include - -#ifdef emacs -# include "lisp.h" -# include "blockinput.h" -# ifdef EMACS_FREE -# undef free -# define free EMACS_FREE -# endif -#else -# define memory_full() abort () -#endif - -/* If compiling with GCC 2, this file's not needed. */ -#if !defined (__GNUC__) || __GNUC__ < 2 - -/* If someone has defined alloca as a macro, - there must be some other way alloca is supposed to work. */ -# ifndef alloca - -# ifdef emacs -# ifdef static -/* actually, only want this if static is defined as "" - -- this is for usg, in which emacs must undefine static - in order to make unexec workable - */ -# ifndef STACK_DIRECTION -you -lose --- must know STACK_DIRECTION at compile-time -/* Using #error here is not wise since this file should work for - old and obscure compilers. */ -# endif /* STACK_DIRECTION undefined */ -# endif /* static */ -# endif /* emacs */ - -/* If your stack is a linked list of frames, you have to - provide an "address metric" ADDRESS_FUNCTION macro. */ - -# if defined (CRAY) && defined (CRAY_STACKSEG_END) -long i00afunc (); -# define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) -# else -# define ADDRESS_FUNCTION(arg) &(arg) -# endif - -/* Define STACK_DIRECTION if you know the direction of stack - growth for your system; otherwise it will be automatically - deduced at run-time. - - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ - -# ifndef STACK_DIRECTION -# define STACK_DIRECTION 0 /* Direction unknown. */ -# endif - -# if STACK_DIRECTION != 0 - -# define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ - -# else /* STACK_DIRECTION == 0; need run-time code. */ - -static int stack_dir; /* 1 or -1 once known. */ -# define STACK_DIR stack_dir - -static void -find_stack_direction (void) -{ - static char *addr = NULL; /* Address of first `dummy', once known. */ - auto char dummy; /* To get stack address. */ - - if (addr == NULL) - { /* Initial entry. */ - addr = ADDRESS_FUNCTION (dummy); - - find_stack_direction (); /* Recurse once. */ - } - else - { - /* Second entry. */ - if (ADDRESS_FUNCTION (dummy) > addr) - stack_dir = 1; /* Stack grew upward. */ - else - stack_dir = -1; /* Stack grew downward. */ - } -} - -# endif /* STACK_DIRECTION == 0 */ - -/* An "alloca header" is used to: - (a) chain together all alloca'ed blocks; - (b) keep track of stack depth. - - It is very important that sizeof(header) agree with malloc - alignment chunk size. The following default should work okay. */ - -# ifndef ALIGN_SIZE -# define ALIGN_SIZE sizeof(double) -# endif - -typedef union hdr -{ - char align[ALIGN_SIZE]; /* To force sizeof(header). */ - struct - { - union hdr *next; /* For chaining headers. */ - char *deep; /* For stack depth measure. */ - } h; -} header; - -static header *last_alloca_header = NULL; /* -> last alloca header. */ - -/* Return a pointer to at least SIZE bytes of storage, - which will be automatically reclaimed upon exit from - the procedure that called alloca. Originally, this space - was supposed to be taken from the current stack frame of the - caller, but that method cannot be made to work for some - implementations of C, for example under Gould's UTX/32. */ - -void * -alloca (size_t size) -{ - auto char probe; /* Probes stack depth: */ - register char *depth = ADDRESS_FUNCTION (probe); - -# if STACK_DIRECTION == 0 - if (STACK_DIR == 0) /* Unknown growth direction. */ - find_stack_direction (); -# endif - - /* Reclaim garbage, defined as all alloca'd storage that - was allocated from deeper in the stack than currently. */ - - { - register header *hp; /* Traverses linked list. */ - -# ifdef emacs - BLOCK_INPUT; -# endif - - for (hp = last_alloca_header; hp != NULL;) - if ((STACK_DIR > 0 && hp->h.deep > depth) - || (STACK_DIR < 0 && hp->h.deep < depth)) - { - register header *np = hp->h.next; - - free (hp); /* Collect garbage. */ - - hp = np; /* -> next header. */ - } - else - break; /* Rest are not deeper. */ - - last_alloca_header = hp; /* -> last valid storage. */ - -# ifdef emacs - UNBLOCK_INPUT; -# endif - } - - if (size == 0) - return NULL; /* No allocation required. */ - - /* Allocate combined header + user data storage. */ - - { - /* Address of header. */ - register header *new; - - size_t combined_size = sizeof (header) + size; - if (combined_size < sizeof (header)) - memory_full (); - - new = malloc (combined_size); - - if (! new) - memory_full (); - - new->h.next = last_alloca_header; - new->h.deep = depth; - - last_alloca_header = new; - - /* User storage begins just after header. */ - - return (void *) (new + 1); - } -} - -# if defined (CRAY) && defined (CRAY_STACKSEG_END) - -# ifdef DEBUG_I00AFUNC -# include -# endif - -# ifndef CRAY_STACK -# define CRAY_STACK -# ifndef CRAY2 -/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ -struct stack_control_header - { - long shgrow:32; /* Number of times stack has grown. */ - long shaseg:32; /* Size of increments to stack. */ - long shhwm:32; /* High water mark of stack. */ - long shsize:32; /* Current size of stack (all segments). */ - }; - -/* The stack segment linkage control information occurs at - the high-address end of a stack segment. (The stack - grows from low addresses to high addresses.) The initial - part of the stack segment linkage control information is - 0200 (octal) words. This provides for register storage - for the routine which overflows the stack. */ - -struct stack_segment_linkage - { - long ss[0200]; /* 0200 overflow words. */ - long sssize:32; /* Number of words in this segment. */ - long ssbase:32; /* Offset to stack base. */ - long:32; - long sspseg:32; /* Offset to linkage control of previous - segment of stack. */ - long:32; - long sstcpt:32; /* Pointer to task common address block. */ - long sscsnm; /* Private control structure number for - microtasking. */ - long ssusr1; /* Reserved for user. */ - long ssusr2; /* Reserved for user. */ - long sstpid; /* Process ID for pid based multi-tasking. */ - long ssgvup; /* Pointer to multitasking thread giveup. */ - long sscray[7]; /* Reserved for Cray Research. */ - long ssa0; - long ssa1; - long ssa2; - long ssa3; - long ssa4; - long ssa5; - long ssa6; - long ssa7; - long sss0; - long sss1; - long sss2; - long sss3; - long sss4; - long sss5; - long sss6; - long sss7; - }; - -# else /* CRAY2 */ -/* The following structure defines the vector of words - returned by the STKSTAT library routine. */ -struct stk_stat - { - long now; /* Current total stack size. */ - long maxc; /* Amount of contiguous space which would - be required to satisfy the maximum - stack demand to date. */ - long high_water; /* Stack high-water mark. */ - long overflows; /* Number of stack overflow ($STKOFEN) calls. */ - long hits; /* Number of internal buffer hits. */ - long extends; /* Number of block extensions. */ - long stko_mallocs; /* Block allocations by $STKOFEN. */ - long underflows; /* Number of stack underflow calls ($STKRETN). */ - long stko_free; /* Number of deallocations by $STKRETN. */ - long stkm_free; /* Number of deallocations by $STKMRET. */ - long segments; /* Current number of stack segments. */ - long maxs; /* Maximum number of stack segments so far. */ - long pad_size; /* Stack pad size. */ - long current_address; /* Current stack segment address. */ - long current_size; /* Current stack segment size. This - number is actually corrupted by STKSTAT to - include the fifteen word trailer area. */ - long initial_address; /* Address of initial segment. */ - long initial_size; /* Size of initial segment. */ - }; - -/* The following structure describes the data structure which trails - any stack segment. I think that the description in 'asdef' is - out of date. I only describe the parts that I am sure about. */ - -struct stk_trailer - { - long this_address; /* Address of this block. */ - long this_size; /* Size of this block (does not include - this trailer). */ - long unknown2; - long unknown3; - long link; /* Address of trailer block of previous - segment. */ - long unknown5; - long unknown6; - long unknown7; - long unknown8; - long unknown9; - long unknown10; - long unknown11; - long unknown12; - long unknown13; - long unknown14; - }; - -# endif /* CRAY2 */ -# endif /* not CRAY_STACK */ - -# ifdef CRAY2 -/* Determine a "stack measure" for an arbitrary ADDRESS. - I doubt that "lint" will like this much. */ - -static long -i00afunc (long *address) -{ - struct stk_stat status; - struct stk_trailer *trailer; - long *block, size; - long result = 0; - - /* We want to iterate through all of the segments. The first - step is to get the stack status structure. We could do this - more quickly and more directly, perhaps, by referencing the - $LM00 common block, but I know that this works. */ - - STKSTAT (&status); - - /* Set up the iteration. */ - - trailer = (struct stk_trailer *) (status.current_address - + status.current_size - - 15); - - /* There must be at least one stack segment. Therefore it is - a fatal error if "trailer" is null. */ - - if (trailer == 0) - abort (); - - /* Discard segments that do not contain our argument address. */ - - while (trailer != 0) - { - block = (long *) trailer->this_address; - size = trailer->this_size; - if (block == 0 || size == 0) - abort (); - trailer = (struct stk_trailer *) trailer->link; - if ((block <= address) && (address < (block + size))) - break; - } - - /* Set the result to the offset in this segment and add the sizes - of all predecessor segments. */ - - result = address - block; - - if (trailer == 0) - { - return result; - } - - do - { - if (trailer->this_size <= 0) - abort (); - result += trailer->this_size; - trailer = (struct stk_trailer *) trailer->link; - } - while (trailer != 0); - - /* We are done. Note that if you present a bogus address (one - not in any segment), you will get a different number back, formed - from subtracting the address of the first block. This is probably - not what you want. */ - - return (result); -} - -# else /* not CRAY2 */ -/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. - Determine the number of the cell within the stack, - given the address of the cell. The purpose of this - routine is to linearize, in some sense, stack addresses - for alloca. */ - -static long -i00afunc (long address) -{ - long stkl = 0; - - long size, pseg, this_segment, stack; - long result = 0; - - struct stack_segment_linkage *ssptr; - - /* Register B67 contains the address of the end of the - current stack segment. If you (as a subprogram) store - your registers on the stack and find that you are past - the contents of B67, you have overflowed the segment. - - B67 also points to the stack segment linkage control - area, which is what we are really interested in. */ - - stkl = CRAY_STACKSEG_END (); - ssptr = (struct stack_segment_linkage *) stkl; - - /* If one subtracts 'size' from the end of the segment, - one has the address of the first word of the segment. - - If this is not the first segment, 'pseg' will be - nonzero. */ - - pseg = ssptr->sspseg; - size = ssptr->sssize; - - this_segment = stkl - size; - - /* It is possible that calling this routine itself caused - a stack overflow. Discard stack segments which do not - contain the target address. */ - - while (!(this_segment <= address && address <= stkl)) - { -# ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); -# endif - if (pseg == 0) - break; - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - this_segment = stkl - size; - } - - result = address - this_segment; - - /* If you subtract pseg from the current end of the stack, - you get the address of the previous stack segment's end. - This seems a little convoluted to me, but I'll bet you save - a cycle somewhere. */ - - while (pseg != 0) - { -# ifdef DEBUG_I00AFUNC - fprintf (stderr, "%011o %011o\n", pseg, size); -# endif - stkl = stkl - pseg; - ssptr = (struct stack_segment_linkage *) stkl; - size = ssptr->sssize; - pseg = ssptr->sspseg; - result += size; - } - return (result); -} - -# endif /* not CRAY2 */ -# endif /* CRAY */ - -# endif /* no alloca */ -#endif /* not GCC version 3 */ diff --git a/grub-core/gnulib/alloca.in.h b/grub-core/gnulib/alloca.in.h deleted file mode 100644 index 44f20b7a1..000000000 --- a/grub-core/gnulib/alloca.in.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Memory allocation on the stack. - - Copyright (C) 1995, 1999, 2001-2004, 2006-2010 Free Software Foundation, - 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - USA. */ - -/* Avoid using the symbol _ALLOCA_H here, as Bison assumes _ALLOCA_H - means there is a real alloca function. */ -#ifndef _GL_ALLOCA_H -#define _GL_ALLOCA_H - -/* alloca (N) returns a pointer to N bytes of memory - allocated on the stack, which will last until the function returns. - Use of alloca should be avoided: - - inside arguments of function calls - undefined behaviour, - - in inline functions - the allocation may actually last until the - calling function returns, - - for huge N (say, N >= 65536) - you never know how large (or small) - the stack is, and when the stack cannot fulfill the memory allocation - request, the program just crashes. - */ - -#ifndef alloca -# ifdef __GNUC__ -# define alloca __builtin_alloca -# elif defined _AIX -# define alloca __alloca -# elif defined _MSC_VER -# include -# define alloca _alloca -# elif defined __DECC && defined __VMS -# define alloca __ALLOCA -# else -# include -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -# endif -#endif - -#endif /* _GL_ALLOCA_H */ diff --git a/grub-core/gnulib/argp-ba.c b/grub-core/gnulib/argp-ba.c deleted file mode 100644 index 95feabb86..000000000 --- a/grub-core/gnulib/argp-ba.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Default definition for ARGP_PROGRAM_BUG_ADDRESS. - Copyright (C) 1996, 1997, 1999, 2009, 2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* If set by the user program, it should point to string that is the - bug-reporting address for the program. It will be printed by argp_help if - the ARGP_HELP_BUG_ADDR flag is set (as it is by various standard help - messages), embedded in a sentence that says something like `Report bugs to - ADDR.'. */ -const char *argp_program_bug_address -/* This variable should be zero-initialized. On most systems, putting it into - BSS is sufficient. Not so on MacOS X 10.3 and 10.4, see - - . */ -#if defined __ELF__ - /* On ELF systems, variables in BSS behave well. */ -#else - = (const char *) 0 -#endif - ; diff --git a/grub-core/gnulib/argp-eexst.c b/grub-core/gnulib/argp-eexst.c deleted file mode 100644 index 115a8cd5d..000000000 --- a/grub-core/gnulib/argp-eexst.c +++ /dev/null @@ -1,30 +0,0 @@ -/* Default definition for ARGP_ERR_EXIT_STATUS - Copyright (C) 1997, 2009, 2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "argp.h" - -/* The exit status that argp will use when exiting due to a parsing error. - If not defined or set by the user program, this defaults to EX_USAGE from - . */ -error_t argp_err_exit_status = EX_USAGE; diff --git a/grub-core/gnulib/argp-fmtstream.c b/grub-core/gnulib/argp-fmtstream.c deleted file mode 100644 index 248a09a3b..000000000 --- a/grub-core/gnulib/argp-fmtstream.c +++ /dev/null @@ -1,489 +0,0 @@ -/* Word-wrapping and line-truncating streams - Copyright (C) 1997-1999, 2001-2003, 2005, 2009-2010 Free Software - Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* This package emulates glibc `line_wrap_stream' semantics for systems that - don't have that. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include -#include - -#include "argp-fmtstream.h" -#include "argp-namefrob.h" - -#ifndef ARGP_FMTSTREAM_USE_LINEWRAP - -#ifndef isblank -#define isblank(ch) ((ch)==' ' || (ch)=='\t') -#endif - -#if defined _LIBC && defined USE_IN_LIBIO -# include -# include -# define __vsnprintf(s, l, f, a) _IO_vsnprintf (s, l, f, a) -#endif - -#define INIT_BUF_SIZE 200 -#define PRINTF_SIZE_GUESS 150 - -/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines - written on it with LMARGIN spaces and limits them to RMARGIN columns - total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by - replacing the whitespace before them with a newline and WMARGIN spaces. - Otherwise, chars beyond RMARGIN are simply dropped until a newline. - Returns NULL if there was an error. */ -argp_fmtstream_t -__argp_make_fmtstream (FILE *stream, - size_t lmargin, size_t rmargin, ssize_t wmargin) -{ - argp_fmtstream_t fs; - - fs = (struct argp_fmtstream *) malloc (sizeof (struct argp_fmtstream)); - if (fs != NULL) - { - fs->stream = stream; - - fs->lmargin = lmargin; - fs->rmargin = rmargin; - fs->wmargin = wmargin; - fs->point_col = 0; - fs->point_offs = 0; - - fs->buf = (char *) malloc (INIT_BUF_SIZE); - if (! fs->buf) - { - free (fs); - fs = 0; - } - else - { - fs->p = fs->buf; - fs->end = fs->buf + INIT_BUF_SIZE; - } - } - - return fs; -} -#if 0 -/* Not exported. */ -#ifdef weak_alias -weak_alias (__argp_make_fmtstream, argp_make_fmtstream) -#endif -#endif - -/* Flush FS to its stream, and free it (but don't close the stream). */ -void -__argp_fmtstream_free (argp_fmtstream_t fs) -{ - __argp_fmtstream_update (fs); - if (fs->p > fs->buf) - { -#ifdef USE_IN_LIBIO - __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf); -#else - fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); -#endif - } - free (fs->buf); - free (fs); -} -#if 0 -/* Not exported. */ -#ifdef weak_alias -weak_alias (__argp_fmtstream_free, argp_fmtstream_free) -#endif -#endif - - -size_t -__argp_get_display_len (const char *beg, const char *end) -{ - const char *ptr; - size_t r = 0; - mbstate_t ps; - - memset (&ps, 0, sizeof (ps)); - - for (ptr = beg; ptr < end && *ptr; ) - { - wchar_t wc; - size_t s; - - s = mbrtowc (&wc, ptr, end - ptr, &ps); - if (s == (size_t) -1) - break; - r += wcwidth (wc); - ptr += s; - } - return r; -} - -static inline char * -add_length (char *ptr, char *end, size_t l) -{ - mbstate_t ps; - - memset (&ps, 0, sizeof (ps)); - - while (ptr < end && *ptr) - { - wchar_t wc; - size_t s, k; - - s = mbrtowc (&wc, ptr, end - ptr, &ps); - if (s == (size_t) -1) - break; - k = wcwidth (wc); - if (k >= l) - break; - l -= k; - ptr += s; - } - return ptr; -} - -/* Process FS's buffer so that line wrapping is done from POINT_OFFS to the - end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ -void -__argp_fmtstream_update (argp_fmtstream_t fs) -{ - char *buf, *nl; - size_t len; - - /* Scan the buffer for newlines. */ - buf = fs->buf + fs->point_offs; - while (buf < fs->p) - { - size_t r; - - if (fs->point_col == 0 && fs->lmargin != 0) - { - /* We are starting a new line. Print spaces to the left margin. */ - const size_t pad = fs->lmargin; - if (fs->p + pad < fs->end) - { - /* We can fit in them in the buffer by moving the - buffer text up and filling in the beginning. */ - memmove (buf + pad, buf, fs->p - buf); - fs->p += pad; /* Compensate for bigger buffer. */ - memset (buf, ' ', pad); /* Fill in the spaces. */ - buf += pad; /* Don't bother searching them. */ - } - else - { - /* No buffer space for spaces. Must flush. */ - size_t i; - for (i = 0; i < pad; i++) - { -#ifdef USE_IN_LIBIO - if (_IO_fwide (fs->stream, 0) > 0) - putwc_unlocked (L' ', fs->stream); - else -#endif - putc_unlocked (' ', fs->stream); - } - } - fs->point_col = pad; - } - - len = fs->p - buf; - nl = memchr (buf, '\n', len); - - if (fs->point_col < 0) - fs->point_col = 0; - - if (!nl) - { - size_t display_len = __argp_get_display_len (buf, fs->p); - /* The buffer ends in a partial line. */ - - if (fs->point_col + display_len < fs->rmargin) - { - /* The remaining buffer text is a partial line and fits - within the maximum line width. Advance point for the - characters to be written and stop scanning. */ - fs->point_col += display_len; - break; - } - else - /* Set the end-of-line pointer for the code below to - the end of the buffer. */ - nl = fs->p; - } - else - { - size_t display_len = __argp_get_display_len (buf, nl); - if (display_len < (ssize_t) fs->rmargin) - { - /* The buffer contains a full line that fits within the maximum - line width. Reset point and scan the next line. */ - fs->point_col = 0; - buf = nl + 1; - continue; - } - } - - /* This line is too long. */ - r = fs->rmargin - 1; - - if (fs->wmargin < 0) - { - /* Truncate the line by overwriting the excess with the - newline and anything after it in the buffer. */ - if (nl < fs->p) - { - memmove (buf + (r - fs->point_col), nl, fs->p - nl); - fs->p -= buf + (r - fs->point_col) - nl; - /* Reset point for the next line and start scanning it. */ - fs->point_col = 0; - buf += r + 1; /* Skip full line plus \n. */ - } - else - { - /* The buffer ends with a partial line that is beyond the - maximum line width. Advance point for the characters - written, and discard those past the max from the buffer. */ - fs->point_col += len; - fs->p -= fs->point_col - r; - break; - } - } - else - { - /* Do word wrap. Go to the column just past the maximum line - width and scan back for the beginning of the word there. - Then insert a line break. */ - - char *p, *nextline; - int i; - - p = add_length (buf, fs->p, (r + 1 - fs->point_col)); - while (p >= buf && !isblank ((unsigned char) *p)) - --p; - nextline = p + 1; /* This will begin the next line. */ - - if (nextline > buf) - { - /* Swallow separating blanks. */ - if (p >= buf) - do - --p; - while (p >= buf && isblank ((unsigned char) *p)); - nl = p + 1; /* The newline will replace the first blank. */ - } - else - { - /* A single word that is greater than the maximum line width. - Oh well. Put it on an overlong line by itself. */ - p = add_length (buf, fs->p, (r + 1 - fs->point_col)); - /* Find the end of the long word. */ - if (p < nl) - do - ++p; - while (p < nl && !isblank ((unsigned char) *p)); - if (p == nl) - { - /* It already ends a line. No fussing required. */ - fs->point_col = 0; - buf = nl + 1; - continue; - } - /* We will move the newline to replace the first blank. */ - nl = p; - /* Swallow separating blanks. */ - do - ++p; - while (isblank ((unsigned char) *p)); - /* The next line will start here. */ - nextline = p; - } - - /* Note: There are a bunch of tests below for - NEXTLINE == BUF + LEN + 1; this case is where NL happens to fall - at the end of the buffer, and NEXTLINE is in fact empty (and so - we need not be careful to maintain its contents). */ - - if ((nextline == buf + len + 1 - ? fs->end - nl < fs->wmargin + 1 - : nextline - (nl + 1) < fs->wmargin) - && fs->p > nextline) - { - /* The margin needs more blanks than we removed. */ - if (__argp_get_display_len (fs->p, fs->end) > fs->wmargin + 1) - /* Make some space for them. */ - { - size_t mv = fs->p - nextline; - memmove (nl + 1 + fs->wmargin, nextline, mv); - nextline = nl + 1 + fs->wmargin; - len = nextline + mv - buf; - *nl++ = '\n'; - } - else - /* Output the first line so we can use the space. */ - { -#ifdef _LIBC - __fxprintf (fs->stream, "%.*s\n", - (int) (nl - fs->buf), fs->buf); -#else - if (nl > fs->buf) - fwrite_unlocked (fs->buf, 1, nl - fs->buf, fs->stream); - putc_unlocked ('\n', fs->stream); -#endif - - len += buf - fs->buf; - nl = buf = fs->buf; - } - } - else - /* We can fit the newline and blanks in before - the next word. */ - *nl++ = '\n'; - - if (nextline - nl >= fs->wmargin - || (nextline == buf + len + 1 && fs->end - nextline >= fs->wmargin)) - /* Add blanks up to the wrap margin column. */ - for (i = 0; i < fs->wmargin; ++i) - *nl++ = ' '; - else - for (i = 0; i < fs->wmargin; ++i) -#ifdef USE_IN_LIBIO - if (_IO_fwide (fs->stream, 0) > 0) - putwc_unlocked (L' ', fs->stream); - else -#endif - putc_unlocked (' ', fs->stream); - - /* Copy the tail of the original buffer into the current buffer - position. */ - if (nl < nextline) - memmove (nl, nextline, buf + len - nextline); - len -= nextline - buf; - - /* Continue the scan on the remaining lines in the buffer. */ - buf = nl; - - /* Restore bufp to include all the remaining text. */ - fs->p = nl + len; - - /* Reset the counter of what has been output this line. If wmargin - is 0, we want to avoid the lmargin getting added, so we set - point_col to a magic value of -1 in that case. */ - fs->point_col = fs->wmargin ? fs->wmargin : -1; - } - } - - /* Remember that we've scanned as far as the end of the buffer. */ - fs->point_offs = fs->p - fs->buf; -} - -/* Ensure that FS has space for AMOUNT more bytes in its buffer, either by - growing the buffer, or by flushing it. True is returned iff we succeed. */ -int -__argp_fmtstream_ensure (struct argp_fmtstream *fs, size_t amount) -{ - if ((size_t) (fs->end - fs->p) < amount) - { - ssize_t wrote; - - /* Flush FS's buffer. */ - __argp_fmtstream_update (fs); - -#ifdef _LIBC - __fxprintf (fs->stream, "%.*s", (int) (fs->p - fs->buf), fs->buf); - wrote = fs->p - fs->buf; -#else - wrote = fwrite_unlocked (fs->buf, 1, fs->p - fs->buf, fs->stream); -#endif - if (wrote == fs->p - fs->buf) - { - fs->p = fs->buf; - fs->point_offs = 0; - } - else - { - fs->p -= wrote; - fs->point_offs -= wrote; - memmove (fs->buf, fs->buf + wrote, fs->p - fs->buf); - return 0; - } - - if ((size_t) (fs->end - fs->buf) < amount) - /* Gotta grow the buffer. */ - { - size_t old_size = fs->end - fs->buf; - size_t new_size = old_size + amount; - char *new_buf; - - if (new_size < old_size || ! (new_buf = realloc (fs->buf, new_size))) - { - __set_errno (ENOMEM); - return 0; - } - - fs->buf = new_buf; - fs->end = new_buf + new_size; - fs->p = fs->buf; - } - } - - return 1; -} - -ssize_t -__argp_fmtstream_printf (struct argp_fmtstream *fs, const char *fmt, ...) -{ - int out; - size_t avail; - size_t size_guess = PRINTF_SIZE_GUESS; /* How much space to reserve. */ - - do - { - va_list args; - - if (! __argp_fmtstream_ensure (fs, size_guess)) - return -1; - - va_start (args, fmt); - avail = fs->end - fs->p; - out = __vsnprintf (fs->p, avail, fmt, args); - va_end (args); - if ((size_t) out >= avail) - size_guess = out + 1; - } - while ((size_t) out >= avail); - - fs->p += out; - - return out; -} -#if 0 -/* Not exported. */ -#ifdef weak_alias -weak_alias (__argp_fmtstream_printf, argp_fmtstream_printf) -#endif -#endif - -#endif /* !ARGP_FMTSTREAM_USE_LINEWRAP */ diff --git a/grub-core/gnulib/argp-fmtstream.h b/grub-core/gnulib/argp-fmtstream.h deleted file mode 100644 index 8a67817b1..000000000 --- a/grub-core/gnulib/argp-fmtstream.h +++ /dev/null @@ -1,357 +0,0 @@ -/* Word-wrapping and line-truncating streams. - Copyright (C) 1997, 2006-2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* This package emulates glibc `line_wrap_stream' semantics for systems that - don't have that. If the system does have it, it is just a wrapper for - that. This header file is only used internally while compiling argp, and - shouldn't be installed. */ - -#ifndef _ARGP_FMTSTREAM_H -#define _ARGP_FMTSTREAM_H - -#include -#include -#include - -#ifndef __attribute__ -/* The __attribute__ feature is available in gcc versions 2.5 and later. - The __-protected variants of the attributes 'format' and 'printf' are - accepted by gcc versions 2.6.4 (effectively 2.7) and later. - We enable __attribute__ only if these are supported too, because - gnulib and libintl do '#define printf __printf__' when they override - the 'printf' function. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __attribute__(Spec) /* empty */ -# endif -#endif - -#if (_LIBC - 0 && !defined (USE_IN_LIBIO)) \ - || (defined (__GNU_LIBRARY__) && defined (HAVE_LINEWRAP_H)) -/* line_wrap_stream is available, so use that. */ -#define ARGP_FMTSTREAM_USE_LINEWRAP -#endif - -#ifdef ARGP_FMTSTREAM_USE_LINEWRAP -/* Just be a simple wrapper for line_wrap_stream; the semantics are - *slightly* different, as line_wrap_stream doesn't actually make a new - object, it just modifies the given stream (reversibly) to do - line-wrapping. Since we control who uses this code, it doesn't matter. */ - -#include - -typedef FILE *argp_fmtstream_t; - -#define argp_make_fmtstream line_wrap_stream -#define __argp_make_fmtstream line_wrap_stream -#define argp_fmtstream_free line_unwrap_stream -#define __argp_fmtstream_free line_unwrap_stream - -#define __argp_fmtstream_putc(fs,ch) putc(ch,fs) -#define argp_fmtstream_putc(fs,ch) putc(ch,fs) -#define __argp_fmtstream_puts(fs,str) fputs(str,fs) -#define argp_fmtstream_puts(fs,str) fputs(str,fs) -#define __argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) -#define argp_fmtstream_write(fs,str,len) fwrite(str,1,len,fs) -#define __argp_fmtstream_printf fprintf -#define argp_fmtstream_printf fprintf - -#define __argp_fmtstream_lmargin line_wrap_lmargin -#define argp_fmtstream_lmargin line_wrap_lmargin -#define __argp_fmtstream_set_lmargin line_wrap_set_lmargin -#define argp_fmtstream_set_lmargin line_wrap_set_lmargin -#define __argp_fmtstream_rmargin line_wrap_rmargin -#define argp_fmtstream_rmargin line_wrap_rmargin -#define __argp_fmtstream_set_rmargin line_wrap_set_rmargin -#define argp_fmtstream_set_rmargin line_wrap_set_rmargin -#define __argp_fmtstream_wmargin line_wrap_wmargin -#define argp_fmtstream_wmargin line_wrap_wmargin -#define __argp_fmtstream_set_wmargin line_wrap_set_wmargin -#define argp_fmtstream_set_wmargin line_wrap_set_wmargin -#define __argp_fmtstream_point line_wrap_point -#define argp_fmtstream_point line_wrap_point - -#else /* !ARGP_FMTSTREAM_USE_LINEWRAP */ -/* Guess we have to define our own version. */ - -struct argp_fmtstream -{ - FILE *stream; /* The stream we're outputting to. */ - - size_t lmargin, rmargin; /* Left and right margins. */ - ssize_t wmargin; /* Margin to wrap to, or -1 to truncate. */ - - /* Point in buffer to which we've processed for wrapping, but not output. */ - size_t point_offs; - /* Output column at POINT_OFFS, or -1 meaning 0 but don't add lmargin. */ - ssize_t point_col; - - char *buf; /* Output buffer. */ - char *p; /* Current end of text in BUF. */ - char *end; /* Absolute end of BUF. */ -}; - -typedef struct argp_fmtstream *argp_fmtstream_t; - -/* Return an argp_fmtstream that outputs to STREAM, and which prefixes lines - written on it with LMARGIN spaces and limits them to RMARGIN columns - total. If WMARGIN >= 0, words that extend past RMARGIN are wrapped by - replacing the whitespace before them with a newline and WMARGIN spaces. - Otherwise, chars beyond RMARGIN are simply dropped until a newline. - Returns NULL if there was an error. */ -extern argp_fmtstream_t __argp_make_fmtstream (FILE *__stream, - size_t __lmargin, - size_t __rmargin, - ssize_t __wmargin); -extern argp_fmtstream_t argp_make_fmtstream (FILE *__stream, - size_t __lmargin, - size_t __rmargin, - ssize_t __wmargin); - -/* Flush __FS to its stream, and free it (but don't close the stream). */ -extern void __argp_fmtstream_free (argp_fmtstream_t __fs); -extern void argp_fmtstream_free (argp_fmtstream_t __fs); - -extern ssize_t __argp_fmtstream_printf (argp_fmtstream_t __fs, - const char *__fmt, ...) - __attribute__ ((__format__ (printf, 2, 3))); -extern ssize_t argp_fmtstream_printf (argp_fmtstream_t __fs, - const char *__fmt, ...) - __attribute__ ((__format__ (printf, 2, 3))); - -#if _LIBC || !defined __OPTIMIZE__ -extern int __argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); -extern int argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch); - -extern int __argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); -extern int argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str); - -extern size_t __argp_fmtstream_write (argp_fmtstream_t __fs, - const char *__str, size_t __len); -extern size_t argp_fmtstream_write (argp_fmtstream_t __fs, - const char *__str, size_t __len); -#endif - -/* Access macros for various bits of state. */ -#define argp_fmtstream_lmargin(__fs) ((__fs)->lmargin) -#define argp_fmtstream_rmargin(__fs) ((__fs)->rmargin) -#define argp_fmtstream_wmargin(__fs) ((__fs)->wmargin) -#define __argp_fmtstream_lmargin argp_fmtstream_lmargin -#define __argp_fmtstream_rmargin argp_fmtstream_rmargin -#define __argp_fmtstream_wmargin argp_fmtstream_wmargin - -#if _LIBC || !defined __OPTIMIZE__ -/* Set __FS's left margin to LMARGIN and return the old value. */ -extern size_t argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, - size_t __lmargin); -extern size_t __argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, - size_t __lmargin); - -/* Set __FS's right margin to __RMARGIN and return the old value. */ -extern size_t argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, - size_t __rmargin); -extern size_t __argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, - size_t __rmargin); - -/* Set __FS's wrap margin to __WMARGIN and return the old value. */ -extern size_t argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, - size_t __wmargin); -extern size_t __argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, - size_t __wmargin); - -/* Return the column number of the current output point in __FS. */ -extern size_t argp_fmtstream_point (argp_fmtstream_t __fs); -extern size_t __argp_fmtstream_point (argp_fmtstream_t __fs); -#endif - -/* Internal routines. */ -extern void _argp_fmtstream_update (argp_fmtstream_t __fs); -extern void __argp_fmtstream_update (argp_fmtstream_t __fs); -extern int _argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); -extern int __argp_fmtstream_ensure (argp_fmtstream_t __fs, size_t __amount); - -#ifdef __OPTIMIZE__ -/* Inline versions of above routines. */ - -#if !_LIBC -#define __argp_fmtstream_putc argp_fmtstream_putc -#define __argp_fmtstream_puts argp_fmtstream_puts -#define __argp_fmtstream_write argp_fmtstream_write -#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin -#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin -#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin -#define __argp_fmtstream_point argp_fmtstream_point -#define __argp_fmtstream_update _argp_fmtstream_update -#define __argp_fmtstream_ensure _argp_fmtstream_ensure -#endif - -#ifndef ARGP_FS_EI -# ifdef __GNUC__ - /* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 - inline semantics, unless -fgnu89-inline is used. It defines a macro - __GNUC_STDC_INLINE__ to indicate this situation or a macro - __GNUC_GNU_INLINE__ to indicate the opposite situation. - - GCC 4.2 with -std=c99 or -std=gnu99 implements the GNU C inline - semantics but warns, unless -fgnu89-inline is used: - warning: C99 inline functions are not supported; using GNU89 - warning: to disable this warning use -fgnu89-inline or the gnu_inline function attribute - It defines a macro __GNUC_GNU_INLINE__ to indicate this situation. - - Whereas Apple GCC 4.0.1 build 5479 without -std=c99 or -std=gnu99 - implements the GNU C inline semantics and defines the macro - __GNUC_GNU_INLINE__, but it does not warn and does not support - __attribute__ ((__gnu_inline__)). - - All in all, these are the possible combinations. For every compiler, - we need to choose ARGP_FS_EI so that the corresponding table cell - contains an "ok". - - \ ARGP_FS_EI inline extern extern - \ inline inline - CC \ __attribute__ - ((gnu_inline)) - - gcc 4.3.0 error ok ok - gcc 4.3.0 -std=gnu99 -fgnu89-inline error ok ok - gcc 4.3.0 -std=gnu99 ok error ok - - gcc 4.2.2 error ok ok - gcc 4.2.2 -std=gnu99 -fgnu89-inline error ok ok - gcc 4.2.2 -std=gnu99 error warning ok - - gcc 4.1.2 error ok warning - gcc 4.1.2 -std=gnu99 error ok warning - - Apple gcc 4.0.1 error ok warning - Apple gcc 4.0.1 -std=gnu99 ok error warning - */ -# if defined __GNUC_STDC_INLINE__ -# define ARGP_FS_EI inline -# elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) -# define ARGP_FS_EI extern inline __attribute__ ((__gnu_inline__)) -# else -# define ARGP_FS_EI extern inline -# endif -# else - /* With other compilers, assume the ISO C99 meaning of 'inline', if - the compiler supports 'inline' at all. */ -# define ARGP_FS_EI inline -# endif -#endif - -ARGP_FS_EI size_t -__argp_fmtstream_write (argp_fmtstream_t __fs, - const char *__str, size_t __len) -{ - if (__fs->p + __len <= __fs->end || __argp_fmtstream_ensure (__fs, __len)) - { - memcpy (__fs->p, __str, __len); - __fs->p += __len; - return __len; - } - else - return 0; -} - -ARGP_FS_EI int -__argp_fmtstream_puts (argp_fmtstream_t __fs, const char *__str) -{ - size_t __len = strlen (__str); - if (__len) - { - size_t __wrote = __argp_fmtstream_write (__fs, __str, __len); - return __wrote == __len ? 0 : -1; - } - else - return 0; -} - -ARGP_FS_EI int -__argp_fmtstream_putc (argp_fmtstream_t __fs, int __ch) -{ - if (__fs->p < __fs->end || __argp_fmtstream_ensure (__fs, 1)) - return *__fs->p++ = __ch; - else - return EOF; -} - -/* Set __FS's left margin to __LMARGIN and return the old value. */ -ARGP_FS_EI size_t -__argp_fmtstream_set_lmargin (argp_fmtstream_t __fs, size_t __lmargin) -{ - size_t __old; - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - __old = __fs->lmargin; - __fs->lmargin = __lmargin; - return __old; -} - -/* Set __FS's right margin to __RMARGIN and return the old value. */ -ARGP_FS_EI size_t -__argp_fmtstream_set_rmargin (argp_fmtstream_t __fs, size_t __rmargin) -{ - size_t __old; - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - __old = __fs->rmargin; - __fs->rmargin = __rmargin; - return __old; -} - -/* Set FS's wrap margin to __WMARGIN and return the old value. */ -ARGP_FS_EI size_t -__argp_fmtstream_set_wmargin (argp_fmtstream_t __fs, size_t __wmargin) -{ - size_t __old; - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - __old = __fs->wmargin; - __fs->wmargin = __wmargin; - return __old; -} - -/* Return the column number of the current output point in __FS. */ -ARGP_FS_EI size_t -__argp_fmtstream_point (argp_fmtstream_t __fs) -{ - if ((size_t) (__fs->p - __fs->buf) > __fs->point_offs) - __argp_fmtstream_update (__fs); - return __fs->point_col >= 0 ? __fs->point_col : 0; -} - -size_t -__argp_get_display_len (const char *beg, const char *end); - -#if !_LIBC -#undef __argp_fmtstream_putc -#undef __argp_fmtstream_puts -#undef __argp_fmtstream_write -#undef __argp_fmtstream_set_lmargin -#undef __argp_fmtstream_set_rmargin -#undef __argp_fmtstream_set_wmargin -#undef __argp_fmtstream_point -#undef __argp_fmtstream_update -#undef __argp_fmtstream_ensure -#endif - -#endif /* __OPTIMIZE__ */ - -#endif /* ARGP_FMTSTREAM_USE_LINEWRAP */ - -#endif /* argp-fmtstream.h */ diff --git a/grub-core/gnulib/argp-fs-xinl.c b/grub-core/gnulib/argp-fs-xinl.c deleted file mode 100644 index 2c683f914..000000000 --- a/grub-core/gnulib/argp-fs-xinl.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Real definitions for extern inline functions in argp-fmtstream.h - Copyright (C) 1997, 2003, 2004, 2009, 2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#define ARGP_FS_EI -#undef __OPTIMIZE__ -#define __OPTIMIZE__ 1 -#include "argp-fmtstream.h" - -#if 0 -/* Not exported. */ -/* Add weak aliases. */ -#if _LIBC - 0 && !defined (ARGP_FMTSTREAM_USE_LINEWRAP) && defined (weak_alias) - -weak_alias (__argp_fmtstream_putc, argp_fmtstream_putc) -weak_alias (__argp_fmtstream_puts, argp_fmtstream_puts) -weak_alias (__argp_fmtstream_write, argp_fmtstream_write) -weak_alias (__argp_fmtstream_set_lmargin, argp_fmtstream_set_lmargin) -weak_alias (__argp_fmtstream_set_rmargin, argp_fmtstream_set_rmargin) -weak_alias (__argp_fmtstream_set_wmargin, argp_fmtstream_set_wmargin) -weak_alias (__argp_fmtstream_point, argp_fmtstream_point) - -#endif -#endif diff --git a/grub-core/gnulib/argp-help.c b/grub-core/gnulib/argp-help.c deleted file mode 100644 index c82e38e75..000000000 --- a/grub-core/gnulib/argp-help.c +++ /dev/null @@ -1,1951 +0,0 @@ -/* Hierarchial argument parsing help output - Copyright (C) 1995-2005, 2007, 2009-2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef USE_IN_LIBIO -# include -#endif - -#ifdef _LIBC -# include -# undef dgettext -# define dgettext(domain, msgid) \ - INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES) -#else -# include "gettext.h" -#endif - -#include "argp.h" -#include "argp-fmtstream.h" -#include "argp-namefrob.h" - -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -/* User-selectable (using an environment variable) formatting parameters. - - These may be specified in an environment variable called `ARGP_HELP_FMT', - with a contents like: VAR1=VAL1,VAR2=VAL2,BOOLVAR2,no-BOOLVAR2 - Where VALn must be a positive integer. The list of variables is in the - UPARAM_NAMES vector, below. */ - -/* Default parameters. */ -#define DUP_ARGS 0 /* True if option argument can be duplicated. */ -#define DUP_ARGS_NOTE 1 /* True to print a note about duplicate args. */ -#define SHORT_OPT_COL 2 /* column in which short options start */ -#define LONG_OPT_COL 6 /* column in which long options start */ -#define DOC_OPT_COL 2 /* column in which doc options start */ -#define OPT_DOC_COL 29 /* column in which option text starts */ -#define HEADER_COL 1 /* column in which group headers are printed */ -#define USAGE_INDENT 12 /* indentation of wrapped usage lines */ -#define RMARGIN 79 /* right margin used for wrapping */ - -/* User-selectable (using an environment variable) formatting parameters. - They must all be of type `int' for the parsing code to work. */ -struct uparams -{ - /* If true, arguments for an option are shown with both short and long - options, even when a given option has both, e.g. `-x ARG, --longx=ARG'. - If false, then if an option has both, the argument is only shown with - the long one, e.g., `-x, --longx=ARG', and a message indicating that - this really means both is printed below the options. */ - int dup_args; - - /* This is true if when DUP_ARGS is false, and some duplicate arguments have - been suppressed, an explanatory message should be printed. */ - int dup_args_note; - - /* Various output columns. */ - int short_opt_col; /* column in which short options start */ - int long_opt_col; /* column in which long options start */ - int doc_opt_col; /* column in which doc options start */ - int opt_doc_col; /* column in which option text starts */ - int header_col; /* column in which group headers are printed */ - int usage_indent; /* indentation of wrapped usage lines */ - int rmargin; /* right margin used for wrapping */ - - int valid; /* True when the values in here are valid. */ -}; - -/* This is a global variable, as user options are only ever read once. */ -static struct uparams uparams = { - DUP_ARGS, DUP_ARGS_NOTE, - SHORT_OPT_COL, LONG_OPT_COL, DOC_OPT_COL, OPT_DOC_COL, HEADER_COL, - USAGE_INDENT, RMARGIN, - 0 -}; - -/* A particular uparam, and what the user name is. */ -struct uparam_name -{ - const char *name; /* User name. */ - int is_bool; /* Whether it's `boolean'. */ - size_t uparams_offs; /* Location of the (int) field in UPARAMS. */ -}; - -/* The name-field mappings we know about. */ -static const struct uparam_name uparam_names[] = -{ - { "dup-args", 1, offsetof (struct uparams, dup_args) }, - { "dup-args-note", 1, offsetof (struct uparams, dup_args_note) }, - { "short-opt-col", 0, offsetof (struct uparams, short_opt_col) }, - { "long-opt-col", 0, offsetof (struct uparams, long_opt_col) }, - { "doc-opt-col", 0, offsetof (struct uparams, doc_opt_col) }, - { "opt-doc-col", 0, offsetof (struct uparams, opt_doc_col) }, - { "header-col", 0, offsetof (struct uparams, header_col) }, - { "usage-indent", 0, offsetof (struct uparams, usage_indent) }, - { "rmargin", 0, offsetof (struct uparams, rmargin) }, - { 0 } -}; - -static void -validate_uparams (const struct argp_state *state, struct uparams *upptr) -{ - const struct uparam_name *up; - - for (up = uparam_names; up->name; up++) - { - if (up->is_bool - || up->uparams_offs == offsetof (struct uparams, rmargin)) - continue; - if (*(int *)((char *)upptr + up->uparams_offs) >= upptr->rmargin) - { - __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, - "\ -ARGP_HELP_FMT: %s value is less than or equal to %s"), - "rmargin", up->name); - return; - } - } - uparams = *upptr; - uparams.valid = 1; -} - -/* Read user options from the environment, and fill in UPARAMS appropiately. */ -static void -fill_in_uparams (const struct argp_state *state) -{ - const char *var = getenv ("ARGP_HELP_FMT"); - struct uparams new_params = uparams; - -#define SKIPWS(p) do { while (isspace ((unsigned char) *p)) p++; } while (0); - - if (var) - { - /* Parse var. */ - while (*var) - { - SKIPWS (var); - - if (isalpha ((unsigned char) *var)) - { - size_t var_len; - const struct uparam_name *un; - int unspec = 0, val = 0; - const char *arg = var; - - while (isalnum ((unsigned char) *arg) || *arg == '-' || *arg == '_') - arg++; - var_len = arg - var; - - SKIPWS (arg); - - if (*arg == '\0' || *arg == ',') - unspec = 1; - else if (*arg == '=') - { - arg++; - SKIPWS (arg); - } - - if (unspec) - { - if (var[0] == 'n' && var[1] == 'o' && var[2] == '-') - { - val = 0; - var += 3; - var_len -= 3; - } - else - val = 1; - } - else if (isdigit ((unsigned char) *arg)) - { - val = atoi (arg); - while (isdigit ((unsigned char) *arg)) - arg++; - SKIPWS (arg); - } - - for (un = uparam_names; un->name; un++) - if (strlen (un->name) == var_len - && strncmp (var, un->name, var_len) == 0) - { - if (unspec && !un->is_bool) - __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, - "\ -%.*s: ARGP_HELP_FMT parameter requires a value"), - (int) var_len, var); - else if (val < 0) - __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, - "\ -%.*s: ARGP_HELP_FMT parameter must be positive"), - (int) var_len, var); - else - *(int *)((char *)&new_params + un->uparams_offs) = val; - break; - } - if (! un->name) - __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, "\ -%.*s: Unknown ARGP_HELP_FMT parameter"), - (int) var_len, var); - - var = arg; - if (*var == ',') - var++; - } - else if (*var) - { - __argp_failure (state, 0, 0, - dgettext (state->root_argp->argp_domain, - "Garbage in ARGP_HELP_FMT: %s"), var); - break; - } - } - validate_uparams (state, &new_params); - } -} - -/* Returns true if OPT hasn't been marked invisible. Visibility only affects - whether OPT is displayed or used in sorting, not option shadowing. */ -#define ovisible(opt) (! ((opt)->flags & OPTION_HIDDEN)) - -/* Returns true if OPT is an alias for an earlier option. */ -#define oalias(opt) ((opt)->flags & OPTION_ALIAS) - -/* Returns true if OPT is an documentation-only entry. */ -#define odoc(opt) ((opt)->flags & OPTION_DOC) - -/* Returns true if OPT should not be translated */ -#define onotrans(opt) ((opt)->flags & OPTION_NO_TRANS) - -/* Returns true if OPT is the end-of-list marker for a list of options. */ -#define oend(opt) __option_is_end (opt) - -/* Returns true if OPT has a short option. */ -#define oshort(opt) __option_is_short (opt) - -/* - The help format for a particular option is like: - - -xARG, -yARG, --long1=ARG, --long2=ARG Documentation... - - Where ARG will be omitted if there's no argument, for this option, or - will be surrounded by "[" and "]" appropiately if the argument is - optional. The documentation string is word-wrapped appropiately, and if - the list of options is long enough, it will be started on a separate line. - If there are no short options for a given option, the first long option is - indented slighly in a way that's supposed to make most long options appear - to be in a separate column. - - For example, the following output (from ps): - - -p PID, --pid=PID List the process PID - --pgrp=PGRP List processes in the process group PGRP - -P, -x, --no-parent Include processes without parents - -Q, --all-fields Don't elide unusable fields (normally if there's - some reason ps can't print a field for any - process, it's removed from the output entirely) - -r, --reverse, --gratuitously-long-reverse-option - Reverse the order of any sort - --session[=SID] Add the processes from the session SID (which - defaults to the sid of the current process) - - Here are some more options: - -f ZOT, --foonly=ZOT Glork a foonly - -z, --zaza Snit a zar - - -?, --help Give this help list - --usage Give a short usage message - -V, --version Print program version - - The struct argp_option array for the above could look like: - - { - {"pid", 'p', "PID", 0, "List the process PID"}, - {"pgrp", OPT_PGRP, "PGRP", 0, "List processes in the process group PGRP"}, - {"no-parent", 'P', 0, 0, "Include processes without parents"}, - {0, 'x', 0, OPTION_ALIAS}, - {"all-fields",'Q', 0, 0, "Don't elide unusable fields (normally" - " if there's some reason ps can't" - " print a field for any process, it's" - " removed from the output entirely)" }, - {"reverse", 'r', 0, 0, "Reverse the order of any sort"}, - {"gratuitously-long-reverse-option", 0, 0, OPTION_ALIAS}, - {"session", OPT_SESS, "SID", OPTION_ARG_OPTIONAL, - "Add the processes from the session" - " SID (which defaults to the sid of" - " the current process)" }, - - {0,0,0,0, "Here are some more options:"}, - {"foonly", 'f', "ZOT", 0, "Glork a foonly"}, - {"zaza", 'z', 0, 0, "Snit a zar"}, - - {0} - } - - Note that the last three options are automatically supplied by argp_parse, - unless you tell it not to with ARGP_NO_HELP. - -*/ - -/* Returns true if CH occurs between BEG and END. */ -static int -find_char (char ch, char *beg, char *end) -{ - while (beg < end) - if (*beg == ch) - return 1; - else - beg++; - return 0; -} - -struct hol_cluster; /* fwd decl */ - -struct hol_entry -{ - /* First option. */ - const struct argp_option *opt; - /* Number of options (including aliases). */ - unsigned num; - - /* A pointers into the HOL's short_options field, to the first short option - letter for this entry. The order of the characters following this point - corresponds to the order of options pointed to by OPT, and there are at - most NUM. A short option recorded in a option following OPT is only - valid if it occurs in the right place in SHORT_OPTIONS (otherwise it's - probably been shadowed by some other entry). */ - char *short_options; - - /* Entries are sorted by their group first, in the order: - 1, 2, ..., n, 0, -m, ..., -2, -1 - and then alphabetically within each group. The default is 0. */ - int group; - - /* The cluster of options this entry belongs to, or 0 if none. */ - struct hol_cluster *cluster; - - /* The argp from which this option came. */ - const struct argp *argp; - - /* Position in the array */ - unsigned ord; -}; - -/* A cluster of entries to reflect the argp tree structure. */ -struct hol_cluster -{ - /* A descriptive header printed before options in this cluster. */ - const char *header; - - /* Used to order clusters within the same group with the same parent, - according to the order in which they occurred in the parent argp's child - list. */ - int index; - - /* How to sort this cluster with respect to options and other clusters at the - same depth (clusters always follow options in the same group). */ - int group; - - /* The cluster to which this cluster belongs, or 0 if it's at the base - level. */ - struct hol_cluster *parent; - - /* The argp from which this cluster is (eventually) derived. */ - const struct argp *argp; - - /* The distance this cluster is from the root. */ - int depth; - - /* Clusters in a given hol are kept in a linked list, to make freeing them - possible. */ - struct hol_cluster *next; -}; - -/* A list of options for help. */ -struct hol -{ - /* An array of hol_entry's. */ - struct hol_entry *entries; - /* The number of entries in this hol. If this field is zero, the others - are undefined. */ - unsigned num_entries; - - /* A string containing all short options in this HOL. Each entry contains - pointers into this string, so the order can't be messed with blindly. */ - char *short_options; - - /* Clusters of entries in this hol. */ - struct hol_cluster *clusters; -}; - -/* Create a struct hol from the options in ARGP. CLUSTER is the - hol_cluster in which these entries occur, or 0, if at the root. */ -static struct hol * -make_hol (const struct argp *argp, struct hol_cluster *cluster) -{ - char *so; - const struct argp_option *o; - const struct argp_option *opts = argp->options; - struct hol_entry *entry; - unsigned num_short_options = 0; - struct hol *hol = malloc (sizeof (struct hol)); - - assert (hol); - - hol->num_entries = 0; - hol->clusters = 0; - - if (opts) - { - int cur_group = 0; - - /* The first option must not be an alias. */ - assert (! oalias (opts)); - - /* Calculate the space needed. */ - for (o = opts; ! oend (o); o++) - { - if (! oalias (o)) - hol->num_entries++; - if (oshort (o)) - num_short_options++; /* This is an upper bound. */ - } - - hol->entries = malloc (sizeof (struct hol_entry) * hol->num_entries); - hol->short_options = malloc (num_short_options + 1); - - assert (hol->entries && hol->short_options); - if (SIZE_MAX <= UINT_MAX) - assert (hol->num_entries <= SIZE_MAX / sizeof (struct hol_entry)); - - /* Fill in the entries. */ - so = hol->short_options; - for (o = opts, entry = hol->entries; ! oend (o); entry++) - { - entry->opt = o; - entry->num = 0; - entry->short_options = so; - entry->group = cur_group = - o->group - ? o->group - : ((!o->name && !o->key) - ? cur_group + 1 - : cur_group); - entry->cluster = cluster; - entry->argp = argp; - - do - { - entry->num++; - if (oshort (o) && ! find_char (o->key, hol->short_options, so)) - /* O has a valid short option which hasn't already been used.*/ - *so++ = o->key; - o++; - } - while (! oend (o) && oalias (o)); - } - *so = '\0'; /* null terminated so we can find the length */ - } - - return hol; -} - -/* Add a new cluster to HOL, with the given GROUP and HEADER (taken from the - associated argp child list entry), INDEX, and PARENT, and return a pointer - to it. ARGP is the argp that this cluster results from. */ -static struct hol_cluster * -hol_add_cluster (struct hol *hol, int group, const char *header, int index, - struct hol_cluster *parent, const struct argp *argp) -{ - struct hol_cluster *cl = malloc (sizeof (struct hol_cluster)); - if (cl) - { - cl->group = group; - cl->header = header; - - cl->index = index; - cl->parent = parent; - cl->argp = argp; - cl->depth = parent ? parent->depth + 1 : 0; - - cl->next = hol->clusters; - hol->clusters = cl; - } - return cl; -} - -/* Free HOL and any resources it uses. */ -static void -hol_free (struct hol *hol) -{ - struct hol_cluster *cl = hol->clusters; - - while (cl) - { - struct hol_cluster *next = cl->next; - free (cl); - cl = next; - } - - if (hol->num_entries > 0) - { - free (hol->entries); - free (hol->short_options); - } - - free (hol); -} - -static int -hol_entry_short_iterate (const struct hol_entry *entry, - int (*func)(const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie), - const char *domain, void *cookie) -{ - unsigned nopts; - int val = 0; - const struct argp_option *opt, *real = entry->opt; - char *so = entry->short_options; - - for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) - if (oshort (opt) && *so == opt->key) - { - if (!oalias (opt)) - real = opt; - if (ovisible (opt)) - val = (*func)(opt, real, domain, cookie); - so++; - } - - return val; -} - -static inline int -__attribute__ ((always_inline)) -hol_entry_long_iterate (const struct hol_entry *entry, - int (*func)(const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie), - const char *domain, void *cookie) -{ - unsigned nopts; - int val = 0; - const struct argp_option *opt, *real = entry->opt; - - for (opt = real, nopts = entry->num; nopts > 0 && !val; opt++, nopts--) - if (opt->name) - { - if (!oalias (opt)) - real = opt; - if (ovisible (opt)) - val = (*func)(opt, real, domain, cookie); - } - - return val; -} - -/* Iterator that returns true for the first short option. */ -static int -until_short (const struct argp_option *opt, const struct argp_option *real, - const char *domain, void *cookie) -{ - return oshort (opt) ? opt->key : 0; -} - -/* Returns the first valid short option in ENTRY, or 0 if there is none. */ -static char -hol_entry_first_short (const struct hol_entry *entry) -{ - return hol_entry_short_iterate (entry, until_short, - entry->argp->argp_domain, 0); -} - -/* Returns the first valid long option in ENTRY, or 0 if there is none. */ -static const char * -hol_entry_first_long (const struct hol_entry *entry) -{ - const struct argp_option *opt; - unsigned num; - for (opt = entry->opt, num = entry->num; num > 0; opt++, num--) - if (opt->name && ovisible (opt)) - return opt->name; - return 0; -} - -/* Returns the entry in HOL with the long option name NAME, or 0 if there is - none. */ -static struct hol_entry * -hol_find_entry (struct hol *hol, const char *name) -{ - struct hol_entry *entry = hol->entries; - unsigned num_entries = hol->num_entries; - - while (num_entries-- > 0) - { - const struct argp_option *opt = entry->opt; - unsigned num_opts = entry->num; - - while (num_opts-- > 0) - if (opt->name && ovisible (opt) && strcmp (opt->name, name) == 0) - return entry; - else - opt++; - - entry++; - } - - return 0; -} - -/* If an entry with the long option NAME occurs in HOL, set it's special - sort position to GROUP. */ -static void -hol_set_group (struct hol *hol, const char *name, int group) -{ - struct hol_entry *entry = hol_find_entry (hol, name); - if (entry) - entry->group = group; -} - -/* Order by group: 0, 1, 2, ..., n, -m, ..., -2, -1. - EQ is what to return if GROUP1 and GROUP2 are the same. */ -static int -group_cmp (int group1, int group2, int eq) -{ - if (group1 == group2) - return eq; - else if ((group1 < 0 && group2 < 0) || (group1 >= 0 && group2 >= 0)) - return group1 - group2; - else - return group2 - group1; -} - -/* Compare clusters CL1 & CL2 by the order that they should appear in - output. */ -static int -hol_cluster_cmp (const struct hol_cluster *cl1, const struct hol_cluster *cl2) -{ - /* If one cluster is deeper than the other, use its ancestor at the same - level, so that finding the common ancestor is straightforward. - - clN->depth > 0 means that clN->parent != NULL (see hol_add_cluster) */ - while (cl1->depth > cl2->depth) - cl1 = cl1->parent; - while (cl2->depth > cl1->depth) - cl2 = cl2->parent; - - /* Now reduce both clusters to their ancestors at the point where both have - a common parent; these can be directly compared. */ - while (cl1->parent != cl2->parent) - cl1 = cl1->parent, cl2 = cl2->parent; - - return group_cmp (cl1->group, cl2->group, cl2->index - cl1->index); -} - -/* Return the ancestor of CL that's just below the root (i.e., has a parent - of 0). */ -static struct hol_cluster * -hol_cluster_base (struct hol_cluster *cl) -{ - while (cl->parent) - cl = cl->parent; - return cl; -} - -/* Return true if CL1 is a child of CL2. */ -static int -hol_cluster_is_child (const struct hol_cluster *cl1, - const struct hol_cluster *cl2) -{ - while (cl1 && cl1 != cl2) - cl1 = cl1->parent; - return cl1 == cl2; -} - -/* Given the name of a OPTION_DOC option, modifies NAME to start at the tail - that should be used for comparisons, and returns true iff it should be - treated as a non-option. */ -static int -canon_doc_option (const char **name) -{ - int non_opt; - - if (!*name) - non_opt = 1; - else - { - /* Skip initial whitespace. */ - while (isspace ((unsigned char) **name)) - (*name)++; - /* Decide whether this looks like an option (leading `-') or not. */ - non_opt = (**name != '-'); - /* Skip until part of name used for sorting. */ - while (**name && !isalnum ((unsigned char) **name)) - (*name)++; - } - return non_opt; -} - -#define HOL_ENTRY_PTRCMP(a,b) ((a)->ord < (b)->ord ? -1 : 1) - -/* Order ENTRY1 & ENTRY2 by the order which they should appear in a help - listing. */ -static int -hol_entry_cmp (const struct hol_entry *entry1, - const struct hol_entry *entry2) -{ - /* The group numbers by which the entries should be ordered; if either is - in a cluster, then this is just the group within the cluster. */ - int group1 = entry1->group, group2 = entry2->group; - int rc; - - if (entry1->cluster != entry2->cluster) - { - /* The entries are not within the same cluster, so we can't compare them - directly, we have to use the appropiate clustering level too. */ - if (! entry1->cluster) - /* ENTRY1 is at the `base level', not in a cluster, so we have to - compare it's group number with that of the base cluster in which - ENTRY2 resides. Note that if they're in the same group, the - clustered option always comes laster. */ - return group_cmp (group1, hol_cluster_base (entry2->cluster)->group, -1); - else if (! entry2->cluster) - /* Likewise, but ENTRY2's not in a cluster. */ - return group_cmp (hol_cluster_base (entry1->cluster)->group, group2, 1); - else - /* Both entries are in clusters, we can just compare the clusters. */ - return (rc = hol_cluster_cmp (entry1->cluster, entry2->cluster)) ? - rc : HOL_ENTRY_PTRCMP (entry1, entry2); - } - else if (group1 == group2) - /* The entries are both in the same cluster and group, so compare them - alphabetically. */ - { - int short1 = hol_entry_first_short (entry1); - int short2 = hol_entry_first_short (entry2); - int doc1 = odoc (entry1->opt); - int doc2 = odoc (entry2->opt); - const char *long1 = hol_entry_first_long (entry1); - const char *long2 = hol_entry_first_long (entry2); - - if (doc1) - doc1 = canon_doc_option (&long1); - if (doc2) - doc2 = canon_doc_option (&long2); - - if (doc1 != doc2) - /* `documentation' options always follow normal options (or - documentation options that *look* like normal options). */ - return doc1 - doc2; - else if (!short1 && !short2 && long1 && long2) - /* Only long options. */ - return (rc = __strcasecmp (long1, long2)) ? - rc : HOL_ENTRY_PTRCMP (entry1, entry2); - else - /* Compare short/short, long/short, short/long, using the first - character of long options. Entries without *any* valid - options (such as options with OPTION_HIDDEN set) will be put - first, but as they're not displayed, it doesn't matter where - they are. */ - { - unsigned char first1 = short1 ? short1 : long1 ? *long1 : 0; - unsigned char first2 = short2 ? short2 : long2 ? *long2 : 0; - /* Use tolower, not _tolower, since only the former is - guaranteed to work on something already lower case. */ - int lower_cmp = tolower (first1) - tolower (first2); - /* Compare ignoring case, except when the options are both the - same letter, in which case lower-case always comes first. */ - return lower_cmp ? lower_cmp : - (rc = first2 - first1) ? - rc : HOL_ENTRY_PTRCMP (entry1, entry2); - } - } - else - /* Within the same cluster, but not the same group, so just compare - groups. */ - return group_cmp (group1, group2, HOL_ENTRY_PTRCMP (entry1, entry2)); -} - -/* Version of hol_entry_cmp with correct signature for qsort. */ -static int -hol_entry_qcmp (const void *entry1_v, const void *entry2_v) -{ - return hol_entry_cmp (entry1_v, entry2_v); -} - -/* Sort HOL by group and alphabetically by option name (with short options - taking precedence over long). Since the sorting is for display purposes - only, the shadowing of options isn't effected. */ -static void -hol_sort (struct hol *hol) -{ - if (hol->num_entries > 0) - { - unsigned i; - struct hol_entry *e; - for (i = 0, e = hol->entries; i < hol->num_entries; i++, e++) - e->ord = i; - qsort (hol->entries, hol->num_entries, sizeof (struct hol_entry), - hol_entry_qcmp); - } -} - -/* Append MORE to HOL, destroying MORE in the process. Options in HOL shadow - any in MORE with the same name. */ -static void -hol_append (struct hol *hol, struct hol *more) -{ - struct hol_cluster **cl_end = &hol->clusters; - - /* Steal MORE's cluster list, and add it to the end of HOL's. */ - while (*cl_end) - cl_end = &(*cl_end)->next; - *cl_end = more->clusters; - more->clusters = 0; - - /* Merge entries. */ - if (more->num_entries > 0) - { - if (hol->num_entries == 0) - { - hol->num_entries = more->num_entries; - hol->entries = more->entries; - hol->short_options = more->short_options; - more->num_entries = 0; /* Mark MORE's fields as invalid. */ - } - else - /* Append the entries in MORE to those in HOL, taking care to only add - non-shadowed SHORT_OPTIONS values. */ - { - unsigned left; - char *so, *more_so; - struct hol_entry *e; - unsigned num_entries = hol->num_entries + more->num_entries; - struct hol_entry *entries = - malloc (num_entries * sizeof (struct hol_entry)); - unsigned hol_so_len = strlen (hol->short_options); - char *short_options = - malloc (hol_so_len + strlen (more->short_options) + 1); - - assert (entries && short_options); - if (SIZE_MAX <= UINT_MAX) - assert (num_entries <= SIZE_MAX / sizeof (struct hol_entry)); - - __mempcpy (__mempcpy (entries, hol->entries, - hol->num_entries * sizeof (struct hol_entry)), - more->entries, - more->num_entries * sizeof (struct hol_entry)); - - __mempcpy (short_options, hol->short_options, hol_so_len); - - /* Fix up the short options pointers from HOL. */ - for (e = entries, left = hol->num_entries; left > 0; e++, left--) - e->short_options += (short_options - hol->short_options); - - /* Now add the short options from MORE, fixing up its entries - too. */ - so = short_options + hol_so_len; - more_so = more->short_options; - for (left = more->num_entries; left > 0; e++, left--) - { - int opts_left; - const struct argp_option *opt; - - e->short_options = so; - - for (opts_left = e->num, opt = e->opt; opts_left; opt++, opts_left--) - { - int ch = *more_so; - if (oshort (opt) && ch == opt->key) - /* The next short option in MORE_SO, CH, is from OPT. */ - { - if (! find_char (ch, short_options, - short_options + hol_so_len)) - /* The short option CH isn't shadowed by HOL's options, - so add it to the sum. */ - *so++ = ch; - more_so++; - } - } - } - - *so = '\0'; - - free (hol->entries); - free (hol->short_options); - - hol->entries = entries; - hol->num_entries = num_entries; - hol->short_options = short_options; - } - } - - hol_free (more); -} - -/* Inserts enough spaces to make sure STREAM is at column COL. */ -static void -indent_to (argp_fmtstream_t stream, unsigned col) -{ - int needed = col - __argp_fmtstream_point (stream); - while (needed-- > 0) - __argp_fmtstream_putc (stream, ' '); -} - -/* Output to STREAM either a space, or a newline if there isn't room for at - least ENSURE characters before the right margin. */ -static void -space (argp_fmtstream_t stream, size_t ensure) -{ - if (__argp_fmtstream_point (stream) + ensure - >= __argp_fmtstream_rmargin (stream)) - __argp_fmtstream_putc (stream, '\n'); - else - __argp_fmtstream_putc (stream, ' '); -} - -/* If the option REAL has an argument, we print it in using the printf - format REQ_FMT or OPT_FMT depending on whether it's a required or - optional argument. */ -static void -arg (const struct argp_option *real, const char *req_fmt, const char *opt_fmt, - const char *domain, argp_fmtstream_t stream) -{ - if (real->arg) - { - if (real->flags & OPTION_ARG_OPTIONAL) - __argp_fmtstream_printf (stream, opt_fmt, - dgettext (domain, real->arg)); - else - __argp_fmtstream_printf (stream, req_fmt, - dgettext (domain, real->arg)); - } -} - -/* Helper functions for hol_entry_help. */ - -/* State used during the execution of hol_help. */ -struct hol_help_state -{ - /* PREV_ENTRY should contain the previous entry printed, or 0. */ - struct hol_entry *prev_entry; - - /* If an entry is in a different group from the previous one, and SEP_GROUPS - is true, then a blank line will be printed before any output. */ - int sep_groups; - - /* True if a duplicate option argument was suppressed (only ever set if - UPARAMS.dup_args is false). */ - int suppressed_dup_arg; -}; - -/* Some state used while printing a help entry (used to communicate with - helper functions). See the doc for hol_entry_help for more info, as most - of the fields are copied from its arguments. */ -struct pentry_state -{ - const struct hol_entry *entry; - argp_fmtstream_t stream; - struct hol_help_state *hhstate; - - /* True if nothing's been printed so far. */ - int first; - - /* If non-zero, the state that was used to print this help. */ - const struct argp_state *state; -}; - -/* If a user doc filter should be applied to DOC, do so. */ -static const char * -filter_doc (const char *doc, int key, const struct argp *argp, - const struct argp_state *state) -{ - if (argp->help_filter) - /* We must apply a user filter to this output. */ - { - void *input = __argp_input (argp, state); - return (*argp->help_filter) (key, doc, input); - } - else - /* No filter. */ - return doc; -} - -/* Prints STR as a header line, with the margin lines set appropiately, and - notes the fact that groups should be separated with a blank line. ARGP is - the argp that should dictate any user doc filtering to take place. Note - that the previous wrap margin isn't restored, but the left margin is reset - to 0. */ -static void -print_header (const char *str, const struct argp *argp, - struct pentry_state *pest) -{ - const char *tstr = dgettext (argp->argp_domain, str); - const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_HEADER, argp, pest->state); - - if (fstr) - { - if (*fstr) - { - if (pest->hhstate->prev_entry) - /* Precede with a blank line. */ - __argp_fmtstream_putc (pest->stream, '\n'); - indent_to (pest->stream, uparams.header_col); - __argp_fmtstream_set_lmargin (pest->stream, uparams.header_col); - __argp_fmtstream_set_wmargin (pest->stream, uparams.header_col); - __argp_fmtstream_puts (pest->stream, fstr); - __argp_fmtstream_set_lmargin (pest->stream, 0); - __argp_fmtstream_putc (pest->stream, '\n'); - } - - pest->hhstate->sep_groups = 1; /* Separate subsequent groups. */ - } - - if (fstr != tstr) - free ((char *) fstr); -} - -/* Inserts a comma if this isn't the first item on the line, and then makes - sure we're at least to column COL. If this *is* the first item on a line, - prints any pending whitespace/headers that should precede this line. Also - clears FIRST. */ -static void -comma (unsigned col, struct pentry_state *pest) -{ - if (pest->first) - { - const struct hol_entry *pe = pest->hhstate->prev_entry; - const struct hol_cluster *cl = pest->entry->cluster; - - if (pest->hhstate->sep_groups && pe && pest->entry->group != pe->group) - __argp_fmtstream_putc (pest->stream, '\n'); - - if (cl && cl->header && *cl->header - && (!pe - || (pe->cluster != cl - && !hol_cluster_is_child (pe->cluster, cl)))) - /* If we're changing clusters, then this must be the start of the - ENTRY's cluster unless that is an ancestor of the previous one - (in which case we had just popped into a sub-cluster for a bit). - If so, then print the cluster's header line. */ - { - int old_wm = __argp_fmtstream_wmargin (pest->stream); - print_header (cl->header, cl->argp, pest); - __argp_fmtstream_set_wmargin (pest->stream, old_wm); - } - - pest->first = 0; - } - else - __argp_fmtstream_puts (pest->stream, ", "); - - indent_to (pest->stream, col); -} - -/* Print help for ENTRY to STREAM. */ -static void -hol_entry_help (struct hol_entry *entry, const struct argp_state *state, - argp_fmtstream_t stream, struct hol_help_state *hhstate) -{ - unsigned num; - const struct argp_option *real = entry->opt, *opt; - char *so = entry->short_options; - int have_long_opt = 0; /* We have any long options. */ - /* Saved margins. */ - int old_lm = __argp_fmtstream_set_lmargin (stream, 0); - int old_wm = __argp_fmtstream_wmargin (stream); - /* PEST is a state block holding some of our variables that we'd like to - share with helper functions. */ - struct pentry_state pest; - - pest.entry = entry; - pest.stream = stream; - pest.hhstate = hhstate; - pest.first = 1; - pest.state = state; - - if (! odoc (real)) - for (opt = real, num = entry->num; num > 0; opt++, num--) - if (opt->name && ovisible (opt)) - { - have_long_opt = 1; - break; - } - - /* First emit short options. */ - __argp_fmtstream_set_wmargin (stream, uparams.short_opt_col); /* For truly bizarre cases. */ - for (opt = real, num = entry->num; num > 0; opt++, num--) - if (oshort (opt) && opt->key == *so) - /* OPT has a valid (non shadowed) short option. */ - { - if (ovisible (opt)) - { - comma (uparams.short_opt_col, &pest); - __argp_fmtstream_putc (stream, '-'); - __argp_fmtstream_putc (stream, *so); - if (!have_long_opt || uparams.dup_args) - arg (real, " %s", "[%s]", state->root_argp->argp_domain, stream); - else if (real->arg) - hhstate->suppressed_dup_arg = 1; - } - so++; - } - - /* Now, long options. */ - if (odoc (real)) - /* A `documentation' option. */ - { - __argp_fmtstream_set_wmargin (stream, uparams.doc_opt_col); - for (opt = real, num = entry->num; num > 0; opt++, num--) - if (opt->name && *opt->name && ovisible (opt)) - { - comma (uparams.doc_opt_col, &pest); - /* Calling dgettext here isn't quite right, since sorting will - have been done on the original; but documentation options - should be pretty rare anyway... */ - __argp_fmtstream_puts (stream, - onotrans (opt) ? - opt->name : - dgettext (state->root_argp->argp_domain, - opt->name)); - } - } - else - /* A real long option. */ - { - int first_long_opt = 1; - - __argp_fmtstream_set_wmargin (stream, uparams.long_opt_col); - for (opt = real, num = entry->num; num > 0; opt++, num--) - if (opt->name && ovisible (opt)) - { - comma (uparams.long_opt_col, &pest); - __argp_fmtstream_printf (stream, "--%s", opt->name); - if (first_long_opt || uparams.dup_args) - arg (real, "=%s", "[=%s]", state->root_argp->argp_domain, - stream); - else if (real->arg) - hhstate->suppressed_dup_arg = 1; - } - } - - /* Next, documentation strings. */ - __argp_fmtstream_set_lmargin (stream, 0); - - if (pest.first) - { - /* Didn't print any switches, what's up? */ - if (!oshort (real) && !real->name) - /* This is a group header, print it nicely. */ - print_header (real->doc, entry->argp, &pest); - else - /* Just a totally shadowed option or null header; print nothing. */ - goto cleanup; /* Just return, after cleaning up. */ - } - else - { - const char *tstr = real->doc ? dgettext (state->root_argp->argp_domain, - real->doc) : 0; - const char *fstr = filter_doc (tstr, real->key, entry->argp, state); - if (fstr && *fstr) - { - unsigned int col = __argp_fmtstream_point (stream); - - __argp_fmtstream_set_lmargin (stream, uparams.opt_doc_col); - __argp_fmtstream_set_wmargin (stream, uparams.opt_doc_col); - - if (col > (unsigned int) (uparams.opt_doc_col + 3)) - __argp_fmtstream_putc (stream, '\n'); - else if (col >= (unsigned int) uparams.opt_doc_col) - __argp_fmtstream_puts (stream, " "); - else - indent_to (stream, uparams.opt_doc_col); - - __argp_fmtstream_puts (stream, fstr); - } - if (fstr && fstr != tstr) - free ((char *) fstr); - - /* Reset the left margin. */ - __argp_fmtstream_set_lmargin (stream, 0); - __argp_fmtstream_putc (stream, '\n'); - } - - hhstate->prev_entry = entry; - -cleanup: - __argp_fmtstream_set_lmargin (stream, old_lm); - __argp_fmtstream_set_wmargin (stream, old_wm); -} - -/* Output a long help message about the options in HOL to STREAM. */ -static void -hol_help (struct hol *hol, const struct argp_state *state, - argp_fmtstream_t stream) -{ - unsigned num; - struct hol_entry *entry; - struct hol_help_state hhstate = { 0, 0, 0 }; - - for (entry = hol->entries, num = hol->num_entries; num > 0; entry++, num--) - hol_entry_help (entry, state, stream, &hhstate); - - if (hhstate.suppressed_dup_arg && uparams.dup_args_note) - { - const char *tstr = dgettext (state->root_argp->argp_domain, "\ -Mandatory or optional arguments to long options are also mandatory or \ -optional for any corresponding short options."); - const char *fstr = filter_doc (tstr, ARGP_KEY_HELP_DUP_ARGS_NOTE, - state ? state->root_argp : 0, state); - if (fstr && *fstr) - { - __argp_fmtstream_putc (stream, '\n'); - __argp_fmtstream_puts (stream, fstr); - __argp_fmtstream_putc (stream, '\n'); - } - if (fstr && fstr != tstr) - free ((char *) fstr); - } -} - -/* Helper functions for hol_usage. */ - -/* If OPT is a short option without an arg, append its key to the string - pointer pointer to by COOKIE, and advance the pointer. */ -static int -add_argless_short_opt (const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie) -{ - char **snao_end = cookie; - if (!(opt->arg || real->arg) - && !((opt->flags | real->flags) & OPTION_NO_USAGE)) - *(*snao_end)++ = opt->key; - return 0; -} - -/* If OPT is a short option with an arg, output a usage entry for it to the - stream pointed at by COOKIE. */ -static int -usage_argful_short_opt (const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie) -{ - argp_fmtstream_t stream = cookie; - const char *arg = opt->arg; - int flags = opt->flags | real->flags; - - if (! arg) - arg = real->arg; - - if (arg && !(flags & OPTION_NO_USAGE)) - { - arg = dgettext (domain, arg); - - if (flags & OPTION_ARG_OPTIONAL) - __argp_fmtstream_printf (stream, " [-%c[%s]]", opt->key, arg); - else - { - /* Manually do line wrapping so that it (probably) won't - get wrapped at the embedded space. */ - space (stream, 6 + strlen (arg)); - __argp_fmtstream_printf (stream, "[-%c %s]", opt->key, arg); - } - } - - return 0; -} - -/* Output a usage entry for the long option opt to the stream pointed at by - COOKIE. */ -static int -usage_long_opt (const struct argp_option *opt, - const struct argp_option *real, - const char *domain, void *cookie) -{ - argp_fmtstream_t stream = cookie; - const char *arg = opt->arg; - int flags = opt->flags | real->flags; - - if (! arg) - arg = real->arg; - - if (! (flags & OPTION_NO_USAGE) && !odoc (opt)) - { - if (arg) - { - arg = dgettext (domain, arg); - if (flags & OPTION_ARG_OPTIONAL) - __argp_fmtstream_printf (stream, " [--%s[=%s]]", opt->name, arg); - else - __argp_fmtstream_printf (stream, " [--%s=%s]", opt->name, arg); - } - else - __argp_fmtstream_printf (stream, " [--%s]", opt->name); - } - - return 0; -} - -/* Print a short usage description for the arguments in HOL to STREAM. */ -static void -hol_usage (struct hol *hol, argp_fmtstream_t stream) -{ - if (hol->num_entries > 0) - { - unsigned nentries; - struct hol_entry *entry; - char *short_no_arg_opts = alloca (strlen (hol->short_options) + 1); - char *snao_end = short_no_arg_opts; - - /* First we put a list of short options without arguments. */ - for (entry = hol->entries, nentries = hol->num_entries - ; nentries > 0 - ; entry++, nentries--) - hol_entry_short_iterate (entry, add_argless_short_opt, - entry->argp->argp_domain, &snao_end); - if (snao_end > short_no_arg_opts) - { - *snao_end++ = 0; - __argp_fmtstream_printf (stream, " [-%s]", short_no_arg_opts); - } - - /* Now a list of short options *with* arguments. */ - for (entry = hol->entries, nentries = hol->num_entries - ; nentries > 0 - ; entry++, nentries--) - hol_entry_short_iterate (entry, usage_argful_short_opt, - entry->argp->argp_domain, stream); - - /* Finally, a list of long options (whew!). */ - for (entry = hol->entries, nentries = hol->num_entries - ; nentries > 0 - ; entry++, nentries--) - hol_entry_long_iterate (entry, usage_long_opt, - entry->argp->argp_domain, stream); - } -} - -/* Make a HOL containing all levels of options in ARGP. CLUSTER is the - cluster in which ARGP's entries should be clustered, or 0. */ -static struct hol * -argp_hol (const struct argp *argp, struct hol_cluster *cluster) -{ - const struct argp_child *child = argp->children; - struct hol *hol = make_hol (argp, cluster); - if (child) - while (child->argp) - { - struct hol_cluster *child_cluster = - ((child->group || child->header) - /* Put CHILD->argp within its own cluster. */ - ? hol_add_cluster (hol, child->group, child->header, - child - argp->children, cluster, argp) - /* Just merge it into the parent's cluster. */ - : cluster); - hol_append (hol, argp_hol (child->argp, child_cluster)) ; - child++; - } - return hol; -} - -/* Calculate how many different levels with alternative args strings exist in - ARGP. */ -static size_t -argp_args_levels (const struct argp *argp) -{ - size_t levels = 0; - const struct argp_child *child = argp->children; - - if (argp->args_doc && strchr (argp->args_doc, '\n')) - levels++; - - if (child) - while (child->argp) - levels += argp_args_levels ((child++)->argp); - - return levels; -} - -/* Print all the non-option args documented in ARGP to STREAM. Any output is - preceded by a space. LEVELS is a pointer to a byte vector the length - returned by argp_args_levels; it should be initialized to zero, and - updated by this routine for the next call if ADVANCE is true. True is - returned as long as there are more patterns to output. */ -static int -argp_args_usage (const struct argp *argp, const struct argp_state *state, - char **levels, int advance, argp_fmtstream_t stream) -{ - char *our_level = *levels; - int multiple = 0; - const struct argp_child *child = argp->children; - const char *tdoc = dgettext (argp->argp_domain, argp->args_doc), *nl = 0; - const char *fdoc = filter_doc (tdoc, ARGP_KEY_HELP_ARGS_DOC, argp, state); - - if (fdoc) - { - const char *cp = fdoc; - nl = __strchrnul (cp, '\n'); - if (*nl != '\0') - /* This is a `multi-level' args doc; advance to the correct position - as determined by our state in LEVELS, and update LEVELS. */ - { - int i; - multiple = 1; - for (i = 0; i < *our_level; i++) - cp = nl + 1, nl = __strchrnul (cp, '\n'); - (*levels)++; - } - - /* Manually do line wrapping so that it (probably) won't get wrapped at - any embedded spaces. */ - space (stream, 1 + __argp_get_display_len (cp, nl)); - - __argp_fmtstream_write (stream, cp, nl - cp); - } - if (fdoc && fdoc != tdoc) - free ((char *)fdoc); /* Free user's modified doc string. */ - - if (child) - while (child->argp) - advance = !argp_args_usage ((child++)->argp, state, levels, advance, stream); - - if (advance && multiple) - { - /* Need to increment our level. */ - if (*nl) - /* There's more we can do here. */ - { - (*our_level)++; - advance = 0; /* Our parent shouldn't advance also. */ - } - else if (*our_level > 0) - /* We had multiple levels, but used them up; reset to zero. */ - *our_level = 0; - } - - return !advance; -} - -/* Print the documentation for ARGP to STREAM; if POST is false, then - everything preceeding a `\v' character in the documentation strings (or - the whole string, for those with none) is printed, otherwise, everything - following the `\v' character (nothing for strings without). Each separate - bit of documentation is separated a blank line, and if PRE_BLANK is true, - then the first is as well. If FIRST_ONLY is true, only the first - occurrence is output. Returns true if anything was output. */ -static int -argp_doc (const struct argp *argp, const struct argp_state *state, - int post, int pre_blank, int first_only, - argp_fmtstream_t stream) -{ - const char *text; - const char *inp_text; - size_t inp_text_len = 0; - const char *trans_text; - void *input = 0; - int anything = 0; - const struct argp_child *child = argp->children; - - if (argp->doc) - { - char *vt = strchr (argp->doc, '\v'); - if (vt) - { - if (post) - inp_text = vt + 1; - else - { - inp_text_len = vt - argp->doc; - inp_text = __strndup (argp->doc, inp_text_len); - } - } - else - inp_text = post ? 0 : argp->doc; - trans_text = inp_text ? dgettext (argp->argp_domain, inp_text) : NULL; - } - else - trans_text = inp_text = 0; - - if (argp->help_filter) - /* We have to filter the doc strings. */ - { - input = __argp_input (argp, state); - text = - (*argp->help_filter) (post - ? ARGP_KEY_HELP_POST_DOC - : ARGP_KEY_HELP_PRE_DOC, - trans_text, input); - } - else - text = (const char *) trans_text; - - if (text) - { - if (pre_blank) - __argp_fmtstream_putc (stream, '\n'); - - __argp_fmtstream_puts (stream, text); - - if (__argp_fmtstream_point (stream) > __argp_fmtstream_lmargin (stream)) - __argp_fmtstream_putc (stream, '\n'); - - anything = 1; - } - - if (text && text != trans_text) - free ((char *) text); /* Free TEXT returned from the help filter. */ - - if (inp_text && inp_text_len) - free ((char *) inp_text); /* We copied INP_TEXT, so free it now. */ - - if (post && argp->help_filter) - /* Now see if we have to output a ARGP_KEY_HELP_EXTRA text. */ - { - text = (*argp->help_filter) (ARGP_KEY_HELP_EXTRA, 0, input); - if (text) - { - if (anything || pre_blank) - __argp_fmtstream_putc (stream, '\n'); - __argp_fmtstream_puts (stream, text); - free ((char *) text); - if (__argp_fmtstream_point (stream) - > __argp_fmtstream_lmargin (stream)) - __argp_fmtstream_putc (stream, '\n'); - anything = 1; - } - } - - if (child) - while (child->argp && !(first_only && anything)) - anything |= - argp_doc ((child++)->argp, state, - post, anything || pre_blank, first_only, - stream); - - return anything; -} - -/* Output a usage message for ARGP to STREAM. If called from - argp_state_help, STATE is the relevent parsing state. FLAGS are from the - set ARGP_HELP_*. NAME is what to use wherever a `program name' is - needed. */ -static void -_help (const struct argp *argp, const struct argp_state *state, FILE *stream, - unsigned flags, char *name) -{ - int anything = 0; /* Whether we've output anything. */ - struct hol *hol = 0; - argp_fmtstream_t fs; - - if (! stream) - return; - -#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) - __flockfile (stream); -#endif - - if (! uparams.valid) - fill_in_uparams (state); - - fs = __argp_make_fmtstream (stream, 0, uparams.rmargin, 0); - if (! fs) - { -#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) - __funlockfile (stream); -#endif - return; - } - - if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG)) - { - hol = argp_hol (argp, 0); - - /* If present, these options always come last. */ - hol_set_group (hol, "help", -1); - hol_set_group (hol, "version", -1); - - hol_sort (hol); - } - - if (flags & (ARGP_HELP_USAGE | ARGP_HELP_SHORT_USAGE)) - /* Print a short `Usage:' message. */ - { - int first_pattern = 1, more_patterns; - size_t num_pattern_levels = argp_args_levels (argp); - char *pattern_levels = alloca (num_pattern_levels); - - memset (pattern_levels, 0, num_pattern_levels); - - do - { - int old_lm; - int old_wm = __argp_fmtstream_set_wmargin (fs, uparams.usage_indent); - char *levels = pattern_levels; - - if (first_pattern) - __argp_fmtstream_printf (fs, "%s %s", - dgettext (argp->argp_domain, "Usage:"), - name); - else - __argp_fmtstream_printf (fs, "%s %s", - dgettext (argp->argp_domain, " or: "), - name); - - /* We set the lmargin as well as the wmargin, because hol_usage - manually wraps options with newline to avoid annoying breaks. */ - old_lm = __argp_fmtstream_set_lmargin (fs, uparams.usage_indent); - - if (flags & ARGP_HELP_SHORT_USAGE) - /* Just show where the options go. */ - { - if (hol->num_entries > 0) - __argp_fmtstream_puts (fs, dgettext (argp->argp_domain, - " [OPTION...]")); - } - else - /* Actually print the options. */ - { - hol_usage (hol, fs); - flags |= ARGP_HELP_SHORT_USAGE; /* But only do so once. */ - } - - more_patterns = argp_args_usage (argp, state, &levels, 1, fs); - - __argp_fmtstream_set_wmargin (fs, old_wm); - __argp_fmtstream_set_lmargin (fs, old_lm); - - __argp_fmtstream_putc (fs, '\n'); - anything = 1; - - first_pattern = 0; - } - while (more_patterns); - } - - if (flags & ARGP_HELP_PRE_DOC) - anything |= argp_doc (argp, state, 0, 0, 1, fs); - - if (flags & ARGP_HELP_SEE) - { - __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, "\ -Try `%s --help' or `%s --usage' for more information.\n"), - name, name); - anything = 1; - } - - if (flags & ARGP_HELP_LONG) - /* Print a long, detailed help message. */ - { - /* Print info about all the options. */ - if (hol->num_entries > 0) - { - if (anything) - __argp_fmtstream_putc (fs, '\n'); - hol_help (hol, state, fs); - anything = 1; - } - } - - if (flags & ARGP_HELP_POST_DOC) - /* Print any documentation strings at the end. */ - anything |= argp_doc (argp, state, 1, anything, 0, fs); - - if ((flags & ARGP_HELP_BUG_ADDR) && argp_program_bug_address) - { - if (anything) - __argp_fmtstream_putc (fs, '\n'); - __argp_fmtstream_printf (fs, dgettext (argp->argp_domain, - "Report bugs to %s.\n"), - argp_program_bug_address); - anything = 1; - } - -#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) - __funlockfile (stream); -#endif - - if (hol) - hol_free (hol); - - __argp_fmtstream_free (fs); -} - -/* Output a usage message for ARGP to STREAM. FLAGS are from the set - ARGP_HELP_*. NAME is what to use wherever a `program name' is needed. */ -void __argp_help (const struct argp *argp, FILE *stream, - unsigned flags, char *name) -{ - struct argp_state state; - memset (&state, 0, sizeof state); - state.root_argp = argp; - _help (argp, &state, stream, flags, name); -} -#ifdef weak_alias -weak_alias (__argp_help, argp_help) -#endif - -#if ! (defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME) -char * -__argp_short_program_name (void) -{ -# if HAVE_DECL_PROGRAM_INVOCATION_NAME - return __argp_base_name (program_invocation_name); -# else - /* FIXME: What now? Miles suggests that it is better to use NULL, - but currently the value is passed on directly to fputs_unlocked, - so that requires more changes. */ -# if __GNUC__ -# warning No reasonable value to return -# endif /* __GNUC__ */ - return ""; -# endif -} -#endif - -/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are - from the set ARGP_HELP_*. */ -void -__argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags) -{ - if ((!state || ! (state->flags & ARGP_NO_ERRS)) && stream) - { - if (state && (state->flags & ARGP_LONG_ONLY)) - flags |= ARGP_HELP_LONG_ONLY; - - _help (state ? state->root_argp : 0, state, stream, flags, - state ? state->name : __argp_short_program_name ()); - - if (!state || ! (state->flags & ARGP_NO_EXIT)) - { - if (flags & ARGP_HELP_EXIT_ERR) - exit (argp_err_exit_status); - if (flags & ARGP_HELP_EXIT_OK) - exit (0); - } - } -} -#ifdef weak_alias -weak_alias (__argp_state_help, argp_state_help) -#endif - -/* If appropriate, print the printf string FMT and following args, preceded - by the program name and `:', to stderr, and followed by a `Try ... --help' - message, then exit (1). */ -void -__argp_error (const struct argp_state *state, const char *fmt, ...) -{ - if (!state || !(state->flags & ARGP_NO_ERRS)) - { - FILE *stream = state ? state->err_stream : stderr; - - if (stream) - { - va_list ap; - -#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) - __flockfile (stream); -#endif - - va_start (ap, fmt); - -#ifdef USE_IN_LIBIO - if (_IO_fwide (stream, 0) > 0) - { - char *buf; - - if (__asprintf (&buf, fmt, ap) < 0) - buf = NULL; - - __fwprintf (stream, L"%s: %s\n", - state ? state->name : __argp_short_program_name (), - buf); - - free (buf); - } - else -#endif - { - fputs_unlocked (state - ? state->name : __argp_short_program_name (), - stream); - putc_unlocked (':', stream); - putc_unlocked (' ', stream); - - vfprintf (stream, fmt, ap); - - putc_unlocked ('\n', stream); - } - - __argp_state_help (state, stream, ARGP_HELP_STD_ERR); - - va_end (ap); - -#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) - __funlockfile (stream); -#endif - } - } -} -#ifdef weak_alias -weak_alias (__argp_error, argp_error) -#endif - -/* Similar to the standard gnu error-reporting function error(), but will - respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print - to STATE->err_stream. This is useful for argument parsing code that is - shared between program startup (when exiting is desired) and runtime - option parsing (when typically an error code is returned instead). The - difference between this function and argp_error is that the latter is for - *parsing errors*, and the former is for other problems that occur during - parsing but don't reflect a (syntactic) problem with the input. */ -void -__argp_failure (const struct argp_state *state, int status, int errnum, - const char *fmt, ...) -{ - if (!state || !(state->flags & ARGP_NO_ERRS)) - { - FILE *stream = state ? state->err_stream : stderr; - - if (stream) - { -#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) - __flockfile (stream); -#endif - -#ifdef USE_IN_LIBIO - if (_IO_fwide (stream, 0) > 0) - __fwprintf (stream, L"%s", - state ? state->name : __argp_short_program_name ()); - else -#endif - fputs_unlocked (state - ? state->name : __argp_short_program_name (), - stream); - - if (fmt) - { - va_list ap; - - va_start (ap, fmt); -#ifdef USE_IN_LIBIO - if (_IO_fwide (stream, 0) > 0) - { - char *buf; - - if (__asprintf (&buf, fmt, ap) < 0) - buf = NULL; - - __fwprintf (stream, L": %s", buf); - - free (buf); - } - else -#endif - { - putc_unlocked (':', stream); - putc_unlocked (' ', stream); - - vfprintf (stream, fmt, ap); - } - - va_end (ap); - } - - if (errnum) - { - char buf[200]; - -#ifdef USE_IN_LIBIO - if (_IO_fwide (stream, 0) > 0) - __fwprintf (stream, L": %s", - __strerror_r (errnum, buf, sizeof (buf))); - else -#endif - { - char const *s = NULL; - putc_unlocked (':', stream); - putc_unlocked (' ', stream); -#if _LIBC || (HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P) - s = __strerror_r (errnum, buf, sizeof buf); -#elif HAVE_DECL_STRERROR_R - if (__strerror_r (errnum, buf, sizeof buf) == 0) - s = buf; -#endif -#if !_LIBC - if (! s && ! (s = strerror (errnum))) - s = dgettext (state->root_argp->argp_domain, - "Unknown system error"); -#endif - fputs (s, stream); - } - } - -#ifdef USE_IN_LIBIO - if (_IO_fwide (stream, 0) > 0) - putwc_unlocked (L'\n', stream); - else -#endif - putc_unlocked ('\n', stream); - -#if _LIBC || (HAVE_FLOCKFILE && HAVE_FUNLOCKFILE) - __funlockfile (stream); -#endif - - if (status && (!state || !(state->flags & ARGP_NO_EXIT))) - exit (status); - } - } -} -#ifdef weak_alias -weak_alias (__argp_failure, argp_failure) -#endif diff --git a/grub-core/gnulib/argp-namefrob.h b/grub-core/gnulib/argp-namefrob.h deleted file mode 100644 index 24581a626..000000000 --- a/grub-core/gnulib/argp-namefrob.h +++ /dev/null @@ -1,157 +0,0 @@ -/* Name frobnication for compiling argp outside of glibc - Copyright (C) 1997, 2003, 2007, 2009, 2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#if !_LIBC -/* This code is written for inclusion in gnu-libc, and uses names in the - namespace reserved for libc. If we're not compiling in libc, define those - names to be the normal ones instead. */ - -/* argp-parse functions */ -#undef __argp_parse -#define __argp_parse argp_parse -#undef __option_is_end -#define __option_is_end _option_is_end -#undef __option_is_short -#define __option_is_short _option_is_short -#undef __argp_input -#define __argp_input _argp_input - -/* argp-help functions */ -#undef __argp_help -#define __argp_help argp_help -#undef __argp_error -#define __argp_error argp_error -#undef __argp_failure -#define __argp_failure argp_failure -#undef __argp_state_help -#define __argp_state_help argp_state_help -#undef __argp_usage -#define __argp_usage argp_usage - -/* argp-fmtstream functions */ -#undef __argp_make_fmtstream -#define __argp_make_fmtstream argp_make_fmtstream -#undef __argp_fmtstream_free -#define __argp_fmtstream_free argp_fmtstream_free -#undef __argp_fmtstream_putc -#define __argp_fmtstream_putc argp_fmtstream_putc -#undef __argp_fmtstream_puts -#define __argp_fmtstream_puts argp_fmtstream_puts -#undef __argp_fmtstream_write -#define __argp_fmtstream_write argp_fmtstream_write -#undef __argp_fmtstream_printf -#define __argp_fmtstream_printf argp_fmtstream_printf -#undef __argp_fmtstream_set_lmargin -#define __argp_fmtstream_set_lmargin argp_fmtstream_set_lmargin -#undef __argp_fmtstream_set_rmargin -#define __argp_fmtstream_set_rmargin argp_fmtstream_set_rmargin -#undef __argp_fmtstream_set_wmargin -#define __argp_fmtstream_set_wmargin argp_fmtstream_set_wmargin -#undef __argp_fmtstream_point -#define __argp_fmtstream_point argp_fmtstream_point -#undef __argp_fmtstream_update -#define __argp_fmtstream_update _argp_fmtstream_update -#undef __argp_fmtstream_ensure -#define __argp_fmtstream_ensure _argp_fmtstream_ensure -#undef __argp_fmtstream_lmargin -#define __argp_fmtstream_lmargin argp_fmtstream_lmargin -#undef __argp_fmtstream_rmargin -#define __argp_fmtstream_rmargin argp_fmtstream_rmargin -#undef __argp_fmtstream_wmargin -#define __argp_fmtstream_wmargin argp_fmtstream_wmargin - -/* normal libc functions we call */ -#undef __flockfile -#define __flockfile flockfile -#undef __funlockfile -#define __funlockfile funlockfile -#undef __mempcpy -#define __mempcpy mempcpy -#undef __sleep -#define __sleep sleep -#undef __strcasecmp -#define __strcasecmp strcasecmp -#undef __strchrnul -#define __strchrnul strchrnul -#undef __strerror_r -#define __strerror_r strerror_r -#undef __strndup -#define __strndup strndup -#undef __vsnprintf -#define __vsnprintf vsnprintf - -#if defined(HAVE_DECL_CLEARERR_UNLOCKED) && !HAVE_DECL_CLEARERR_UNLOCKED -# define clearerr_unlocked(x) clearerr (x) -#endif -#if defined(HAVE_DECL_FEOF_UNLOCKED) && !HAVE_DECL_FEOF_UNLOCKED -# define feof_unlocked(x) feof (x) -# endif -#if defined(HAVE_DECL_FERROR_UNLOCKED) && !HAVE_DECL_FERROR_UNLOCKED -# define ferror_unlocked(x) ferror (x) -# endif -#if defined(HAVE_DECL_FFLUSH_UNLOCKED) && !HAVE_DECL_FFLUSH_UNLOCKED -# define fflush_unlocked(x) fflush (x) -# endif -#if defined(HAVE_DECL_FGETS_UNLOCKED) && !HAVE_DECL_FGETS_UNLOCKED -# define fgets_unlocked(x,y,z) fgets (x,y,z) -# endif -#if defined(HAVE_DECL_FPUTC_UNLOCKED) && !HAVE_DECL_FPUTC_UNLOCKED -# define fputc_unlocked(x,y) fputc (x,y) -# endif -#if defined(HAVE_DECL_FPUTS_UNLOCKED) && !HAVE_DECL_FPUTS_UNLOCKED -# define fputs_unlocked(x,y) fputs (x,y) -# endif -#if defined(HAVE_DECL_FREAD_UNLOCKED) && !HAVE_DECL_FREAD_UNLOCKED -# define fread_unlocked(w,x,y,z) fread (w,x,y,z) -# endif -#if defined(HAVE_DECL_FWRITE_UNLOCKED) && !HAVE_DECL_FWRITE_UNLOCKED -# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z) -# endif -#if defined(HAVE_DECL_GETC_UNLOCKED) && !HAVE_DECL_GETC_UNLOCKED -# define getc_unlocked(x) getc (x) -# endif -#if defined(HAVE_DECL_GETCHAR_UNLOCKED) && !HAVE_DECL_GETCHAR_UNLOCKED -# define getchar_unlocked() getchar () -# endif -#if defined(HAVE_DECL_PUTC_UNLOCKED) && !HAVE_DECL_PUTC_UNLOCKED -# define putc_unlocked(x,y) putc (x,y) -# endif -#if defined(HAVE_DECL_PUTCHAR_UNLOCKED) && !HAVE_DECL_PUTCHAR_UNLOCKED -# define putchar_unlocked(x) putchar (x) -# endif - -#endif /* !_LIBC */ - -#ifndef __set_errno -#define __set_errno(e) (errno = (e)) -#endif - -#if defined GNULIB_ARGP_DISABLE_DIRNAME -# define __argp_base_name(arg) arg -#elif defined GNULIB_ARGP_EXTERN_BASENAME -extern char *__argp_base_name (const char *arg); -#else -# include "dirname.h" -# define __argp_base_name last_component -#endif - -#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME -# define __argp_short_program_name() (program_invocation_short_name) -#else -extern char *__argp_short_program_name (void); -#endif diff --git a/grub-core/gnulib/argp-parse.c b/grub-core/gnulib/argp-parse.c deleted file mode 100644 index 9c054653c..000000000 --- a/grub-core/gnulib/argp-parse.c +++ /dev/null @@ -1,952 +0,0 @@ -/* Hierarchial argument parsing, layered over getopt - Copyright (C) 1995-2000, 2002-2004, 2009-2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _LIBC -# include -# undef dgettext -# define dgettext(domain, msgid) \ - INTUSE(__dcgettext) (domain, msgid, LC_MESSAGES) -#else -# include "gettext.h" -#endif -#define N_(msgid) msgid - -#include "argp.h" -#include "argp-namefrob.h" - -#define alignof(type) offsetof (struct { char c; type x; }, x) -#define alignto(n, d) ((((n) + (d) - 1) / (d)) * (d)) - -/* Getopt return values. */ -#define KEY_END (-1) /* The end of the options. */ -#define KEY_ARG 1 /* A non-option argument. */ -#define KEY_ERR '?' /* An error parsing the options. */ - -/* The meta-argument used to prevent any further arguments being interpreted - as options. */ -#define QUOTE "--" - -/* The number of bits we steal in a long-option value for our own use. */ -#define GROUP_BITS CHAR_BIT - -/* The number of bits available for the user value. */ -#define USER_BITS ((sizeof ((struct option *)0)->val * CHAR_BIT) - GROUP_BITS) -#define USER_MASK ((1 << USER_BITS) - 1) - -/* EZ alias for ARGP_ERR_UNKNOWN. */ -#define EBADKEY ARGP_ERR_UNKNOWN - -/* Default options. */ - -/* When argp is given the --HANG switch, _ARGP_HANG is set and argp will sleep - for one second intervals, decrementing _ARGP_HANG until it's zero. Thus - you can force the program to continue by attaching a debugger and setting - it to 0 yourself. */ -static volatile int _argp_hang; - -#define OPT_PROGNAME -2 -#define OPT_USAGE -3 -#define OPT_HANG -4 - -static const struct argp_option argp_default_options[] = -{ - {"help", '?', 0, 0, N_("give this help list"), -1}, - {"usage", OPT_USAGE, 0, 0, N_("give a short usage message"), 0}, - {"program-name",OPT_PROGNAME,N_("NAME"), OPTION_HIDDEN, N_("set the program name"), 0}, - {"HANG", OPT_HANG, N_("SECS"), OPTION_ARG_OPTIONAL | OPTION_HIDDEN, - N_("hang for SECS seconds (default 3600)"), 0}, - {NULL, 0, 0, 0, NULL, 0} -}; - -static error_t -argp_default_parser (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - case '?': - __argp_state_help (state, state->out_stream, ARGP_HELP_STD_HELP); - break; - case OPT_USAGE: - __argp_state_help (state, state->out_stream, - ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK); - break; - - case OPT_PROGNAME: /* Set the program name. */ -#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_NAME - program_invocation_name = arg; -#endif - /* [Note that some systems only have PROGRAM_INVOCATION_SHORT_NAME (aka - __PROGNAME), in which case, PROGRAM_INVOCATION_NAME is just defined - to be that, so we have to be a bit careful here.] */ - - /* Update what we use for messages. */ - state->name = __argp_base_name (arg); - -#if defined _LIBC || HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME - program_invocation_short_name = state->name; -#endif - - if ((state->flags & (ARGP_PARSE_ARGV0 | ARGP_NO_ERRS)) - == ARGP_PARSE_ARGV0) - /* Update what getopt uses too. */ - state->argv[0] = arg; - - break; - - case OPT_HANG: - _argp_hang = atoi (arg ? arg : "3600"); - while (_argp_hang-- > 0) - __sleep (1); - break; - - default: - return EBADKEY; - } - return 0; -} - -static const struct argp argp_default_argp = - {argp_default_options, &argp_default_parser, NULL, NULL, NULL, NULL, "libc"}; - - -static const struct argp_option argp_version_options[] = -{ - {"version", 'V', 0, 0, N_("print program version"), -1}, - {NULL, 0, 0, 0, NULL, 0} -}; - -static error_t -argp_version_parser (int key, char *arg, struct argp_state *state) -{ - switch (key) - { - case 'V': - if (argp_program_version_hook) - (*argp_program_version_hook) (state->out_stream, state); - else if (argp_program_version) - fprintf (state->out_stream, "%s\n", argp_program_version); - else - __argp_error (state, dgettext (state->root_argp->argp_domain, - "(PROGRAM ERROR) No version known!?")); - if (! (state->flags & ARGP_NO_EXIT)) - exit (0); - break; - default: - return EBADKEY; - } - return 0; -} - -static const struct argp argp_version_argp = - {argp_version_options, &argp_version_parser, NULL, NULL, NULL, NULL, "libc"}; - -/* Returns the offset into the getopt long options array LONG_OPTIONS of a - long option with called NAME, or -1 if none is found. Passing NULL as - NAME will return the number of options. */ -static int -find_long_option (struct option *long_options, const char *name) -{ - struct option *l = long_options; - while (l->name != NULL) - if (name != NULL && strcmp (l->name, name) == 0) - return l - long_options; - else - l++; - if (name == NULL) - return l - long_options; - else - return -1; -} - - -/* The state of a `group' during parsing. Each group corresponds to a - particular argp structure from the tree of such descending from the top - level argp passed to argp_parse. */ -struct group -{ - /* This group's parsing function. */ - argp_parser_t parser; - - /* Which argp this group is from. */ - const struct argp *argp; - - /* Points to the point in SHORT_OPTS corresponding to the end of the short - options for this group. We use it to determine from which group a - particular short options is from. */ - char *short_end; - - /* The number of non-option args sucessfully handled by this parser. */ - unsigned args_processed; - - /* This group's parser's parent's group. */ - struct group *parent; - unsigned parent_index; /* And the our position in the parent. */ - - /* These fields are swapped into and out of the state structure when - calling this group's parser. */ - void *input, **child_inputs; - void *hook; -}; - -/* Call GROUP's parser with KEY and ARG, swapping any group-specific info - from STATE before calling, and back into state afterwards. If GROUP has - no parser, EBADKEY is returned. */ -static error_t -group_parse (struct group *group, struct argp_state *state, int key, char *arg) -{ - if (group->parser) - { - error_t err; - state->hook = group->hook; - state->input = group->input; - state->child_inputs = group->child_inputs; - state->arg_num = group->args_processed; - err = (*group->parser)(key, arg, state); - group->hook = state->hook; - return err; - } - else - return EBADKEY; -} - -struct parser -{ - const struct argp *argp; - - /* SHORT_OPTS is the getopt short options string for the union of all the - groups of options. */ - char *short_opts; - /* LONG_OPTS is the array of getop long option structures for the union of - all the groups of options. */ - struct option *long_opts; - /* OPT_DATA is the getopt data used for the re-entrant getopt. */ - struct _getopt_data opt_data; - - /* States of the various parsing groups. */ - struct group *groups; - /* The end of the GROUPS array. */ - struct group *egroup; - /* An vector containing storage for the CHILD_INPUTS field in all groups. */ - void **child_inputs; - - /* True if we think using getopt is still useful; if false, then - remaining arguments are just passed verbatim with ARGP_KEY_ARG. This is - cleared whenever getopt returns KEY_END, but may be set again if the user - moves the next argument pointer backwards. */ - int try_getopt; - - /* State block supplied to parsing routines. */ - struct argp_state state; - - /* Memory used by this parser. */ - void *storage; -}; - -/* The next usable entries in the various parser tables being filled in by - convert_options. */ -struct parser_convert_state -{ - struct parser *parser; - char *short_end; - struct option *long_end; - void **child_inputs_end; -}; - -/* Converts all options in ARGP (which is put in GROUP) and ancestors - into getopt options stored in SHORT_OPTS and LONG_OPTS; SHORT_END and - CVT->LONG_END are the points at which new options are added. Returns the - next unused group entry. CVT holds state used during the conversion. */ -static struct group * -convert_options (const struct argp *argp, - struct group *parent, unsigned parent_index, - struct group *group, struct parser_convert_state *cvt) -{ - /* REAL is the most recent non-alias value of OPT. */ - const struct argp_option *real = argp->options; - const struct argp_child *children = argp->children; - - if (real || argp->parser) - { - const struct argp_option *opt; - - if (real) - for (opt = real; !__option_is_end (opt); opt++) - { - if (! (opt->flags & OPTION_ALIAS)) - /* OPT isn't an alias, so we can use values from it. */ - real = opt; - - if (! (real->flags & OPTION_DOC)) - /* A real option (not just documentation). */ - { - if (__option_is_short (opt)) - /* OPT can be used as a short option. */ - { - *cvt->short_end++ = opt->key; - if (real->arg) - { - *cvt->short_end++ = ':'; - if (real->flags & OPTION_ARG_OPTIONAL) - *cvt->short_end++ = ':'; - } - *cvt->short_end = '\0'; /* keep 0 terminated */ - } - - if (opt->name - && find_long_option (cvt->parser->long_opts, opt->name) < 0) - /* OPT can be used as a long option. */ - { - cvt->long_end->name = opt->name; - cvt->long_end->has_arg = - (real->arg - ? (real->flags & OPTION_ARG_OPTIONAL - ? optional_argument - : required_argument) - : no_argument); - cvt->long_end->flag = 0; - /* we add a disambiguating code to all the user's - values (which is removed before we actually call - the function to parse the value); this means that - the user loses use of the high 8 bits in all his - values (the sign of the lower bits is preserved - however)... */ - cvt->long_end->val = - ((opt->key ? opt->key : real->key) & USER_MASK) - + (((group - cvt->parser->groups) + 1) << USER_BITS); - - /* Keep the LONG_OPTS list terminated. */ - (++cvt->long_end)->name = NULL; - } - } - } - - group->parser = argp->parser; - group->argp = argp; - group->short_end = cvt->short_end; - group->args_processed = 0; - group->parent = parent; - group->parent_index = parent_index; - group->input = 0; - group->hook = 0; - group->child_inputs = 0; - - if (children) - /* Assign GROUP's CHILD_INPUTS field some space from - CVT->child_inputs_end.*/ - { - unsigned num_children = 0; - while (children[num_children].argp) - num_children++; - group->child_inputs = cvt->child_inputs_end; - cvt->child_inputs_end += num_children; - } - - parent = group++; - } - else - parent = 0; - - if (children) - { - unsigned index = 0; - while (children->argp) - group = - convert_options (children++->argp, parent, index++, group, cvt); - } - - return group; -} - -/* Find the merged set of getopt options, with keys appropiately prefixed. */ -static void -parser_convert (struct parser *parser, const struct argp *argp, int flags) -{ - struct parser_convert_state cvt; - - cvt.parser = parser; - cvt.short_end = parser->short_opts; - cvt.long_end = parser->long_opts; - cvt.child_inputs_end = parser->child_inputs; - - if (flags & ARGP_IN_ORDER) - *cvt.short_end++ = '-'; - else if (flags & ARGP_NO_ARGS) - *cvt.short_end++ = '+'; - *cvt.short_end = '\0'; - - cvt.long_end->name = NULL; - - parser->argp = argp; - - if (argp) - parser->egroup = convert_options (argp, 0, 0, parser->groups, &cvt); - else - parser->egroup = parser->groups; /* No parsers at all! */ -} - -/* Lengths of various parser fields which we will allocated. */ -struct parser_sizes -{ - size_t short_len; /* Getopt short options string. */ - size_t long_len; /* Getopt long options vector. */ - size_t num_groups; /* Group structures we allocate. */ - size_t num_child_inputs; /* Child input slots. */ -}; - -/* For ARGP, increments the NUM_GROUPS field in SZS by the total number of - argp structures descended from it, and the SHORT_LEN & LONG_LEN fields by - the maximum lengths of the resulting merged getopt short options string and - long-options array, respectively. */ -static void -calc_sizes (const struct argp *argp, struct parser_sizes *szs) -{ - const struct argp_child *child = argp->children; - const struct argp_option *opt = argp->options; - - if (opt || argp->parser) - { - szs->num_groups++; - if (opt) - { - int num_opts = 0; - while (!__option_is_end (opt++)) - num_opts++; - szs->short_len += num_opts * 3; /* opt + up to 2 `:'s */ - szs->long_len += num_opts; - } - } - - if (child) - while (child->argp) - { - calc_sizes ((child++)->argp, szs); - szs->num_child_inputs++; - } -} - -/* Initializes PARSER to parse ARGP in a manner described by FLAGS. */ -static error_t -parser_init (struct parser *parser, const struct argp *argp, - int argc, char **argv, int flags, void *input) -{ - error_t err = 0; - struct group *group; - struct parser_sizes szs; - struct _getopt_data opt_data = _GETOPT_DATA_INITIALIZER; - char *storage; - size_t glen, gsum; - size_t clen, csum; - size_t llen, lsum; - size_t slen, ssum; - - szs.short_len = (flags & ARGP_NO_ARGS) ? 0 : 1; - szs.long_len = 0; - szs.num_groups = 0; - szs.num_child_inputs = 0; - - if (argp) - calc_sizes (argp, &szs); - - /* Lengths of the various bits of storage used by PARSER. */ - glen = (szs.num_groups + 1) * sizeof (struct group); - clen = szs.num_child_inputs * sizeof (void *); - llen = (szs.long_len + 1) * sizeof (struct option); - slen = szs.short_len + 1; - - /* Sums of previous lengths, properly aligned. There's no need to - align gsum, since struct group is aligned at least as strictly as - void * (since it contains a void * member). And there's no need - to align lsum, since struct option is aligned at least as - strictly as char. */ - gsum = glen; - csum = alignto (gsum + clen, alignof (struct option)); - lsum = csum + llen; - ssum = lsum + slen; - - parser->storage = malloc (ssum); - if (! parser->storage) - return ENOMEM; - - storage = parser->storage; - parser->groups = parser->storage; - parser->child_inputs = (void **) (storage + gsum); - parser->long_opts = (struct option *) (storage + csum); - parser->short_opts = storage + lsum; - parser->opt_data = opt_data; - - memset (parser->child_inputs, 0, clen); - parser_convert (parser, argp, flags); - - memset (&parser->state, 0, sizeof (struct argp_state)); - parser->state.root_argp = parser->argp; - parser->state.argc = argc; - parser->state.argv = argv; - parser->state.flags = flags; - parser->state.err_stream = stderr; - parser->state.out_stream = stdout; - parser->state.next = 0; /* Tell getopt to initialize. */ - parser->state.pstate = parser; - - parser->try_getopt = 1; - - /* Call each parser for the first time, giving it a chance to propagate - values to child parsers. */ - if (parser->groups < parser->egroup) - parser->groups->input = input; - for (group = parser->groups; - group < parser->egroup && (!err || err == EBADKEY); - group++) - { - if (group->parent) - /* If a child parser, get the initial input value from the parent. */ - group->input = group->parent->child_inputs[group->parent_index]; - - if (!group->parser - && group->argp->children && group->argp->children->argp) - /* For the special case where no parsing function is supplied for an - argp, propagate its input to its first child, if any (this just - makes very simple wrapper argps more convenient). */ - group->child_inputs[0] = group->input; - - err = group_parse (group, &parser->state, ARGP_KEY_INIT, 0); - } - if (err == EBADKEY) - err = 0; /* Some parser didn't understand. */ - - if (err) - return err; - - if (parser->state.flags & ARGP_NO_ERRS) - { - parser->opt_data.opterr = 0; - if (parser->state.flags & ARGP_PARSE_ARGV0) - /* getopt always skips ARGV[0], so we have to fake it out. As long - as OPTERR is 0, then it shouldn't actually try to access it. */ - parser->state.argv--, parser->state.argc++; - } - else - parser->opt_data.opterr = 1; /* Print error messages. */ - - if (parser->state.argv == argv && argv[0]) - /* There's an argv[0]; use it for messages. */ - parser->state.name = __argp_base_name (argv[0]); - else - parser->state.name = __argp_short_program_name (); - - return 0; -} - -/* Free any storage consumed by PARSER (but not PARSER itself). */ -static error_t -parser_finalize (struct parser *parser, - error_t err, int arg_ebadkey, int *end_index) -{ - struct group *group; - - if (err == EBADKEY && arg_ebadkey) - /* Suppress errors generated by unparsed arguments. */ - err = 0; - - if (! err) - { - if (parser->state.next == parser->state.argc) - /* We successfully parsed all arguments! Call all the parsers again, - just a few more times... */ - { - for (group = parser->groups; - group < parser->egroup && (!err || err==EBADKEY); - group++) - if (group->args_processed == 0) - err = group_parse (group, &parser->state, ARGP_KEY_NO_ARGS, 0); - for (group = parser->egroup - 1; - group >= parser->groups && (!err || err==EBADKEY); - group--) - err = group_parse (group, &parser->state, ARGP_KEY_END, 0); - - if (err == EBADKEY) - err = 0; /* Some parser didn't understand. */ - - /* Tell the user that all arguments are parsed. */ - if (end_index) - *end_index = parser->state.next; - } - else if (end_index) - /* Return any remaining arguments to the user. */ - *end_index = parser->state.next; - else - /* No way to return the remaining arguments, they must be bogus. */ - { - if (!(parser->state.flags & ARGP_NO_ERRS) - && parser->state.err_stream) - fprintf (parser->state.err_stream, - dgettext (parser->argp->argp_domain, - "%s: Too many arguments\n"), - parser->state.name); - err = EBADKEY; - } - } - - /* Okay, we're all done, with either an error or success; call the parsers - to indicate which one. */ - - if (err) - { - /* Maybe print an error message. */ - if (err == EBADKEY) - /* An appropriate message describing what the error was should have - been printed earlier. */ - __argp_state_help (&parser->state, parser->state.err_stream, - ARGP_HELP_STD_ERR); - - /* Since we didn't exit, give each parser an error indication. */ - for (group = parser->groups; group < parser->egroup; group++) - group_parse (group, &parser->state, ARGP_KEY_ERROR, 0); - } - else - /* Notify parsers of success, and propagate back values from parsers. */ - { - /* We pass over the groups in reverse order so that child groups are - given a chance to do there processing before passing back a value to - the parent. */ - for (group = parser->egroup - 1 - ; group >= parser->groups && (!err || err == EBADKEY) - ; group--) - err = group_parse (group, &parser->state, ARGP_KEY_SUCCESS, 0); - if (err == EBADKEY) - err = 0; /* Some parser didn't understand. */ - } - - /* Call parsers once more, to do any final cleanup. Errors are ignored. */ - for (group = parser->egroup - 1; group >= parser->groups; group--) - group_parse (group, &parser->state, ARGP_KEY_FINI, 0); - - if (err == EBADKEY) - err = EINVAL; - - free (parser->storage); - - return err; -} - -/* Call the user parsers to parse the non-option argument VAL, at the current - position, returning any error. The state NEXT pointer is assumed to have - been adjusted (by getopt) to point after this argument; this function will - adjust it correctly to reflect however many args actually end up being - consumed. */ -static error_t -parser_parse_arg (struct parser *parser, char *val) -{ - /* Save the starting value of NEXT, first adjusting it so that the arg - we're parsing is again the front of the arg vector. */ - int index = --parser->state.next; - error_t err = EBADKEY; - struct group *group; - int key = 0; /* Which of ARGP_KEY_ARG[S] we used. */ - - /* Try to parse the argument in each parser. */ - for (group = parser->groups - ; group < parser->egroup && err == EBADKEY - ; group++) - { - parser->state.next++; /* For ARGP_KEY_ARG, consume the arg. */ - key = ARGP_KEY_ARG; - err = group_parse (group, &parser->state, key, val); - - if (err == EBADKEY) - /* This parser doesn't like ARGP_KEY_ARG; try ARGP_KEY_ARGS instead. */ - { - parser->state.next--; /* For ARGP_KEY_ARGS, put back the arg. */ - key = ARGP_KEY_ARGS; - err = group_parse (group, &parser->state, key, 0); - } - } - - if (! err) - { - if (key == ARGP_KEY_ARGS) - /* The default for ARGP_KEY_ARGS is to assume that if NEXT isn't - changed by the user, *all* arguments should be considered - consumed. */ - parser->state.next = parser->state.argc; - - if (parser->state.next > index) - /* Remember that we successfully processed a non-option - argument -- but only if the user hasn't gotten tricky and set - the clock back. */ - (--group)->args_processed += (parser->state.next - index); - else - /* The user wants to reparse some args, give getopt another try. */ - parser->try_getopt = 1; - } - - return err; -} - -/* Call the user parsers to parse the option OPT, with argument VAL, at the - current position, returning any error. */ -static error_t -parser_parse_opt (struct parser *parser, int opt, char *val) -{ - /* The group key encoded in the high bits; 0 for short opts or - group_number + 1 for long opts. */ - int group_key = opt >> USER_BITS; - error_t err = EBADKEY; - - if (group_key == 0) - /* A short option. By comparing OPT's position in SHORT_OPTS to the - various starting positions in each group's SHORT_END field, we can - determine which group OPT came from. */ - { - struct group *group; - char *short_index = strchr (parser->short_opts, opt); - - if (short_index) - for (group = parser->groups; group < parser->egroup; group++) - if (group->short_end > short_index) - { - err = group_parse (group, &parser->state, opt, - parser->opt_data.optarg); - break; - } - } - else - /* A long option. We use shifts instead of masking for extracting - the user value in order to preserve the sign. */ - err = - group_parse (&parser->groups[group_key - 1], &parser->state, - (opt << GROUP_BITS) >> GROUP_BITS, - parser->opt_data.optarg); - - if (err == EBADKEY) - /* At least currently, an option not recognized is an error in the - parser, because we pre-compute which parser is supposed to deal - with each option. */ - { - static const char bad_key_err[] = - N_("(PROGRAM ERROR) Option should have been recognized!?"); - if (group_key == 0) - __argp_error (&parser->state, "-%c: %s", opt, - dgettext (parser->argp->argp_domain, bad_key_err)); - else - { - struct option *long_opt = parser->long_opts; - while (long_opt->val != opt && long_opt->name) - long_opt++; - __argp_error (&parser->state, "--%s: %s", - long_opt->name ? long_opt->name : "???", - dgettext (parser->argp->argp_domain, bad_key_err)); - } - } - - return err; -} - -/* Parse the next argument in PARSER (as indicated by PARSER->state.next). - Any error from the parsers is returned, and *ARGP_EBADKEY indicates - whether a value of EBADKEY is due to an unrecognized argument (which is - generally not fatal). */ -static error_t -parser_parse_next (struct parser *parser, int *arg_ebadkey) -{ - int opt; - error_t err = 0; - - if (parser->state.quoted && parser->state.next < parser->state.quoted) - /* The next argument pointer has been moved to before the quoted - region, so pretend we never saw the quoting `--', and give getopt - another chance. If the user hasn't removed it, getopt will just - process it again. */ - parser->state.quoted = 0; - - if (parser->try_getopt && !parser->state.quoted) - /* Give getopt a chance to parse this. */ - { - /* Put it back in OPTIND for getopt. */ - parser->opt_data.optind = parser->state.next; - /* Distinguish KEY_ERR from a real option. */ - parser->opt_data.optopt = KEY_END; - if (parser->state.flags & ARGP_LONG_ONLY) - opt = _getopt_long_only_r (parser->state.argc, parser->state.argv, - parser->short_opts, parser->long_opts, 0, - &parser->opt_data); - else - opt = _getopt_long_r (parser->state.argc, parser->state.argv, - parser->short_opts, parser->long_opts, 0, - &parser->opt_data); - /* And see what getopt did. */ - parser->state.next = parser->opt_data.optind; - - if (opt == KEY_END) - /* Getopt says there are no more options, so stop using - getopt; we'll continue if necessary on our own. */ - { - parser->try_getopt = 0; - if (parser->state.next > 1 - && strcmp (parser->state.argv[parser->state.next - 1], QUOTE) - == 0) - /* Not only is this the end of the options, but it's a - `quoted' region, which may have args that *look* like - options, so we definitely shouldn't try to use getopt past - here, whatever happens. */ - parser->state.quoted = parser->state.next; - } - else if (opt == KEY_ERR && parser->opt_data.optopt != KEY_END) - /* KEY_ERR can have the same value as a valid user short - option, but in the case of a real error, getopt sets OPTOPT - to the offending character, which can never be KEY_END. */ - { - *arg_ebadkey = 0; - return EBADKEY; - } - } - else - opt = KEY_END; - - if (opt == KEY_END) - { - /* We're past what getopt considers the options. */ - if (parser->state.next >= parser->state.argc - || (parser->state.flags & ARGP_NO_ARGS)) - /* Indicate that we're done. */ - { - *arg_ebadkey = 1; - return EBADKEY; - } - else - /* A non-option arg; simulate what getopt might have done. */ - { - opt = KEY_ARG; - parser->opt_data.optarg = parser->state.argv[parser->state.next++]; - } - } - - if (opt == KEY_ARG) - /* A non-option argument; try each parser in turn. */ - err = parser_parse_arg (parser, parser->opt_data.optarg); - else - err = parser_parse_opt (parser, opt, parser->opt_data.optarg); - - if (err == EBADKEY) - *arg_ebadkey = (opt == KEY_END || opt == KEY_ARG); - - return err; -} - -/* Parse the options strings in ARGC & ARGV according to the argp in ARGP. - FLAGS is one of the ARGP_ flags above. If END_INDEX is non-NULL, the - index in ARGV of the first unparsed option is returned in it. If an - unknown option is present, EINVAL is returned; if some parser routine - returned a non-zero value, it is returned; otherwise 0 is returned. */ -error_t -__argp_parse (const struct argp *argp, int argc, char **argv, unsigned flags, - int *end_index, void *input) -{ - error_t err; - struct parser parser; - - /* If true, then err == EBADKEY is a result of a non-option argument failing - to be parsed (which in some cases isn't actually an error). */ - int arg_ebadkey = 0; - -#ifndef _LIBC - if (!(flags & ARGP_PARSE_ARGV0)) - { -#ifdef HAVE_DECL_PROGRAM_INVOCATION_NAME - if (!program_invocation_name) - program_invocation_name = argv[0]; -#endif -#ifdef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME - if (!program_invocation_short_name) - program_invocation_short_name = __argp_base_name (argv[0]); -#endif - } -#endif - - if (! (flags & ARGP_NO_HELP)) - /* Add our own options. */ - { - struct argp_child *child = alloca (4 * sizeof (struct argp_child)); - struct argp *top_argp = alloca (sizeof (struct argp)); - - /* TOP_ARGP has no options, it just serves to group the user & default - argps. */ - memset (top_argp, 0, sizeof (*top_argp)); - top_argp->children = child; - - memset (child, 0, 4 * sizeof (struct argp_child)); - - if (argp) - (child++)->argp = argp; - (child++)->argp = &argp_default_argp; - if (argp_program_version || argp_program_version_hook) - (child++)->argp = &argp_version_argp; - child->argp = 0; - - argp = top_argp; - } - - /* Construct a parser for these arguments. */ - err = parser_init (&parser, argp, argc, argv, flags, input); - - if (! err) - /* Parse! */ - { - while (! err) - err = parser_parse_next (&parser, &arg_ebadkey); - err = parser_finalize (&parser, err, arg_ebadkey, end_index); - } - - return err; -} -#ifdef weak_alias -weak_alias (__argp_parse, argp_parse) -#endif - -/* Return the input field for ARGP in the parser corresponding to STATE; used - by the help routines. */ -void * -__argp_input (const struct argp *argp, const struct argp_state *state) -{ - if (state && state->pstate) - { - struct group *group; - struct parser *parser = state->pstate; - - for (group = parser->groups; group < parser->egroup; group++) - if (group->argp == argp) - return group->input; - } - - return 0; -} -#ifdef weak_alias -weak_alias (__argp_input, _argp_input) -#endif diff --git a/grub-core/gnulib/argp-pin.c b/grub-core/gnulib/argp-pin.c deleted file mode 100644 index eda4d958e..000000000 --- a/grub-core/gnulib/argp-pin.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Full and short program names for argp module - Copyright (C) 2005, 2009, 2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME -char *program_invocation_short_name = 0; -#endif -#ifndef HAVE_PROGRAM_INVOCATION_NAME -char *program_invocation_name = 0; -#endif - diff --git a/grub-core/gnulib/argp-pv.c b/grub-core/gnulib/argp-pv.c deleted file mode 100644 index e3227d322..000000000 --- a/grub-core/gnulib/argp-pv.c +++ /dev/null @@ -1,34 +0,0 @@ -/* Default definition for ARGP_PROGRAM_VERSION. - Copyright (C) 1996, 1997, 1999, 2006, 2009, 2010 Free Software Foundation, - Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* If set by the user program to a non-zero value, then a default option - --version is added (unless the ARGP_NO_HELP flag is used), which will - print this string followed by a newline and exit (unless the - ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ -const char *argp_program_version -/* This variable should be zero-initialized. On most systems, putting it into - BSS is sufficient. Not so on MacOS X 10.3 and 10.4, see - - . */ -#if defined __ELF__ - /* On ELF systems, variables in BSS behave well. */ -#else - = (const char *) 0 -#endif - ; diff --git a/grub-core/gnulib/argp-pvh.c b/grub-core/gnulib/argp-pvh.c deleted file mode 100644 index fb98fc21c..000000000 --- a/grub-core/gnulib/argp-pvh.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Default definition for ARGP_PROGRAM_VERSION_HOOK. - Copyright (C) 1996, 1997, 1999, 2004, 2009, 2010 Free Software Foundation, - Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "argp.h" - -/* If set by the user program to a non-zero value, then a default option - --version is added (unless the ARGP_NO_HELP flag is used), which calls - this function with a stream to print the version to and a pointer to the - current parsing state, and then exits (unless the ARGP_NO_EXIT flag is - used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ -void (*argp_program_version_hook) (FILE *stream, struct argp_state *state) = NULL; diff --git a/grub-core/gnulib/argp-xinl.c b/grub-core/gnulib/argp-xinl.c deleted file mode 100644 index 6e7e20bba..000000000 --- a/grub-core/gnulib/argp-xinl.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Real definitions for extern inline functions in argp.h - Copyright (C) 1997, 1998, 2004, 2009, 2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#if defined _LIBC || defined HAVE_FEATURES_H -# include -#endif - -#ifndef __USE_EXTERN_INLINES -# define __USE_EXTERN_INLINES 1 -#endif -#define ARGP_EI -#undef __OPTIMIZE__ -#define __OPTIMIZE__ 1 -#include "argp.h" - -/* Add weak aliases. */ -#if _LIBC - 0 && defined (weak_alias) - -weak_alias (__argp_usage, argp_usage) -weak_alias (__option_is_short, _option_is_short) -weak_alias (__option_is_end, _option_is_end) - -#endif diff --git a/grub-core/gnulib/argp.h b/grub-core/gnulib/argp.h deleted file mode 100644 index 3667224a9..000000000 --- a/grub-core/gnulib/argp.h +++ /dev/null @@ -1,645 +0,0 @@ -/* Hierarchial argument parsing, layered over getopt. - Copyright (C) 1995-1999, 2003-2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Written by Miles Bader . - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef _ARGP_H -#define _ARGP_H - -#include -#include -#include -#include - -#define __need_error_t -#include - -#ifndef __THROW -# define __THROW -#endif -#ifndef __NTH -# define __NTH(fct) fct __THROW -#endif - -#ifndef __attribute__ -/* The __attribute__ feature is available in gcc versions 2.5 and later. - The __-protected variants of the attributes 'format' and 'printf' are - accepted by gcc versions 2.6.4 (effectively 2.7) and later. - We enable __attribute__ only if these are supported too, because - gnulib and libintl do '#define printf __printf__' when they override - the 'printf' function. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __attribute__(Spec) /* empty */ -# endif -#endif - -/* GCC 2.95 and later have "__restrict"; C99 compilers have - "restrict", and "configure" may have defined "restrict". - Other compilers use __restrict, __restrict__, and _Restrict, and - 'configure' might #define 'restrict' to those words. */ -#ifndef __restrict -# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) -# if 199901L <= __STDC_VERSION__ -# define __restrict restrict -# else -# define __restrict -# endif -# endif -#endif - -#ifndef __error_t_defined -typedef int error_t; -# define __error_t_defined -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* A description of a particular option. A pointer to an array of - these is passed in the OPTIONS field of an argp structure. Each option - entry can correspond to one long option and/or one short option; more - names for the same option can be added by following an entry in an option - array with options having the OPTION_ALIAS flag set. */ -struct argp_option -{ - /* The long option name. For more than one name for the same option, you - can use following options with the OPTION_ALIAS flag set. */ - const char *name; - - /* What key is returned for this option. If > 0 and printable, then it's - also accepted as a short option. */ - int key; - - /* If non-NULL, this is the name of the argument associated with this - option, which is required unless the OPTION_ARG_OPTIONAL flag is set. */ - const char *arg; - - /* OPTION_ flags. */ - int flags; - - /* The doc string for this option. If both NAME and KEY are 0, This string - will be printed outdented from the normal option column, making it - useful as a group header (it will be the first thing printed in its - group); in this usage, it's conventional to end the string with a `:'. - - Write the initial value as N_("TEXT") if you want xgettext to collect - it into a POT file. */ - const char *doc; - - /* The group this option is in. In a long help message, options are sorted - alphabetically within each group, and the groups presented in the order - 0, 1, 2, ..., n, -m, ..., -2, -1. Every entry in an options array with - if this field 0 will inherit the group number of the previous entry, or - zero if it's the first one, unless its a group header (NAME and KEY both - 0), in which case, the previous entry + 1 is the default. Automagic - options such as --help are put into group -1. */ - int group; -}; - -/* The argument associated with this option is optional. */ -#define OPTION_ARG_OPTIONAL 0x1 - -/* This option isn't displayed in any help messages. */ -#define OPTION_HIDDEN 0x2 - -/* This option is an alias for the closest previous non-alias option. This - means that it will be displayed in the same help entry, and will inherit - fields other than NAME and KEY from the aliased option. */ -#define OPTION_ALIAS 0x4 - -/* This option isn't actually an option (and so should be ignored by the - actual option parser), but rather an arbitrary piece of documentation that - should be displayed in much the same manner as the options. If this flag - is set, then the option NAME field is displayed unmodified (e.g., no `--' - prefix is added) at the left-margin (where a *short* option would normally - be displayed), and the documentation string in the normal place. The NAME - field will be translated using gettext, unless OPTION_NO_TRANS is set (see - below). For purposes of sorting, any leading whitespace and punctuation is - ignored, except that if the first non-whitespace character is not `-', this - entry is displayed after all options (and OPTION_DOC entries with a leading - `-') in the same group. */ -#define OPTION_DOC 0x8 - -/* This option shouldn't be included in `long' usage messages (but is still - included in help messages). This is mainly intended for options that are - completely documented in an argp's ARGS_DOC field, in which case including - the option in the generic usage list would be redundant. For instance, - if ARGS_DOC is "FOO BAR\n-x BLAH", and the `-x' option's purpose is to - distinguish these two cases, -x should probably be marked - OPTION_NO_USAGE. */ -#define OPTION_NO_USAGE 0x10 - -/* Valid only in conjunction with OPTION_DOC. This option disables translation - of option name. */ -#define OPTION_NO_TRANS 0x20 - - -struct argp; /* fwd declare this type */ -struct argp_state; /* " */ -struct argp_child; /* " */ - -/* The type of a pointer to an argp parsing function. */ -typedef error_t (*argp_parser_t) (int key, char *arg, - struct argp_state *state); - -/* What to return for unrecognized keys. For special ARGP_KEY_ keys, such - returns will simply be ignored. For user keys, this error will be turned - into EINVAL (if the call to argp_parse is such that errors are propagated - back to the user instead of exiting); returning EINVAL itself would result - in an immediate stop to parsing in *all* cases. */ -#define ARGP_ERR_UNKNOWN E2BIG /* Hurd should never need E2BIG. XXX */ - -/* Special values for the KEY argument to an argument parsing function. - ARGP_ERR_UNKNOWN should be returned if they aren't understood. - - The sequence of keys to a parsing function is either (where each - uppercased word should be prefixed by `ARGP_KEY_' and opt is a user key): - - INIT opt... NO_ARGS END SUCCESS -- No non-option arguments at all - or INIT (opt | ARG)... END SUCCESS -- All non-option args parsed - or INIT (opt | ARG)... SUCCESS -- Some non-option arg unrecognized - - The third case is where every parser returned ARGP_KEY_UNKNOWN for an - argument, in which case parsing stops at that argument (returning the - unparsed arguments to the caller of argp_parse if requested, or stopping - with an error message if not). - - If an error occurs (either detected by argp, or because the parsing - function returned an error value), then the parser is called with - ARGP_KEY_ERROR, and no further calls are made. */ - -/* This is not an option at all, but rather a command line argument. If a - parser receiving this key returns success, the fact is recorded, and the - ARGP_KEY_NO_ARGS case won't be used. HOWEVER, if while processing the - argument, a parser function decrements the NEXT field of the state it's - passed, the option won't be considered processed; this is to allow you to - actually modify the argument (perhaps into an option), and have it - processed again. */ -#define ARGP_KEY_ARG 0 -/* There are remaining arguments not parsed by any parser, which may be found - starting at (STATE->argv + STATE->next). If success is returned, but - STATE->next left untouched, it's assumed that all arguments were consume, - otherwise, the parser should adjust STATE->next to reflect any arguments - consumed. */ -#define ARGP_KEY_ARGS 0x1000006 -/* There are no more command line arguments at all. */ -#define ARGP_KEY_END 0x1000001 -/* Because it's common to want to do some special processing if there aren't - any non-option args, user parsers are called with this key if they didn't - successfully process any non-option arguments. Called just before - ARGP_KEY_END (where more general validity checks on previously parsed - arguments can take place). */ -#define ARGP_KEY_NO_ARGS 0x1000002 -/* Passed in before any parsing is done. Afterwards, the values of each - element of the CHILD_INPUT field, if any, in the state structure is - copied to each child's state to be the initial value of the INPUT field. */ -#define ARGP_KEY_INIT 0x1000003 -/* Use after all other keys, including SUCCESS & END. */ -#define ARGP_KEY_FINI 0x1000007 -/* Passed in when parsing has successfully been completed (even if there are - still arguments remaining). */ -#define ARGP_KEY_SUCCESS 0x1000004 -/* Passed in if an error occurs. */ -#define ARGP_KEY_ERROR 0x1000005 - -/* An argp structure contains a set of options declarations, a function to - deal with parsing one, documentation string, a possible vector of child - argp's, and perhaps a function to filter help output. When actually - parsing options, getopt is called with the union of all the argp - structures chained together through their CHILD pointers, with conflicts - being resolved in favor of the first occurrence in the chain. */ -struct argp -{ - /* An array of argp_option structures, terminated by an entry with both - NAME and KEY having a value of 0. */ - const struct argp_option *options; - - /* What to do with an option from this structure. KEY is the key - associated with the option, and ARG is any associated argument (NULL if - none was supplied). If KEY isn't understood, ARGP_ERR_UNKNOWN should be - returned. If a non-zero, non-ARGP_ERR_UNKNOWN value is returned, then - parsing is stopped immediately, and that value is returned from - argp_parse(). For special (non-user-supplied) values of KEY, see the - ARGP_KEY_ definitions below. */ - argp_parser_t parser; - - /* A string describing what other arguments are wanted by this program. It - is only used by argp_usage to print the `Usage:' message. If it - contains newlines, the strings separated by them are considered - alternative usage patterns, and printed on separate lines (lines after - the first are prefix by ` or: ' instead of `Usage:'). */ - const char *args_doc; - - /* If non-NULL, a string containing extra text to be printed before and - after the options in a long help message (separated by a vertical tab - `\v' character). - Write the initial value as N_("BEFORE-TEXT") "\v" N_("AFTER-TEXT") if - you want xgettext to collect the two pieces of text into a POT file. */ - const char *doc; - - /* A vector of argp_children structures, terminated by a member with a 0 - argp field, pointing to child argps should be parsed with this one. Any - conflicts are resolved in favor of this argp, or early argps in the - CHILDREN list. This field is useful if you use libraries that supply - their own argp structure, which you want to use in conjunction with your - own. */ - const struct argp_child *children; - - /* If non-zero, this should be a function to filter the output of help - messages. KEY is either a key from an option, in which case TEXT is - that option's help text, or a special key from the ARGP_KEY_HELP_ - defines, below, describing which other help text TEXT is. The function - should return either TEXT, if it should be used as-is, a replacement - string, which should be malloced, and will be freed by argp, or NULL, - meaning `print nothing'. The value for TEXT is *after* any translation - has been done, so if any of the replacement text also needs translation, - that should be done by the filter function. INPUT is either the input - supplied to argp_parse, or NULL, if argp_help was called directly. */ - char *(*help_filter) (int __key, const char *__text, void *__input); - - /* If non-zero the strings used in the argp library are translated using - the domain described by this string. Otherwise the currently installed - default domain is used. */ - const char *argp_domain; -}; - -/* Possible KEY arguments to a help filter function. */ -#define ARGP_KEY_HELP_PRE_DOC 0x2000001 /* Help text preceeding options. */ -#define ARGP_KEY_HELP_POST_DOC 0x2000002 /* Help text following options. */ -#define ARGP_KEY_HELP_HEADER 0x2000003 /* Option header string. */ -#define ARGP_KEY_HELP_EXTRA 0x2000004 /* After all other documentation; - TEXT is NULL for this key. */ -/* Explanatory note emitted when duplicate option arguments have been - suppressed. */ -#define ARGP_KEY_HELP_DUP_ARGS_NOTE 0x2000005 -#define ARGP_KEY_HELP_ARGS_DOC 0x2000006 /* Argument doc string. */ - -/* When an argp has a non-zero CHILDREN field, it should point to a vector of - argp_child structures, each of which describes a subsidiary argp. */ -struct argp_child -{ - /* The child parser. */ - const struct argp *argp; - - /* Flags for this child. */ - int flags; - - /* If non-zero, an optional header to be printed in help output before the - child options. As a side-effect, a non-zero value forces the child - options to be grouped together; to achieve this effect without actually - printing a header string, use a value of "". */ - const char *header; - - /* Where to group the child options relative to the other (`consolidated') - options in the parent argp; the values are the same as the GROUP field - in argp_option structs, but all child-groupings follow parent options at - a particular group level. If both this field and HEADER are zero, then - they aren't grouped at all, but rather merged with the parent options - (merging the child's grouping levels with the parents). */ - int group; -}; - -/* Parsing state. This is provided to parsing functions called by argp, - which may examine and, as noted, modify fields. */ -struct argp_state -{ - /* The top level ARGP being parsed. */ - const struct argp *root_argp; - - /* The argument vector being parsed. May be modified. */ - int argc; - char **argv; - - /* The index in ARGV of the next arg that to be parsed. May be modified. */ - int next; - - /* The flags supplied to argp_parse. May be modified. */ - unsigned flags; - - /* While calling a parsing function with a key of ARGP_KEY_ARG, this is the - number of the current arg, starting at zero, and incremented after each - such call returns. At all other times, this is the number of such - arguments that have been processed. */ - unsigned arg_num; - - /* If non-zero, the index in ARGV of the first argument following a special - `--' argument (which prevents anything following being interpreted as an - option). Only set once argument parsing has proceeded past this point. */ - int quoted; - - /* An arbitrary pointer passed in from the user. */ - void *input; - /* Values to pass to child parsers. This vector will be the same length as - the number of children for the current parser. */ - void **child_inputs; - - /* For the parser's use. Initialized to 0. */ - void *hook; - - /* The name used when printing messages. This is initialized to ARGV[0], - or PROGRAM_INVOCATION_NAME if that is unavailable. */ - char *name; - - /* Streams used when argp prints something. */ - FILE *err_stream; /* For errors; initialized to stderr. */ - FILE *out_stream; /* For information; initialized to stdout. */ - - void *pstate; /* Private, for use by argp. */ -}; - -/* Flags for argp_parse (note that the defaults are those that are - convenient for program command line parsing): */ - -/* Don't ignore the first element of ARGV. Normally (and always unless - ARGP_NO_ERRS is set) the first element of the argument vector is - skipped for option parsing purposes, as it corresponds to the program name - in a command line. */ -#define ARGP_PARSE_ARGV0 0x01 - -/* Don't print error messages for unknown options to stderr; unless this flag - is set, ARGP_PARSE_ARGV0 is ignored, as ARGV[0] is used as the program - name in the error messages. This flag implies ARGP_NO_EXIT (on the - assumption that silent exiting upon errors is bad behaviour). */ -#define ARGP_NO_ERRS 0x02 - -/* Don't parse any non-option args. Normally non-option args are parsed by - calling the parse functions with a key of ARGP_KEY_ARG, and the actual arg - as the value. Since it's impossible to know which parse function wants to - handle it, each one is called in turn, until one returns 0 or an error - other than ARGP_ERR_UNKNOWN; if an argument is handled by no one, the - argp_parse returns prematurely (but with a return value of 0). If all - args have been parsed without error, all parsing functions are called one - last time with a key of ARGP_KEY_END. This flag needn't normally be set, - as the normal behavior is to stop parsing as soon as some argument can't - be handled. */ -#define ARGP_NO_ARGS 0x04 - -/* Parse options and arguments in the same order they occur on the command - line -- normally they're rearranged so that all options come first. */ -#define ARGP_IN_ORDER 0x08 - -/* Don't provide the standard long option --help, which causes usage and - option help information to be output to stdout, and exit (0) called. */ -#define ARGP_NO_HELP 0x10 - -/* Don't exit on errors (they may still result in error messages). */ -#define ARGP_NO_EXIT 0x20 - -/* Use the gnu getopt `long-only' rules for parsing arguments. */ -#define ARGP_LONG_ONLY 0x40 - -/* Turns off any message-printing/exiting options. */ -#define ARGP_SILENT (ARGP_NO_EXIT | ARGP_NO_ERRS | ARGP_NO_HELP) - -/* Parse the options strings in ARGC & ARGV according to the options in ARGP. - FLAGS is one of the ARGP_ flags above. If ARG_INDEX is non-NULL, the - index in ARGV of the first unparsed option is returned in it. If an - unknown option is present, ARGP_ERR_UNKNOWN is returned; if some parser - routine returned a non-zero value, it is returned; otherwise 0 is - returned. This function may also call exit unless the ARGP_NO_HELP flag - is set. INPUT is a pointer to a value to be passed in to the parser. */ -extern error_t argp_parse (const struct argp *__restrict __argp, - int /*argc*/, char **__restrict /*argv*/, - unsigned __flags, int *__restrict __arg_index, - void *__restrict __input); -extern error_t __argp_parse (const struct argp *__restrict __argp, - int /*argc*/, char **__restrict /*argv*/, - unsigned __flags, int *__restrict __arg_index, - void *__restrict __input); - -/* Global variables. */ - -/* GNULIB makes sure both program_invocation_name and - program_invocation_short_name are available */ -#ifdef GNULIB_PROGRAM_INVOCATION_NAME -extern char *program_invocation_name; -# undef HAVE_DECL_PROGRAM_INVOCATION_NAME -# define HAVE_DECL_PROGRAM_INVOCATION_NAME 1 -#endif - -#ifdef GNULIB_PROGRAM_INVOCATION_SHORT_NAME -extern char *program_invocation_short_name; -# undef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME -# define HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME 1 -#endif - -/* If defined or set by the user program to a non-zero value, then a default - option --version is added (unless the ARGP_NO_HELP flag is used), which - will print this string followed by a newline and exit (unless the - ARGP_NO_EXIT flag is used). Overridden by ARGP_PROGRAM_VERSION_HOOK. */ -extern const char *argp_program_version; - -/* If defined or set by the user program to a non-zero value, then a default - option --version is added (unless the ARGP_NO_HELP flag is used), which - calls this function with a stream to print the version to and a pointer to - the current parsing state, and then exits (unless the ARGP_NO_EXIT flag is - used). This variable takes precedent over ARGP_PROGRAM_VERSION. */ -extern void (*argp_program_version_hook) (FILE *__restrict __stream, - struct argp_state *__restrict - __state); - -/* If defined or set by the user program, it should point to string that is - the bug-reporting address for the program. It will be printed by - argp_help if the ARGP_HELP_BUG_ADDR flag is set (as it is by various - standard help messages), embedded in a sentence that says something like - `Report bugs to ADDR.'. */ -extern const char *argp_program_bug_address; - -/* The exit status that argp will use when exiting due to a parsing error. - If not defined or set by the user program, this defaults to EX_USAGE from - . */ -extern error_t argp_err_exit_status; - -/* Flags for argp_help. */ -#define ARGP_HELP_USAGE 0x01 /* a Usage: message. */ -#define ARGP_HELP_SHORT_USAGE 0x02 /* " but don't actually print options. */ -#define ARGP_HELP_SEE 0x04 /* a `Try ... for more help' message. */ -#define ARGP_HELP_LONG 0x08 /* a long help message. */ -#define ARGP_HELP_PRE_DOC 0x10 /* doc string preceding long help. */ -#define ARGP_HELP_POST_DOC 0x20 /* doc string following long help. */ -#define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC) -#define ARGP_HELP_BUG_ADDR 0x40 /* bug report address */ -#define ARGP_HELP_LONG_ONLY 0x80 /* modify output appropriately to - reflect ARGP_LONG_ONLY mode. */ - -/* These ARGP_HELP flags are only understood by argp_state_help. */ -#define ARGP_HELP_EXIT_ERR 0x100 /* Call exit(1) instead of returning. */ -#define ARGP_HELP_EXIT_OK 0x200 /* Call exit(0) instead of returning. */ - -/* The standard thing to do after a program command line parsing error, if an - error message has already been printed. */ -#define ARGP_HELP_STD_ERR \ - (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) -/* The standard thing to do after a program command line parsing error, if no - more specific error message has been printed. */ -#define ARGP_HELP_STD_USAGE \ - (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR) -/* The standard thing to do in response to a --help option. */ -#define ARGP_HELP_STD_HELP \ - (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \ - | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR) - -/* Output a usage message for ARGP to STREAM. FLAGS are from the set - ARGP_HELP_*. */ -extern void argp_help (const struct argp *__restrict __argp, - FILE *__restrict __stream, - unsigned __flags, char *__restrict __name); -extern void __argp_help (const struct argp *__restrict __argp, - FILE *__restrict __stream, unsigned __flags, - char *__name); - -/* The following routines are intended to be called from within an argp - parsing routine (thus taking an argp_state structure as the first - argument). They may or may not print an error message and exit, depending - on the flags in STATE -- in any case, the caller should be prepared for - them *not* to exit, and should return an appropiate error after calling - them. [argp_usage & argp_error should probably be called argp_state_..., - but they're used often enough that they should be short] */ - -/* Output, if appropriate, a usage message for STATE to STREAM. FLAGS are - from the set ARGP_HELP_*. */ -extern void argp_state_help (const struct argp_state *__restrict __state, - FILE *__restrict __stream, - unsigned int __flags); -extern void __argp_state_help (const struct argp_state *__restrict __state, - FILE *__restrict __stream, - unsigned int __flags); - -#if _LIBC || !defined __USE_EXTERN_INLINES -/* Possibly output the standard usage message for ARGP to stderr and exit. */ -extern void argp_usage (const struct argp_state *__state); -extern void __argp_usage (const struct argp_state *__state); -#endif - -/* If appropriate, print the printf string FMT and following args, preceded - by the program name and `:', to stderr, and followed by a `Try ... --help' - message, then exit (1). */ -extern void argp_error (const struct argp_state *__restrict __state, - const char *__restrict __fmt, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); -extern void __argp_error (const struct argp_state *__restrict __state, - const char *__restrict __fmt, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); - -/* Similar to the standard gnu error-reporting function error(), but will - respect the ARGP_NO_EXIT and ARGP_NO_ERRS flags in STATE, and will print - to STATE->err_stream. This is useful for argument parsing code that is - shared between program startup (when exiting is desired) and runtime - option parsing (when typically an error code is returned instead). The - difference between this function and argp_error is that the latter is for - *parsing errors*, and the former is for other problems that occur during - parsing but don't reflect a (syntactic) problem with the input. */ -extern void argp_failure (const struct argp_state *__restrict __state, - int __status, int __errnum, - const char *__restrict __fmt, ...) - __attribute__ ((__format__ (__printf__, 4, 5))); -extern void __argp_failure (const struct argp_state *__restrict __state, - int __status, int __errnum, - const char *__restrict __fmt, ...) - __attribute__ ((__format__ (__printf__, 4, 5))); - -#if _LIBC || !defined __USE_EXTERN_INLINES -/* Returns true if the option OPT is a valid short option. */ -extern int _option_is_short (const struct argp_option *__opt) __THROW; -extern int __option_is_short (const struct argp_option *__opt) __THROW; - -/* Returns true if the option OPT is in fact the last (unused) entry in an - options array. */ -extern int _option_is_end (const struct argp_option *__opt) __THROW; -extern int __option_is_end (const struct argp_option *__opt) __THROW; -#endif - -/* Return the input field for ARGP in the parser corresponding to STATE; used - by the help routines. */ -extern void *_argp_input (const struct argp *__restrict __argp, - const struct argp_state *__restrict __state) - __THROW; -extern void *__argp_input (const struct argp *__restrict __argp, - const struct argp_state *__restrict __state) - __THROW; - -#ifdef __USE_EXTERN_INLINES - -# if !_LIBC -# define __argp_usage argp_usage -# define __argp_state_help argp_state_help -# define __option_is_short _option_is_short -# define __option_is_end _option_is_end -# endif - -# ifndef ARGP_EI -# ifdef __GNUC__ - /* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 - inline semantics, unless -fgnu89-inline is used. It defines a macro - __GNUC_STDC_INLINE__ to indicate this situation or a macro - __GNUC_GNU_INLINE__ to indicate the opposite situation. - GCC 4.2 with -std=c99 or -std=gnu99 implements the GNU C inline - semantics but warns, unless -fgnu89-inline is used: - warning: C99 inline functions are not supported; using GNU89 - warning: to disable this warning use -fgnu89-inline or the gnu_inline function attribute - It defines a macro __GNUC_GNU_INLINE__ to indicate this situation. */ -# if defined __GNUC_STDC_INLINE__ -# define ARGP_EI __inline__ -# elif defined __GNUC_GNU_INLINE__ -# define ARGP_EI extern __inline__ __attribute__ ((__gnu_inline__)) -# else -# define ARGP_EI extern __inline__ -# endif -# else - /* With other compilers, assume the ISO C99 meaning of 'inline', if - the compiler supports 'inline' at all. */ -# define ARGP_EI inline -# endif -# endif - -ARGP_EI void -__argp_usage (const struct argp_state *__state) -{ - __argp_state_help (__state, stderr, ARGP_HELP_STD_USAGE); -} - -ARGP_EI int -__NTH (__option_is_short (const struct argp_option *__opt)) -{ - if (__opt->flags & OPTION_DOC) - return 0; - else - { - int __key = __opt->key; - return __key > 0 && __key <= UCHAR_MAX && isprint (__key); - } -} - -ARGP_EI int -__NTH (__option_is_end (const struct argp_option *__opt)) -{ - return !__opt->key && !__opt->name && !__opt->doc && !__opt->group; -} - -# if !_LIBC -# undef __argp_usage -# undef __argp_state_help -# undef __option_is_short -# undef __option_is_end -# endif -#endif /* Use extern inlines. */ - -#ifdef __cplusplus -} -#endif - -#endif /* argp.h */ diff --git a/grub-core/gnulib/asnprintf.c b/grub-core/gnulib/asnprintf.c deleted file mode 100644 index 3bd2229d5..000000000 --- a/grub-core/gnulib/asnprintf.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Formatted output to strings. - Copyright (C) 1999, 2002, 2006, 2009, 2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "vasnprintf.h" - -#include - -char * -asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) -{ - va_list args; - char *result; - - va_start (args, format); - result = vasnprintf (resultbuf, lengthp, format, args); - va_end (args); - return result; -} diff --git a/grub-core/gnulib/basename-lgpl.c b/grub-core/gnulib/basename-lgpl.c deleted file mode 100644 index a35ff01c2..000000000 --- a/grub-core/gnulib/basename-lgpl.c +++ /dev/null @@ -1,75 +0,0 @@ -/* basename.c -- return the last element in a file name - - Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2010 Free Software - Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -#include "dirname.h" - -#include - -/* Return the address of the last file name component of NAME. If - NAME has no relative file name components because it is a file - system root, return the empty string. */ - -char * -last_component (char const *name) -{ - char const *base = name + FILE_SYSTEM_PREFIX_LEN (name); - char const *p; - bool saw_slash = false; - - while (ISSLASH (*base)) - base++; - - for (p = base; *p; p++) - { - if (ISSLASH (*p)) - saw_slash = true; - else if (saw_slash) - { - base = p; - saw_slash = false; - } - } - - return (char *) base; -} - -/* Return the length of the basename NAME. Typically NAME is the - value returned by base_name or last_component. Act like strlen - (NAME), except omit all trailing slashes. */ - -size_t -base_len (char const *name) -{ - size_t len; - size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name); - - for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--) - continue; - - if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1 - && ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2]) - return 2; - - if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len - && len == prefix_len && ISSLASH (name[prefix_len])) - return prefix_len + 1; - - return len; -} diff --git a/grub-core/gnulib/btowc.c b/grub-core/gnulib/btowc.c deleted file mode 100644 index 8744602aa..000000000 --- a/grub-core/gnulib/btowc.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Convert unibyte character to wide character. - Copyright (C) 2008, 2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -#include -#include - -wint_t -btowc (int c) -{ - if (c != EOF) - { - char buf[1]; - wchar_t wc; - - buf[0] = c; - if (mbtowc (&wc, buf, 1) >= 0) - return wc; - } - return WEOF; -} diff --git a/grub-core/gnulib/config.charset b/grub-core/gnulib/config.charset deleted file mode 100644 index aa7d00dba..000000000 --- a/grub-core/gnulib/config.charset +++ /dev/null @@ -1,683 +0,0 @@ -#! /bin/sh -# Output a system dependent table of character encoding aliases. -# -# Copyright (C) 2000-2004, 2006-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# The table consists of lines of the form -# ALIAS CANONICAL -# -# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)". -# ALIAS is compared in a case sensitive way. -# -# CANONICAL is the GNU canonical name for this character encoding. -# It must be an encoding supported by libiconv. Support by GNU libc is -# also desirable. CANONICAL is case insensitive. Usually an upper case -# MIME charset name is preferred. -# The current list of GNU canonical charset names is as follows. -# -# name MIME? used by which systems -# ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin cygwin -# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin -# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin -# ISO-8859-3 Y glibc solaris cygwin -# ISO-8859-4 Y osf solaris freebsd netbsd openbsd darwin -# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin -# ISO-8859-6 Y glibc aix hpux solaris cygwin -# ISO-8859-7 Y glibc aix hpux irix osf solaris netbsd openbsd darwin cygwin -# ISO-8859-8 Y glibc aix hpux osf solaris cygwin -# ISO-8859-9 Y glibc aix hpux irix osf solaris darwin cygwin -# ISO-8859-13 glibc netbsd openbsd darwin cygwin -# ISO-8859-14 glibc cygwin -# ISO-8859-15 glibc aix osf solaris freebsd netbsd openbsd darwin cygwin -# KOI8-R Y glibc solaris freebsd netbsd openbsd darwin -# KOI8-U Y glibc freebsd netbsd openbsd darwin cygwin -# KOI8-T glibc -# CP437 dos -# CP775 dos -# CP850 aix osf dos -# CP852 dos -# CP855 dos -# CP856 aix -# CP857 dos -# CP861 dos -# CP862 dos -# CP864 dos -# CP865 dos -# CP866 freebsd netbsd openbsd darwin dos -# CP869 dos -# CP874 woe32 dos -# CP922 aix -# CP932 aix cygwin woe32 dos -# CP943 aix -# CP949 osf darwin woe32 dos -# CP950 woe32 dos -# CP1046 aix -# CP1124 aix -# CP1125 dos -# CP1129 aix -# CP1131 darwin -# CP1250 woe32 -# CP1251 glibc solaris netbsd openbsd darwin cygwin woe32 -# CP1252 aix woe32 -# CP1253 woe32 -# CP1254 woe32 -# CP1255 glibc woe32 -# CP1256 woe32 -# CP1257 woe32 -# GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin -# EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin -# EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin -# EUC-TW glibc aix hpux irix osf solaris netbsd -# BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin -# BIG5-HKSCS glibc solaris darwin -# GBK glibc aix osf solaris darwin cygwin woe32 dos -# GB18030 glibc solaris netbsd darwin -# SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin -# JOHAB glibc solaris woe32 -# TIS-620 glibc aix hpux osf solaris cygwin -# VISCII Y glibc -# TCVN5712-1 glibc -# ARMSCII-8 glibc darwin -# GEORGIAN-PS glibc cygwin -# PT154 glibc -# HP-ROMAN8 hpux -# HP-ARABIC8 hpux -# HP-GREEK8 hpux -# HP-HEBREW8 hpux -# HP-TURKISH8 hpux -# HP-KANA8 hpux -# DEC-KANJI osf -# DEC-HANYU osf -# UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin -# -# Note: Names which are not marked as being a MIME name should not be used in -# Internet protocols for information interchange (mail, news, etc.). -# -# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications -# must understand both names and treat them as equivalent. -# -# The first argument passed to this file is the canonical host specification, -# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM -# or -# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM - -host="$1" -os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'` -echo "# This file contains a table of character encoding aliases," -echo "# suitable for operating system '${os}'." -echo "# It was automatically generated from config.charset." -# List of references, updated during installation: -echo "# Packages using this file: " -case "$os" in - linux-gnulibc1*) - # Linux libc5 doesn't have nl_langinfo(CODESET); therefore - # localcharset.c falls back to using the full locale name - # from the environment variables. - echo "C ASCII" - echo "POSIX ASCII" - for l in af af_ZA ca ca_ES da da_DK de de_AT de_BE de_CH de_DE de_LU \ - en en_AU en_BW en_CA en_DK en_GB en_IE en_NZ en_US en_ZA \ - en_ZW es es_AR es_BO es_CL es_CO es_DO es_EC es_ES es_GT \ - es_HN es_MX es_PA es_PE es_PY es_SV es_US es_UY es_VE et \ - et_EE eu eu_ES fi fi_FI fo fo_FO fr fr_BE fr_CA fr_CH fr_FR \ - fr_LU ga ga_IE gl gl_ES id id_ID in in_ID is is_IS it it_CH \ - it_IT kl kl_GL nl nl_BE nl_NL no no_NO pt pt_BR pt_PT sv \ - sv_FI sv_SE; do - echo "$l ISO-8859-1" - echo "$l.iso-8859-1 ISO-8859-1" - echo "$l.iso-8859-15 ISO-8859-15" - echo "$l.iso-8859-15@euro ISO-8859-15" - echo "$l@euro ISO-8859-15" - echo "$l.cp-437 CP437" - echo "$l.cp-850 CP850" - echo "$l.cp-1252 CP1252" - echo "$l.cp-1252@euro CP1252" - #echo "$l.atari-st ATARI-ST" # not a commonly used encoding - echo "$l.utf-8 UTF-8" - echo "$l.utf-8@euro UTF-8" - done - for l in cs cs_CZ hr hr_HR hu hu_HU pl pl_PL ro ro_RO sk sk_SK sl \ - sl_SI sr sr_CS sr_YU; do - echo "$l ISO-8859-2" - echo "$l.iso-8859-2 ISO-8859-2" - echo "$l.cp-852 CP852" - echo "$l.cp-1250 CP1250" - echo "$l.utf-8 UTF-8" - done - for l in mk mk_MK ru ru_RU; do - echo "$l ISO-8859-5" - echo "$l.iso-8859-5 ISO-8859-5" - echo "$l.koi8-r KOI8-R" - echo "$l.cp-866 CP866" - echo "$l.cp-1251 CP1251" - echo "$l.utf-8 UTF-8" - done - for l in ar ar_SA; do - echo "$l ISO-8859-6" - echo "$l.iso-8859-6 ISO-8859-6" - echo "$l.cp-864 CP864" - #echo "$l.cp-868 CP868" # not a commonly used encoding - echo "$l.cp-1256 CP1256" - echo "$l.utf-8 UTF-8" - done - for l in el el_GR gr gr_GR; do - echo "$l ISO-8859-7" - echo "$l.iso-8859-7 ISO-8859-7" - echo "$l.cp-869 CP869" - echo "$l.cp-1253 CP1253" - echo "$l.cp-1253@euro CP1253" - echo "$l.utf-8 UTF-8" - echo "$l.utf-8@euro UTF-8" - done - for l in he he_IL iw iw_IL; do - echo "$l ISO-8859-8" - echo "$l.iso-8859-8 ISO-8859-8" - echo "$l.cp-862 CP862" - echo "$l.cp-1255 CP1255" - echo "$l.utf-8 UTF-8" - done - for l in tr tr_TR; do - echo "$l ISO-8859-9" - echo "$l.iso-8859-9 ISO-8859-9" - echo "$l.cp-857 CP857" - echo "$l.cp-1254 CP1254" - echo "$l.utf-8 UTF-8" - done - for l in lt lt_LT lv lv_LV; do - #echo "$l BALTIC" # not a commonly used encoding, wrong encoding name - echo "$l ISO-8859-13" - done - for l in ru_UA uk uk_UA; do - echo "$l KOI8-U" - done - for l in zh zh_CN; do - #echo "$l GB_2312-80" # not a commonly used encoding, wrong encoding name - echo "$l GB2312" - done - for l in ja ja_JP ja_JP.EUC; do - echo "$l EUC-JP" - done - for l in ko ko_KR; do - echo "$l EUC-KR" - done - for l in th th_TH; do - echo "$l TIS-620" - done - for l in fa fa_IR; do - #echo "$l ISIRI-3342" # a broken encoding - echo "$l.utf-8 UTF-8" - done - ;; - linux* | *-gnu*) - # With glibc-2.1 or newer, we don't need any canonicalization, - # because glibc has iconv and both glibc and libiconv support all - # GNU canonical names directly. Therefore, the Makefile does not - # need to install the alias file at all. - # The following applies only to glibc-2.0.x and older libcs. - echo "ISO_646.IRV:1983 ASCII" - ;; - aix*) - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-6 ISO-8859-6" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-8 ISO-8859-8" - echo "ISO8859-9 ISO-8859-9" - echo "ISO8859-15 ISO-8859-15" - echo "IBM-850 CP850" - echo "IBM-856 CP856" - echo "IBM-921 ISO-8859-13" - echo "IBM-922 CP922" - echo "IBM-932 CP932" - echo "IBM-943 CP943" - echo "IBM-1046 CP1046" - echo "IBM-1124 CP1124" - echo "IBM-1129 CP1129" - echo "IBM-1252 CP1252" - echo "IBM-eucCN GB2312" - echo "IBM-eucJP EUC-JP" - echo "IBM-eucKR EUC-KR" - echo "IBM-eucTW EUC-TW" - echo "big5 BIG5" - echo "GBK GBK" - echo "TIS-620 TIS-620" - echo "UTF-8 UTF-8" - ;; - hpux*) - echo "iso88591 ISO-8859-1" - echo "iso88592 ISO-8859-2" - echo "iso88595 ISO-8859-5" - echo "iso88596 ISO-8859-6" - echo "iso88597 ISO-8859-7" - echo "iso88598 ISO-8859-8" - echo "iso88599 ISO-8859-9" - echo "iso885915 ISO-8859-15" - echo "roman8 HP-ROMAN8" - echo "arabic8 HP-ARABIC8" - echo "greek8 HP-GREEK8" - echo "hebrew8 HP-HEBREW8" - echo "turkish8 HP-TURKISH8" - echo "kana8 HP-KANA8" - echo "tis620 TIS-620" - echo "big5 BIG5" - echo "eucJP EUC-JP" - echo "eucKR EUC-KR" - echo "eucTW EUC-TW" - echo "hp15CN GB2312" - #echo "ccdc ?" # what is this? - echo "SJIS SHIFT_JIS" - echo "utf8 UTF-8" - ;; - irix*) - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-9 ISO-8859-9" - echo "eucCN GB2312" - echo "eucJP EUC-JP" - echo "eucKR EUC-KR" - echo "eucTW EUC-TW" - ;; - osf*) - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-4 ISO-8859-4" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-8 ISO-8859-8" - echo "ISO8859-9 ISO-8859-9" - echo "ISO8859-15 ISO-8859-15" - echo "cp850 CP850" - echo "big5 BIG5" - echo "dechanyu DEC-HANYU" - echo "dechanzi GB2312" - echo "deckanji DEC-KANJI" - echo "deckorean EUC-KR" - echo "eucJP EUC-JP" - echo "eucKR EUC-KR" - echo "eucTW EUC-TW" - echo "GBK GBK" - echo "KSC5601 CP949" - echo "sdeckanji EUC-JP" - echo "SJIS SHIFT_JIS" - echo "TACTIS TIS-620" - echo "UTF-8 UTF-8" - ;; - solaris*) - echo "646 ASCII" - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-3 ISO-8859-3" - echo "ISO8859-4 ISO-8859-4" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-6 ISO-8859-6" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-8 ISO-8859-8" - echo "ISO8859-9 ISO-8859-9" - echo "ISO8859-15 ISO-8859-15" - echo "koi8-r KOI8-R" - echo "ansi-1251 CP1251" - echo "BIG5 BIG5" - echo "Big5-HKSCS BIG5-HKSCS" - echo "gb2312 GB2312" - echo "GBK GBK" - echo "GB18030 GB18030" - echo "cns11643 EUC-TW" - echo "5601 EUC-KR" - echo "ko_KR.johap92 JOHAB" - echo "eucJP EUC-JP" - echo "PCK SHIFT_JIS" - echo "TIS620.2533 TIS-620" - #echo "sun_eu_greek ?" # what is this? - echo "UTF-8 UTF-8" - ;; - freebsd* | os2*) - # FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore - # localcharset.c falls back to using the full locale name - # from the environment variables. - # Likewise for OS/2. OS/2 has XFree86 just like FreeBSD. Just - # reuse FreeBSD's locale data for OS/2. - echo "C ASCII" - echo "US-ASCII ASCII" - for l in la_LN lt_LN; do - echo "$l.ASCII ASCII" - done - for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \ - fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \ - lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do - echo "$l.ISO_8859-1 ISO-8859-1" - echo "$l.DIS_8859-15 ISO-8859-15" - done - for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do - echo "$l.ISO_8859-2 ISO-8859-2" - done - for l in la_LN lt_LT; do - echo "$l.ISO_8859-4 ISO-8859-4" - done - for l in ru_RU ru_SU; do - echo "$l.KOI8-R KOI8-R" - echo "$l.ISO_8859-5 ISO-8859-5" - echo "$l.CP866 CP866" - done - echo "uk_UA.KOI8-U KOI8-U" - echo "zh_TW.BIG5 BIG5" - echo "zh_TW.Big5 BIG5" - echo "zh_CN.EUC GB2312" - echo "ja_JP.EUC EUC-JP" - echo "ja_JP.SJIS SHIFT_JIS" - echo "ja_JP.Shift_JIS SHIFT_JIS" - echo "ko_KR.EUC EUC-KR" - ;; - netbsd*) - echo "646 ASCII" - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-4 ISO-8859-4" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-13 ISO-8859-13" - echo "ISO8859-15 ISO-8859-15" - echo "eucCN GB2312" - echo "eucJP EUC-JP" - echo "eucKR EUC-KR" - echo "eucTW EUC-TW" - echo "BIG5 BIG5" - echo "SJIS SHIFT_JIS" - ;; - openbsd*) - echo "646 ASCII" - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-4 ISO-8859-4" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-13 ISO-8859-13" - echo "ISO8859-15 ISO-8859-15" - ;; - darwin[56]*) - # Darwin 6.8 doesn't have nl_langinfo(CODESET); therefore - # localcharset.c falls back to using the full locale name - # from the environment variables. - echo "C ASCII" - for l in en_AU en_CA en_GB en_US la_LN; do - echo "$l.US-ASCII ASCII" - done - for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \ - fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT nl_BE \ - nl_NL no_NO pt_PT sv_SE; do - echo "$l ISO-8859-1" - echo "$l.ISO8859-1 ISO-8859-1" - echo "$l.ISO8859-15 ISO-8859-15" - done - for l in la_LN; do - echo "$l.ISO8859-1 ISO-8859-1" - echo "$l.ISO8859-15 ISO-8859-15" - done - for l in cs_CZ hr_HR hu_HU la_LN pl_PL sl_SI; do - echo "$l.ISO8859-2 ISO-8859-2" - done - for l in la_LN lt_LT; do - echo "$l.ISO8859-4 ISO-8859-4" - done - for l in ru_RU; do - echo "$l.KOI8-R KOI8-R" - echo "$l.ISO8859-5 ISO-8859-5" - echo "$l.CP866 CP866" - done - for l in bg_BG; do - echo "$l.CP1251 CP1251" - done - echo "uk_UA.KOI8-U KOI8-U" - echo "zh_TW.BIG5 BIG5" - echo "zh_TW.Big5 BIG5" - echo "zh_CN.EUC GB2312" - echo "ja_JP.EUC EUC-JP" - echo "ja_JP.SJIS SHIFT_JIS" - echo "ko_KR.EUC EUC-KR" - ;; - darwin*) - # Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is - # useless: - # - It returns the empty string when LANG is set to a locale of the - # form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8 - # LC_CTYPE file. - # - The environment variables LANG, LC_CTYPE, LC_ALL are not set by - # the system; nl_langinfo(CODESET) returns "US-ASCII" in this case. - # - The documentation says: - # "... all code that calls BSD system routines should ensure - # that the const *char parameters of these routines are in UTF-8 - # encoding. All BSD system functions expect their string - # parameters to be in UTF-8 encoding and nothing else." - # It also says - # "An additional caveat is that string parameters for files, - # paths, and other file-system entities must be in canonical - # UTF-8. In a canonical UTF-8 Unicode string, all decomposable - # characters are decomposed ..." - # but this is not true: You can pass non-decomposed UTF-8 strings - # to file system functions, and it is the OS which will convert - # them to decomposed UTF-8 before accessing the file system. - # - The Apple Terminal application displays UTF-8 by default. - # - However, other applications are free to use different encodings: - # - xterm uses ISO-8859-1 by default. - # - TextEdit uses MacRoman by default. - # We prefer UTF-8 over decomposed UTF-8-MAC because one should - # minimize the use of decomposed Unicode. Unfortunately, through the - # Darwin file system, decomposed UTF-8 strings are leaked into user - # space nevertheless. - # Then there are also the locales with encodings other than US-ASCII - # and UTF-8. These locales can be occasionally useful to users (e.g. - # when grepping through ISO-8859-1 encoded text files), when all their - # file names are in US-ASCII. - echo "ISO8859-1 ISO-8859-1" - echo "ISO8859-2 ISO-8859-2" - echo "ISO8859-4 ISO-8859-4" - echo "ISO8859-5 ISO-8859-5" - echo "ISO8859-7 ISO-8859-7" - echo "ISO8859-9 ISO-8859-9" - echo "ISO8859-13 ISO-8859-13" - echo "ISO8859-15 ISO-8859-15" - echo "KOI8-R KOI8-R" - echo "KOI8-U KOI8-U" - echo "CP866 CP866" - echo "CP949 CP949" - echo "CP1131 CP1131" - echo "CP1251 CP1251" - echo "eucCN GB2312" - echo "GB2312 GB2312" - echo "eucJP EUC-JP" - echo "eucKR EUC-KR" - echo "Big5 BIG5" - echo "Big5HKSCS BIG5-HKSCS" - echo "GBK GBK" - echo "GB18030 GB18030" - echo "SJIS SHIFT_JIS" - echo "ARMSCII-8 ARMSCII-8" - echo "PT154 PT154" - #echo "ISCII-DEV ?" - echo "* UTF-8" - ;; - beos* | haiku*) - # BeOS and Haiku have a single locale, and it has UTF-8 encoding. - echo "* UTF-8" - ;; - msdosdjgpp*) - # DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore - # localcharset.c falls back to using the full locale name - # from the environment variables. - echo "#" - echo "# The encodings given here may not all be correct." - echo "# If you find that the encoding given for your language and" - echo "# country is not the one your DOS machine actually uses, just" - echo "# correct it in this file, and send a mail to" - echo "# Juan Manuel Guerrero " - echo "# and Bruno Haible ." - echo "#" - echo "C ASCII" - # ISO-8859-1 languages - echo "ca CP850" - echo "ca_ES CP850" - echo "da CP865" # not CP850 ?? - echo "da_DK CP865" # not CP850 ?? - echo "de CP850" - echo "de_AT CP850" - echo "de_CH CP850" - echo "de_DE CP850" - echo "en CP850" - echo "en_AU CP850" # not CP437 ?? - echo "en_CA CP850" - echo "en_GB CP850" - echo "en_NZ CP437" - echo "en_US CP437" - echo "en_ZA CP850" # not CP437 ?? - echo "es CP850" - echo "es_AR CP850" - echo "es_BO CP850" - echo "es_CL CP850" - echo "es_CO CP850" - echo "es_CR CP850" - echo "es_CU CP850" - echo "es_DO CP850" - echo "es_EC CP850" - echo "es_ES CP850" - echo "es_GT CP850" - echo "es_HN CP850" - echo "es_MX CP850" - echo "es_NI CP850" - echo "es_PA CP850" - echo "es_PY CP850" - echo "es_PE CP850" - echo "es_SV CP850" - echo "es_UY CP850" - echo "es_VE CP850" - echo "et CP850" - echo "et_EE CP850" - echo "eu CP850" - echo "eu_ES CP850" - echo "fi CP850" - echo "fi_FI CP850" - echo "fr CP850" - echo "fr_BE CP850" - echo "fr_CA CP850" - echo "fr_CH CP850" - echo "fr_FR CP850" - echo "ga CP850" - echo "ga_IE CP850" - echo "gd CP850" - echo "gd_GB CP850" - echo "gl CP850" - echo "gl_ES CP850" - echo "id CP850" # not CP437 ?? - echo "id_ID CP850" # not CP437 ?? - echo "is CP861" # not CP850 ?? - echo "is_IS CP861" # not CP850 ?? - echo "it CP850" - echo "it_CH CP850" - echo "it_IT CP850" - echo "lt CP775" - echo "lt_LT CP775" - echo "lv CP775" - echo "lv_LV CP775" - echo "nb CP865" # not CP850 ?? - echo "nb_NO CP865" # not CP850 ?? - echo "nl CP850" - echo "nl_BE CP850" - echo "nl_NL CP850" - echo "nn CP865" # not CP850 ?? - echo "nn_NO CP865" # not CP850 ?? - echo "no CP865" # not CP850 ?? - echo "no_NO CP865" # not CP850 ?? - echo "pt CP850" - echo "pt_BR CP850" - echo "pt_PT CP850" - echo "sv CP850" - echo "sv_SE CP850" - # ISO-8859-2 languages - echo "cs CP852" - echo "cs_CZ CP852" - echo "hr CP852" - echo "hr_HR CP852" - echo "hu CP852" - echo "hu_HU CP852" - echo "pl CP852" - echo "pl_PL CP852" - echo "ro CP852" - echo "ro_RO CP852" - echo "sk CP852" - echo "sk_SK CP852" - echo "sl CP852" - echo "sl_SI CP852" - echo "sq CP852" - echo "sq_AL CP852" - echo "sr CP852" # CP852 or CP866 or CP855 ?? - echo "sr_CS CP852" # CP852 or CP866 or CP855 ?? - echo "sr_YU CP852" # CP852 or CP866 or CP855 ?? - # ISO-8859-3 languages - echo "mt CP850" - echo "mt_MT CP850" - # ISO-8859-5 languages - echo "be CP866" - echo "be_BE CP866" - echo "bg CP866" # not CP855 ?? - echo "bg_BG CP866" # not CP855 ?? - echo "mk CP866" # not CP855 ?? - echo "mk_MK CP866" # not CP855 ?? - echo "ru CP866" - echo "ru_RU CP866" - echo "uk CP1125" - echo "uk_UA CP1125" - # ISO-8859-6 languages - echo "ar CP864" - echo "ar_AE CP864" - echo "ar_DZ CP864" - echo "ar_EG CP864" - echo "ar_IQ CP864" - echo "ar_IR CP864" - echo "ar_JO CP864" - echo "ar_KW CP864" - echo "ar_MA CP864" - echo "ar_OM CP864" - echo "ar_QA CP864" - echo "ar_SA CP864" - echo "ar_SY CP864" - # ISO-8859-7 languages - echo "el CP869" - echo "el_GR CP869" - # ISO-8859-8 languages - echo "he CP862" - echo "he_IL CP862" - # ISO-8859-9 languages - echo "tr CP857" - echo "tr_TR CP857" - # Japanese - echo "ja CP932" - echo "ja_JP CP932" - # Chinese - echo "zh_CN GBK" - echo "zh_TW CP950" # not CP938 ?? - # Korean - echo "kr CP949" # not CP934 ?? - echo "kr_KR CP949" # not CP934 ?? - # Thai - echo "th CP874" - echo "th_TH CP874" - # Other - echo "eo CP850" - echo "eo_EO CP850" - ;; -esac diff --git a/grub-core/gnulib/dirname-lgpl.c b/grub-core/gnulib/dirname-lgpl.c deleted file mode 100644 index d4506e060..000000000 --- a/grub-core/gnulib/dirname-lgpl.c +++ /dev/null @@ -1,86 +0,0 @@ -/* dirname.c -- return all but the last element in a file name - - Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2010 Free Software - Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -#include "dirname.h" - -#include -#include - -/* Return the length of the prefix of FILE that will be used by - dir_name. If FILE is in the working directory, this returns zero - even though `dir_name (FILE)' will return ".". Works properly even - if there are trailing slashes (by effectively ignoring them). */ - -size_t -dir_len (char const *file) -{ - size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file); - size_t length; - - /* Advance prefix_length beyond important leading slashes. */ - prefix_length += (prefix_length != 0 - ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE - && ISSLASH (file[prefix_length])) - : (ISSLASH (file[0]) - ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT - && ISSLASH (file[1]) && ! ISSLASH (file[2]) - ? 2 : 1)) - : 0)); - - /* Strip the basename and any redundant slashes before it. */ - for (length = last_component (file) - file; - prefix_length < length; length--) - if (! ISSLASH (file[length - 1])) - break; - return length; -} - - -/* In general, we can't use the builtin `dirname' function if available, - since it has different meanings in different environments. - In some environments the builtin `dirname' modifies its argument. - - Return the leading directories part of FILE, allocated with malloc. - Works properly even if there are trailing slashes (by effectively - ignoring them). Return NULL on failure. - - If lstat (FILE) would succeed, then { chdir (dir_name (FILE)); - lstat (base_name (FILE)); } will access the same file. Likewise, - if the sequence { chdir (dir_name (FILE)); - rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE - to "foo" in the same directory FILE was in. */ - -char * -mdir_name (char const *file) -{ - size_t length = dir_len (file); - bool append_dot = (length == 0 - || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE - && length == FILE_SYSTEM_PREFIX_LEN (file) - && file[2] != '\0' && ! ISSLASH (file[2]))); - char *dir = malloc (length + append_dot + 1); - if (!dir) - return NULL; - memcpy (dir, file, length); - if (append_dot) - dir[length++] = '.'; - dir[length] = '\0'; - return dir; -} diff --git a/grub-core/gnulib/dirname.h b/grub-core/gnulib/dirname.h deleted file mode 100644 index fb19508f7..000000000 --- a/grub-core/gnulib/dirname.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Take file names apart into directory and base names. - - Copyright (C) 1998, 2001, 2003-2006, 2009-2010 Free Software Foundation, - 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef DIRNAME_H_ -# define DIRNAME_H_ 1 - -# include -# include - -# ifndef DIRECTORY_SEPARATOR -# define DIRECTORY_SEPARATOR '/' -# endif - -# ifndef ISSLASH -# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) -# endif - -# ifndef FILE_SYSTEM_PREFIX_LEN -# if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX - /* This internal macro assumes ASCII, but all hosts that support drive - letters use ASCII. */ -# define _IS_DRIVE_LETTER(c) (((unsigned int) (c) | ('a' - 'A')) - 'a' \ - <= 'z' - 'a') -# define FILE_SYSTEM_PREFIX_LEN(Filename) \ - (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0) -# else -# define FILE_SYSTEM_PREFIX_LEN(Filename) 0 -# endif -# endif - -# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE -# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0 -# endif - -# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT -# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 -# endif - -# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE -# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)]) -# else -# define IS_ABSOLUTE_FILE_NAME(F) \ - (ISSLASH ((F)[0]) || 0 < FILE_SYSTEM_PREFIX_LEN (F)) -# endif -# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F)) - -# if GNULIB_DIRNAME -char *base_name (char const *file); -char *dir_name (char const *file); -# endif - -char *mdir_name (char const *file); -size_t base_len (char const *file); -size_t dir_len (char const *file); -char *last_component (char const *file); - -bool strip_trailing_slashes (char *file); - -#endif /* not DIRNAME_H_ */ diff --git a/grub-core/gnulib/errno.in.h b/grub-core/gnulib/errno.in.h deleted file mode 100644 index 140e5d134..000000000 --- a/grub-core/gnulib/errno.in.h +++ /dev/null @@ -1,160 +0,0 @@ -/* A POSIX-like . - - Copyright (C) 2008-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GL_ERRNO_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -/* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_ERRNO_H@ - -#ifndef _GL_ERRNO_H -#define _GL_ERRNO_H - - -/* On native Windows platforms, many macros are not defined. */ -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - -/* POSIX says that EAGAIN and EWOULDBLOCK may have the same value. */ -# define EWOULDBLOCK EAGAIN - -/* Values >= 100 seem safe to use. */ -# define ETXTBSY 100 -# define GNULIB_defined_ETXTBSY 1 - -/* These are intentionally the same values as the WSA* error numbers, defined - in . */ -# define EINPROGRESS 10036 -# define EALREADY 10037 -# define ENOTSOCK 10038 -# define EDESTADDRREQ 10039 -# define EMSGSIZE 10040 -# define EPROTOTYPE 10041 -# define ENOPROTOOPT 10042 -# define EPROTONOSUPPORT 10043 -# define ESOCKTNOSUPPORT 10044 /* not required by POSIX */ -# define EOPNOTSUPP 10045 -# define EPFNOSUPPORT 10046 /* not required by POSIX */ -# define EAFNOSUPPORT 10047 -# define EADDRINUSE 10048 -# define EADDRNOTAVAIL 10049 -# define ENETDOWN 10050 -# define ENETUNREACH 10051 -# define ENETRESET 10052 -# define ECONNABORTED 10053 -# define ECONNRESET 10054 -# define ENOBUFS 10055 -# define EISCONN 10056 -# define ENOTCONN 10057 -# define ESHUTDOWN 10058 /* not required by POSIX */ -# define ETOOMANYREFS 10059 /* not required by POSIX */ -# define ETIMEDOUT 10060 -# define ECONNREFUSED 10061 -# define ELOOP 10062 -# define EHOSTDOWN 10064 /* not required by POSIX */ -# define EHOSTUNREACH 10065 -# define EPROCLIM 10067 /* not required by POSIX */ -# define EUSERS 10068 /* not required by POSIX */ -# define EDQUOT 10069 -# define ESTALE 10070 -# define EREMOTE 10071 /* not required by POSIX */ -# define GNULIB_defined_ESOCK 1 - -# endif - - -/* On OSF/1 5.1, when _XOPEN_SOURCE_EXTENDED is not defined, the macros - EMULTIHOP, ENOLINK, EOVERFLOW are not defined. */ -# if @EMULTIHOP_HIDDEN@ -# define EMULTIHOP @EMULTIHOP_VALUE@ -# define GNULIB_defined_EMULTIHOP 1 -# endif -# if @ENOLINK_HIDDEN@ -# define ENOLINK @ENOLINK_VALUE@ -# define GNULIB_defined_ENOLINK 1 -# endif -# if @EOVERFLOW_HIDDEN@ -# define EOVERFLOW @EOVERFLOW_VALUE@ -# define GNULIB_defined_EOVERFLOW 1 -# endif - - -/* On OpenBSD 4.0 and on native Windows, the macros ENOMSG, EIDRM, ENOLINK, - EPROTO, EMULTIHOP, EBADMSG, EOVERFLOW, ENOTSUP, ECANCELED are not defined. - Define them here. Values >= 2000 seem safe to use: Solaris ESTALE = 151, - HP-UX EWOULDBLOCK = 246, IRIX EDQUOT = 1133. - - Note: When one of these systems defines some of these macros some day, - binaries will have to be recompiled so that they recognizes the new - errno values from the system. */ - -# ifndef ENOMSG -# define ENOMSG 2000 -# define GNULIB_defined_ENOMSG 1 -# endif - -# ifndef EIDRM -# define EIDRM 2001 -# define GNULIB_defined_EIDRM 1 -# endif - -# ifndef ENOLINK -# define ENOLINK 2002 -# define GNULIB_defined_ENOLINK 1 -# endif - -# ifndef EPROTO -# define EPROTO 2003 -# define GNULIB_defined_EPROTO 1 -# endif - -# ifndef EMULTIHOP -# define EMULTIHOP 2004 -# define GNULIB_defined_EMULTIHOP 1 -# endif - -# ifndef EBADMSG -# define EBADMSG 2005 -# define GNULIB_defined_EBADMSG 1 -# endif - -# ifndef EOVERFLOW -# define EOVERFLOW 2006 -# define GNULIB_defined_EOVERFLOW 1 -# endif - -# ifndef ENOTSUP -# define ENOTSUP 2007 -# define GNULIB_defined_ENOTSUP 1 -# endif - -# ifndef ESTALE -# define ESTALE 2009 -# define GNULIB_defined_ESTALE 1 -# endif - -# ifndef ECANCELED -# define ECANCELED 2008 -# define GNULIB_defined_ECANCELED 1 -# endif - - -#endif /* _GL_ERRNO_H */ -#endif /* _GL_ERRNO_H */ diff --git a/grub-core/gnulib/error.c b/grub-core/gnulib/error.c deleted file mode 100644 index ed9dba0d2..000000000 --- a/grub-core/gnulib/error.c +++ /dev/null @@ -1,394 +0,0 @@ -/* Error handler for noninteractive utilities - Copyright (C) 1990-1998, 2000-2007, 2009-2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* Written by David MacKenzie . */ - -#if !_LIBC -# include -#endif - -#include "error.h" - -#include -#include -#include -#include - -#if !_LIBC && ENABLE_NLS -# include "gettext.h" -# define _(msgid) gettext (msgid) -#endif - -#ifdef _LIBC -# include -# include -# include -# include -# define mbsrtowcs __mbsrtowcs -#endif - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -#endif - -#ifndef _ -# define _(String) String -#endif - -/* If NULL, error will flush stdout, then print on stderr the program - name, a colon and a space. Otherwise, error will call this - function without parameters instead. */ -void (*error_print_progname) (void); - -/* This variable is incremented each time `error' is called. */ -unsigned int error_message_count; - -#ifdef _LIBC -/* In the GNU C library, there is a predefined variable for this. */ - -# define program_name program_invocation_name -# include -# include -# include - -/* In GNU libc we want do not want to use the common name `error' directly. - Instead make it a weak alias. */ -extern void __error (int status, int errnum, const char *message, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); -extern void __error_at_line (int status, int errnum, const char *file_name, - unsigned int line_number, const char *message, - ...) - __attribute__ ((__format__ (__printf__, 5, 6)));; -# define error __error -# define error_at_line __error_at_line - -# include -# define fflush(s) INTUSE(_IO_fflush) (s) -# undef putc -# define putc(c, fp) INTUSE(_IO_putc) (c, fp) - -# include - -#else /* not _LIBC */ - -# include -# include - -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ -/* Get declarations of the Win32 API functions. */ -# define WIN32_LEAN_AND_MEAN -# include -# endif - -/* The gnulib override of fcntl is not needed in this file. */ -# undef fcntl - -# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P -# ifndef HAVE_DECL_STRERROR_R -"this configure-time declaration test was not run" -# endif -char *strerror_r (); -# endif - -/* The calling program should define program_name and set it to the - name of the executing program. */ -extern char *program_name; - -# if HAVE_STRERROR_R || defined strerror_r -# define __strerror_r strerror_r -# endif /* HAVE_STRERROR_R || defined strerror_r */ -#endif /* not _LIBC */ - -#if !_LIBC -/* Return non-zero if FD is open. */ -static inline int -is_open (int fd) -{ -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - /* On Win32: The initial state of unassigned standard file descriptors is - that they are open but point to an INVALID_HANDLE_VALUE. There is no - fcntl, and the gnulib replacement fcntl does not support F_GETFL. */ - return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE; -# else -# ifndef F_GETFL -# error Please port fcntl to your platform -# endif - return 0 <= fcntl (fd, F_GETFL); -# endif -} -#endif - -static inline void -flush_stdout (void) -{ -#if !_LIBC - int stdout_fd; - -# if GNULIB_FREOPEN_SAFER - /* Use of gnulib's freopen-safer module normally ensures that - fileno (stdout) == 1 - whenever stdout is open. */ - stdout_fd = STDOUT_FILENO; -# else - /* POSIX states that fileno (stdout) after fclose is unspecified. But in - practice it is not a problem, because stdout is statically allocated and - the fd of a FILE stream is stored as a field in its allocated memory. */ - stdout_fd = fileno (stdout); -# endif - /* POSIX states that fflush (stdout) after fclose is unspecified; it - is safe in glibc, but not on all other platforms. fflush (NULL) - is always defined, but too draconian. */ - if (0 <= stdout_fd && is_open (stdout_fd)) -#endif - fflush (stdout); -} - -static void -print_errno_message (int errnum) -{ - char const *s; - -#if defined HAVE_STRERROR_R || _LIBC - char errbuf[1024]; -# if STRERROR_R_CHAR_P || _LIBC - s = __strerror_r (errnum, errbuf, sizeof errbuf); -# else - if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) - s = errbuf; - else - s = 0; -# endif -#else - s = strerror (errnum); -#endif - -#if !_LIBC - if (! s) - s = _("Unknown system error"); -#endif - -#if _LIBC - __fxprintf (NULL, ": %s", s); -#else - fprintf (stderr, ": %s", s); -#endif -} - -static void -error_tail (int status, int errnum, const char *message, va_list args) -{ -#if _LIBC - if (_IO_fwide (stderr, 0) > 0) - { -# define ALLOCA_LIMIT 2000 - size_t len = strlen (message) + 1; - wchar_t *wmessage = NULL; - mbstate_t st; - size_t res; - const char *tmp; - bool use_malloc = false; - - while (1) - { - if (__libc_use_alloca (len * sizeof (wchar_t))) - wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); - else - { - if (!use_malloc) - wmessage = NULL; - - wchar_t *p = (wchar_t *) realloc (wmessage, - len * sizeof (wchar_t)); - if (p == NULL) - { - free (wmessage); - fputws_unlocked (L"out of memory\n", stderr); - return; - } - wmessage = p; - use_malloc = true; - } - - memset (&st, '\0', sizeof (st)); - tmp = message; - - res = mbsrtowcs (wmessage, &tmp, len, &st); - if (res != len) - break; - - if (__builtin_expect (len >= SIZE_MAX / 2, 0)) - { - /* This really should not happen if everything is fine. */ - res = (size_t) -1; - break; - } - - len *= 2; - } - - if (res == (size_t) -1) - { - /* The string cannot be converted. */ - if (use_malloc) - { - free (wmessage); - use_malloc = false; - } - wmessage = (wchar_t *) L"???"; - } - - __vfwprintf (stderr, wmessage, args); - - if (use_malloc) - free (wmessage); - } - else -#endif - vfprintf (stderr, message, args); - va_end (args); - - ++error_message_count; - if (errnum) - print_errno_message (errnum); -#if _LIBC - __fxprintf (NULL, "\n"); -#else - putc ('\n', stderr); -#endif - fflush (stderr); - if (status) - exit (status); -} - - -/* Print the program name and error message MESSAGE, which is a printf-style - format string with optional args. - If ERRNUM is nonzero, print its corresponding system error message. - Exit with status STATUS if it is nonzero. */ -void -error (int status, int errnum, const char *message, ...) -{ - va_list args; - -#if defined _LIBC && defined __libc_ptf_call - /* We do not want this call to be cut short by a thread - cancellation. Therefore disable cancellation for now. */ - int state = PTHREAD_CANCEL_ENABLE; - __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), - 0); -#endif - - flush_stdout (); -#ifdef _LIBC - _IO_flockfile (stderr); -#endif - if (error_print_progname) - (*error_print_progname) (); - else - { -#if _LIBC - __fxprintf (NULL, "%s: ", program_name); -#else - fprintf (stderr, "%s: ", program_name); -#endif - } - - va_start (args, message); - error_tail (status, errnum, message, args); - -#ifdef _LIBC - _IO_funlockfile (stderr); -# ifdef __libc_ptf_call - __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); -# endif -#endif -} - -/* Sometimes we want to have at most one error per line. This - variable controls whether this mode is selected or not. */ -int error_one_per_line; - -void -error_at_line (int status, int errnum, const char *file_name, - unsigned int line_number, const char *message, ...) -{ - va_list args; - - if (error_one_per_line) - { - static const char *old_file_name; - static unsigned int old_line_number; - - if (old_line_number == line_number - && (file_name == old_file_name - || strcmp (old_file_name, file_name) == 0)) - /* Simply return and print nothing. */ - return; - - old_file_name = file_name; - old_line_number = line_number; - } - -#if defined _LIBC && defined __libc_ptf_call - /* We do not want this call to be cut short by a thread - cancellation. Therefore disable cancellation for now. */ - int state = PTHREAD_CANCEL_ENABLE; - __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), - 0); -#endif - - flush_stdout (); -#ifdef _LIBC - _IO_flockfile (stderr); -#endif - if (error_print_progname) - (*error_print_progname) (); - else - { -#if _LIBC - __fxprintf (NULL, "%s:", program_name); -#else - fprintf (stderr, "%s:", program_name); -#endif - } - -#if _LIBC - __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ", - file_name, line_number); -#else - fprintf (stderr, file_name != NULL ? "%s:%d: " : " ", - file_name, line_number); -#endif - - va_start (args, message); - error_tail (status, errnum, message, args); - -#ifdef _LIBC - _IO_funlockfile (stderr); -# ifdef __libc_ptf_call - __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); -# endif -#endif -} - -#ifdef _LIBC -/* Make the weak alias. */ -# undef error -# undef error_at_line -weak_alias (__error, error) -weak_alias (__error_at_line, error_at_line) -#endif diff --git a/grub-core/gnulib/error.h b/grub-core/gnulib/error.h deleted file mode 100644 index 9deef02d2..000000000 --- a/grub-core/gnulib/error.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Declaration for error-reporting function - Copyright (C) 1995, 1996, 1997, 2003, 2006, 2008, 2009, 2010 Free Software - Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef _ERROR_H -#define _ERROR_H 1 - -#ifndef __attribute__ -/* The __attribute__ feature is available in gcc versions 2.5 and later. - The __-protected variants of the attributes 'format' and 'printf' are - accepted by gcc versions 2.6.4 (effectively 2.7) and later. - We enable __attribute__ only if these are supported too, because - gnulib and libintl do '#define printf __printf__' when they override - the 'printf' function. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __attribute__(Spec) /* empty */ -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Print a message with `fprintf (stderr, FORMAT, ...)'; - if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). - If STATUS is nonzero, terminate the program with `exit (STATUS)'. */ - -extern void error (int __status, int __errnum, const char *__format, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); - -extern void error_at_line (int __status, int __errnum, const char *__fname, - unsigned int __lineno, const char *__format, ...) - __attribute__ ((__format__ (__printf__, 5, 6))); - -/* If NULL, error will flush stdout, then print on stderr the program - name, a colon and a space. Otherwise, error will call this - function without parameters instead. */ -extern void (*error_print_progname) (void); - -/* This variable is incremented each time `error' is called. */ -extern unsigned int error_message_count; - -/* Sometimes we want to have at most one error per line. This - variable controls whether this mode is selected or not. */ -extern int error_one_per_line; - -#ifdef __cplusplus -} -#endif - -#endif /* error.h */ diff --git a/grub-core/gnulib/float+.h b/grub-core/gnulib/float+.h deleted file mode 100644 index b55e5e6de..000000000 --- a/grub-core/gnulib/float+.h +++ /dev/null @@ -1,148 +0,0 @@ -/* Supplemental information about the floating-point formats. - Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2007. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _FLOATPLUS_H -#define _FLOATPLUS_H - -#include -#include - -/* Number of bits in the mantissa of a floating-point number, including the - "hidden bit". */ -#if FLT_RADIX == 2 -# define FLT_MANT_BIT FLT_MANT_DIG -# define DBL_MANT_BIT DBL_MANT_DIG -# define LDBL_MANT_BIT LDBL_MANT_DIG -#elif FLT_RADIX == 4 -# define FLT_MANT_BIT (FLT_MANT_DIG * 2) -# define DBL_MANT_BIT (DBL_MANT_DIG * 2) -# define LDBL_MANT_BIT (LDBL_MANT_DIG * 2) -#elif FLT_RADIX == 16 -# define FLT_MANT_BIT (FLT_MANT_DIG * 4) -# define DBL_MANT_BIT (DBL_MANT_DIG * 4) -# define LDBL_MANT_BIT (LDBL_MANT_DIG * 4) -#endif - -/* Bit mask that can be used to mask the exponent, as an unsigned number. */ -#define FLT_EXP_MASK ((FLT_MAX_EXP - FLT_MIN_EXP) | 7) -#define DBL_EXP_MASK ((DBL_MAX_EXP - DBL_MIN_EXP) | 7) -#define LDBL_EXP_MASK ((LDBL_MAX_EXP - LDBL_MIN_EXP) | 7) - -/* Number of bits used for the exponent of a floating-point number, including - the exponent's sign. */ -#define FLT_EXP_BIT \ - (FLT_EXP_MASK < 0x100 ? 8 : \ - FLT_EXP_MASK < 0x200 ? 9 : \ - FLT_EXP_MASK < 0x400 ? 10 : \ - FLT_EXP_MASK < 0x800 ? 11 : \ - FLT_EXP_MASK < 0x1000 ? 12 : \ - FLT_EXP_MASK < 0x2000 ? 13 : \ - FLT_EXP_MASK < 0x4000 ? 14 : \ - FLT_EXP_MASK < 0x8000 ? 15 : \ - FLT_EXP_MASK < 0x10000 ? 16 : \ - FLT_EXP_MASK < 0x20000 ? 17 : \ - FLT_EXP_MASK < 0x40000 ? 18 : \ - FLT_EXP_MASK < 0x80000 ? 19 : \ - FLT_EXP_MASK < 0x100000 ? 20 : \ - FLT_EXP_MASK < 0x200000 ? 21 : \ - FLT_EXP_MASK < 0x400000 ? 22 : \ - FLT_EXP_MASK < 0x800000 ? 23 : \ - FLT_EXP_MASK < 0x1000000 ? 24 : \ - FLT_EXP_MASK < 0x2000000 ? 25 : \ - FLT_EXP_MASK < 0x4000000 ? 26 : \ - FLT_EXP_MASK < 0x8000000 ? 27 : \ - FLT_EXP_MASK < 0x10000000 ? 28 : \ - FLT_EXP_MASK < 0x20000000 ? 29 : \ - FLT_EXP_MASK < 0x40000000 ? 30 : \ - FLT_EXP_MASK <= 0x7fffffff ? 31 : \ - 32) -#define DBL_EXP_BIT \ - (DBL_EXP_MASK < 0x100 ? 8 : \ - DBL_EXP_MASK < 0x200 ? 9 : \ - DBL_EXP_MASK < 0x400 ? 10 : \ - DBL_EXP_MASK < 0x800 ? 11 : \ - DBL_EXP_MASK < 0x1000 ? 12 : \ - DBL_EXP_MASK < 0x2000 ? 13 : \ - DBL_EXP_MASK < 0x4000 ? 14 : \ - DBL_EXP_MASK < 0x8000 ? 15 : \ - DBL_EXP_MASK < 0x10000 ? 16 : \ - DBL_EXP_MASK < 0x20000 ? 17 : \ - DBL_EXP_MASK < 0x40000 ? 18 : \ - DBL_EXP_MASK < 0x80000 ? 19 : \ - DBL_EXP_MASK < 0x100000 ? 20 : \ - DBL_EXP_MASK < 0x200000 ? 21 : \ - DBL_EXP_MASK < 0x400000 ? 22 : \ - DBL_EXP_MASK < 0x800000 ? 23 : \ - DBL_EXP_MASK < 0x1000000 ? 24 : \ - DBL_EXP_MASK < 0x2000000 ? 25 : \ - DBL_EXP_MASK < 0x4000000 ? 26 : \ - DBL_EXP_MASK < 0x8000000 ? 27 : \ - DBL_EXP_MASK < 0x10000000 ? 28 : \ - DBL_EXP_MASK < 0x20000000 ? 29 : \ - DBL_EXP_MASK < 0x40000000 ? 30 : \ - DBL_EXP_MASK <= 0x7fffffff ? 31 : \ - 32) -#define LDBL_EXP_BIT \ - (LDBL_EXP_MASK < 0x100 ? 8 : \ - LDBL_EXP_MASK < 0x200 ? 9 : \ - LDBL_EXP_MASK < 0x400 ? 10 : \ - LDBL_EXP_MASK < 0x800 ? 11 : \ - LDBL_EXP_MASK < 0x1000 ? 12 : \ - LDBL_EXP_MASK < 0x2000 ? 13 : \ - LDBL_EXP_MASK < 0x4000 ? 14 : \ - LDBL_EXP_MASK < 0x8000 ? 15 : \ - LDBL_EXP_MASK < 0x10000 ? 16 : \ - LDBL_EXP_MASK < 0x20000 ? 17 : \ - LDBL_EXP_MASK < 0x40000 ? 18 : \ - LDBL_EXP_MASK < 0x80000 ? 19 : \ - LDBL_EXP_MASK < 0x100000 ? 20 : \ - LDBL_EXP_MASK < 0x200000 ? 21 : \ - LDBL_EXP_MASK < 0x400000 ? 22 : \ - LDBL_EXP_MASK < 0x800000 ? 23 : \ - LDBL_EXP_MASK < 0x1000000 ? 24 : \ - LDBL_EXP_MASK < 0x2000000 ? 25 : \ - LDBL_EXP_MASK < 0x4000000 ? 26 : \ - LDBL_EXP_MASK < 0x8000000 ? 27 : \ - LDBL_EXP_MASK < 0x10000000 ? 28 : \ - LDBL_EXP_MASK < 0x20000000 ? 29 : \ - LDBL_EXP_MASK < 0x40000000 ? 30 : \ - LDBL_EXP_MASK <= 0x7fffffff ? 31 : \ - 32) - -/* Number of bits used for a floating-point number: the mantissa (not - counting the "hidden bit", since it may or may not be explicit), the - exponent, and the sign. */ -#define FLT_TOTAL_BIT ((FLT_MANT_BIT - 1) + FLT_EXP_BIT + 1) -#define DBL_TOTAL_BIT ((DBL_MANT_BIT - 1) + DBL_EXP_BIT + 1) -#define LDBL_TOTAL_BIT ((LDBL_MANT_BIT - 1) + LDBL_EXP_BIT + 1) - -/* Number of bytes used for a floating-point number. - This can be smaller than the 'sizeof'. For example, on i386 systems, - 'long double' most often have LDBL_MANT_BIT = 64, LDBL_EXP_BIT = 16, hence - LDBL_TOTAL_BIT = 80 bits, i.e. 10 bytes of consecutive memory, but - sizeof (long double) = 12 or = 16. */ -#define SIZEOF_FLT ((FLT_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) -#define SIZEOF_DBL ((DBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) -#define SIZEOF_LDBL ((LDBL_TOTAL_BIT + CHAR_BIT - 1) / CHAR_BIT) - -/* Verify that SIZEOF_FLT <= sizeof (float) etc. */ -typedef int verify_sizeof_flt[2 * (SIZEOF_FLT <= sizeof (float)) - 1]; -typedef int verify_sizeof_dbl[2 * (SIZEOF_DBL <= sizeof (double)) - 1]; -typedef int verify_sizeof_ldbl[2 * (SIZEOF_LDBL <= sizeof (long double)) - 1]; - -#endif /* _FLOATPLUS_H */ diff --git a/grub-core/gnulib/float.in.h b/grub-core/gnulib/float.in.h deleted file mode 100644 index caf822f1d..000000000 --- a/grub-core/gnulib/float.in.h +++ /dev/null @@ -1,62 +0,0 @@ -/* A correct . - - Copyright (C) 2007-2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef _GL_FLOAT_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -/* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_FLOAT_H@ - -#ifndef _GL_FLOAT_H -#define _GL_FLOAT_H - -/* 'long double' properties. */ -#if defined __i386__ && (defined __BEOS__ || defined __OpenBSD__) -/* Number of mantissa units, in base FLT_RADIX. */ -# undef LDBL_MANT_DIG -# define LDBL_MANT_DIG 64 -/* Number of decimal digits that is sufficient for representing a number. */ -# undef LDBL_DIG -# define LDBL_DIG 18 -/* x-1 where x is the smallest representable number > 1. */ -# undef LDBL_EPSILON -# define LDBL_EPSILON 1.0842021724855044340E-19L -/* Minimum e such that FLT_RADIX^(e-1) is a normalized number. */ -# undef LDBL_MIN_EXP -# define LDBL_MIN_EXP (-16381) -/* Maximum e such that FLT_RADIX^(e-1) is a representable finite number. */ -# undef LDBL_MAX_EXP -# define LDBL_MAX_EXP 16384 -/* Minimum positive normalized number. */ -# undef LDBL_MIN -# define LDBL_MIN 3.3621031431120935063E-4932L -/* Maximum representable finite number. */ -# undef LDBL_MAX -# define LDBL_MAX 1.1897314953572317650E+4932L -/* Minimum e such that 10^e is in the range of normalized numbers. */ -# undef LDBL_MIN_10_EXP -# define LDBL_MIN_10_EXP (-4931) -/* Maximum e such that 10^e is in the range of representable finite numbers. */ -# undef LDBL_MAX_10_EXP -# define LDBL_MAX_10_EXP 4932 -#endif - -#endif /* _GL_FLOAT_H */ -#endif /* _GL_FLOAT_H */ diff --git a/grub-core/gnulib/fnmatch.c b/grub-core/gnulib/fnmatch.c deleted file mode 100644 index d73e47dae..000000000 --- a/grub-core/gnulib/fnmatch.c +++ /dev/null @@ -1,354 +0,0 @@ -/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _LIBC -# include -#endif - -/* Enable GNU extensions in fnmatch.h. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#if ! defined __builtin_expect && __GNUC__ < 3 -# define __builtin_expect(expr, expected) (expr) -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define WIDE_CHAR_SUPPORT \ - (HAVE_WCTYPE_H && HAVE_BTOWC && HAVE_ISWCTYPE \ - && HAVE_WMEMCHR && (HAVE_WMEMCPY || HAVE_WMEMPCPY)) - -/* For platform which support the ISO C amendement 1 functionality we - support user defined character classes. */ -#if defined _LIBC || WIDE_CHAR_SUPPORT -# include -# include -#endif - -/* We need some of the locale data (the collation sequence information) - but there is no interface to get this information in general. Therefore - we support a correct implementation only in glibc. */ -#ifdef _LIBC -# include "../locale/localeinfo.h" -# include "../locale/elem-hash.h" -# include "../locale/coll-lookup.h" -# include - -# define CONCAT(a,b) __CONCAT(a,b) -# define mbsrtowcs __mbsrtowcs -# define fnmatch __fnmatch -extern int fnmatch (const char *pattern, const char *string, int flags); -#endif - -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */ -#define NO_LEADING_PERIOD(flags) \ - ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD)) - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself, and have not detected a bug - in the library. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#if defined _LIBC || !defined __GNU_LIBRARY__ || !HAVE_FNMATCH_GNU - - -# if ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK)) -# define isblank(c) ((c) == ' ' || (c) == '\t') -# endif - -# define STREQ(s1, s2) (strcmp (s1, s2) == 0) - -# if defined _LIBC || WIDE_CHAR_SUPPORT -/* The GNU C library provides support for user-defined character classes - and the functions from ISO C amendement 1. */ -# ifdef CHARCLASS_NAME_MAX -# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX -# else -/* This shouldn't happen but some implementation might still have this - problem. Use a reasonable default value. */ -# define CHAR_CLASS_MAX_LENGTH 256 -# endif - -# ifdef _LIBC -# define IS_CHAR_CLASS(string) __wctype (string) -# else -# define IS_CHAR_CLASS(string) wctype (string) -# endif - -# ifdef _LIBC -# define ISWCTYPE(WC, WT) __iswctype (WC, WT) -# else -# define ISWCTYPE(WC, WT) iswctype (WC, WT) -# endif - -# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC -/* In this case we are implementing the multibyte character handling. */ -# define HANDLE_MULTIBYTE 1 -# endif - -# else -# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ - -# define IS_CHAR_CLASS(string) \ - (STREQ (string, "alpha") || STREQ (string, "upper") \ - || STREQ (string, "lower") || STREQ (string, "digit") \ - || STREQ (string, "alnum") || STREQ (string, "xdigit") \ - || STREQ (string, "space") || STREQ (string, "print") \ - || STREQ (string, "punct") || STREQ (string, "graph") \ - || STREQ (string, "cntrl") || STREQ (string, "blank")) -# endif - -/* Avoid depending on library functions or files - whose names are inconsistent. */ - -/* Global variable. */ -static int posixly_correct; - -# ifndef internal_function -/* Inside GNU libc we mark some function in a special way. In other - environments simply ignore the marking. */ -# define internal_function -# endif - -/* Note that this evaluates C many times. */ -# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) -# define CHAR char -# define UCHAR unsigned char -# define INT int -# define FCT internal_fnmatch -# define EXT ext_match -# define END end_pattern -# define L_(CS) CS -# ifdef _LIBC -# define BTOWC(C) __btowc (C) -# else -# define BTOWC(C) btowc (C) -# endif -# define STRLEN(S) strlen (S) -# define STRCAT(D, S) strcat (D, S) -# ifdef _LIBC -# define MEMPCPY(D, S, N) __mempcpy (D, S, N) -# else -# if HAVE_MEMPCPY -# define MEMPCPY(D, S, N) mempcpy (D, S, N) -# else -# define MEMPCPY(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) -# endif -# endif -# define MEMCHR(S, C, N) memchr (S, C, N) -# define STRCOLL(S1, S2) strcoll (S1, S2) -# include "fnmatch_loop.c" - - -# if HANDLE_MULTIBYTE -# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c)) -# define CHAR wchar_t -# define UCHAR wint_t -# define INT wint_t -# define FCT internal_fnwmatch -# define EXT ext_wmatch -# define END end_wpattern -# define L_(CS) L##CS -# define BTOWC(C) (C) -# ifdef _LIBC -# define STRLEN(S) __wcslen (S) -# define STRCAT(D, S) __wcscat (D, S) -# define MEMPCPY(D, S, N) __wmempcpy (D, S, N) -# else -# define STRLEN(S) wcslen (S) -# define STRCAT(D, S) wcscat (D, S) -# if HAVE_WMEMPCPY -# define MEMPCPY(D, S, N) wmempcpy (D, S, N) -# else -# define MEMPCPY(D, S, N) (wmemcpy (D, S, N) + (N)) -# endif -# endif -# define MEMCHR(S, C, N) wmemchr (S, C, N) -# define STRCOLL(S1, S2) wcscoll (S1, S2) -# define WIDE_CHAR_VERSION 1 - -# undef IS_CHAR_CLASS -/* We have to convert the wide character string in a multibyte string. But - we know that the character class names consist of alphanumeric characters - from the portable character set, and since the wide character encoding - for a member of the portable character set is the same code point as - its single-byte encoding, we can use a simplified method to convert the - string to a multibyte character string. */ -static wctype_t -is_char_class (const wchar_t *wcs) -{ - char s[CHAR_CLASS_MAX_LENGTH + 1]; - char *cp = s; - - do - { - /* Test for a printable character from the portable character set. */ -# ifdef _LIBC - if (*wcs < 0x20 || *wcs > 0x7e - || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60) - return (wctype_t) 0; -# else - switch (*wcs) - { - case L' ': case L'!': case L'"': case L'#': case L'%': - case L'&': case L'\'': case L'(': case L')': case L'*': - case L'+': case L',': case L'-': case L'.': case L'/': - case L'0': case L'1': case L'2': case L'3': case L'4': - case L'5': case L'6': case L'7': case L'8': case L'9': - case L':': case L';': case L'<': case L'=': case L'>': - case L'?': - case L'A': case L'B': case L'C': case L'D': case L'E': - case L'F': case L'G': case L'H': case L'I': case L'J': - case L'K': case L'L': case L'M': case L'N': case L'O': - case L'P': case L'Q': case L'R': case L'S': case L'T': - case L'U': case L'V': case L'W': case L'X': case L'Y': - case L'Z': - case L'[': case L'\\': case L']': case L'^': case L'_': - case L'a': case L'b': case L'c': case L'd': case L'e': - case L'f': case L'g': case L'h': case L'i': case L'j': - case L'k': case L'l': case L'm': case L'n': case L'o': - case L'p': case L'q': case L'r': case L's': case L't': - case L'u': case L'v': case L'w': case L'x': case L'y': - case L'z': case L'{': case L'|': case L'}': case L'~': - break; - default: - return (wctype_t) 0; - } -# endif - - /* Avoid overrunning the buffer. */ - if (cp == s + CHAR_CLASS_MAX_LENGTH) - return (wctype_t) 0; - - *cp++ = (char) *wcs++; - } - while (*wcs != L'\0'); - - *cp = '\0'; - -# ifdef _LIBC - return __wctype (s); -# else - return wctype (s); -# endif -} -# define IS_CHAR_CLASS(string) is_char_class (string) - -# include "fnmatch_loop.c" -# endif - - -int -fnmatch (const char *pattern, const char *string, int flags) -{ -# if HANDLE_MULTIBYTE -# define ALLOCA_LIMIT 2000 - if (__builtin_expect (MB_CUR_MAX, 1) != 1) - { - mbstate_t ps; - size_t patsize; - size_t strsize; - size_t totsize; - wchar_t *wpattern; - wchar_t *wstring; - int res; - - /* Calculate the size needed to convert the strings to - wide characters. */ - memset (&ps, '\0', sizeof (ps)); - patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1; - if (__builtin_expect (patsize != 0, 1)) - { - assert (mbsinit (&ps)); - strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1; - if (__builtin_expect (strsize != 0, 1)) - { - assert (mbsinit (&ps)); - totsize = patsize + strsize; - if (__builtin_expect (! (patsize <= totsize - && totsize <= SIZE_MAX / sizeof (wchar_t)), - 0)) - { - errno = ENOMEM; - return -1; - } - - /* Allocate room for the wide characters. */ - if (__builtin_expect (totsize < ALLOCA_LIMIT, 1)) - wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t)); - else - { - wpattern = malloc (totsize * sizeof (wchar_t)); - if (__builtin_expect (! wpattern, 0)) - { - errno = ENOMEM; - return -1; - } - } - wstring = wpattern + patsize; - - /* Convert the strings into wide characters. */ - mbsrtowcs (wpattern, &pattern, patsize, &ps); - assert (mbsinit (&ps)); - mbsrtowcs (wstring, &string, strsize, &ps); - - res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1, - flags & FNM_PERIOD, flags); - - if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0)) - free (wpattern); - return res; - } - } - } - -# endif /* HANDLE_MULTIBYTE */ - - return internal_fnmatch (pattern, string, string + strlen (string), - flags & FNM_PERIOD, flags); -} - -# ifdef _LIBC -# undef fnmatch -versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3); -# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3) -strong_alias (__fnmatch, __fnmatch_old) -compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0); -# endif -libc_hidden_ver (__fnmatch, fnmatch) -# endif - -#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/grub-core/gnulib/fnmatch.in.h b/grub-core/gnulib/fnmatch.in.h deleted file mode 100644 index 8caab1959..000000000 --- a/grub-core/gnulib/fnmatch.in.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2001, 2002, 2003, - 2005, 2007, 2009, 2010 Free Software Foundation, Inc. - - This file is part of the GNU C Library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _FNMATCH_H -#define _FNMATCH_H 1 - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* We #undef these before defining them because some losing systems - (HP-UX A.08.07 for example) define these in . */ -#undef FNM_PATHNAME -#undef FNM_NOESCAPE -#undef FNM_PERIOD - -/* Bits set in the FLAGS argument to `fnmatch'. */ -#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ -#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ -#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ - -#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE -# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ -# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ -# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ -# define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */ -#endif - -/* Value returned by `fnmatch' if STRING does not match PATTERN. */ -#define FNM_NOMATCH 1 - -/* This value is returned if the implementation does not support - `fnmatch'. Since this is not the case here it will never be - returned but the conformance test suites still require the symbol - to be defined. */ -#ifdef _XOPEN_SOURCE -# define FNM_NOSYS (-1) -#endif - -/* Match NAME against the file name pattern PATTERN, - returning zero if it matches, FNM_NOMATCH if not. */ -extern int fnmatch (const char *__pattern, const char *__name, - int __flags) - _GL_ARG_NONNULL ((1, 2)); - -#ifdef __cplusplus -} -#endif - -#endif /* fnmatch.h */ diff --git a/grub-core/gnulib/fnmatch_loop.c b/grub-core/gnulib/fnmatch_loop.c deleted file mode 100644 index 741c993ef..000000000 --- a/grub-core/gnulib/fnmatch_loop.c +++ /dev/null @@ -1,1215 +0,0 @@ -/* Copyright (C) 1991, 1992, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2009, 2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Match STRING against the file name pattern PATTERN, returning zero if - it matches, nonzero if not. */ -static int EXT (INT opt, const CHAR *pattern, const CHAR *string, - const CHAR *string_end, bool no_leading_period, int flags) - internal_function; -static const CHAR *END (const CHAR *patternp) internal_function; - -static int -internal_function -FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, - bool no_leading_period, int flags) -{ - register const CHAR *p = pattern, *n = string; - register UCHAR c; -#ifdef _LIBC -# if WIDE_CHAR_VERSION - const char *collseq = (const char *) - _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); -# else - const UCHAR *collseq = (const UCHAR *) - _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); -# endif -#endif - - while ((c = *p++) != L_('\0')) - { - bool new_no_leading_period = false; - c = FOLD (c); - - switch (c) - { - case L_('?'): - if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') - { - int res; - - res = EXT (c, p, n, string_end, no_leading_period, - flags); - if (res != -1) - return res; - } - - if (n == string_end) - return FNM_NOMATCH; - else if (*n == L_('/') && (flags & FNM_FILE_NAME)) - return FNM_NOMATCH; - else if (*n == L_('.') && no_leading_period) - return FNM_NOMATCH; - break; - - case L_('\\'): - if (!(flags & FNM_NOESCAPE)) - { - c = *p++; - if (c == L_('\0')) - /* Trailing \ loses. */ - return FNM_NOMATCH; - c = FOLD (c); - } - if (n == string_end || FOLD ((UCHAR) *n) != c) - return FNM_NOMATCH; - break; - - case L_('*'): - if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') - { - int res; - - res = EXT (c, p, n, string_end, no_leading_period, - flags); - if (res != -1) - return res; - } - - if (n != string_end && *n == L_('.') && no_leading_period) - return FNM_NOMATCH; - - for (c = *p++; c == L_('?') || c == L_('*'); c = *p++) - { - if (*p == L_('(') && (flags & FNM_EXTMATCH) != 0) - { - const CHAR *endp = END (p); - if (endp != p) - { - /* This is a pattern. Skip over it. */ - p = endp; - continue; - } - } - - if (c == L_('?')) - { - /* A ? needs to match one character. */ - if (n == string_end) - /* There isn't another character; no match. */ - return FNM_NOMATCH; - else if (*n == L_('/') - && __builtin_expect (flags & FNM_FILE_NAME, 0)) - /* A slash does not match a wildcard under - FNM_FILE_NAME. */ - return FNM_NOMATCH; - else - /* One character of the string is consumed in matching - this ? wildcard, so *??? won't match if there are - less than three characters. */ - ++n; - } - } - - if (c == L_('\0')) - /* The wildcard(s) is/are the last element of the pattern. - If the name is a file name and contains another slash - this means it cannot match, unless the FNM_LEADING_DIR - flag is set. */ - { - int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH; - - if (flags & FNM_FILE_NAME) - { - if (flags & FNM_LEADING_DIR) - result = 0; - else - { - if (MEMCHR (n, L_('/'), string_end - n) == NULL) - result = 0; - } - } - - return result; - } - else - { - const CHAR *endp; - - endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L_('/') : L_('\0'), - string_end - n); - if (endp == NULL) - endp = string_end; - - if (c == L_('[') - || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0 - && (c == L_('@') || c == L_('+') || c == L_('!')) - && *p == L_('('))) - { - int flags2 = ((flags & FNM_FILE_NAME) - ? flags : (flags & ~FNM_PERIOD)); - bool no_leading_period2 = no_leading_period; - - for (--p; n < endp; ++n, no_leading_period2 = false) - if (FCT (p, n, string_end, no_leading_period2, flags2) - == 0) - return 0; - } - else if (c == L_('/') && (flags & FNM_FILE_NAME)) - { - while (n < string_end && *n != L_('/')) - ++n; - if (n < string_end && *n == L_('/') - && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags) - == 0)) - return 0; - } - else - { - int flags2 = ((flags & FNM_FILE_NAME) - ? flags : (flags & ~FNM_PERIOD)); - int no_leading_period2 = no_leading_period; - - if (c == L_('\\') && !(flags & FNM_NOESCAPE)) - c = *p; - c = FOLD (c); - for (--p; n < endp; ++n, no_leading_period2 = false) - if (FOLD ((UCHAR) *n) == c - && (FCT (p, n, string_end, no_leading_period2, flags2) - == 0)) - return 0; - } - } - - /* If we come here no match is possible with the wildcard. */ - return FNM_NOMATCH; - - case L_('['): - { - /* Nonzero if the sense of the character class is inverted. */ - register bool not; - CHAR cold; - UCHAR fn; - - if (posixly_correct == 0) - posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; - - if (n == string_end) - return FNM_NOMATCH; - - if (*n == L_('.') && no_leading_period) - return FNM_NOMATCH; - - if (*n == L_('/') && (flags & FNM_FILE_NAME)) - /* `/' cannot be matched. */ - return FNM_NOMATCH; - - not = (*p == L_('!') || (posixly_correct < 0 && *p == L_('^'))); - if (not) - ++p; - - fn = FOLD ((UCHAR) *n); - - c = *p++; - for (;;) - { - if (!(flags & FNM_NOESCAPE) && c == L_('\\')) - { - if (*p == L_('\0')) - return FNM_NOMATCH; - c = FOLD ((UCHAR) *p); - ++p; - - goto normal_bracket; - } - else if (c == L_('[') && *p == L_(':')) - { - /* Leave room for the null. */ - CHAR str[CHAR_CLASS_MAX_LENGTH + 1]; - size_t c1 = 0; -#if defined _LIBC || WIDE_CHAR_SUPPORT - wctype_t wt; -#endif - const CHAR *startp = p; - - for (;;) - { - if (c1 == CHAR_CLASS_MAX_LENGTH) - /* The name is too long and therefore the pattern - is ill-formed. */ - return FNM_NOMATCH; - - c = *++p; - if (c == L_(':') && p[1] == L_(']')) - { - p += 2; - break; - } - if (c < L_('a') || c >= L_('z')) - { - /* This cannot possibly be a character class name. - Match it as a normal range. */ - p = startp; - c = L_('['); - goto normal_bracket; - } - str[c1++] = c; - } - str[c1] = L_('\0'); - -#if defined _LIBC || WIDE_CHAR_SUPPORT - wt = IS_CHAR_CLASS (str); - if (wt == 0) - /* Invalid character class name. */ - return FNM_NOMATCH; - -# if defined _LIBC && ! WIDE_CHAR_VERSION - /* The following code is glibc specific but does - there a good job in speeding up the code since - we can avoid the btowc() call. */ - if (_ISCTYPE ((UCHAR) *n, wt)) - goto matched; -# else - if (ISWCTYPE (BTOWC ((UCHAR) *n), wt)) - goto matched; -# endif -#else - if ((STREQ (str, L_("alnum")) && isalnum ((UCHAR) *n)) - || (STREQ (str, L_("alpha")) && isalpha ((UCHAR) *n)) - || (STREQ (str, L_("blank")) && isblank ((UCHAR) *n)) - || (STREQ (str, L_("cntrl")) && iscntrl ((UCHAR) *n)) - || (STREQ (str, L_("digit")) && isdigit ((UCHAR) *n)) - || (STREQ (str, L_("graph")) && isgraph ((UCHAR) *n)) - || (STREQ (str, L_("lower")) && islower ((UCHAR) *n)) - || (STREQ (str, L_("print")) && isprint ((UCHAR) *n)) - || (STREQ (str, L_("punct")) && ispunct ((UCHAR) *n)) - || (STREQ (str, L_("space")) && isspace ((UCHAR) *n)) - || (STREQ (str, L_("upper")) && isupper ((UCHAR) *n)) - || (STREQ (str, L_("xdigit")) && isxdigit ((UCHAR) *n))) - goto matched; -#endif - c = *p++; - } -#ifdef _LIBC - else if (c == L_('[') && *p == L_('=')) - { - UCHAR str[1]; - uint32_t nrules = - _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - const CHAR *startp = p; - - c = *++p; - if (c == L_('\0')) - { - p = startp; - c = L_('['); - goto normal_bracket; - } - str[0] = c; - - c = *++p; - if (c != L_('=') || p[1] != L_(']')) - { - p = startp; - c = L_('['); - goto normal_bracket; - } - p += 2; - - if (nrules == 0) - { - if ((UCHAR) *n == str[0]) - goto matched; - } - else - { - const int32_t *table; -# if WIDE_CHAR_VERSION - const int32_t *weights; - const int32_t *extra; -# else - const unsigned char *weights; - const unsigned char *extra; -# endif - const int32_t *indirect; - int32_t idx; - const UCHAR *cp = (const UCHAR *) str; - - /* This #include defines a local function! */ -# if WIDE_CHAR_VERSION -# include -# else -# include -# endif - -# if WIDE_CHAR_VERSION - table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); - weights = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); - extra = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); - indirect = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); -# else - table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - weights = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); -# endif - - idx = findidx (&cp); - if (idx != 0) - { - /* We found a table entry. Now see whether the - character we are currently at has the same - equivalance class value. */ - int len = weights[idx & 0xffffff]; - int32_t idx2; - const UCHAR *np = (const UCHAR *) n; - - idx2 = findidx (&np); - if (idx2 != 0 - && (idx >> 24) == (idx2 >> 24) - && len == weights[idx2 & 0xffffff]) - { - int cnt = 0; - - idx &= 0xffffff; - idx2 &= 0xffffff; - - while (cnt < len - && (weights[idx + 1 + cnt] - == weights[idx2 + 1 + cnt])) - ++cnt; - - if (cnt == len) - goto matched; - } - } - } - - c = *p++; - } -#endif - else if (c == L_('\0')) - /* [ (unterminated) loses. */ - return FNM_NOMATCH; - else - { - bool is_range = false; - -#ifdef _LIBC - bool is_seqval = false; - - if (c == L_('[') && *p == L_('.')) - { - uint32_t nrules = - _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - const CHAR *startp = p; - size_t c1 = 0; - - while (1) - { - c = *++p; - if (c == L_('.') && p[1] == L_(']')) - { - p += 2; - break; - } - if (c == '\0') - return FNM_NOMATCH; - ++c1; - } - - /* We have to handling the symbols differently in - ranges since then the collation sequence is - important. */ - is_range = *p == L_('-') && p[1] != L_('\0'); - - if (nrules == 0) - { - /* There are no names defined in the collation - data. Therefore we only accept the trivial - names consisting of the character itself. */ - if (c1 != 1) - return FNM_NOMATCH; - - if (!is_range && *n == startp[1]) - goto matched; - - cold = startp[1]; - c = *p++; - } - else - { - int32_t table_size; - const int32_t *symb_table; -# ifdef WIDE_CHAR_VERSION - char str[c1]; - size_t strcnt; -# else -# define str (startp + 1) -# endif - const unsigned char *extra; - int32_t idx; - int32_t elem; - int32_t second; - int32_t hash; - -# ifdef WIDE_CHAR_VERSION - /* We have to convert the name to a single-byte - string. This is possible since the names - consist of ASCII characters and the internal - representation is UCS4. */ - for (strcnt = 0; strcnt < c1; ++strcnt) - str[strcnt] = startp[1 + strcnt]; -# endif - - table_size = - _NL_CURRENT_WORD (LC_COLLATE, - _NL_COLLATE_SYMB_HASH_SIZEMB); - symb_table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_TABLEMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_EXTRAMB); - - /* Locate the character in the hashing table. */ - hash = elem_hash (str, c1); - - idx = 0; - elem = hash % table_size; - if (symb_table[2 * elem] != 0) - { - second = hash % (table_size - 2) + 1; - - do - { - /* First compare the hashing value. */ - if (symb_table[2 * elem] == hash - && (c1 - == extra[symb_table[2 * elem + 1]]) - && memcmp (str, - &extra[symb_table[2 * elem - + 1] - + 1], c1) == 0) - { - /* Yep, this is the entry. */ - idx = symb_table[2 * elem + 1]; - idx += 1 + extra[idx]; - break; - } - - /* Next entry. */ - elem += second; - } - while (symb_table[2 * elem] != 0); - } - - if (symb_table[2 * elem] != 0) - { - /* Compare the byte sequence but only if - this is not part of a range. */ -# ifdef WIDE_CHAR_VERSION - int32_t *wextra; - - idx += 1 + extra[idx]; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - - wextra = (int32_t *) &extra[idx + 4]; -# endif - - if (! is_range) - { -# ifdef WIDE_CHAR_VERSION - for (c1 = 0; - (int32_t) c1 < wextra[idx]; - ++c1) - if (n[c1] != wextra[1 + c1]) - break; - - if ((int32_t) c1 == wextra[idx]) - goto matched; -# else - for (c1 = 0; c1 < extra[idx]; ++c1) - if (n[c1] != extra[1 + c1]) - break; - - if (c1 == extra[idx]) - goto matched; -# endif - } - - /* Get the collation sequence value. */ - is_seqval = true; -# ifdef WIDE_CHAR_VERSION - cold = wextra[1 + wextra[idx]]; -# else - /* Adjust for the alignment. */ - idx += 1 + extra[idx]; - idx = (idx + 3) & ~4; - cold = *((int32_t *) &extra[idx]); -# endif - - c = *p++; - } - else if (c1 == 1) - { - /* No valid character. Match it as a - single byte. */ - if (!is_range && *n == str[0]) - goto matched; - - cold = str[0]; - c = *p++; - } - else - return FNM_NOMATCH; - } - } - else -# undef str -#endif - { - c = FOLD (c); - normal_bracket: - - /* We have to handling the symbols differently in - ranges since then the collation sequence is - important. */ - is_range = (*p == L_('-') && p[1] != L_('\0') - && p[1] != L_(']')); - - if (!is_range && c == fn) - goto matched; - -#if _LIBC - /* This is needed if we goto normal_bracket; from - outside of is_seqval's scope. */ - is_seqval = false; -#endif - - cold = c; - c = *p++; - } - - if (c == L_('-') && *p != L_(']')) - { -#if _LIBC - /* We have to find the collation sequence - value for C. Collation sequence is nothing - we can regularly access. The sequence - value is defined by the order in which the - definitions of the collation values for the - various characters appear in the source - file. A strange concept, nowhere - documented. */ - uint32_t fcollseq; - uint32_t lcollseq; - UCHAR cend = *p++; - -# ifdef WIDE_CHAR_VERSION - /* Search in the `names' array for the characters. */ - fcollseq = __collseq_table_lookup (collseq, fn); - if (fcollseq == ~((uint32_t) 0)) - /* XXX We don't know anything about the character - we are supposed to match. This means we are - failing. */ - goto range_not_matched; - - if (is_seqval) - lcollseq = cold; - else - lcollseq = __collseq_table_lookup (collseq, cold); -# else - fcollseq = collseq[fn]; - lcollseq = is_seqval ? cold : collseq[(UCHAR) cold]; -# endif - - is_seqval = false; - if (cend == L_('[') && *p == L_('.')) - { - uint32_t nrules = - _NL_CURRENT_WORD (LC_COLLATE, - _NL_COLLATE_NRULES); - const CHAR *startp = p; - size_t c1 = 0; - - while (1) - { - c = *++p; - if (c == L_('.') && p[1] == L_(']')) - { - p += 2; - break; - } - if (c == '\0') - return FNM_NOMATCH; - ++c1; - } - - if (nrules == 0) - { - /* There are no names defined in the - collation data. Therefore we only - accept the trivial names consisting - of the character itself. */ - if (c1 != 1) - return FNM_NOMATCH; - - cend = startp[1]; - } - else - { - int32_t table_size; - const int32_t *symb_table; -# ifdef WIDE_CHAR_VERSION - char str[c1]; - size_t strcnt; -# else -# define str (startp + 1) -# endif - const unsigned char *extra; - int32_t idx; - int32_t elem; - int32_t second; - int32_t hash; - -# ifdef WIDE_CHAR_VERSION - /* We have to convert the name to a single-byte - string. This is possible since the names - consist of ASCII characters and the internal - representation is UCS4. */ - for (strcnt = 0; strcnt < c1; ++strcnt) - str[strcnt] = startp[1 + strcnt]; -# endif - - table_size = - _NL_CURRENT_WORD (LC_COLLATE, - _NL_COLLATE_SYMB_HASH_SIZEMB); - symb_table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_TABLEMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_EXTRAMB); - - /* Locate the character in the hashing - table. */ - hash = elem_hash (str, c1); - - idx = 0; - elem = hash % table_size; - if (symb_table[2 * elem] != 0) - { - second = hash % (table_size - 2) + 1; - - do - { - /* First compare the hashing value. */ - if (symb_table[2 * elem] == hash - && (c1 - == extra[symb_table[2 * elem + 1]]) - && memcmp (str, - &extra[symb_table[2 * elem + 1] - + 1], c1) == 0) - { - /* Yep, this is the entry. */ - idx = symb_table[2 * elem + 1]; - idx += 1 + extra[idx]; - break; - } - - /* Next entry. */ - elem += second; - } - while (symb_table[2 * elem] != 0); - } - - if (symb_table[2 * elem] != 0) - { - /* Compare the byte sequence but only if - this is not part of a range. */ -# ifdef WIDE_CHAR_VERSION - int32_t *wextra; - - idx += 1 + extra[idx]; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~4; - - wextra = (int32_t *) &extra[idx + 4]; -# endif - /* Get the collation sequence value. */ - is_seqval = true; -# ifdef WIDE_CHAR_VERSION - cend = wextra[1 + wextra[idx]]; -# else - /* Adjust for the alignment. */ - idx += 1 + extra[idx]; - idx = (idx + 3) & ~4; - cend = *((int32_t *) &extra[idx]); -# endif - } - else if (symb_table[2 * elem] != 0 && c1 == 1) - { - cend = str[0]; - c = *p++; - } - else - return FNM_NOMATCH; - } -# undef str - } - else - { - if (!(flags & FNM_NOESCAPE) && cend == L_('\\')) - cend = *p++; - if (cend == L_('\0')) - return FNM_NOMATCH; - cend = FOLD (cend); - } - - /* XXX It is not entirely clear to me how to handle - characters which are not mentioned in the - collation specification. */ - if ( -# ifdef WIDE_CHAR_VERSION - lcollseq == 0xffffffff || -# endif - lcollseq <= fcollseq) - { - /* We have to look at the upper bound. */ - uint32_t hcollseq; - - if (is_seqval) - hcollseq = cend; - else - { -# ifdef WIDE_CHAR_VERSION - hcollseq = - __collseq_table_lookup (collseq, cend); - if (hcollseq == ~((uint32_t) 0)) - { - /* Hum, no information about the upper - bound. The matching succeeds if the - lower bound is matched exactly. */ - if (lcollseq != fcollseq) - goto range_not_matched; - - goto matched; - } -# else - hcollseq = collseq[cend]; -# endif - } - - if (lcollseq <= hcollseq && fcollseq <= hcollseq) - goto matched; - } -# ifdef WIDE_CHAR_VERSION - range_not_matched: -# endif -#else - /* We use a boring value comparison of the character - values. This is better than comparing using - `strcoll' since the latter would have surprising - and sometimes fatal consequences. */ - UCHAR cend = *p++; - - if (!(flags & FNM_NOESCAPE) && cend == L_('\\')) - cend = *p++; - if (cend == L_('\0')) - return FNM_NOMATCH; - - /* It is a range. */ - if (cold <= fn && fn <= cend) - goto matched; -#endif - - c = *p++; - } - } - - if (c == L_(']')) - break; - } - - if (!not) - return FNM_NOMATCH; - break; - - matched: - /* Skip the rest of the [...] that already matched. */ - do - { - ignore_next: - c = *p++; - - if (c == L_('\0')) - /* [... (unterminated) loses. */ - return FNM_NOMATCH; - - if (!(flags & FNM_NOESCAPE) && c == L_('\\')) - { - if (*p == L_('\0')) - return FNM_NOMATCH; - /* XXX 1003.2d11 is unclear if this is right. */ - ++p; - } - else if (c == L_('[') && *p == L_(':')) - { - int c1 = 0; - const CHAR *startp = p; - - while (1) - { - c = *++p; - if (++c1 == CHAR_CLASS_MAX_LENGTH) - return FNM_NOMATCH; - - if (*p == L_(':') && p[1] == L_(']')) - break; - - if (c < L_('a') || c >= L_('z')) - { - p = startp; - goto ignore_next; - } - } - p += 2; - c = *p++; - } - else if (c == L_('[') && *p == L_('=')) - { - c = *++p; - if (c == L_('\0')) - return FNM_NOMATCH; - c = *++p; - if (c != L_('=') || p[1] != L_(']')) - return FNM_NOMATCH; - p += 2; - c = *p++; - } - else if (c == L_('[') && *p == L_('.')) - { - ++p; - while (1) - { - c = *++p; - if (c == '\0') - return FNM_NOMATCH; - - if (*p == L_('.') && p[1] == L_(']')) - break; - } - p += 2; - c = *p++; - } - } - while (c != L_(']')); - if (not) - return FNM_NOMATCH; - } - break; - - case L_('+'): - case L_('@'): - case L_('!'): - if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') - { - int res; - - res = EXT (c, p, n, string_end, no_leading_period, flags); - if (res != -1) - return res; - } - goto normal_match; - - case L_('/'): - if (NO_LEADING_PERIOD (flags)) - { - if (n == string_end || c != (UCHAR) *n) - return FNM_NOMATCH; - - new_no_leading_period = true; - break; - } - /* FALLTHROUGH */ - default: - normal_match: - if (n == string_end || c != FOLD ((UCHAR) *n)) - return FNM_NOMATCH; - } - - no_leading_period = new_no_leading_period; - ++n; - } - - if (n == string_end) - return 0; - - if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L_('/')) - /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ - return 0; - - return FNM_NOMATCH; -} - - -static const CHAR * -internal_function -END (const CHAR *pattern) -{ - const CHAR *p = pattern; - - while (1) - if (*++p == L_('\0')) - /* This is an invalid pattern. */ - return pattern; - else if (*p == L_('[')) - { - /* Handle brackets special. */ - if (posixly_correct == 0) - posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; - - /* Skip the not sign. We have to recognize it because of a possibly - following ']'. */ - if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^'))) - ++p; - /* A leading ']' is recognized as such. */ - if (*p == L_(']')) - ++p; - /* Skip over all characters of the list. */ - while (*p != L_(']')) - if (*p++ == L_('\0')) - /* This is no valid pattern. */ - return pattern; - } - else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@') - || *p == L_('!')) && p[1] == L_('(')) - p = END (p + 1); - else if (*p == L_(')')) - break; - - return p + 1; -} - - -static int -internal_function -EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, - bool no_leading_period, int flags) -{ - const CHAR *startp; - size_t level; - struct patternlist - { - struct patternlist *next; - CHAR str[1]; - } *list = NULL; - struct patternlist **lastp = &list; - size_t pattern_len = STRLEN (pattern); - const CHAR *p; - const CHAR *rs; - enum { ALLOCA_LIMIT = 8000 }; - - /* Parse the pattern. Store the individual parts in the list. */ - level = 0; - for (startp = p = pattern + 1; ; ++p) - if (*p == L_('\0')) - /* This is an invalid pattern. */ - return -1; - else if (*p == L_('[')) - { - /* Handle brackets special. */ - if (posixly_correct == 0) - posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; - - /* Skip the not sign. We have to recognize it because of a possibly - following ']'. */ - if (*++p == L_('!') || (posixly_correct < 0 && *p == L_('^'))) - ++p; - /* A leading ']' is recognized as such. */ - if (*p == L_(']')) - ++p; - /* Skip over all characters of the list. */ - while (*p != L_(']')) - if (*p++ == L_('\0')) - /* This is no valid pattern. */ - return -1; - } - else if ((*p == L_('?') || *p == L_('*') || *p == L_('+') || *p == L_('@') - || *p == L_('!')) && p[1] == L_('(')) - /* Remember the nesting level. */ - ++level; - else if (*p == L_(')')) - { - if (level-- == 0) - { - /* This means we found the end of the pattern. */ -#define NEW_PATTERN \ - struct patternlist *newp; \ - size_t plen; \ - size_t plensize; \ - size_t newpsize; \ - \ - plen = (opt == L_('?') || opt == L_('@') \ - ? pattern_len \ - : p - startp + 1UL); \ - plensize = plen * sizeof (CHAR); \ - newpsize = offsetof (struct patternlist, str) + plensize; \ - if ((size_t) -1 / sizeof (CHAR) < plen \ - || newpsize < offsetof (struct patternlist, str) \ - || ALLOCA_LIMIT <= newpsize) \ - return -1; \ - newp = (struct patternlist *) alloca (newpsize); \ - *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L_('\0'); \ - newp->next = NULL; \ - *lastp = newp; \ - lastp = &newp->next - NEW_PATTERN; - break; - } - } - else if (*p == L_('|')) - { - if (level == 0) - { - NEW_PATTERN; - startp = p + 1; - } - } - assert (list != NULL); - assert (p[-1] == L_(')')); -#undef NEW_PATTERN - - switch (opt) - { - case L_('*'): - if (FCT (p, string, string_end, no_leading_period, flags) == 0) - return 0; - /* FALLTHROUGH */ - - case L_('+'): - do - { - for (rs = string; rs <= string_end; ++rs) - /* First match the prefix with the current pattern with the - current pattern. */ - if (FCT (list->str, string, rs, no_leading_period, - flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0 - /* This was successful. Now match the rest with the rest - of the pattern. */ - && (FCT (p, rs, string_end, - rs == string - ? no_leading_period - : rs[-1] == '/' && NO_LEADING_PERIOD (flags), - flags & FNM_FILE_NAME - ? flags : flags & ~FNM_PERIOD) == 0 - /* This didn't work. Try the whole pattern. */ - || (rs != string - && FCT (pattern - 1, rs, string_end, - rs == string - ? no_leading_period - : rs[-1] == '/' && NO_LEADING_PERIOD (flags), - flags & FNM_FILE_NAME - ? flags : flags & ~FNM_PERIOD) == 0))) - /* It worked. Signal success. */ - return 0; - } - while ((list = list->next) != NULL); - - /* None of the patterns lead to a match. */ - return FNM_NOMATCH; - - case L_('?'): - if (FCT (p, string, string_end, no_leading_period, flags) == 0) - return 0; - /* FALLTHROUGH */ - - case L_('@'): - do - /* I cannot believe it but `strcat' is actually acceptable - here. Match the entire string with the prefix from the - pattern list and the rest of the pattern following the - pattern list. */ - if (FCT (STRCAT (list->str, p), string, string_end, - no_leading_period, - flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) - /* It worked. Signal success. */ - return 0; - while ((list = list->next) != NULL); - - /* None of the patterns lead to a match. */ - return FNM_NOMATCH; - - case L_('!'): - for (rs = string; rs <= string_end; ++rs) - { - struct patternlist *runp; - - for (runp = list; runp != NULL; runp = runp->next) - if (FCT (runp->str, string, rs, no_leading_period, - flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) - break; - - /* If none of the patterns matched see whether the rest does. */ - if (runp == NULL - && (FCT (p, rs, string_end, - rs == string - ? no_leading_period - : rs[-1] == '/' && NO_LEADING_PERIOD (flags), - flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) - == 0)) - /* This is successful. */ - return 0; - } - - /* None of the patterns together with the rest of the pattern - lead to a match. */ - return FNM_NOMATCH; - - default: - assert (! "Invalid extended matching operator"); - break; - } - - return -1; -} - - -#undef FOLD -#undef CHAR -#undef UCHAR -#undef INT -#undef FCT -#undef EXT -#undef END -#undef MEMPCPY -#undef MEMCHR -#undef STRCOLL -#undef STRLEN -#undef STRCAT -#undef L_ -#undef BTOWC diff --git a/grub-core/gnulib/getdelim.c b/grub-core/gnulib/getdelim.c deleted file mode 100644 index 66d07b9ae..000000000 --- a/grub-core/gnulib/getdelim.c +++ /dev/null @@ -1,137 +0,0 @@ -/* getdelim.c --- Implementation of replacement getdelim function. - Copyright (C) 1994, 1996, 1997, 1998, 2001, 2003, 2005, 2006, 2007, 2008, - 2009, 2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ - -/* Ported from glibc by Simon Josefsson. */ - -#include - -/* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc - optimizes away the lineptr == NULL || n == NULL || fp == NULL tests below. */ -#define _GL_ARG_NONNULL(params) - -#include - -#include -#include -#include -#include - -#ifndef SSIZE_MAX -# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) -#endif - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -# define getc_maybe_unlocked(fp) getc(fp) -#elif !HAVE_FLOCKFILE || !HAVE_FUNLOCKFILE || !HAVE_DECL_GETC_UNLOCKED -# undef flockfile -# undef funlockfile -# define flockfile(x) ((void) 0) -# define funlockfile(x) ((void) 0) -# define getc_maybe_unlocked(fp) getc(fp) -#else -# define getc_maybe_unlocked(fp) getc_unlocked(fp) -#endif - -/* Read up to (and including) a DELIMITER from FP into *LINEPTR (and - NUL-terminate it). *LINEPTR is a pointer returned from malloc (or - NULL), pointing to *N characters of space. It is realloc'ed as - necessary. Returns the number of characters read (not including - the null terminator), or -1 on error or EOF. */ - -ssize_t -getdelim (char **lineptr, size_t *n, int delimiter, FILE *fp) -{ - ssize_t result; - size_t cur_len = 0; - - if (lineptr == NULL || n == NULL || fp == NULL) - { - errno = EINVAL; - return -1; - } - - flockfile (fp); - - if (*lineptr == NULL || *n == 0) - { - char *new_lineptr; - *n = 120; - new_lineptr = (char *) realloc (*lineptr, *n); - if (new_lineptr == NULL) - { - result = -1; - goto unlock_return; - } - *lineptr = new_lineptr; - } - - for (;;) - { - int i; - - i = getc_maybe_unlocked (fp); - if (i == EOF) - { - result = -1; - break; - } - - /* Make enough space for len+1 (for final NUL) bytes. */ - if (cur_len + 1 >= *n) - { - size_t needed_max = - SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; - size_t needed = 2 * *n + 1; /* Be generous. */ - char *new_lineptr; - - if (needed_max < needed) - needed = needed_max; - if (cur_len + 1 >= needed) - { - result = -1; - errno = EOVERFLOW; - goto unlock_return; - } - - new_lineptr = (char *) realloc (*lineptr, needed); - if (new_lineptr == NULL) - { - result = -1; - goto unlock_return; - } - - *lineptr = new_lineptr; - *n = needed; - } - - (*lineptr)[cur_len] = i; - cur_len++; - - if (i == delimiter) - break; - } - (*lineptr)[cur_len] = '\0'; - result = cur_len ? cur_len : result; - - unlock_return: - funlockfile (fp); /* doesn't set errno */ - - return result; -} diff --git a/grub-core/gnulib/getline.c b/grub-core/gnulib/getline.c deleted file mode 100644 index 30c076e87..000000000 --- a/grub-core/gnulib/getline.c +++ /dev/null @@ -1,29 +0,0 @@ -/* getline.c --- Implementation of replacement getline function. - Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ - -/* Written by Simon Josefsson. */ - -#include - -#include - -ssize_t -getline (char **lineptr, size_t *n, FILE *stream) -{ - return getdelim (lineptr, n, '\n', stream); -} diff --git a/grub-core/gnulib/getopt.c b/grub-core/gnulib/getopt.c deleted file mode 100644 index 3791f1293..000000000 --- a/grub-core/gnulib/getopt.c +++ /dev/null @@ -1,1192 +0,0 @@ -/* Getopt for GNU. - NOTE: getopt is part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to drepper@gnu.org - before changing it! - Copyright (C) 1987-1996, 1998-2004, 2006, 2008-2010 Free Software - Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef _LIBC -# include -#endif - -#include "getopt.h" - -#include -#include -#include -#include - -#ifdef _LIBC -# include -#else -# include "gettext.h" -# define _(msgid) gettext (msgid) -#endif - -#if defined _LIBC && defined USE_IN_LIBIO -# include -#endif - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As `getopt_long' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Using `getopt' or setting the environment variable POSIXLY_CORRECT - disables permutation. - Then the behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt_int.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* 1003.2 says this must be 1 before any call. */ -int optind = 1; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ - -int optopt = '?'; - -/* Keep a global copy of all internal members of getopt_data. */ - -static struct _getopt_data getopt_data; - - -#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV -extern char *getenv (); -#endif - -#ifdef _LIBC -/* Stored original parameters. - XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ -extern int __libc_argc; -extern char **__libc_argv; - -/* Bash 2.0 gives us an environment variable containing flags - indicating ARGV elements that should not be considered arguments. */ - -# ifdef USE_NONOPTION_FLAGS -/* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; -# endif - -# ifdef USE_NONOPTION_FLAGS -# define SWAP_FLAGS(ch1, ch2) \ - if (d->__nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -# else -# define SWAP_FLAGS(ch1, ch2) -# endif -#else /* !_LIBC */ -# define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -static void -exchange (char **argv, struct _getopt_data *d) -{ - int bottom = d->__first_nonopt; - int middle = d->__last_nonopt; - int top = d->optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; - else - { - memset (__mempcpy (new_str, __getopt_nonoption_flags, - d->__nonoption_flags_max_len), - '\0', top + 1 - d->__nonoption_flags_max_len); - d->__nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } - } -#endif - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - d->__first_nonopt += (d->optind - d->__last_nonopt); - d->__last_nonopt = d->optind; -} - -/* Initialize the internal data when the first call is made. */ - -static const char * -_getopt_initialize (int argc _GL_UNUSED, - char **argv _GL_UNUSED, const char *optstring, - struct _getopt_data *d, int posixly_correct) -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - d->__first_nonopt = d->__last_nonopt = d->optind; - - d->__nextchar = NULL; - - d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - d->__ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - d->__ordering = REQUIRE_ORDER; - ++optstring; - } - else if (d->__posixly_correct) - d->__ordering = REQUIRE_ORDER; - else - d->__ordering = PERMUTE; - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - if (!d->__posixly_correct - && argc == __libc_argc && argv == __libc_argv) - { - if (d->__nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - d->__nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = d->__nonoption_flags_max_len = strlen (orig_str); - if (d->__nonoption_flags_max_len < argc) - d->__nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (d->__nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - d->__nonoption_flags_max_len = -1; - else - memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', d->__nonoption_flags_max_len - len); - } - } - d->__nonoption_flags_len = d->__nonoption_flags_max_len; - } - else - d->__nonoption_flags_len = 0; -#endif - - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns -1. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ - -int -_getopt_internal_r (int argc, char **argv, const char *optstring, - const struct option *longopts, int *longind, - int long_only, struct _getopt_data *d, int posixly_correct) -{ - int print_errors = d->opterr; - - if (argc < 1) - return -1; - - d->optarg = NULL; - - if (d->optind == 0 || !d->__initialized) - { - if (d->optind == 0) - d->optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring, d, - posixly_correct); - d->__initialized = 1; - } - else if (optstring[0] == '-' || optstring[0] == '+') - optstring++; - if (optstring[0] == ':') - print_errors = 0; - - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ -#if defined _LIBC && defined USE_NONOPTION_FLAGS -# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ - || (d->optind < d->__nonoption_flags_len \ - && __getopt_nonoption_flags[d->optind] == '1')) -#else -# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') -#endif - - if (d->__nextchar == NULL || *d->__nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (d->__last_nonopt > d->optind) - d->__last_nonopt = d->optind; - if (d->__first_nonopt > d->optind) - d->__first_nonopt = d->optind; - - if (d->__ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (d->__first_nonopt != d->__last_nonopt - && d->__last_nonopt != d->optind) - exchange ((char **) argv, d); - else if (d->__last_nonopt != d->optind) - d->__first_nonopt = d->optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (d->optind < argc && NONOPTION_P) - d->optind++; - d->__last_nonopt = d->optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (d->optind != argc && !strcmp (argv[d->optind], "--")) - { - d->optind++; - - if (d->__first_nonopt != d->__last_nonopt - && d->__last_nonopt != d->optind) - exchange ((char **) argv, d); - else if (d->__first_nonopt == d->__last_nonopt) - d->__first_nonopt = d->optind; - d->__last_nonopt = argc; - - d->optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (d->optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (d->__first_nonopt != d->__last_nonopt) - d->optind = d->__first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (d->__ordering == REQUIRE_ORDER) - return -1; - d->optarg = argv[d->optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - d->__nextchar = (argv[d->optind] + 1 - + (longopts != NULL && argv[d->optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[d->optind][1] == '-' - || (long_only && (argv[d->optind][2] - || !strchr (optstring, argv[d->optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) - { - if ((unsigned int) (nameend - d->__nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else if (long_only - || pfound->has_arg != p->has_arg - || pfound->flag != p->flag - || pfound->val != p->val) - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("%s: option '%s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("%s: option '%s' is ambiguous\n"), - argv[0], argv[d->optind]); -#endif - } - d->__nextchar += strlen (d->__nextchar); - d->optind++; - d->optopt = 0; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - d->optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - - if (argv[d->optind - 1][1] == '-') - { - /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("\ -%s: option '--%s' doesn't allow an argument\n"), - argv[0], pfound->name); -#else - fprintf (stderr, _("\ -%s: option '--%s' doesn't allow an argument\n"), - argv[0], pfound->name); -#endif - } - else - { - /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("\ -%s: option '%c%s' doesn't allow an argument\n"), - argv[0], argv[d->optind - 1][0], - pfound->name); -#else - fprintf (stderr, _("\ -%s: option '%c%s' doesn't allow an argument\n"), - argv[0], argv[d->optind - 1][0], - pfound->name); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - - d->__nextchar += strlen (d->__nextchar); - - d->optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option '--%s' requires an argument\n"), - argv[0], pfound->name) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option '--%s' requires an argument\n"), - argv[0], pfound->name); -#endif - } - d->__nextchar += strlen (d->__nextchar); - d->optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - d->__nextchar += strlen (d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[d->optind][1] == '-' - || strchr (optstring, *d->__nextchar) == NULL) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - - if (argv[d->optind][1] == '-') - { - /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: unrecognized option '--%s'\n"), - argv[0], d->__nextchar); -#else - fprintf (stderr, _("%s: unrecognized option '--%s'\n"), - argv[0], d->__nextchar); -#endif - } - else - { - /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: unrecognized option '%c%s'\n"), - argv[0], argv[d->optind][0], d->__nextchar); -#else - fprintf (stderr, _("%s: unrecognized option '%c%s'\n"), - argv[0], argv[d->optind][0], d->__nextchar); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - d->__nextchar = (char *) ""; - d->optind++; - d->optopt = 0; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *d->__nextchar++; - const char *temp = strchr (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*d->__nextchar == '\0') - ++d->optind; - - if (temp == NULL || c == ':' || c == ';') - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: invalid option -- '%c'\n"), - argv[0], c); -#else - fprintf (stderr, _("%s: invalid option -- '%c'\n"), argv[0], c); -#endif - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - d->optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, - _("%s: option requires an argument -- '%c'\n"), - argv[0], c) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option requires an argument -- '%c'\n"), - argv[0], c); -#endif - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `d->optind' once; - increment it again when taking next ARGV-elt as argument. */ - d->optarg = argv[d->optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; - nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) - { - if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else if (long_only - || pfound->has_arg != p->has_arg - || pfound->flag != p->flag - || pfound->val != p->val) - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"), - argv[0], d->optarg) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"), - argv[0], d->optarg); -#endif - } - d->__nextchar += strlen (d->__nextchar); - d->optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option '-W %s' doesn't allow an argument\n"), - argv[0], pfound->name) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("\ -%s: option '-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); -#endif - } - - d->__nextchar += strlen (d->__nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option '-W %s' requires an argument\n"), - argv[0], pfound->name) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("\ -%s: option '-W %s' requires an argument\n"), - argv[0], pfound->name); -#endif - } - d->__nextchar += strlen (d->__nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - else - d->optarg = NULL; - d->__nextchar += strlen (d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - d->__nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else - d->optarg = NULL; - d->__nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option requires an argument -- '%c'\n"), - argv[0], c) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option requires an argument -- '%c'\n"), - argv[0], c); -#endif - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - d->optarg = argv[d->optind++]; - d->__nextchar = NULL; - } - } - return c; - } -} - -int -_getopt_internal (int argc, char **argv, const char *optstring, - const struct option *longopts, int *longind, int long_only, - int posixly_correct) -{ - int result; - - getopt_data.optind = optind; - getopt_data.opterr = opterr; - - result = _getopt_internal_r (argc, argv, optstring, longopts, - longind, long_only, &getopt_data, - posixly_correct); - - optind = getopt_data.optind; - optarg = getopt_data.optarg; - optopt = getopt_data.optopt; - - return result; -} - -/* glibc gets a LSB-compliant getopt. - Standalone applications get a POSIX-compliant getopt. */ -#if _LIBC -enum { POSIXLY_CORRECT = 0 }; -#else -enum { POSIXLY_CORRECT = 1 }; -#endif - -int -getopt (int argc, char *const *argv, const char *optstring) -{ - return _getopt_internal (argc, (char **) argv, optstring, - (const struct option *) 0, - (int *) 0, - 0, POSIXLY_CORRECT); -} - -#ifdef _LIBC -int -__posix_getopt (int argc, char *const *argv, const char *optstring) -{ - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0, 1); -} -#endif - - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -int -main (int argc, char **argv) -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value '%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/grub-core/gnulib/getopt.in.h b/grub-core/gnulib/getopt.in.h deleted file mode 100644 index 57a8e8992..000000000 --- a/grub-core/gnulib/getopt.in.h +++ /dev/null @@ -1,249 +0,0 @@ -/* Declarations for getopt. - Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2007, 2009-2010 Free Software - Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef _GL_GETOPT_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -/* The include_next requires a split double-inclusion guard. We must - also inform the replacement unistd.h to not recursively use - ; our definitions will be present soon enough. */ -#if @HAVE_GETOPT_H@ -# define _GL_SYSTEM_GETOPT -# @INCLUDE_NEXT@ @NEXT_GETOPT_H@ -# undef _GL_SYSTEM_GETOPT -#endif - -#ifndef _GL_GETOPT_H - -#ifndef __need_getopt -# define _GL_GETOPT_H 1 -#endif - -/* Standalone applications should #define __GETOPT_PREFIX to an - identifier that prefixes the external functions and variables - defined in this header. When this happens, include the - headers that might declare getopt so that they will not cause - confusion if included after this file (if the system had , - we have already included it). Then systematically rename - identifiers so that they do not collide with the system functions - and variables. Renaming avoids problems with some compilers and - linkers. */ -#if defined __GETOPT_PREFIX && !defined __need_getopt -# if !@HAVE_GETOPT_H@ -# include -# include -# include -# endif -# undef __need_getopt -# undef getopt -# undef getopt_long -# undef getopt_long_only -# undef optarg -# undef opterr -# undef optind -# undef optopt -# undef option -# define __GETOPT_CONCAT(x, y) x ## y -# define __GETOPT_XCONCAT(x, y) __GETOPT_CONCAT (x, y) -# define __GETOPT_ID(y) __GETOPT_XCONCAT (__GETOPT_PREFIX, y) -# define getopt __GETOPT_ID (getopt) -# define getopt_long __GETOPT_ID (getopt_long) -# define getopt_long_only __GETOPT_ID (getopt_long_only) -# define optarg __GETOPT_ID (optarg) -# define opterr __GETOPT_ID (opterr) -# define optind __GETOPT_ID (optind) -# define optopt __GETOPT_ID (optopt) -# define option __GETOPT_ID (option) -# define _getopt_internal __GETOPT_ID (getopt_internal) -#endif - -/* Standalone applications get correct prototypes for getopt_long and - getopt_long_only; they declare "char **argv". libc uses prototypes - with "char *const *argv" that are incorrect because getopt_long and - getopt_long_only can permute argv; this is required for backward - compatibility (e.g., for LSB 2.0.1). - - This used to be `#if defined __GETOPT_PREFIX && !defined __need_getopt', - but it caused redefinition warnings if both unistd.h and getopt.h were - included, since unistd.h includes getopt.h having previously defined - __need_getopt. - - The only place where __getopt_argv_const is used is in definitions - of getopt_long and getopt_long_only below, but these are visible - only if __need_getopt is not defined, so it is quite safe to rewrite - the conditional as follows: -*/ -#if !defined __need_getopt -# if defined __GETOPT_PREFIX -# define __getopt_argv_const /* empty */ -# else -# define __getopt_argv_const const -# endif -#endif - -/* If __GNU_LIBRARY__ is not already defined, either we are being used - standalone, or this is the first header included in the source file. - If we are being used with glibc, we need to include , but - that does not exist if we are standalone. So: if __GNU_LIBRARY__ is - not defined, include , which will pull in for us - if it's from glibc. (Why ctype.h? It's guaranteed to exist and it - doesn't flood the namespace with stuff the way some other headers do.) */ -#if !defined __GNU_LIBRARY__ -# include -#endif - -#ifndef __THROW -# ifndef __GNUC_PREREQ -# define __GNUC_PREREQ(maj, min) (0) -# endif -# if defined __cplusplus && __GNUC_PREREQ (2,8) -# define __THROW throw () -# else -# define __THROW -# endif -#endif - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -#ifdef __cplusplus -extern "C" { -#endif - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -extern int optind; - -/* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ - -extern int opterr; - -/* Set to an option character which was unrecognized. */ - -extern int optopt; - -#ifndef __need_getopt -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. - - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - -struct option -{ - const char *name; - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; - -/* Names for the values of the `has_arg' field of `struct option'. */ - -# define no_argument 0 -# define required_argument 1 -# define optional_argument 2 -#endif /* need getopt */ - - -/* Get definitions and prototypes for functions to process the - arguments in ARGV (ARGC of them, minus the program name) for - options given in OPTS. - - Return the option character from OPTS just read. Return -1 when - there are no more options. For unrecognized options, or options - missing arguments, `optopt' is set to the option letter, and '?' is - returned. - - The OPTS string is a list of characters which are recognized option - letters, optionally followed by colons, specifying that that letter - takes an argument, to be placed in `optarg'. - - If a letter in OPTS is followed by two colons, its argument is - optional. This behavior is specific to the GNU `getopt'. - - The argument `--' causes premature termination of argument - scanning, explicitly telling `getopt' that there are no more - options. - - If OPTS begins with `-', then non-option arguments are treated as - arguments to the option '\1'. This behavior is specific to the GNU - `getopt'. If OPTS begins with `+', or POSIXLY_CORRECT is set in - the environment, then do not permute arguments. */ - -extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) - __THROW _GL_ARG_NONNULL ((2, 3)); - -#ifndef __need_getopt -extern int getopt_long (int ___argc, char *__getopt_argv_const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind) - __THROW _GL_ARG_NONNULL ((2, 3)); -extern int getopt_long_only (int ___argc, char *__getopt_argv_const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind) - __THROW _GL_ARG_NONNULL ((2, 3)); - -#endif - -#ifdef __cplusplus -} -#endif - -/* Make sure we later can get all the definitions and declarations. */ -#undef __need_getopt - -#endif /* getopt.h */ -#endif /* getopt.h */ diff --git a/grub-core/gnulib/getopt1.c b/grub-core/gnulib/getopt1.c deleted file mode 100644 index 046d69f94..000000000 --- a/grub-core/gnulib/getopt1.c +++ /dev/null @@ -1,170 +0,0 @@ -/* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, - 1998, 2004, 2006, 2009, 2010 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifdef _LIBC -# include -#else -# include -# include "getopt.h" -#endif -#include "getopt_int.h" - -#include - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -#include -#endif - -#ifndef NULL -#define NULL 0 -#endif - -int -getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, - const struct option *long_options, int *opt_index) -{ - return _getopt_internal (argc, (char **) argv, options, long_options, - opt_index, 0, 0); -} - -int -_getopt_long_r (int argc, char **argv, const char *options, - const struct option *long_options, int *opt_index, - struct _getopt_data *d) -{ - return _getopt_internal_r (argc, argv, options, long_options, opt_index, - 0, d, 0); -} - -/* Like getopt_long, but '-' as well as '--' can indicate a long option. - If an option that starts with '-' (not '--') doesn't match a long option, - but does match a short option, it is parsed as a short option - instead. */ - -int -getopt_long_only (int argc, char *__getopt_argv_const *argv, - const char *options, - const struct option *long_options, int *opt_index) -{ - return _getopt_internal (argc, (char **) argv, options, long_options, - opt_index, 1, 0); -} - -int -_getopt_long_only_r (int argc, char **argv, const char *options, - const struct option *long_options, int *opt_index, - struct _getopt_data *d) -{ - return _getopt_internal_r (argc, argv, options, long_options, opt_index, - 1, d, 0); -} - - -#ifdef TEST - -#include - -int -main (int argc, char **argv) -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static const struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case 'd': - printf ("option d with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/grub-core/gnulib/getopt_int.h b/grub-core/gnulib/getopt_int.h deleted file mode 100644 index 980b7507f..000000000 --- a/grub-core/gnulib/getopt_int.h +++ /dev/null @@ -1,135 +0,0 @@ -/* Internal declarations for getopt. - Copyright (C) 1989-1994, 1996-1999, 2001, 2003-2004, 2009-2010 Free Software - Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef _GETOPT_INT_H -#define _GETOPT_INT_H 1 - -#include - -extern int _getopt_internal (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only, int __posixly_correct); - - -/* Reentrant versions which can handle parsing multiple argument - vectors at the same time. */ - -/* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters, or by calling getopt. - - PERMUTE is the default. We permute the contents of ARGV as we - scan, so that eventually all the non-options are at the end. - This allows options to be given in any order, even with programs - that were not written to expect this. - - RETURN_IN_ORDER is an option available to programs that were - written to expect options and other ARGV-elements in any order - and that care about the ordering of the two. We describe each - non-option ARGV-element as if it were the argument of an option - with character code 1. Using `-' as the first character of the - list of option characters selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - -enum __ord - { - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER - }; - -/* Data type for reentrant functions. */ -struct _getopt_data -{ - /* These have exactly the same meaning as the corresponding global - variables, except that they are used for the reentrant - versions of getopt. */ - int optind; - int opterr; - int optopt; - char *optarg; - - /* Internal members. */ - - /* True if the internal members have been initialized. */ - int __initialized; - - /* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - char *__nextchar; - - /* See __ord above. */ - enum __ord __ordering; - - /* If the POSIXLY_CORRECT environment variable is set - or getopt was called. */ - int __posixly_correct; - - - /* Handle permutation of arguments. */ - - /* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first - of them; `last_nonopt' is the index after the last of them. */ - - int __first_nonopt; - int __last_nonopt; - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - int __nonoption_flags_max_len; - int __nonoption_flags_len; -# endif -}; - -/* The initializer is necessary to set OPTIND and OPTERR to their - default values and to clear the initialization flag. */ -#define _GETOPT_DATA_INITIALIZER { 1, 1 } - -extern int _getopt_internal_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only, struct _getopt_data *__data, - int __posixly_correct); - -extern int _getopt_long_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - struct _getopt_data *__data); - -extern int _getopt_long_only_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, - int *__longind, - struct _getopt_data *__data); - -#endif /* getopt_int.h */ diff --git a/grub-core/gnulib/gettext.h b/grub-core/gnulib/gettext.h deleted file mode 100644 index 881ae3304..000000000 --- a/grub-core/gnulib/gettext.h +++ /dev/null @@ -1,280 +0,0 @@ -/* Convenience header for conditional use of GNU . - Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2010 Free Software - Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _LIBGETTEXT_H -#define _LIBGETTEXT_H 1 - -/* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS - -/* Get declarations of GNU message catalog functions. */ -# include - -/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by - the gettext() and ngettext() macros. This is an alternative to calling - textdomain(), and is useful for libraries. */ -# ifdef DEFAULT_TEXT_DOMAIN -# undef gettext -# define gettext(Msgid) \ - dgettext (DEFAULT_TEXT_DOMAIN, Msgid) -# undef ngettext -# define ngettext(Msgid1, Msgid2, N) \ - dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) -# endif - -#else - -/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which - chokes if dcgettext is defined as a macro. So include it now, to make - later inclusions of a NOP. We don't include - as well because people using "gettext.h" will not include , - and also including would fail on SunOS 4, whereas - is OK. */ -#if defined(__sun) -# include -#endif - -/* Many header files from the libstdc++ coming with g++ 3.3 or newer include - , which chokes if dcgettext is defined as a macro. So include - it now, to make later inclusions of a NOP. */ -#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) -# include -# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H -# include -# endif -#endif - -/* Disabled NLS. - The casts to 'const char *' serve the purpose of producing warnings - for invalid uses of the value returned from these functions. - On pre-ANSI systems without 'const', the config.h file is supposed to - contain "#define const". */ -# undef gettext -# define gettext(Msgid) ((const char *) (Msgid)) -# undef dgettext -# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) -# undef dcgettext -# define dcgettext(Domainname, Msgid, Category) \ - ((void) (Category), dgettext (Domainname, Msgid)) -# undef ngettext -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 \ - ? ((void) (Msgid2), (const char *) (Msgid1)) \ - : ((void) (Msgid1), (const char *) (Msgid2))) -# undef dngettext -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) -# undef dcngettext -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N)) -# undef textdomain -# define textdomain(Domainname) ((const char *) (Domainname)) -# undef bindtextdomain -# define bindtextdomain(Domainname, Dirname) \ - ((void) (Domainname), (const char *) (Dirname)) -# undef bind_textdomain_codeset -# define bind_textdomain_codeset(Domainname, Codeset) \ - ((void) (Domainname), (const char *) (Codeset)) - -#endif - -/* A pseudo function call that serves as a marker for the automated - extraction of messages, but does not call gettext(). The run-time - translation is done at a different place in the code. - The argument, String, should be a literal string. Concatenated strings - and other string expressions won't work. - The macro's expansion is not parenthesized, so that it is suitable as - initializer for static 'char[]' or 'const char[]' variables. */ -#define gettext_noop(String) String - -/* The separator between msgctxt and msgid in a .mo file. */ -#define GETTEXT_CONTEXT_GLUE "\004" - -/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a - MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be - short and rarely need to change. - The letter 'p' stands for 'particular' or 'special'. */ -#ifdef DEFAULT_TEXT_DOMAIN -# define pgettext(Msgctxt, Msgid) \ - pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#else -# define pgettext(Msgctxt, Msgid) \ - pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#endif -#define dpgettext(Domainname, Msgctxt, Msgid) \ - pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ - pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) -#ifdef DEFAULT_TEXT_DOMAIN -# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#else -# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#endif -#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ - npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -pgettext_aux (const char *domain, - const char *msg_ctxt_id, const char *msgid, - int category) -{ - const char *translation = dcgettext (domain, msg_ctxt_id, category); - if (translation == msg_ctxt_id) - return msgid; - else - return translation; -} - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -npgettext_aux (const char *domain, - const char *msg_ctxt_id, const char *msgid, - const char *msgid_plural, unsigned long int n, - int category) -{ - const char *translation = - dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); - if (translation == msg_ctxt_id || translation == msgid_plural) - return (n == 1 ? msgid : msgid_plural); - else - return translation; -} - -/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID - can be arbitrary expressions. But for string literals these macros are - less efficient than those above. */ - -#include - -#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ - (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \ - /* || __STDC_VERSION__ >= 199901L */ ) - -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS -#include -#endif - -#define pgettext_expr(Msgctxt, Msgid) \ - dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) -#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ - dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -dcpgettext_expr (const char *domain, - const char *msgctxt, const char *msgid, - int category) -{ - size_t msgctxt_len = strlen (msgctxt) + 1; - size_t msgid_len = strlen (msgid) + 1; - const char *translation; -#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - char msg_ctxt_id[msgctxt_len + msgid_len]; -#else - char buf[1024]; - char *msg_ctxt_id = - (msgctxt_len + msgid_len <= sizeof (buf) - ? buf - : (char *) malloc (msgctxt_len + msgid_len)); - if (msg_ctxt_id != NULL) -#endif - { - memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); - msg_ctxt_id[msgctxt_len - 1] = '\004'; - memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); - translation = dcgettext (domain, msg_ctxt_id, category); -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - if (msg_ctxt_id != buf) - free (msg_ctxt_id); -#endif - if (translation != msg_ctxt_id) - return translation; - } - return msgid; -} - -#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ - dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) -#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ - dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -dcnpgettext_expr (const char *domain, - const char *msgctxt, const char *msgid, - const char *msgid_plural, unsigned long int n, - int category) -{ - size_t msgctxt_len = strlen (msgctxt) + 1; - size_t msgid_len = strlen (msgid) + 1; - const char *translation; -#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - char msg_ctxt_id[msgctxt_len + msgid_len]; -#else - char buf[1024]; - char *msg_ctxt_id = - (msgctxt_len + msgid_len <= sizeof (buf) - ? buf - : (char *) malloc (msgctxt_len + msgid_len)); - if (msg_ctxt_id != NULL) -#endif - { - memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); - msg_ctxt_id[msgctxt_len - 1] = '\004'; - memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); - translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - if (msg_ctxt_id != buf) - free (msg_ctxt_id); -#endif - if (!(translation == msg_ctxt_id || translation == msgid_plural)) - return translation; - } - return (n == 1 ? msgid : msgid_plural); -} - -#endif /* _LIBGETTEXT_H */ diff --git a/grub-core/gnulib/intprops.h b/grub-core/gnulib/intprops.h deleted file mode 100644 index 46f4d47d7..000000000 --- a/grub-core/gnulib/intprops.h +++ /dev/null @@ -1,83 +0,0 @@ -/* intprops.h -- properties of integer types - - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2009, 2010 Free Software - Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* Written by Paul Eggert. */ - -#ifndef GL_INTPROPS_H -# define GL_INTPROPS_H - -# include - -/* The extra casts in the following macros work around compiler bugs, - e.g., in Cray C 5.0.3.0. */ - -/* True if the arithmetic type T is an integer type. bool counts as - an integer. */ -# define TYPE_IS_INTEGER(t) ((t) 1.5 == 1) - -/* True if negative values of the signed integer type T use two's - complement, ones' complement, or signed magnitude representation, - respectively. Much GNU code assumes two's complement, but some - people like to be portable to all possible C hosts. */ -# define TYPE_TWOS_COMPLEMENT(t) ((t) ~ (t) 0 == (t) -1) -# define TYPE_ONES_COMPLEMENT(t) ((t) ~ (t) 0 == 0) -# define TYPE_SIGNED_MAGNITUDE(t) ((t) ~ (t) 0 < (t) -1) - -/* True if the arithmetic type T is signed. */ -# define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) - -/* The maximum and minimum values for the integer type T. These - macros have undefined behavior if T is signed and has padding bits. - If this is a problem for you, please let us know how to fix it for - your host. */ -# define TYPE_MINIMUM(t) \ - ((t) (! TYPE_SIGNED (t) \ - ? (t) 0 \ - : TYPE_SIGNED_MAGNITUDE (t) \ - ? ~ (t) 0 \ - : ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1))) -# define TYPE_MAXIMUM(t) \ - ((t) (! TYPE_SIGNED (t) \ - ? (t) -1 \ - : ~ (~ (t) 0 << (sizeof (t) * CHAR_BIT - 1)))) - -/* Return zero if T can be determined to be an unsigned type. - Otherwise, return 1. - When compiling with GCC, INT_STRLEN_BOUND uses this macro to obtain a - tighter bound. Otherwise, it overestimates the true bound by one byte - when applied to unsigned types of size 2, 4, 16, ... bytes. - The symbol signed_type_or_expr__ is private to this header file. */ -# if __GNUC__ >= 2 -# define signed_type_or_expr__(t) TYPE_SIGNED (__typeof__ (t)) -# else -# define signed_type_or_expr__(t) 1 -# endif - -/* Bound on length of the string representing an integer type or expression T. - Subtract 1 for the sign bit if T is signed; log10 (2.0) < 146/485; - add 1 for integer division truncation; add 1 more for a minus sign - if needed. */ -# define INT_STRLEN_BOUND(t) \ - ((sizeof (t) * CHAR_BIT - signed_type_or_expr__ (t)) * 146 / 485 \ - + signed_type_or_expr__ (t) + 1) - -/* Bound on buffer size needed to represent an integer type or expression T, - including the terminating null. */ -# define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) - -#endif /* GL_INTPROPS_H */ diff --git a/grub-core/gnulib/langinfo.in.h b/grub-core/gnulib/langinfo.in.h deleted file mode 100644 index 3a92647b9..000000000 --- a/grub-core/gnulib/langinfo.in.h +++ /dev/null @@ -1,173 +0,0 @@ -/* Substitute for and wrapper around . - Copyright (C) 2009, 2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* - * POSIX for platforms that lack it or have an incomplete one. - * - */ - -#ifndef _GL_LANGINFO_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -/* The include_next requires a split double-inclusion guard. */ -#if @HAVE_LANGINFO_H@ -# @INCLUDE_NEXT@ @NEXT_LANGINFO_H@ -#endif - -#ifndef _GL_LANGINFO_H -#define _GL_LANGINFO_H - - -#if !@HAVE_LANGINFO_H@ - -/* A platform that lacks . */ - -/* Assume that it also lacks and the nl_item type. */ -typedef int nl_item; - -/* nl_langinfo items of the LC_CTYPE category */ -# define CODESET 10000 -/* nl_langinfo items of the LC_NUMERIC category */ -# define RADIXCHAR 10001 -# define THOUSEP 10002 -/* nl_langinfo items of the LC_TIME category */ -# define D_T_FMT 10003 -# define D_FMT 10004 -# define T_FMT 10005 -# define T_FMT_AMPM 10006 -# define AM_STR 10007 -# define PM_STR 10008 -# define DAY_1 10009 -# define DAY_2 (DAY_1 + 1) -# define DAY_3 (DAY_1 + 2) -# define DAY_4 (DAY_1 + 3) -# define DAY_5 (DAY_1 + 4) -# define DAY_6 (DAY_1 + 5) -# define DAY_7 (DAY_1 + 6) -# define ABDAY_1 10016 -# define ABDAY_2 (ABDAY_1 + 1) -# define ABDAY_3 (ABDAY_1 + 2) -# define ABDAY_4 (ABDAY_1 + 3) -# define ABDAY_5 (ABDAY_1 + 4) -# define ABDAY_6 (ABDAY_1 + 5) -# define ABDAY_7 (ABDAY_1 + 6) -# define MON_1 10023 -# define MON_2 (MON_1 + 1) -# define MON_3 (MON_1 + 2) -# define MON_4 (MON_1 + 3) -# define MON_5 (MON_1 + 4) -# define MON_6 (MON_1 + 5) -# define MON_7 (MON_1 + 6) -# define MON_8 (MON_1 + 7) -# define MON_9 (MON_1 + 8) -# define MON_10 (MON_1 + 9) -# define MON_11 (MON_1 + 10) -# define MON_12 (MON_1 + 11) -# define ABMON_1 10035 -# define ABMON_2 (ABMON_1 + 1) -# define ABMON_3 (ABMON_1 + 2) -# define ABMON_4 (ABMON_1 + 3) -# define ABMON_5 (ABMON_1 + 4) -# define ABMON_6 (ABMON_1 + 5) -# define ABMON_7 (ABMON_1 + 6) -# define ABMON_8 (ABMON_1 + 7) -# define ABMON_9 (ABMON_1 + 8) -# define ABMON_10 (ABMON_1 + 9) -# define ABMON_11 (ABMON_1 + 10) -# define ABMON_12 (ABMON_1 + 11) -# define ERA 10047 -# define ERA_D_FMT 10048 -# define ERA_D_T_FMT 10049 -# define ERA_T_FMT 10050 -# define ALT_DIGITS 10051 -/* nl_langinfo items of the LC_MONETARY category */ -# define CRNCYSTR 10052 -/* nl_langinfo items of the LC_MESSAGES category */ -# define YESEXPR 10053 -# define NOEXPR 10054 - -#else - -/* A platform that has . */ - -# if !@HAVE_LANGINFO_CODESET@ -# define CODESET 10000 -# define GNULIB_defined_CODESET 1 -# endif - -# if !@HAVE_LANGINFO_T_FMT_AMPM@ -# define T_FMT_AMPM 10006 -# define GNULIB_defined_T_FMT_AMPM 1 -# endif - -# if !@HAVE_LANGINFO_ERA@ -# define ERA 10047 -# define ERA_D_FMT 10048 -# define ERA_D_T_FMT 10049 -# define ERA_T_FMT 10050 -# define ALT_DIGITS 10051 -# define GNULIB_defined_ERA 1 -# endif - -# if !@HAVE_LANGINFO_YESEXPR@ -# define YESEXPR 10053 -# define NOEXPR 10054 -# define GNULIB_defined_YESEXPR 1 -# endif - -#endif - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - -/* Declare overridden functions. */ - - -/* Return a piece of locale dependent information. - Note: The difference between nl_langinfo (CODESET) and locale_charset () - is that the latter normalizes the encoding names to GNU conventions. */ - -#if @GNULIB_NL_LANGINFO@ -# if @REPLACE_NL_LANGINFO@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef nl_langinfo -# define nl_langinfo rpl_nl_langinfo -# endif -_GL_FUNCDECL_RPL (nl_langinfo, char *, (nl_item item)); -_GL_CXXALIAS_RPL (nl_langinfo, char *, (nl_item item)); -# else -# if !@HAVE_NL_LANGINFO@ -_GL_FUNCDECL_SYS (nl_langinfo, char *, (nl_item item)); -# endif -_GL_CXXALIAS_SYS (nl_langinfo, char *, (nl_item item)); -# endif -_GL_CXXALIASWARN (nl_langinfo); -#elif defined GNULIB_POSIXCHECK -# undef nl_langinfo -# if HAVE_RAW_DECL_NL_LANGINFO -_GL_WARN_ON_USE (nl_langinfo, "nl_langinfo is not portable - " - "use gnulib module nl_langinfo for portability"); -# endif -#endif - - -#endif /* _GL_LANGINFO_H */ -#endif /* _GL_LANGINFO_H */ diff --git a/grub-core/gnulib/localcharset.c b/grub-core/gnulib/localcharset.c deleted file mode 100644 index fa2207fe1..000000000 --- a/grub-core/gnulib/localcharset.c +++ /dev/null @@ -1,548 +0,0 @@ -/* Determine a canonical name for the current locale's character encoding. - - Copyright (C) 2000-2006, 2008-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Bruno Haible . */ - -#include - -/* Specification. */ -#include "localcharset.h" - -#include -#include -#include -#include -#include - -#if defined __APPLE__ && defined __MACH__ && HAVE_LANGINFO_CODESET -# define DARWIN7 /* Darwin 7 or newer, i.e. MacOS X 10.3 or newer */ -#endif - -#if defined _WIN32 || defined __WIN32__ -# define WIN32_NATIVE -#endif - -#if defined __EMX__ -/* Assume EMX program runs on OS/2, even if compiled under DOS. */ -# ifndef OS2 -# define OS2 -# endif -#endif - -#if !defined WIN32_NATIVE -# include -# if HAVE_LANGINFO_CODESET -# include -# else -# if 0 /* see comment below */ -# include -# endif -# endif -# ifdef __CYGWIN__ -# define WIN32_LEAN_AND_MEAN -# include -# endif -#elif defined WIN32_NATIVE -# define WIN32_LEAN_AND_MEAN -# include -#endif -#if defined OS2 -# define INCL_DOS -# include -#endif - -#if ENABLE_RELOCATABLE -# include "relocatable.h" -#else -# define relocate(pathname) (pathname) -#endif - -/* Get LIBDIR. */ -#ifndef LIBDIR -# include "configmake.h" -#endif - -/* Define O_NOFOLLOW to 0 on platforms where it does not exist. */ -#ifndef O_NOFOLLOW -# define O_NOFOLLOW 0 -#endif - -#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ - /* Win32, Cygwin, OS/2, DOS */ -# define ISSLASH(C) ((C) == '/' || (C) == '\\') -#endif - -#ifndef DIRECTORY_SEPARATOR -# define DIRECTORY_SEPARATOR '/' -#endif - -#ifndef ISSLASH -# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) -#endif - -#if HAVE_DECL_GETC_UNLOCKED -# undef getc -# define getc getc_unlocked -#endif - -/* The following static variable is declared 'volatile' to avoid a - possible multithread problem in the function get_charset_aliases. If we - are running in a threaded environment, and if two threads initialize - 'charset_aliases' simultaneously, both will produce the same value, - and everything will be ok if the two assignments to 'charset_aliases' - are atomic. But I don't know what will happen if the two assignments mix. */ -#if __STDC__ != 1 -# define volatile /* empty */ -#endif -/* Pointer to the contents of the charset.alias file, if it has already been - read, else NULL. Its format is: - ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */ -static const char * volatile charset_aliases; - -/* Return a pointer to the contents of the charset.alias file. */ -static const char * -get_charset_aliases (void) -{ - const char *cp; - - cp = charset_aliases; - if (cp == NULL) - { -#if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__) - const char *dir; - const char *base = "charset.alias"; - char *file_name; - - /* Make it possible to override the charset.alias location. This is - necessary for running the testsuite before "make install". */ - dir = getenv ("CHARSETALIASDIR"); - if (dir == NULL || dir[0] == '\0') - dir = relocate (LIBDIR); - - /* Concatenate dir and base into freshly allocated file_name. */ - { - size_t dir_len = strlen (dir); - size_t base_len = strlen (base); - int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); - file_name = (char *) malloc (dir_len + add_slash + base_len + 1); - if (file_name != NULL) - { - memcpy (file_name, dir, dir_len); - if (add_slash) - file_name[dir_len] = DIRECTORY_SEPARATOR; - memcpy (file_name + dir_len + add_slash, base, base_len + 1); - } - } - - if (file_name == NULL) - /* Out of memory. Treat the file as empty. */ - cp = ""; - else - { - int fd; - - /* Open the file. Reject symbolic links on platforms that support - O_NOFOLLOW. This is a security feature. Without it, an attacker - could retrieve parts of the contents (namely, the tail of the - first line that starts with "* ") of an arbitrary file by placing - a symbolic link to that file under the name "charset.alias" in - some writable directory and defining the environment variable - CHARSETALIASDIR to point to that directory. */ - fd = open (file_name, - O_RDONLY | (HAVE_WORKING_O_NOFOLLOW ? O_NOFOLLOW : 0)); - if (fd < 0) - /* File not found. Treat it as empty. */ - cp = ""; - else - { - FILE *fp; - - fp = fdopen (fd, "r"); - if (fp == NULL) - { - /* Out of memory. Treat the file as empty. */ - close (fd); - cp = ""; - } - else - { - /* Parse the file's contents. */ - char *res_ptr = NULL; - size_t res_size = 0; - - for (;;) - { - int c; - char buf1[50+1]; - char buf2[50+1]; - size_t l1, l2; - char *old_res_ptr; - - c = getc (fp); - if (c == EOF) - break; - if (c == '\n' || c == ' ' || c == '\t') - continue; - if (c == '#') - { - /* Skip comment, to end of line. */ - do - c = getc (fp); - while (!(c == EOF || c == '\n')); - if (c == EOF) - break; - continue; - } - ungetc (c, fp); - if (fscanf (fp, "%50s %50s", buf1, buf2) < 2) - break; - l1 = strlen (buf1); - l2 = strlen (buf2); - old_res_ptr = res_ptr; - if (res_size == 0) - { - res_size = l1 + 1 + l2 + 1; - res_ptr = (char *) malloc (res_size + 1); - } - else - { - res_size += l1 + 1 + l2 + 1; - res_ptr = (char *) realloc (res_ptr, res_size + 1); - } - if (res_ptr == NULL) - { - /* Out of memory. */ - res_size = 0; - if (old_res_ptr != NULL) - free (old_res_ptr); - break; - } - strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1); - strcpy (res_ptr + res_size - (l2 + 1), buf2); - } - fclose (fp); - if (res_size == 0) - cp = ""; - else - { - *(res_ptr + res_size) = '\0'; - cp = res_ptr; - } - } - } - - free (file_name); - } - -#else - -# if defined DARWIN7 - /* To avoid the trouble of installing a file that is shared by many - GNU packages -- many packaging systems have problems with this --, - simply inline the aliases here. */ - cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" - "ISO8859-2" "\0" "ISO-8859-2" "\0" - "ISO8859-4" "\0" "ISO-8859-4" "\0" - "ISO8859-5" "\0" "ISO-8859-5" "\0" - "ISO8859-7" "\0" "ISO-8859-7" "\0" - "ISO8859-9" "\0" "ISO-8859-9" "\0" - "ISO8859-13" "\0" "ISO-8859-13" "\0" - "ISO8859-15" "\0" "ISO-8859-15" "\0" - "KOI8-R" "\0" "KOI8-R" "\0" - "KOI8-U" "\0" "KOI8-U" "\0" - "CP866" "\0" "CP866" "\0" - "CP949" "\0" "CP949" "\0" - "CP1131" "\0" "CP1131" "\0" - "CP1251" "\0" "CP1251" "\0" - "eucCN" "\0" "GB2312" "\0" - "GB2312" "\0" "GB2312" "\0" - "eucJP" "\0" "EUC-JP" "\0" - "eucKR" "\0" "EUC-KR" "\0" - "Big5" "\0" "BIG5" "\0" - "Big5HKSCS" "\0" "BIG5-HKSCS" "\0" - "GBK" "\0" "GBK" "\0" - "GB18030" "\0" "GB18030" "\0" - "SJIS" "\0" "SHIFT_JIS" "\0" - "ARMSCII-8" "\0" "ARMSCII-8" "\0" - "PT154" "\0" "PT154" "\0" - /*"ISCII-DEV" "\0" "?" "\0"*/ - "*" "\0" "UTF-8" "\0"; -# endif - -# if defined VMS - /* To avoid the troubles of an extra file charset.alias_vms in the - sources of many GNU packages, simply inline the aliases here. */ - /* The list of encodings is taken from the OpenVMS 7.3-1 documentation - "Compaq C Run-Time Library Reference Manual for OpenVMS systems" - section 10.7 "Handling Different Character Sets". */ - cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" - "ISO8859-2" "\0" "ISO-8859-2" "\0" - "ISO8859-5" "\0" "ISO-8859-5" "\0" - "ISO8859-7" "\0" "ISO-8859-7" "\0" - "ISO8859-8" "\0" "ISO-8859-8" "\0" - "ISO8859-9" "\0" "ISO-8859-9" "\0" - /* Japanese */ - "eucJP" "\0" "EUC-JP" "\0" - "SJIS" "\0" "SHIFT_JIS" "\0" - "DECKANJI" "\0" "DEC-KANJI" "\0" - "SDECKANJI" "\0" "EUC-JP" "\0" - /* Chinese */ - "eucTW" "\0" "EUC-TW" "\0" - "DECHANYU" "\0" "DEC-HANYU" "\0" - "DECHANZI" "\0" "GB2312" "\0" - /* Korean */ - "DECKOREAN" "\0" "EUC-KR" "\0"; -# endif - -# if defined WIN32_NATIVE || defined __CYGWIN__ - /* To avoid the troubles of installing a separate file in the same - directory as the DLL and of retrieving the DLL's directory at - runtime, simply inline the aliases here. */ - - cp = "CP936" "\0" "GBK" "\0" - "CP1361" "\0" "JOHAB" "\0" - "CP20127" "\0" "ASCII" "\0" - "CP20866" "\0" "KOI8-R" "\0" - "CP20936" "\0" "GB2312" "\0" - "CP21866" "\0" "KOI8-RU" "\0" - "CP28591" "\0" "ISO-8859-1" "\0" - "CP28592" "\0" "ISO-8859-2" "\0" - "CP28593" "\0" "ISO-8859-3" "\0" - "CP28594" "\0" "ISO-8859-4" "\0" - "CP28595" "\0" "ISO-8859-5" "\0" - "CP28596" "\0" "ISO-8859-6" "\0" - "CP28597" "\0" "ISO-8859-7" "\0" - "CP28598" "\0" "ISO-8859-8" "\0" - "CP28599" "\0" "ISO-8859-9" "\0" - "CP28605" "\0" "ISO-8859-15" "\0" - "CP38598" "\0" "ISO-8859-8" "\0" - "CP51932" "\0" "EUC-JP" "\0" - "CP51936" "\0" "GB2312" "\0" - "CP51949" "\0" "EUC-KR" "\0" - "CP51950" "\0" "EUC-TW" "\0" - "CP54936" "\0" "GB18030" "\0" - "CP65001" "\0" "UTF-8" "\0"; -# endif -#endif - - charset_aliases = cp; - } - - return cp; -} - -/* Determine the current locale's character encoding, and canonicalize it - into one of the canonical names listed in config.charset. - The result must not be freed; it is statically allocated. - If the canonical name cannot be determined, the result is a non-canonical - name. */ - -#ifdef STATIC -STATIC -#endif -const char * -locale_charset (void) -{ - const char *codeset; - const char *aliases; - -#if !(defined WIN32_NATIVE || defined OS2) - -# if HAVE_LANGINFO_CODESET - - /* Most systems support nl_langinfo (CODESET) nowadays. */ - codeset = nl_langinfo (CODESET); - -# ifdef __CYGWIN__ - /* Cygwin < 1.7 does not have locales. nl_langinfo (CODESET) always - returns "US-ASCII". Return the suffix of the locale name from the - environment variables (if present) or the codepage as a number. */ - if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0) - { - const char *locale; - static char buf[2 + 10 + 1]; - - locale = getenv ("LC_ALL"); - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_CTYPE"); - if (locale == NULL || locale[0] == '\0') - locale = getenv ("LANG"); - } - if (locale != NULL && locale[0] != '\0') - { - /* If the locale name contains an encoding after the dot, return - it. */ - const char *dot = strchr (locale, '.'); - - if (dot != NULL) - { - const char *modifier; - - dot++; - /* Look for the possible @... trailer and remove it, if any. */ - modifier = strchr (dot, '@'); - if (modifier == NULL) - return dot; - if (modifier - dot < sizeof (buf)) - { - memcpy (buf, dot, modifier - dot); - buf [modifier - dot] = '\0'; - return buf; - } - } - } - - /* Woe32 has a function returning the locale's codepage as a number: - GetACP(). This encoding is used by Cygwin, unless the user has set - the environment variable CYGWIN=codepage:oem (which very few people - do). - Output directed to console windows needs to be converted (to - GetOEMCP() if the console is using a raster font, or to - GetConsoleOutputCP() if it is using a TrueType font). Cygwin does - this conversion transparently (see winsup/cygwin/fhandler_console.cc), - converting to GetConsoleOutputCP(). This leads to correct results, - except when SetConsoleOutputCP has been called and a raster font is - in use. */ - sprintf (buf, "CP%u", GetACP ()); - codeset = buf; - } -# endif - -# else - - /* On old systems which lack it, use setlocale or getenv. */ - const char *locale = NULL; - - /* But most old systems don't have a complete set of locales. Some - (like SunOS 4 or DJGPP) have only the C locale. Therefore we don't - use setlocale here; it would return "C" when it doesn't support the - locale name the user has set. */ -# if 0 - locale = setlocale (LC_CTYPE, NULL); -# endif - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_ALL"); - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_CTYPE"); - if (locale == NULL || locale[0] == '\0') - locale = getenv ("LANG"); - } - } - - /* On some old systems, one used to set locale = "iso8859_1". On others, - you set it to "language_COUNTRY.charset". In any case, we resolve it - through the charset.alias file. */ - codeset = locale; - -# endif - -#elif defined WIN32_NATIVE - - static char buf[2 + 10 + 1]; - - /* Woe32 has a function returning the locale's codepage as a number: - GetACP(). - When the output goes to a console window, it needs to be provided in - GetOEMCP() encoding if the console is using a raster font, or in - GetConsoleOutputCP() encoding if it is using a TrueType font. - But in GUI programs and for output sent to files and pipes, GetACP() - encoding is the best bet. */ - sprintf (buf, "CP%u", GetACP ()); - codeset = buf; - -#elif defined OS2 - - const char *locale; - static char buf[2 + 10 + 1]; - ULONG cp[3]; - ULONG cplen; - - /* Allow user to override the codeset, as set in the operating system, - with standard language environment variables. */ - locale = getenv ("LC_ALL"); - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_CTYPE"); - if (locale == NULL || locale[0] == '\0') - locale = getenv ("LANG"); - } - if (locale != NULL && locale[0] != '\0') - { - /* If the locale name contains an encoding after the dot, return it. */ - const char *dot = strchr (locale, '.'); - - if (dot != NULL) - { - const char *modifier; - - dot++; - /* Look for the possible @... trailer and remove it, if any. */ - modifier = strchr (dot, '@'); - if (modifier == NULL) - return dot; - if (modifier - dot < sizeof (buf)) - { - memcpy (buf, dot, modifier - dot); - buf [modifier - dot] = '\0'; - return buf; - } - } - - /* Resolve through the charset.alias file. */ - codeset = locale; - } - else - { - /* OS/2 has a function returning the locale's codepage as a number. */ - if (DosQueryCp (sizeof (cp), cp, &cplen)) - codeset = ""; - else - { - sprintf (buf, "CP%u", cp[0]); - codeset = buf; - } - } - -#endif - - if (codeset == NULL) - /* The canonical name cannot be determined. */ - codeset = ""; - - /* Resolve alias. */ - for (aliases = get_charset_aliases (); - *aliases != '\0'; - aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) - if (strcmp (codeset, aliases) == 0 - || (aliases[0] == '*' && aliases[1] == '\0')) - { - codeset = aliases + strlen (aliases) + 1; - break; - } - - /* Don't return an empty string. GNU libc and GNU libiconv interpret - the empty string as denoting "the locale's character encoding", - thus GNU libiconv would call this function a second time. */ - if (codeset[0] == '\0') - codeset = "ASCII"; - - return codeset; -} diff --git a/grub-core/gnulib/localcharset.h b/grub-core/gnulib/localcharset.h deleted file mode 100644 index 899b3bae7..000000000 --- a/grub-core/gnulib/localcharset.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Determine a canonical name for the current locale's character encoding. - Copyright (C) 2000-2003, 2009-2010 Free Software Foundation, Inc. - This file is part of the GNU CHARSET Library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _LOCALCHARSET_H -#define _LOCALCHARSET_H - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Determine the current locale's character encoding, and canonicalize it - into one of the canonical names listed in config.charset. - The result must not be freed; it is statically allocated. - If the canonical name cannot be determined, the result is a non-canonical - name. */ -extern const char * locale_charset (void); - - -#ifdef __cplusplus -} -#endif - - -#endif /* _LOCALCHARSET_H */ diff --git a/grub-core/gnulib/malloc.c b/grub-core/gnulib/malloc.c deleted file mode 100644 index 4fa38ee41..000000000 --- a/grub-core/gnulib/malloc.c +++ /dev/null @@ -1,60 +0,0 @@ -/* malloc() function that is glibc compatible. - - Copyright (C) 1997-1998, 2006-2007, 2009-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* written by Jim Meyering and Bruno Haible */ - -#include -/* Only the AC_FUNC_MALLOC macro defines 'malloc' already in config.h. */ -#ifdef malloc -# define NEED_MALLOC_GNU 1 -# undef malloc -/* Whereas the gnulib module 'malloc-gnu' defines HAVE_MALLOC_GNU. */ -#elif GNULIB_MALLOC_GNU && !HAVE_MALLOC_GNU -# define NEED_MALLOC_GNU 1 -#endif - -/* Specification. */ -#include - -#include - -/* Call the system's malloc below. */ -#undef malloc - -/* Allocate an N-byte block of memory from the heap. - If N is zero, allocate a 1-byte block. */ - -void * -rpl_malloc (size_t n) -{ - void *result; - -#if NEED_MALLOC_GNU - if (n == 0) - n = 1; -#endif - - result = malloc (n); - -#if !HAVE_MALLOC_POSIX - if (result == NULL) - errno = ENOMEM; -#endif - - return result; -} diff --git a/grub-core/gnulib/mbrtowc.c b/grub-core/gnulib/mbrtowc.c deleted file mode 100644 index 5c2650e95..000000000 --- a/grub-core/gnulib/mbrtowc.c +++ /dev/null @@ -1,386 +0,0 @@ -/* Convert multibyte character to wide character. - Copyright (C) 1999-2002, 2005-2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -#if GNULIB_defined_mbstate_t -/* Implement mbrtowc() on top of mbtowc(). */ - -# include -# include - -# include "localcharset.h" -# include "streq.h" -# include "verify.h" - - -verify (sizeof (mbstate_t) >= 4); - -static char internal_state[4]; - -size_t -mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) -{ - char *pstate = (char *)ps; - - if (pstate == NULL) - pstate = internal_state; - - if (s == NULL) - { - pwc = NULL; - s = ""; - n = 1; - } - - if (n == 0) - return (size_t)(-2); - - /* Here n > 0. */ - { - size_t nstate = pstate[0]; - char buf[4]; - const char *p; - size_t m; - - switch (nstate) - { - case 0: - p = s; - m = n; - break; - case 3: - buf[2] = pstate[3]; - /*FALLTHROUGH*/ - case 2: - buf[1] = pstate[2]; - /*FALLTHROUGH*/ - case 1: - buf[0] = pstate[1]; - p = buf; - m = nstate; - buf[m++] = s[0]; - if (n >= 2 && m < 4) - { - buf[m++] = s[1]; - if (n >= 3 && m < 4) - buf[m++] = s[2]; - } - break; - default: - errno = EINVAL; - return (size_t)(-1); - } - - /* Here m > 0. */ - -# if __GLIBC__ - /* Work around bug */ - mbtowc (NULL, NULL, 0); -# endif - { - int res = mbtowc (pwc, p, m); - - if (res >= 0) - { - if (pwc != NULL && ((*pwc == 0) != (res == 0))) - abort (); - if (nstate >= (res > 0 ? res : 1)) - abort (); - res -= nstate; - pstate[0] = 0; - return res; - } - - /* mbtowc does not distinguish between invalid and incomplete multibyte - sequences. But mbrtowc needs to make this distinction. - There are two possible approaches: - - Use iconv() and its return value. - - Use built-in knowledge about the possible encodings. - Given the low quality of implementation of iconv() on the systems that - lack mbrtowc(), we use the second approach. - The possible encodings are: - - 8-bit encodings, - - EUC-JP, EUC-KR, GB2312, EUC-TW, BIG5, GB18030, SJIS, - - UTF-8. - Use specialized code for each. */ - if (m >= 4 || m >= MB_CUR_MAX) - goto invalid; - /* Here MB_CUR_MAX > 1 and 0 < m < 4. */ - { - const char *encoding = locale_charset (); - - if (STREQ (encoding, "UTF-8", 'U', 'T', 'F', '-', '8', 0, 0, 0, 0)) - { - /* Cf. unistr/u8-mblen.c. */ - unsigned char c = (unsigned char) p[0]; - - if (c >= 0xc2) - { - if (c < 0xe0) - { - if (m == 1) - goto incomplete; - } - else if (c < 0xf0) - { - if (m == 1) - goto incomplete; - if (m == 2) - { - unsigned char c2 = (unsigned char) p[1]; - - if ((c2 ^ 0x80) < 0x40 - && (c >= 0xe1 || c2 >= 0xa0) - && (c != 0xed || c2 < 0xa0)) - goto incomplete; - } - } - else if (c <= 0xf4) - { - if (m == 1) - goto incomplete; - else /* m == 2 || m == 3 */ - { - unsigned char c2 = (unsigned char) p[1]; - - if ((c2 ^ 0x80) < 0x40 - && (c >= 0xf1 || c2 >= 0x90) - && (c < 0xf4 || (c == 0xf4 && c2 < 0x90))) - { - if (m == 2) - goto incomplete; - else /* m == 3 */ - { - unsigned char c3 = (unsigned char) p[2]; - - if ((c3 ^ 0x80) < 0x40) - goto incomplete; - } - } - } - } - } - goto invalid; - } - - /* As a reference for this code, you can use the GNU libiconv - implementation. Look for uses of the RET_TOOFEW macro. */ - - if (STREQ (encoding, "EUC-JP", 'E', 'U', 'C', '-', 'J', 'P', 0, 0, 0)) - { - if (m == 1) - { - unsigned char c = (unsigned char) p[0]; - - if ((c >= 0xa1 && c < 0xff) || c == 0x8e || c == 0x8f) - goto incomplete; - } - if (m == 2) - { - unsigned char c = (unsigned char) p[0]; - - if (c == 0x8f) - { - unsigned char c2 = (unsigned char) p[1]; - - if (c2 >= 0xa1 && c2 < 0xff) - goto incomplete; - } - } - goto invalid; - } - if (STREQ (encoding, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) - || STREQ (encoding, "GB2312", 'G', 'B', '2', '3', '1', '2', 0, 0, 0) - || STREQ (encoding, "BIG5", 'B', 'I', 'G', '5', 0, 0, 0, 0, 0)) - { - if (m == 1) - { - unsigned char c = (unsigned char) p[0]; - - if (c >= 0xa1 && c < 0xff) - goto incomplete; - } - goto invalid; - } - if (STREQ (encoding, "EUC-TW", 'E', 'U', 'C', '-', 'T', 'W', 0, 0, 0)) - { - if (m == 1) - { - unsigned char c = (unsigned char) p[0]; - - if ((c >= 0xa1 && c < 0xff) || c == 0x8e) - goto incomplete; - } - else /* m == 2 || m == 3 */ - { - unsigned char c = (unsigned char) p[0]; - - if (c == 0x8e) - goto incomplete; - } - goto invalid; - } - if (STREQ (encoding, "GB18030", 'G', 'B', '1', '8', '0', '3', '0', 0, 0)) - { - if (m == 1) - { - unsigned char c = (unsigned char) p[0]; - - if ((c >= 0x90 && c <= 0xe3) || (c >= 0xf8 && c <= 0xfe)) - goto incomplete; - } - else /* m == 2 || m == 3 */ - { - unsigned char c = (unsigned char) p[0]; - - if (c >= 0x90 && c <= 0xe3) - { - unsigned char c2 = (unsigned char) p[1]; - - if (c2 >= 0x30 && c2 <= 0x39) - { - if (m == 2) - goto incomplete; - else /* m == 3 */ - { - unsigned char c3 = (unsigned char) p[2]; - - if (c3 >= 0x81 && c3 <= 0xfe) - goto incomplete; - } - } - } - } - goto invalid; - } - if (STREQ (encoding, "SJIS", 'S', 'J', 'I', 'S', 0, 0, 0, 0, 0)) - { - if (m == 1) - { - unsigned char c = (unsigned char) p[0]; - - if ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xea) - || (c >= 0xf0 && c <= 0xf9)) - goto incomplete; - } - goto invalid; - } - - /* An unknown multibyte encoding. */ - goto incomplete; - } - - incomplete: - { - size_t k = nstate; - /* Here 0 <= k < m < 4. */ - pstate[++k] = s[0]; - if (k < m) - { - pstate[++k] = s[1]; - if (k < m) - pstate[++k] = s[2]; - } - if (k != m) - abort (); - } - pstate[0] = m; - return (size_t)(-2); - - invalid: - errno = EILSEQ; - /* The conversion state is undefined, says POSIX. */ - return (size_t)(-1); - } - } -} - -#else -/* Override the system's mbrtowc() function. */ - -# undef mbrtowc - -size_t -rpl_mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) -{ -# if MBRTOWC_NULL_ARG_BUG || MBRTOWC_RETVAL_BUG - if (s == NULL) - { - pwc = NULL; - s = ""; - n = 1; - } -# endif - -# if MBRTOWC_RETVAL_BUG - { - static mbstate_t internal_state; - - /* Override mbrtowc's internal state. We can not call mbsinit() on the - hidden internal state, but we can call it on our variable. */ - if (ps == NULL) - ps = &internal_state; - - if (!mbsinit (ps)) - { - /* Parse the rest of the multibyte character byte for byte. */ - size_t count = 0; - for (; n > 0; s++, n--) - { - wchar_t wc; - size_t ret = mbrtowc (&wc, s, 1, ps); - - if (ret == (size_t)(-1)) - return (size_t)(-1); - count++; - if (ret != (size_t)(-2)) - { - /* The multibyte character has been completed. */ - if (pwc != NULL) - *pwc = wc; - return (wc == 0 ? 0 : count); - } - } - return (size_t)(-2); - } - } -# endif - -# if MBRTOWC_NUL_RETVAL_BUG - { - wchar_t wc; - size_t ret = mbrtowc (&wc, s, n, ps); - - if (ret != (size_t)(-1) && ret != (size_t)(-2)) - { - if (pwc != NULL) - *pwc = wc; - if (wc == 0) - ret = 0; - } - return ret; - } -# else - return mbrtowc (pwc, s, n, ps); -# endif -} - -#endif diff --git a/grub-core/gnulib/mbsinit.c b/grub-core/gnulib/mbsinit.c deleted file mode 100644 index 066ddfe5b..000000000 --- a/grub-core/gnulib/mbsinit.c +++ /dev/null @@ -1,47 +0,0 @@ -/* Test for initial conversion state. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -#include "verify.h" - -/* Platforms that lack mbsinit() also lack mbrlen(), mbrtowc(), mbsrtowcs() - and wcrtomb(), wcsrtombs(). - We assume that - - sizeof (mbstate_t) >= 4, - - only stateless encodings are supported (such as UTF-8 and EUC-JP, but - not ISO-2022 variants), - - for each encoding, the number of bytes for a wide character is <= 4. - (This maximum is attained for UTF-8, GB18030, EUC-TW.) - We define the meaning of mbstate_t as follows: - - In mb -> wc direction, mbstate_t's first byte contains the number of - buffered bytes (in the range 0..3), followed by up to 3 buffered bytes. - - In wc -> mb direction, mbstate_t contains no information. In other - words, it is always in the initial state. */ - -verify (sizeof (mbstate_t) >= 4); - -int -mbsinit (const mbstate_t *ps) -{ - const char *pstate = (const char *)ps; - - return pstate[0] == 0; -} diff --git a/grub-core/gnulib/mbsrtowcs-state.c b/grub-core/gnulib/mbsrtowcs-state.c deleted file mode 100644 index 35045f657..000000000 --- a/grub-core/gnulib/mbsrtowcs-state.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Convert string to wide string. - Copyright (C) 2008-2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -#include - -/* Internal state used by the functions mbsrtowcs() and mbsnrtowcs(). */ -mbstate_t _gl_mbsrtowcs_state -/* The state must initially be in the "initial state"; so, zero-initialize it. - On most systems, putting it into BSS is sufficient. Not so on MacOS X 10.3, - see . - When it needs an initializer, use 0 or {0} as initializer? 0 only works - when mbstate_t is a scalar type (such as when gnulib defines it, or on - AIX, IRIX, mingw). {0} works as an initializer in all cases: for a struct - or union type, but also for a scalar type (ISO C 99, 6.7.8.(11)). */ -#if defined __ELF__ - /* On ELF systems, variables in BSS behave well. */ -#else - /* Use braces, to be on the safe side. */ - = { 0 } -#endif - ; diff --git a/grub-core/gnulib/mbsrtowcs.c b/grub-core/gnulib/mbsrtowcs.c deleted file mode 100644 index c577f36f2..000000000 --- a/grub-core/gnulib/mbsrtowcs.c +++ /dev/null @@ -1,136 +0,0 @@ -/* Convert string to wide string. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -#include -#include -#include - -#include "strnlen1.h" - - -extern mbstate_t _gl_mbsrtowcs_state; - -size_t -mbsrtowcs (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps) -{ - if (ps == NULL) - ps = &_gl_mbsrtowcs_state; - { - const char *src = *srcp; - - if (dest != NULL) - { - wchar_t *destptr = dest; - - for (; len > 0; destptr++, len--) - { - size_t src_avail; - size_t ret; - - /* An optimized variant of - src_avail = strnlen1 (src, MB_LEN_MAX); */ - if (src[0] == '\0') - src_avail = 1; - else if (src[1] == '\0') - src_avail = 2; - else if (src[2] == '\0') - src_avail = 3; - else if (MB_LEN_MAX <= 4 || src[3] == '\0') - src_avail = 4; - else - src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4); - - /* Parse the next multibyte character. */ - ret = mbrtowc (destptr, src, src_avail, ps); - - if (ret == (size_t)(-2)) - /* Encountered a multibyte character that extends past a '\0' byte - or that is longer than MB_LEN_MAX bytes. Cannot happen. */ - abort (); - - if (ret == (size_t)(-1)) - goto bad_input; - if (ret == 0) - { - src = NULL; - /* Here mbsinit (ps). */ - break; - } - src += ret; - } - - *srcp = src; - return destptr - dest; - } - else - { - /* Ignore dest and len, don't store *srcp at the end, and - don't clobber *ps. */ - mbstate_t state = *ps; - size_t totalcount = 0; - - for (;; totalcount++) - { - size_t src_avail; - size_t ret; - - /* An optimized variant of - src_avail = strnlen1 (src, MB_LEN_MAX); */ - if (src[0] == '\0') - src_avail = 1; - else if (src[1] == '\0') - src_avail = 2; - else if (src[2] == '\0') - src_avail = 3; - else if (MB_LEN_MAX <= 4 || src[3] == '\0') - src_avail = 4; - else - src_avail = 4 + strnlen1 (src + 4, MB_LEN_MAX - 4); - - /* Parse the next multibyte character. */ - ret = mbrtowc (NULL, src, src_avail, &state); - - if (ret == (size_t)(-2)) - /* Encountered a multibyte character that extends past a '\0' byte - or that is longer than MB_LEN_MAX bytes. Cannot happen. */ - abort (); - - if (ret == (size_t)(-1)) - goto bad_input2; - if (ret == 0) - { - /* Here mbsinit (&state). */ - break; - } - src += ret; - } - - return totalcount; - } - - bad_input: - *srcp = src; - bad_input2: - errno = EILSEQ; - return (size_t)(-1); - } -} diff --git a/grub-core/gnulib/memchr.c b/grub-core/gnulib/memchr.c deleted file mode 100644 index 6c2b2d6c7..000000000 --- a/grub-core/gnulib/memchr.c +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright (C) 1991, 1993, 1996-1997, 1999-2000, 2003-2004, 2006, 2008-2010 - Free Software Foundation, Inc. - - Based on strlen implementation by Torbjorn Granlund (tege@sics.se), - with help from Dan Sahlin (dan@sics.se) and - commentary by Jim Blandy (jimb@ai.mit.edu); - adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), - and implemented by Roland McGrath (roland@ai.mit.edu). - -NOTE: The canonical source of this file is maintained with the GNU C Library. -Bugs can be reported to bug-glibc@prep.ai.mit.edu. - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 3 of the License, or any -later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . */ - -#ifndef _LIBC -# include -#endif - -#include - -#include - -#if defined _LIBC -# include -#else -# define reg_char char -#endif - -#include - -#if HAVE_BP_SYM_H || defined _LIBC -# include -#else -# define BP_SYM(sym) sym -#endif - -#undef __memchr -#ifdef _LIBC -# undef memchr -#endif - -#ifndef weak_alias -# define __memchr memchr -#endif - -/* Search no more than N bytes of S for C. */ -void * -__memchr (void const *s, int c_in, size_t n) -{ - /* On 32-bit hardware, choosing longword to be a 32-bit unsigned - long instead of a 64-bit uintmax_t tends to give better - performance. On 64-bit hardware, unsigned long is generally 64 - bits already. Change this typedef to experiment with - performance. */ - typedef unsigned long int longword; - - const unsigned char *char_ptr; - const longword *longword_ptr; - longword repeated_one; - longword repeated_c; - unsigned reg_char c; - - c = (unsigned char) c_in; - - /* Handle the first few bytes by reading one byte at a time. - Do this until CHAR_PTR is aligned on a longword boundary. */ - for (char_ptr = (const unsigned char *) s; - n > 0 && (size_t) char_ptr % sizeof (longword) != 0; - --n, ++char_ptr) - if (*char_ptr == c) - return (void *) char_ptr; - - longword_ptr = (const longword *) char_ptr; - - /* All these elucidatory comments refer to 4-byte longwords, - but the theory applies equally well to any size longwords. */ - - /* Compute auxiliary longword values: - repeated_one is a value which has a 1 in every byte. - repeated_c has c in every byte. */ - repeated_one = 0x01010101; - repeated_c = c | (c << 8); - repeated_c |= repeated_c << 16; - if (0xffffffffU < (longword) -1) - { - repeated_one |= repeated_one << 31 << 1; - repeated_c |= repeated_c << 31 << 1; - if (8 < sizeof (longword)) - { - size_t i; - - for (i = 64; i < sizeof (longword) * 8; i *= 2) - { - repeated_one |= repeated_one << i; - repeated_c |= repeated_c << i; - } - } - } - - /* Instead of the traditional loop which tests each byte, we will test a - longword at a time. The tricky part is testing if *any of the four* - bytes in the longword in question are equal to c. We first use an xor - with repeated_c. This reduces the task to testing whether *any of the - four* bytes in longword1 is zero. - - We compute tmp = - ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). - That is, we perform the following operations: - 1. Subtract repeated_one. - 2. & ~longword1. - 3. & a mask consisting of 0x80 in every byte. - Consider what happens in each byte: - - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, - and step 3 transforms it into 0x80. A carry can also be propagated - to more significant bytes. - - If a byte of longword1 is nonzero, let its lowest 1 bit be at - position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, - the byte ends in a single bit of value 0 and k bits of value 1. - After step 2, the result is just k bits of value 1: 2^k - 1. After - step 3, the result is 0. And no carry is produced. - So, if longword1 has only non-zero bytes, tmp is zero. - Whereas if longword1 has a zero byte, call j the position of the least - significant zero byte. Then the result has a zero at positions 0, ..., - j-1 and a 0x80 at position j. We cannot predict the result at the more - significant bytes (positions j+1..3), but it does not matter since we - already have a non-zero bit at position 8*j+7. - - So, the test whether any byte in longword1 is zero is equivalent to - testing whether tmp is nonzero. */ - - while (n >= sizeof (longword)) - { - longword longword1 = *longword_ptr ^ repeated_c; - - if ((((longword1 - repeated_one) & ~longword1) - & (repeated_one << 7)) != 0) - break; - longword_ptr++; - n -= sizeof (longword); - } - - char_ptr = (const unsigned char *) longword_ptr; - - /* At this point, we know that either n < sizeof (longword), or one of the - sizeof (longword) bytes starting at char_ptr is == c. On little-endian - machines, we could determine the first such byte without any further - memory accesses, just by looking at the tmp result from the last loop - iteration. But this does not work on big-endian machines. Choose code - that works in both cases. */ - - for (; n > 0; --n, ++char_ptr) - { - if (*char_ptr == c) - return (void *) char_ptr; - } - - return NULL; -} -#ifdef weak_alias -weak_alias (__memchr, BP_SYM (memchr)) -#endif diff --git a/grub-core/gnulib/memchr.valgrind b/grub-core/gnulib/memchr.valgrind deleted file mode 100644 index 60f247e10..000000000 --- a/grub-core/gnulib/memchr.valgrind +++ /dev/null @@ -1,14 +0,0 @@ -# Suppress a valgrind message about use of uninitialized memory in memchr(). -# POSIX states that when the character is found, memchr must not read extra -# bytes in an overestimated length (for example, where memchr is used to -# implement strnlen). However, we use a safe word read to provide a speedup. -{ - memchr-value4 - Memcheck:Value4 - fun:rpl_memchr -} -{ - memchr-value8 - Memcheck:Value8 - fun:rpl_memchr -} diff --git a/grub-core/gnulib/mempcpy.c b/grub-core/gnulib/mempcpy.c deleted file mode 100644 index b624d69fd..000000000 --- a/grub-core/gnulib/mempcpy.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Copy memory area and return pointer after last written byte. - Copyright (C) 2003, 2007, 2009, 2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include - -/* Copy N bytes of SRC to DEST, return pointer to bytes after the - last written byte. */ -void * -mempcpy (void *dest, const void *src, size_t n) -{ - return (char *) memcpy (dest, src, n) + n; -} diff --git a/grub-core/gnulib/nl_langinfo.c b/grub-core/gnulib/nl_langinfo.c deleted file mode 100644 index a3d0d11eb..000000000 --- a/grub-core/gnulib/nl_langinfo.c +++ /dev/null @@ -1,270 +0,0 @@ -/* nl_langinfo() replacement: query locale dependent information. - - Copyright (C) 2007-2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -#if REPLACE_NL_LANGINFO - -/* Override nl_langinfo with support for added nl_item values. */ - -# include -# include - -# undef nl_langinfo - -char * -rpl_nl_langinfo (nl_item item) -{ - switch (item) - { -# if GNULIB_defined_CODESET - case CODESET: - { - const char *locale; - static char buf[2 + 10 + 1]; - - locale = setlocale (LC_CTYPE, NULL); - if (locale != NULL && locale[0] != '\0') - { - /* If the locale name contains an encoding after the dot, return - it. */ - const char *dot = strchr (locale, '.'); - - if (dot != NULL) - { - const char *modifier; - - dot++; - /* Look for the possible @... trailer and remove it, if any. */ - modifier = strchr (dot, '@'); - if (modifier == NULL) - return dot; - if (modifier - dot < sizeof (buf)) - { - memcpy (buf, dot, modifier - dot); - buf [modifier - dot] = '\0'; - return buf; - } - } - } - return ""; - } -# endif -# if GNULIB_defined_T_FMT_AMPM - case T_FMT_AMPM: - return "%I:%M:%S %p"; -# endif -# if GNULIB_defined_ERA - case ERA: - /* The format is not standardized. In glibc it is a sequence of strings - of the form "direction:offset:start_date:end_date:era_name:era_format" - with an empty string at the end. */ - return ""; - case ERA_D_FMT: - /* The %Ex conversion in strftime behaves like %x if the locale does not - have an alternative time format. */ - item = D_FMT; - break; - case ERA_D_T_FMT: - /* The %Ec conversion in strftime behaves like %c if the locale does not - have an alternative time format. */ - item = D_T_FMT; - break; - case ERA_T_FMT: - /* The %EX conversion in strftime behaves like %X if the locale does not - have an alternative time format. */ - item = T_FMT; - break; - case ALT_DIGITS: - /* The format is not standardized. In glibc it is a sequence of 10 - strings, appended in memory. */ - return "\0\0\0\0\0\0\0\0\0\0"; -# endif -# if GNULIB_defined_YESEXPR - case YESEXPR: - return "^[yY]"; - case NOEXPR: - return "^[nN]"; -# endif - default: - break; - } - return nl_langinfo (item); -} - -#else - -/* Provide nl_langinfo from scratch. */ - -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - -/* Native Windows platforms. */ - -# define WIN32_LEAN_AND_MEAN /* avoid including junk */ -# include - -# include - -# else - -/* An old Unix platform without locales, such as Linux libc5 or BeOS. */ - -# endif - -# include - -char * -nl_langinfo (nl_item item) -{ - switch (item) - { - /* nl_langinfo items of the LC_CTYPE category */ - case CODESET: -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - { - static char buf[2 + 10 + 1]; - - /* Woe32 has a function returning the locale's codepage as a number. */ - sprintf (buf, "CP%u", GetACP ()); - return buf; - } -# elif defined __BEOS__ - return "UTF-8"; -# else - return "ISO-8859-1"; -# endif - /* nl_langinfo items of the LC_NUMERIC category */ - case RADIXCHAR: - return localeconv () ->decimal_point; - case THOUSEP: - return localeconv () ->thousands_sep; - /* nl_langinfo items of the LC_TIME category. - TODO: Really use the locale. */ - case D_T_FMT: - case ERA_D_T_FMT: - return "%a %b %e %H:%M:%S %Y"; - case D_FMT: - case ERA_D_FMT: - return "%m/%d/%y"; - case T_FMT: - case ERA_T_FMT: - return "%H:%M:%S"; - case T_FMT_AMPM: - return "%I:%M:%S %p"; - case AM_STR: - return "AM"; - case PM_STR: - return "PM"; - case DAY_1: - return "Sunday"; - case DAY_2: - return "Monday"; - case DAY_3: - return "Tuesday"; - case DAY_4: - return "Wednesday"; - case DAY_5: - return "Thursday"; - case DAY_6: - return "Friday"; - case DAY_7: - return "Saturday"; - case ABDAY_1: - return "Sun"; - case ABDAY_2: - return "Mon"; - case ABDAY_3: - return "Tue"; - case ABDAY_4: - return "Wed"; - case ABDAY_5: - return "Thu"; - case ABDAY_6: - return "Fri"; - case ABDAY_7: - return "Sat"; - case MON_1: - return "January"; - case MON_2: - return "February"; - case MON_3: - return "March"; - case MON_4: - return "April"; - case MON_5: - return "May"; - case MON_6: - return "June"; - case MON_7: - return "July"; - case MON_8: - return "August"; - case MON_9: - return "September"; - case MON_10: - return "October"; - case MON_11: - return "November"; - case MON_12: - return "December"; - case ABMON_1: - return "Jan"; - case ABMON_2: - return "Feb"; - case ABMON_3: - return "Mar"; - case ABMON_4: - return "Apr"; - case ABMON_5: - return "May"; - case ABMON_6: - return "Jun"; - case ABMON_7: - return "Jul"; - case ABMON_8: - return "Aug"; - case ABMON_9: - return "Sep"; - case ABMON_10: - return "Oct"; - case ABMON_11: - return "Nov"; - case ABMON_12: - return "Dec"; - case ERA: - return ""; - case ALT_DIGITS: - return "\0\0\0\0\0\0\0\0\0\0"; - /* nl_langinfo items of the LC_MONETARY category - TODO: Really use the locale. */ - case CRNCYSTR: - return "-"; - /* nl_langinfo items of the LC_MESSAGES category - TODO: Really use the locale. */ - case YESEXPR: - return "^[yY]"; - case NOEXPR: - return "^[nN]"; - default: - return ""; - } -} - -#endif diff --git a/grub-core/gnulib/printf-args.c b/grub-core/gnulib/printf-args.c deleted file mode 100644 index 46c03a21e..000000000 --- a/grub-core/gnulib/printf-args.c +++ /dev/null @@ -1,188 +0,0 @@ -/* Decomposed printf argument list. - Copyright (C) 1999, 2002-2003, 2005-2007, 2009-2010 Free Software - Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* This file can be parametrized with the following macros: - ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. - PRINTF_FETCHARGS Name of the function to be defined. - STATIC Set to 'static' to declare the function static. */ - -#ifndef PRINTF_FETCHARGS -# include -#endif - -/* Specification. */ -#ifndef PRINTF_FETCHARGS -# include "printf-args.h" -#endif - -#ifdef STATIC -STATIC -#endif -int -PRINTF_FETCHARGS (va_list args, arguments *a) -{ - size_t i; - argument *ap; - - for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++) - switch (ap->type) - { - case TYPE_SCHAR: - ap->a.a_schar = va_arg (args, /*signed char*/ int); - break; - case TYPE_UCHAR: - ap->a.a_uchar = va_arg (args, /*unsigned char*/ int); - break; - case TYPE_SHORT: - ap->a.a_short = va_arg (args, /*short*/ int); - break; - case TYPE_USHORT: - ap->a.a_ushort = va_arg (args, /*unsigned short*/ int); - break; - case TYPE_INT: - ap->a.a_int = va_arg (args, int); - break; - case TYPE_UINT: - ap->a.a_uint = va_arg (args, unsigned int); - break; - case TYPE_LONGINT: - ap->a.a_longint = va_arg (args, long int); - break; - case TYPE_ULONGINT: - ap->a.a_ulongint = va_arg (args, unsigned long int); - break; -#if HAVE_LONG_LONG_INT - case TYPE_LONGLONGINT: - ap->a.a_longlongint = va_arg (args, long long int); - break; - case TYPE_ULONGLONGINT: - ap->a.a_ulonglongint = va_arg (args, unsigned long long int); - break; -#endif - case TYPE_DOUBLE: - ap->a.a_double = va_arg (args, double); - break; - case TYPE_LONGDOUBLE: - ap->a.a_longdouble = va_arg (args, long double); - break; - case TYPE_CHAR: - ap->a.a_char = va_arg (args, int); - break; -#if HAVE_WINT_T - case TYPE_WIDE_CHAR: - /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by - default argument promotions", this is not the case in mingw32, - where wint_t is 'unsigned short'. */ - ap->a.a_wide_char = - (sizeof (wint_t) < sizeof (int) - ? (wint_t) va_arg (args, int) - : va_arg (args, wint_t)); - break; -#endif - case TYPE_STRING: - ap->a.a_string = va_arg (args, const char *); - /* A null pointer is an invalid argument for "%s", but in practice - it occurs quite frequently in printf statements that produce - debug output. Use a fallback in this case. */ - if (ap->a.a_string == NULL) - ap->a.a_string = "(NULL)"; - break; -#if HAVE_WCHAR_T - case TYPE_WIDE_STRING: - ap->a.a_wide_string = va_arg (args, const wchar_t *); - /* A null pointer is an invalid argument for "%ls", but in practice - it occurs quite frequently in printf statements that produce - debug output. Use a fallback in this case. */ - if (ap->a.a_wide_string == NULL) - { - static const wchar_t wide_null_string[] = - { - (wchar_t)'(', - (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L', - (wchar_t)')', - (wchar_t)0 - }; - ap->a.a_wide_string = wide_null_string; - } - break; -#endif - case TYPE_POINTER: - ap->a.a_pointer = va_arg (args, void *); - break; - case TYPE_COUNT_SCHAR_POINTER: - ap->a.a_count_schar_pointer = va_arg (args, signed char *); - break; - case TYPE_COUNT_SHORT_POINTER: - ap->a.a_count_short_pointer = va_arg (args, short *); - break; - case TYPE_COUNT_INT_POINTER: - ap->a.a_count_int_pointer = va_arg (args, int *); - break; - case TYPE_COUNT_LONGINT_POINTER: - ap->a.a_count_longint_pointer = va_arg (args, long int *); - break; -#if HAVE_LONG_LONG_INT - case TYPE_COUNT_LONGLONGINT_POINTER: - ap->a.a_count_longlongint_pointer = va_arg (args, long long int *); - break; -#endif -#if ENABLE_UNISTDIO - /* The unistdio extensions. */ - case TYPE_U8_STRING: - ap->a.a_u8_string = va_arg (args, const uint8_t *); - /* A null pointer is an invalid argument for "%U", but in practice - it occurs quite frequently in printf statements that produce - debug output. Use a fallback in this case. */ - if (ap->a.a_u8_string == NULL) - { - static const uint8_t u8_null_string[] = - { '(', 'N', 'U', 'L', 'L', ')', 0 }; - ap->a.a_u8_string = u8_null_string; - } - break; - case TYPE_U16_STRING: - ap->a.a_u16_string = va_arg (args, const uint16_t *); - /* A null pointer is an invalid argument for "%lU", but in practice - it occurs quite frequently in printf statements that produce - debug output. Use a fallback in this case. */ - if (ap->a.a_u16_string == NULL) - { - static const uint16_t u16_null_string[] = - { '(', 'N', 'U', 'L', 'L', ')', 0 }; - ap->a.a_u16_string = u16_null_string; - } - break; - case TYPE_U32_STRING: - ap->a.a_u32_string = va_arg (args, const uint32_t *); - /* A null pointer is an invalid argument for "%llU", but in practice - it occurs quite frequently in printf statements that produce - debug output. Use a fallback in this case. */ - if (ap->a.a_u32_string == NULL) - { - static const uint32_t u32_null_string[] = - { '(', 'N', 'U', 'L', 'L', ')', 0 }; - ap->a.a_u32_string = u32_null_string; - } - break; -#endif - default: - /* Unknown type. */ - return -1; - } - return 0; -} diff --git a/grub-core/gnulib/printf-args.h b/grub-core/gnulib/printf-args.h deleted file mode 100644 index 2536ebafd..000000000 --- a/grub-core/gnulib/printf-args.h +++ /dev/null @@ -1,155 +0,0 @@ -/* Decomposed printf argument list. - Copyright (C) 1999, 2002-2003, 2006-2007, 2009-2010 Free Software - Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _PRINTF_ARGS_H -#define _PRINTF_ARGS_H - -/* This file can be parametrized with the following macros: - ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. - PRINTF_FETCHARGS Name of the function to be declared. - STATIC Set to 'static' to declare the function static. */ - -/* Default parameters. */ -#ifndef PRINTF_FETCHARGS -# define PRINTF_FETCHARGS printf_fetchargs -#endif - -/* Get size_t. */ -#include - -/* Get wchar_t. */ -#if HAVE_WCHAR_T -# include -#endif - -/* Get wint_t. */ -#if HAVE_WINT_T -# include -#endif - -/* Get va_list. */ -#include - - -/* Argument types */ -typedef enum -{ - TYPE_NONE, - TYPE_SCHAR, - TYPE_UCHAR, - TYPE_SHORT, - TYPE_USHORT, - TYPE_INT, - TYPE_UINT, - TYPE_LONGINT, - TYPE_ULONGINT, -#if HAVE_LONG_LONG_INT - TYPE_LONGLONGINT, - TYPE_ULONGLONGINT, -#endif - TYPE_DOUBLE, - TYPE_LONGDOUBLE, - TYPE_CHAR, -#if HAVE_WINT_T - TYPE_WIDE_CHAR, -#endif - TYPE_STRING, -#if HAVE_WCHAR_T - TYPE_WIDE_STRING, -#endif - TYPE_POINTER, - TYPE_COUNT_SCHAR_POINTER, - TYPE_COUNT_SHORT_POINTER, - TYPE_COUNT_INT_POINTER, - TYPE_COUNT_LONGINT_POINTER -#if HAVE_LONG_LONG_INT -, TYPE_COUNT_LONGLONGINT_POINTER -#endif -#if ENABLE_UNISTDIO - /* The unistdio extensions. */ -, TYPE_U8_STRING -, TYPE_U16_STRING -, TYPE_U32_STRING -#endif -} arg_type; - -/* Polymorphic argument */ -typedef struct -{ - arg_type type; - union - { - signed char a_schar; - unsigned char a_uchar; - short a_short; - unsigned short a_ushort; - int a_int; - unsigned int a_uint; - long int a_longint; - unsigned long int a_ulongint; -#if HAVE_LONG_LONG_INT - long long int a_longlongint; - unsigned long long int a_ulonglongint; -#endif - float a_float; - double a_double; - long double a_longdouble; - int a_char; -#if HAVE_WINT_T - wint_t a_wide_char; -#endif - const char* a_string; -#if HAVE_WCHAR_T - const wchar_t* a_wide_string; -#endif - void* a_pointer; - signed char * a_count_schar_pointer; - short * a_count_short_pointer; - int * a_count_int_pointer; - long int * a_count_longint_pointer; -#if HAVE_LONG_LONG_INT - long long int * a_count_longlongint_pointer; -#endif -#if ENABLE_UNISTDIO - /* The unistdio extensions. */ - const uint8_t * a_u8_string; - const uint16_t * a_u16_string; - const uint32_t * a_u32_string; -#endif - } - a; -} -argument; - -typedef struct -{ - size_t count; - argument *arg; -} -arguments; - - -/* Fetch the arguments, putting them into a. */ -#ifdef STATIC -STATIC -#else -extern -#endif -int PRINTF_FETCHARGS (va_list args, arguments *a); - -#endif /* _PRINTF_ARGS_H */ diff --git a/grub-core/gnulib/printf-parse.c b/grub-core/gnulib/printf-parse.c deleted file mode 100644 index f612beb5b..000000000 --- a/grub-core/gnulib/printf-parse.c +++ /dev/null @@ -1,627 +0,0 @@ -/* Formatted output to strings. - Copyright (C) 1999-2000, 2002-2003, 2006-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* This file can be parametrized with the following macros: - CHAR_T The element type of the format string. - CHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters - in the format string are ASCII. - DIRECTIVE Structure denoting a format directive. - Depends on CHAR_T. - DIRECTIVES Structure denoting the set of format directives of a - format string. Depends on CHAR_T. - PRINTF_PARSE Function that parses a format string. - Depends on CHAR_T. - STATIC Set to 'static' to declare the function static. - ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. */ - -#ifndef PRINTF_PARSE -# include -#endif - -/* Specification. */ -#ifndef PRINTF_PARSE -# include "printf-parse.h" -#endif - -/* Default parameters. */ -#ifndef PRINTF_PARSE -# define PRINTF_PARSE printf_parse -# define CHAR_T char -# define DIRECTIVE char_directive -# define DIRECTIVES char_directives -#endif - -/* Get size_t, NULL. */ -#include - -/* Get intmax_t. */ -#if defined IN_LIBINTL || defined IN_LIBASPRINTF -# if HAVE_STDINT_H_WITH_UINTMAX -# include -# endif -# if HAVE_INTTYPES_H_WITH_UINTMAX -# include -# endif -#else -# include -#endif - -/* malloc(), realloc(), free(). */ -#include - -/* errno. */ -#include - -/* Checked size_t computations. */ -#include "xsize.h" - -#if CHAR_T_ONLY_ASCII -/* c_isascii(). */ -# include "c-ctype.h" -#endif - -#ifdef STATIC -STATIC -#endif -int -PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a) -{ - const CHAR_T *cp = format; /* pointer into format */ - size_t arg_posn = 0; /* number of regular arguments consumed */ - size_t d_allocated; /* allocated elements of d->dir */ - size_t a_allocated; /* allocated elements of a->arg */ - size_t max_width_length = 0; - size_t max_precision_length = 0; - - d->count = 0; - d_allocated = 1; - d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE)); - if (d->dir == NULL) - /* Out of memory. */ - goto out_of_memory_1; - - a->count = 0; - a_allocated = 0; - a->arg = NULL; - -#define REGISTER_ARG(_index_,_type_) \ - { \ - size_t n = (_index_); \ - if (n >= a_allocated) \ - { \ - size_t memory_size; \ - argument *memory; \ - \ - a_allocated = xtimes (a_allocated, 2); \ - if (a_allocated <= n) \ - a_allocated = xsum (n, 1); \ - memory_size = xtimes (a_allocated, sizeof (argument)); \ - if (size_overflow_p (memory_size)) \ - /* Overflow, would lead to out of memory. */ \ - goto out_of_memory; \ - memory = (argument *) (a->arg \ - ? realloc (a->arg, memory_size) \ - : malloc (memory_size)); \ - if (memory == NULL) \ - /* Out of memory. */ \ - goto out_of_memory; \ - a->arg = memory; \ - } \ - while (a->count <= n) \ - a->arg[a->count++].type = TYPE_NONE; \ - if (a->arg[n].type == TYPE_NONE) \ - a->arg[n].type = (_type_); \ - else if (a->arg[n].type != (_type_)) \ - /* Ambiguous type for positional argument. */ \ - goto error; \ - } - - while (*cp != '\0') - { - CHAR_T c = *cp++; - if (c == '%') - { - size_t arg_index = ARG_NONE; - DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */ - - /* Initialize the next directive. */ - dp->dir_start = cp - 1; - dp->flags = 0; - dp->width_start = NULL; - dp->width_end = NULL; - dp->width_arg_index = ARG_NONE; - dp->precision_start = NULL; - dp->precision_end = NULL; - dp->precision_arg_index = ARG_NONE; - dp->arg_index = ARG_NONE; - - /* Test for positional argument. */ - if (*cp >= '0' && *cp <= '9') - { - const CHAR_T *np; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - ; - if (*np == '$') - { - size_t n = 0; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - n = xsum (xtimes (n, 10), *np - '0'); - if (n == 0) - /* Positional argument 0. */ - goto error; - if (size_overflow_p (n)) - /* n too large, would lead to out of memory later. */ - goto error; - arg_index = n - 1; - cp = np + 1; - } - } - - /* Read the flags. */ - for (;;) - { - if (*cp == '\'') - { - dp->flags |= FLAG_GROUP; - cp++; - } - else if (*cp == '-') - { - dp->flags |= FLAG_LEFT; - cp++; - } - else if (*cp == '+') - { - dp->flags |= FLAG_SHOWSIGN; - cp++; - } - else if (*cp == ' ') - { - dp->flags |= FLAG_SPACE; - cp++; - } - else if (*cp == '#') - { - dp->flags |= FLAG_ALT; - cp++; - } - else if (*cp == '0') - { - dp->flags |= FLAG_ZERO; - cp++; - } - else - break; - } - - /* Parse the field width. */ - if (*cp == '*') - { - dp->width_start = cp; - cp++; - dp->width_end = cp; - if (max_width_length < 1) - max_width_length = 1; - - /* Test for positional argument. */ - if (*cp >= '0' && *cp <= '9') - { - const CHAR_T *np; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - ; - if (*np == '$') - { - size_t n = 0; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - n = xsum (xtimes (n, 10), *np - '0'); - if (n == 0) - /* Positional argument 0. */ - goto error; - if (size_overflow_p (n)) - /* n too large, would lead to out of memory later. */ - goto error; - dp->width_arg_index = n - 1; - cp = np + 1; - } - } - if (dp->width_arg_index == ARG_NONE) - { - dp->width_arg_index = arg_posn++; - if (dp->width_arg_index == ARG_NONE) - /* arg_posn wrapped around. */ - goto error; - } - REGISTER_ARG (dp->width_arg_index, TYPE_INT); - } - else if (*cp >= '0' && *cp <= '9') - { - size_t width_length; - - dp->width_start = cp; - for (; *cp >= '0' && *cp <= '9'; cp++) - ; - dp->width_end = cp; - width_length = dp->width_end - dp->width_start; - if (max_width_length < width_length) - max_width_length = width_length; - } - - /* Parse the precision. */ - if (*cp == '.') - { - cp++; - if (*cp == '*') - { - dp->precision_start = cp - 1; - cp++; - dp->precision_end = cp; - if (max_precision_length < 2) - max_precision_length = 2; - - /* Test for positional argument. */ - if (*cp >= '0' && *cp <= '9') - { - const CHAR_T *np; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - ; - if (*np == '$') - { - size_t n = 0; - - for (np = cp; *np >= '0' && *np <= '9'; np++) - n = xsum (xtimes (n, 10), *np - '0'); - if (n == 0) - /* Positional argument 0. */ - goto error; - if (size_overflow_p (n)) - /* n too large, would lead to out of memory - later. */ - goto error; - dp->precision_arg_index = n - 1; - cp = np + 1; - } - } - if (dp->precision_arg_index == ARG_NONE) - { - dp->precision_arg_index = arg_posn++; - if (dp->precision_arg_index == ARG_NONE) - /* arg_posn wrapped around. */ - goto error; - } - REGISTER_ARG (dp->precision_arg_index, TYPE_INT); - } - else - { - size_t precision_length; - - dp->precision_start = cp - 1; - for (; *cp >= '0' && *cp <= '9'; cp++) - ; - dp->precision_end = cp; - precision_length = dp->precision_end - dp->precision_start; - if (max_precision_length < precision_length) - max_precision_length = precision_length; - } - } - - { - arg_type type; - - /* Parse argument type/size specifiers. */ - { - int flags = 0; - - for (;;) - { - if (*cp == 'h') - { - flags |= (1 << (flags & 1)); - cp++; - } - else if (*cp == 'L') - { - flags |= 4; - cp++; - } - else if (*cp == 'l') - { - flags += 8; - cp++; - } - else if (*cp == 'j') - { - if (sizeof (intmax_t) > sizeof (long)) - { - /* intmax_t = long long */ - flags += 16; - } - else if (sizeof (intmax_t) > sizeof (int)) - { - /* intmax_t = long */ - flags += 8; - } - cp++; - } - else if (*cp == 'z' || *cp == 'Z') - { - /* 'z' is standardized in ISO C 99, but glibc uses 'Z' - because the warning facility in gcc-2.95.2 understands - only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */ - if (sizeof (size_t) > sizeof (long)) - { - /* size_t = long long */ - flags += 16; - } - else if (sizeof (size_t) > sizeof (int)) - { - /* size_t = long */ - flags += 8; - } - cp++; - } - else if (*cp == 't') - { - if (sizeof (ptrdiff_t) > sizeof (long)) - { - /* ptrdiff_t = long long */ - flags += 16; - } - else if (sizeof (ptrdiff_t) > sizeof (int)) - { - /* ptrdiff_t = long */ - flags += 8; - } - cp++; - } -#if defined __APPLE__ && defined __MACH__ - /* On MacOS X 10.3, PRIdMAX is defined as "qd". - We cannot change it to "lld" because PRIdMAX must also - be understood by the system's printf routines. */ - else if (*cp == 'q') - { - if (64 / 8 > sizeof (long)) - { - /* int64_t = long long */ - flags += 16; - } - else - { - /* int64_t = long */ - flags += 8; - } - cp++; - } -#endif -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - /* On native Win32, PRIdMAX is defined as "I64d". - We cannot change it to "lld" because PRIdMAX must also - be understood by the system's printf routines. */ - else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4') - { - if (64 / 8 > sizeof (long)) - { - /* __int64 = long long */ - flags += 16; - } - else - { - /* __int64 = long */ - flags += 8; - } - cp += 3; - } -#endif - else - break; - } - - /* Read the conversion character. */ - c = *cp++; - switch (c) - { - case 'd': case 'i': -#if HAVE_LONG_LONG_INT - /* If 'long long' exists and is larger than 'long': */ - if (flags >= 16 || (flags & 4)) - type = TYPE_LONGLONGINT; - else -#endif - /* If 'long long' exists and is the same as 'long', we parse - "lld" into TYPE_LONGINT. */ - if (flags >= 8) - type = TYPE_LONGINT; - else if (flags & 2) - type = TYPE_SCHAR; - else if (flags & 1) - type = TYPE_SHORT; - else - type = TYPE_INT; - break; - case 'o': case 'u': case 'x': case 'X': -#if HAVE_LONG_LONG_INT - /* If 'long long' exists and is larger than 'long': */ - if (flags >= 16 || (flags & 4)) - type = TYPE_ULONGLONGINT; - else -#endif - /* If 'unsigned long long' exists and is the same as - 'unsigned long', we parse "llu" into TYPE_ULONGINT. */ - if (flags >= 8) - type = TYPE_ULONGINT; - else if (flags & 2) - type = TYPE_UCHAR; - else if (flags & 1) - type = TYPE_USHORT; - else - type = TYPE_UINT; - break; - case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': - case 'a': case 'A': - if (flags >= 16 || (flags & 4)) - type = TYPE_LONGDOUBLE; - else - type = TYPE_DOUBLE; - break; - case 'c': - if (flags >= 8) -#if HAVE_WINT_T - type = TYPE_WIDE_CHAR; -#else - goto error; -#endif - else - type = TYPE_CHAR; - break; -#if HAVE_WINT_T - case 'C': - type = TYPE_WIDE_CHAR; - c = 'c'; - break; -#endif - case 's': - if (flags >= 8) -#if HAVE_WCHAR_T - type = TYPE_WIDE_STRING; -#else - goto error; -#endif - else - type = TYPE_STRING; - break; -#if HAVE_WCHAR_T - case 'S': - type = TYPE_WIDE_STRING; - c = 's'; - break; -#endif - case 'p': - type = TYPE_POINTER; - break; - case 'n': -#if HAVE_LONG_LONG_INT - /* If 'long long' exists and is larger than 'long': */ - if (flags >= 16 || (flags & 4)) - type = TYPE_COUNT_LONGLONGINT_POINTER; - else -#endif - /* If 'long long' exists and is the same as 'long', we parse - "lln" into TYPE_COUNT_LONGINT_POINTER. */ - if (flags >= 8) - type = TYPE_COUNT_LONGINT_POINTER; - else if (flags & 2) - type = TYPE_COUNT_SCHAR_POINTER; - else if (flags & 1) - type = TYPE_COUNT_SHORT_POINTER; - else - type = TYPE_COUNT_INT_POINTER; - break; -#if ENABLE_UNISTDIO - /* The unistdio extensions. */ - case 'U': - if (flags >= 16) - type = TYPE_U32_STRING; - else if (flags >= 8) - type = TYPE_U16_STRING; - else - type = TYPE_U8_STRING; - break; -#endif - case '%': - type = TYPE_NONE; - break; - default: - /* Unknown conversion character. */ - goto error; - } - } - - if (type != TYPE_NONE) - { - dp->arg_index = arg_index; - if (dp->arg_index == ARG_NONE) - { - dp->arg_index = arg_posn++; - if (dp->arg_index == ARG_NONE) - /* arg_posn wrapped around. */ - goto error; - } - REGISTER_ARG (dp->arg_index, type); - } - dp->conversion = c; - dp->dir_end = cp; - } - - d->count++; - if (d->count >= d_allocated) - { - size_t memory_size; - DIRECTIVE *memory; - - d_allocated = xtimes (d_allocated, 2); - memory_size = xtimes (d_allocated, sizeof (DIRECTIVE)); - if (size_overflow_p (memory_size)) - /* Overflow, would lead to out of memory. */ - goto out_of_memory; - memory = (DIRECTIVE *) realloc (d->dir, memory_size); - if (memory == NULL) - /* Out of memory. */ - goto out_of_memory; - d->dir = memory; - } - } -#if CHAR_T_ONLY_ASCII - else if (!c_isascii (c)) - { - /* Non-ASCII character. Not supported. */ - goto error; - } -#endif - } - d->dir[d->count].dir_start = cp; - - d->max_width_length = max_width_length; - d->max_precision_length = max_precision_length; - return 0; - -error: - if (a->arg) - free (a->arg); - if (d->dir) - free (d->dir); - errno = EINVAL; - return -1; - -out_of_memory: - if (a->arg) - free (a->arg); - if (d->dir) - free (d->dir); -out_of_memory_1: - errno = ENOMEM; - return -1; -} - -#undef PRINTF_PARSE -#undef DIRECTIVES -#undef DIRECTIVE -#undef CHAR_T_ONLY_ASCII -#undef CHAR_T diff --git a/grub-core/gnulib/printf-parse.h b/grub-core/gnulib/printf-parse.h deleted file mode 100644 index 0f2b70820..000000000 --- a/grub-core/gnulib/printf-parse.h +++ /dev/null @@ -1,180 +0,0 @@ -/* Parse printf format string. - Copyright (C) 1999, 2002-2003, 2005, 2007, 2009-2010 Free Software - Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _PRINTF_PARSE_H -#define _PRINTF_PARSE_H - -/* This file can be parametrized with the following macros: - ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. - STATIC Set to 'static' to declare the function static. */ - -#include "printf-args.h" - - -/* Flags */ -#define FLAG_GROUP 1 /* ' flag */ -#define FLAG_LEFT 2 /* - flag */ -#define FLAG_SHOWSIGN 4 /* + flag */ -#define FLAG_SPACE 8 /* space flag */ -#define FLAG_ALT 16 /* # flag */ -#define FLAG_ZERO 32 - -/* arg_index value indicating that no argument is consumed. */ -#define ARG_NONE (~(size_t)0) - -/* xxx_directive: A parsed directive. - xxx_directives: A parsed format string. */ - -/* A parsed directive. */ -typedef struct -{ - const char* dir_start; - const char* dir_end; - int flags; - const char* width_start; - const char* width_end; - size_t width_arg_index; - const char* precision_start; - const char* precision_end; - size_t precision_arg_index; - char conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ - size_t arg_index; -} -char_directive; - -/* A parsed format string. */ -typedef struct -{ - size_t count; - char_directive *dir; - size_t max_width_length; - size_t max_precision_length; -} -char_directives; - -#if ENABLE_UNISTDIO - -/* A parsed directive. */ -typedef struct -{ - const uint8_t* dir_start; - const uint8_t* dir_end; - int flags; - const uint8_t* width_start; - const uint8_t* width_end; - size_t width_arg_index; - const uint8_t* precision_start; - const uint8_t* precision_end; - size_t precision_arg_index; - uint8_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ - size_t arg_index; -} -u8_directive; - -/* A parsed format string. */ -typedef struct -{ - size_t count; - u8_directive *dir; - size_t max_width_length; - size_t max_precision_length; -} -u8_directives; - -/* A parsed directive. */ -typedef struct -{ - const uint16_t* dir_start; - const uint16_t* dir_end; - int flags; - const uint16_t* width_start; - const uint16_t* width_end; - size_t width_arg_index; - const uint16_t* precision_start; - const uint16_t* precision_end; - size_t precision_arg_index; - uint16_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ - size_t arg_index; -} -u16_directive; - -/* A parsed format string. */ -typedef struct -{ - size_t count; - u16_directive *dir; - size_t max_width_length; - size_t max_precision_length; -} -u16_directives; - -/* A parsed directive. */ -typedef struct -{ - const uint32_t* dir_start; - const uint32_t* dir_end; - int flags; - const uint32_t* width_start; - const uint32_t* width_end; - size_t width_arg_index; - const uint32_t* precision_start; - const uint32_t* precision_end; - size_t precision_arg_index; - uint32_t conversion; /* d i o u x X f F e E g G a A c s p n U % but not C S */ - size_t arg_index; -} -u32_directive; - -/* A parsed format string. */ -typedef struct -{ - size_t count; - u32_directive *dir; - size_t max_width_length; - size_t max_precision_length; -} -u32_directives; - -#endif - - -/* Parses the format string. Fills in the number N of directives, and fills - in directives[0], ..., directives[N-1], and sets directives[N].dir_start - to the end of the format string. Also fills in the arg_type fields of the - arguments and the needed count of arguments. */ -#if ENABLE_UNISTDIO -extern int - ulc_printf_parse (const char *format, char_directives *d, arguments *a); -extern int - u8_printf_parse (const uint8_t *format, u8_directives *d, arguments *a); -extern int - u16_printf_parse (const uint16_t *format, u16_directives *d, - arguments *a); -extern int - u32_printf_parse (const uint32_t *format, u32_directives *d, - arguments *a); -#else -# ifdef STATIC -STATIC -# else -extern -# endif -int printf_parse (const char *format, char_directives *d, arguments *a); -#endif - -#endif /* _PRINTF_PARSE_H */ diff --git a/grub-core/gnulib/progname.c b/grub-core/gnulib/progname.c deleted file mode 100644 index 1415e6a55..000000000 --- a/grub-core/gnulib/progname.c +++ /dev/null @@ -1,92 +0,0 @@ -/* Program name management. - Copyright (C) 2001-2003, 2005-2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2001. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - - -#include - -/* Specification. */ -#undef ENABLE_RELOCATABLE /* avoid defining set_program_name as a macro */ -#include "progname.h" - -#include /* get program_invocation_name declaration */ -#include -#include -#include - - -/* String containing name the program is called with. - To be initialized by main(). */ -const char *program_name = NULL; - -/* Set program_name, based on argv[0]. - argv0 must be a string allocated with indefinite extent, and must not be - modified after this call. */ -void -set_program_name (const char *argv0) -{ - /* libtool creates a temporary executable whose name is sometimes prefixed - with "lt-" (depends on the platform). It also makes argv[0] absolute. - But the name of the temporary executable is a detail that should not be - visible to the end user and to the test suite. - Remove this "/.libs/" or "/.libs/lt-" prefix here. */ - const char *slash; - const char *base; - - /* Sanity check. POSIX requires the invoking process to pass a non-NULL - argv[0]. */ - if (argv0 == NULL) - { - /* It's a bug in the invoking program. Help diagnosing it. */ - fputs ("A NULL argv[0] was passed through an exec system call.\n", - stderr); - abort (); - } - - slash = strrchr (argv0, '/'); - base = (slash != NULL ? slash + 1 : argv0); - if (base - argv0 >= 7 && strncmp (base - 7, "/.libs/", 7) == 0) - { - argv0 = base; - if (strncmp (base, "lt-", 3) == 0) - { - argv0 = base + 3; - /* On glibc systems, remove the "lt-" prefix from the variable - program_invocation_short_name. */ -#if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME - program_invocation_short_name = (char *) argv0; -#endif - } - } - - /* But don't strip off a leading / in general, because when the user - runs - /some/hidden/place/bin/cp foo foo - he should get the error message - /some/hidden/place/bin/cp: `foo' and `foo' are the same file - not - cp: `foo' and `foo' are the same file - */ - - program_name = argv0; - - /* On glibc systems, the error() function comes from libc and uses the - variable program_invocation_name, not program_name. So set this variable - as well. */ -#if HAVE_DECL_PROGRAM_INVOCATION_NAME - program_invocation_name = (char *) argv0; -#endif -} diff --git a/grub-core/gnulib/progname.h b/grub-core/gnulib/progname.h deleted file mode 100644 index 5ba303bd0..000000000 --- a/grub-core/gnulib/progname.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Program name management. - Copyright (C) 2001-2004, 2006, 2009-2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2001. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef _PROGNAME_H -#define _PROGNAME_H - -/* Programs using this file should do the following in main(): - set_program_name (argv[0]); - */ - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* String containing name the program is called with. */ -extern const char *program_name; - -/* Set program_name, based on argv[0]. - argv0 must be a string allocated with indefinite extent, and must not be - modified after this call. */ -extern void set_program_name (const char *argv0); - -#if ENABLE_RELOCATABLE - -/* Set program_name, based on argv[0], and original installation prefix and - directory, for relocatability. */ -extern void set_program_name_and_installdir (const char *argv0, - const char *orig_installprefix, - const char *orig_installdir); -#undef set_program_name -#define set_program_name(ARG0) \ - set_program_name_and_installdir (ARG0, INSTALLPREFIX, INSTALLDIR) - -/* Return the full pathname of the current executable, based on the earlier - call to set_program_name_and_installdir. Return NULL if unknown. */ -extern char *get_full_program_name (void); - -#endif - - -#ifdef __cplusplus -} -#endif - - -#endif /* _PROGNAME_H */ diff --git a/grub-core/gnulib/rawmemchr.c b/grub-core/gnulib/rawmemchr.c deleted file mode 100644 index 0a88777d9..000000000 --- a/grub-core/gnulib/rawmemchr.c +++ /dev/null @@ -1,136 +0,0 @@ -/* Searching in a string. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -/* Find the first occurrence of C in S. */ -void * -rawmemchr (const void *s, int c_in) -{ - /* On 32-bit hardware, choosing longword to be a 32-bit unsigned - long instead of a 64-bit uintmax_t tends to give better - performance. On 64-bit hardware, unsigned long is generally 64 - bits already. Change this typedef to experiment with - performance. */ - typedef unsigned long int longword; - - const unsigned char *char_ptr; - const longword *longword_ptr; - longword repeated_one; - longword repeated_c; - unsigned char c; - - c = (unsigned char) c_in; - - /* Handle the first few bytes by reading one byte at a time. - Do this until CHAR_PTR is aligned on a longword boundary. */ - for (char_ptr = (const unsigned char *) s; - (size_t) char_ptr % sizeof (longword) != 0; - ++char_ptr) - if (*char_ptr == c) - return (void *) char_ptr; - - longword_ptr = (const longword *) char_ptr; - - /* All these elucidatory comments refer to 4-byte longwords, - but the theory applies equally well to any size longwords. */ - - /* Compute auxiliary longword values: - repeated_one is a value which has a 1 in every byte. - repeated_c has c in every byte. */ - repeated_one = 0x01010101; - repeated_c = c | (c << 8); - repeated_c |= repeated_c << 16; - if (0xffffffffU < (longword) -1) - { - repeated_one |= repeated_one << 31 << 1; - repeated_c |= repeated_c << 31 << 1; - if (8 < sizeof (longword)) - { - size_t i; - - for (i = 64; i < sizeof (longword) * 8; i *= 2) - { - repeated_one |= repeated_one << i; - repeated_c |= repeated_c << i; - } - } - } - - /* Instead of the traditional loop which tests each byte, we will - test a longword at a time. The tricky part is testing if *any of - the four* bytes in the longword in question are equal to NUL or - c. We first use an xor with repeated_c. This reduces the task - to testing whether *any of the four* bytes in longword1 is zero. - - We compute tmp = - ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). - That is, we perform the following operations: - 1. Subtract repeated_one. - 2. & ~longword1. - 3. & a mask consisting of 0x80 in every byte. - Consider what happens in each byte: - - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, - and step 3 transforms it into 0x80. A carry can also be propagated - to more significant bytes. - - If a byte of longword1 is nonzero, let its lowest 1 bit be at - position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, - the byte ends in a single bit of value 0 and k bits of value 1. - After step 2, the result is just k bits of value 1: 2^k - 1. After - step 3, the result is 0. And no carry is produced. - So, if longword1 has only non-zero bytes, tmp is zero. - Whereas if longword1 has a zero byte, call j the position of the least - significant zero byte. Then the result has a zero at positions 0, ..., - j-1 and a 0x80 at position j. We cannot predict the result at the more - significant bytes (positions j+1..3), but it does not matter since we - already have a non-zero bit at position 8*j+7. - - The test whether any byte in longword1 is zero is equivalent - to testing whether tmp is nonzero. - - This test can read beyond the end of a string, depending on where - C_IN is encountered. However, this is considered safe since the - initialization phase ensured that the read will be aligned, - therefore, the read will not cross page boundaries and will not - cause a fault. */ - - while (1) - { - longword longword1 = *longword_ptr ^ repeated_c; - - if ((((longword1 - repeated_one) & ~longword1) - & (repeated_one << 7)) != 0) - break; - longword_ptr++; - } - - char_ptr = (const unsigned char *) longword_ptr; - - /* At this point, we know that one of the sizeof (longword) bytes - starting at char_ptr is == c. On little-endian machines, we - could determine the first such byte without any further memory - accesses, just by looking at the tmp result from the last loop - iteration. But this does not work on big-endian machines. - Choose code that works in both cases. */ - - char_ptr = (unsigned char *) longword_ptr; - while (*char_ptr != c) - char_ptr++; - return (void *) char_ptr; -} diff --git a/grub-core/gnulib/rawmemchr.valgrind b/grub-core/gnulib/rawmemchr.valgrind deleted file mode 100644 index 636392368..000000000 --- a/grub-core/gnulib/rawmemchr.valgrind +++ /dev/null @@ -1,12 +0,0 @@ -# Suppress a valgrind message about use of uninitialized memory in rawmemchr(). -# This use is OK because it provides only a speedup. -{ - rawmemchr-value4 - Memcheck:Value4 - fun:rawmemchr -} -{ - rawmemchr-value8 - Memcheck:Value8 - fun:rawmemchr -} diff --git a/grub-core/gnulib/realloc.c b/grub-core/gnulib/realloc.c deleted file mode 100644 index 053208f37..000000000 --- a/grub-core/gnulib/realloc.c +++ /dev/null @@ -1,91 +0,0 @@ -/* realloc() function that is glibc compatible. - - Copyright (C) 1997, 2003-2004, 2006-2007, 2009-2010 Free Software - Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* written by Jim Meyering and Bruno Haible */ - -#include - -/* Only the AC_FUNC_REALLOC macro defines 'realloc' already in config.h. */ -#ifdef realloc -# define NEED_REALLOC_GNU 1 -/* Whereas the gnulib module 'realloc-gnu' defines HAVE_REALLOC_GNU. */ -#elif GNULIB_REALLOC_GNU && !HAVE_REALLOC_GNU -# define NEED_REALLOC_GNU 1 -#endif - -/* Infer the properties of the system's malloc function. - The gnulib module 'malloc-gnu' defines HAVE_MALLOC_GNU. */ -#if GNULIB_MALLOC_GNU && HAVE_MALLOC_GNU -# define SYSTEM_MALLOC_GLIBC_COMPATIBLE 1 -#endif - -/* Below we want to call the system's malloc and realloc. - Undefine the symbols here so that including provides a - declaration of malloc(), not of rpl_malloc(), and likewise for realloc. */ -#undef malloc -#undef realloc - -/* Specification. */ -#include - -#include - -/* Below we want to call the system's malloc and realloc. - Undefine the symbols, if they were defined by gnulib's - replacement. */ -#undef malloc -#undef realloc - -/* Change the size of an allocated block of memory P to N bytes, - with error checking. If N is zero, change it to 1. If P is NULL, - use malloc. */ - -void * -rpl_realloc (void *p, size_t n) -{ - void *result; - -#if NEED_REALLOC_GNU - if (n == 0) - { - n = 1; - - /* In theory realloc might fail, so don't rely on it to free. */ - free (p); - p = NULL; - } -#endif - - if (p == NULL) - { -#if GNULIB_REALLOC_GNU && !NEED_REALLOC_GNU && !SYSTEM_MALLOC_GLIBC_COMPATIBLE - if (n == 0) - n = 1; -#endif - result = malloc (n); - } - else - result = realloc (p, n); - -#if !HAVE_REALLOC_POSIX - if (result == NULL) - errno = ENOMEM; -#endif - - return result; -} diff --git a/grub-core/gnulib/ref-add.sin b/grub-core/gnulib/ref-add.sin deleted file mode 100644 index dbb61df3d..000000000 --- a/grub-core/gnulib/ref-add.sin +++ /dev/null @@ -1,30 +0,0 @@ -# Add this package to a list of references stored in a text file. -# -# Copyright (C) 2000, 2009, 2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# Written by Bruno Haible . -# -/^# Packages using this file: / { - s/# Packages using this file:// - ta - :a - s/ @PACKAGE@ / @PACKAGE@ / - tb - s/ $/ @PACKAGE@ / - :b - s/^/# Packages using this file:/ -} diff --git a/grub-core/gnulib/ref-del.sin b/grub-core/gnulib/ref-del.sin deleted file mode 100644 index 4c31a6eaf..000000000 --- a/grub-core/gnulib/ref-del.sin +++ /dev/null @@ -1,25 +0,0 @@ -# Remove this package from a list of references stored in a text file. -# -# Copyright (C) 2000, 2009, 2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# Written by Bruno Haible . -# -/^# Packages using this file: / { - s/# Packages using this file:// - s/ @PACKAGE@ / / - s/^/# Packages using this file:/ -} diff --git a/grub-core/gnulib/regcomp.c b/grub-core/gnulib/regcomp.c deleted file mode 100644 index ddea3fb65..000000000 --- a/grub-core/gnulib/regcomp.c +++ /dev/null @@ -1,3877 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free - Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, - size_t length, reg_syntax_t syntax); -static void re_compile_fastmap_iter (regex_t *bufp, - const re_dfastate_t *init_state, - char *fastmap); -static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); -#ifdef RE_ENABLE_I18N -static void free_charset (re_charset_t *cset); -#endif /* RE_ENABLE_I18N */ -static void free_workarea_compile (regex_t *preg); -static reg_errcode_t create_initial_state (re_dfa_t *dfa); -#ifdef RE_ENABLE_I18N -static void optimize_utf8 (re_dfa_t *dfa); -#endif -static reg_errcode_t analyze (regex_t *preg); -static reg_errcode_t preorder (bin_tree_t *root, - reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra); -static reg_errcode_t postorder (bin_tree_t *root, - reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra); -static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node); -static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node); -static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg, - bin_tree_t *node); -static reg_errcode_t calc_first (void *extra, bin_tree_t *node); -static reg_errcode_t calc_next (void *extra, bin_tree_t *node); -static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node); -static Idx duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint); -static Idx search_duplicated_node (const re_dfa_t *dfa, Idx org_node, - unsigned int constraint); -static reg_errcode_t calc_eclosure (re_dfa_t *dfa); -static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, - Idx node, bool root); -static reg_errcode_t calc_inveclosure (re_dfa_t *dfa); -static Idx fetch_number (re_string_t *input, re_token_t *token, - reg_syntax_t syntax); -static int peek_token (re_token_t *token, re_string_t *input, - reg_syntax_t syntax) internal_function; -static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, - reg_syntax_t syntax, reg_errcode_t *err); -static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, - re_dfa_t *dfa, re_token_t *token, - reg_syntax_t syntax, reg_errcode_t *err); -static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, - re_token_t *token, reg_syntax_t syntax, - reg_errcode_t *err); -static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, - re_string_t *regexp, - re_token_t *token, int token_len, - re_dfa_t *dfa, - reg_syntax_t syntax, - bool accept_hyphen); -static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, - re_string_t *regexp, - re_token_t *token); -#ifdef RE_ENABLE_I18N -static reg_errcode_t build_equiv_class (bitset_t sbcset, - re_charset_t *mbcset, - Idx *equiv_class_alloc, - const unsigned char *name); -static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, - bitset_t sbcset, - re_charset_t *mbcset, - Idx *char_class_alloc, - const unsigned char *class_name, - reg_syntax_t syntax); -#else /* not RE_ENABLE_I18N */ -static reg_errcode_t build_equiv_class (bitset_t sbcset, - const unsigned char *name); -static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, - bitset_t sbcset, - const unsigned char *class_name, - reg_syntax_t syntax); -#endif /* not RE_ENABLE_I18N */ -static bin_tree_t *build_charclass_op (re_dfa_t *dfa, - RE_TRANSLATE_TYPE trans, - const unsigned char *class_name, - const unsigned char *extra, - bool non_match, reg_errcode_t *err); -static bin_tree_t *create_tree (re_dfa_t *dfa, - bin_tree_t *left, bin_tree_t *right, - re_token_type_t type); -static bin_tree_t *create_token_tree (re_dfa_t *dfa, - bin_tree_t *left, bin_tree_t *right, - const re_token_t *token); -static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); -static void free_token (re_token_t *node); -static reg_errcode_t free_tree (void *extra, bin_tree_t *node); -static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); - -/* This table gives an error message for each of the error codes listed - in regex.h. Obviously the order here has to be same as there. - POSIX doesn't require that we do anything for REG_NOERROR, - but why not be nice? */ - -static const char __re_error_msgid[] = - { -#define REG_NOERROR_IDX 0 - gettext_noop ("Success") /* REG_NOERROR */ - "\0" -#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") - gettext_noop ("No match") /* REG_NOMATCH */ - "\0" -#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") - gettext_noop ("Invalid regular expression") /* REG_BADPAT */ - "\0" -#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") - gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ - "\0" -#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") - gettext_noop ("Invalid character class name") /* REG_ECTYPE */ - "\0" -#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") - gettext_noop ("Trailing backslash") /* REG_EESCAPE */ - "\0" -#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") - gettext_noop ("Invalid back reference") /* REG_ESUBREG */ - "\0" -#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") - gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ - "\0" -#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") - gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ - "\0" -#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") - gettext_noop ("Unmatched \\{") /* REG_EBRACE */ - "\0" -#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") - gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ - "\0" -#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") - gettext_noop ("Invalid range end") /* REG_ERANGE */ - "\0" -#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") - gettext_noop ("Memory exhausted") /* REG_ESPACE */ - "\0" -#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") - gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ - "\0" -#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") - gettext_noop ("Premature end of regular expression") /* REG_EEND */ - "\0" -#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") - gettext_noop ("Regular expression too big") /* REG_ESIZE */ - "\0" -#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") - gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ - }; - -static const size_t __re_error_msgid_idx[] = - { - REG_NOERROR_IDX, - REG_NOMATCH_IDX, - REG_BADPAT_IDX, - REG_ECOLLATE_IDX, - REG_ECTYPE_IDX, - REG_EESCAPE_IDX, - REG_ESUBREG_IDX, - REG_EBRACK_IDX, - REG_EPAREN_IDX, - REG_EBRACE_IDX, - REG_BADBR_IDX, - REG_ERANGE_IDX, - REG_ESPACE_IDX, - REG_BADRPT_IDX, - REG_EEND_IDX, - REG_ESIZE_IDX, - REG_ERPAREN_IDX - }; - -/* Entry points for GNU code. */ - -/* re_compile_pattern is the GNU regular expression compiler: it - compiles PATTERN (of length LENGTH) and puts the result in BUFP. - Returns 0 if the pattern was valid, otherwise an error string. - - Assumes the `allocated' (and perhaps `buffer') and `translate' fields - are set in BUFP on entry. */ - -#ifdef _LIBC -const char * -re_compile_pattern (pattern, length, bufp) - const char *pattern; - size_t length; - struct re_pattern_buffer *bufp; -#else /* size_t might promote */ -const char * -re_compile_pattern (const char *pattern, size_t length, - struct re_pattern_buffer *bufp) -#endif -{ - reg_errcode_t ret; - - /* And GNU code determines whether or not to get register information - by passing null for the REGS argument to re_match, etc., not by - setting no_sub, unless RE_NO_SUB is set. */ - bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); - - /* Match anchors at newline. */ - bufp->newline_anchor = 1; - - ret = re_compile_internal (bufp, pattern, length, re_syntax_options); - - if (!ret) - return NULL; - return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); -} -#ifdef _LIBC -weak_alias (__re_compile_pattern, re_compile_pattern) -#endif - -/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can - also be assigned to arbitrarily: each pattern buffer stores its own - syntax, so it can be changed between regex compilations. */ -/* This has no initializer because initialized variables in Emacs - become read-only after dumping. */ -reg_syntax_t re_syntax_options; - - -/* Specify the precise syntax of regexps for compilation. This provides - for compatibility for various utilities which historically have - different, incompatible syntaxes. - - The argument SYNTAX is a bit mask comprised of the various bits - defined in regex.h. We return the old syntax. */ - -reg_syntax_t -re_set_syntax (syntax) - reg_syntax_t syntax; -{ - reg_syntax_t ret = re_syntax_options; - - re_syntax_options = syntax; - return ret; -} -#ifdef _LIBC -weak_alias (__re_set_syntax, re_set_syntax) -#endif - -int -re_compile_fastmap (bufp) - struct re_pattern_buffer *bufp; -{ - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; - char *fastmap = bufp->fastmap; - - memset (fastmap, '\0', sizeof (char) * SBC_MAX); - re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); - if (dfa->init_state != dfa->init_state_word) - re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); - if (dfa->init_state != dfa->init_state_nl) - re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); - if (dfa->init_state != dfa->init_state_begbuf) - re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); - bufp->fastmap_accurate = 1; - return 0; -} -#ifdef _LIBC -weak_alias (__re_compile_fastmap, re_compile_fastmap) -#endif - -static inline void -__attribute ((always_inline)) -re_set_fastmap (char *fastmap, bool icase, int ch) -{ - fastmap[ch] = 1; - if (icase) - fastmap[tolower (ch)] = 1; -} - -/* Helper function for re_compile_fastmap. - Compile fastmap for the initial_state INIT_STATE. */ - -static void -re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, - char *fastmap) -{ - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; - Idx node_cnt; - bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); - for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) - { - Idx node = init_state->nodes.elems[node_cnt]; - re_token_type_t type = dfa->nodes[node].type; - - if (type == CHARACTER) - { - re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); -#ifdef RE_ENABLE_I18N - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) - { - unsigned char buf[MB_LEN_MAX]; - unsigned char *p; - wchar_t wc; - mbstate_t state; - - p = buf; - *p++ = dfa->nodes[node].opr.c; - while (++node < dfa->nodes_len - && dfa->nodes[node].type == CHARACTER - && dfa->nodes[node].mb_partial) - *p++ = dfa->nodes[node].opr.c; - memset (&state, '\0', sizeof (state)); - if (__mbrtowc (&wc, (const char *) buf, p - buf, - &state) == p - buf - && (__wcrtomb ((char *) buf, towlower (wc), &state) - != (size_t) -1)) - re_set_fastmap (fastmap, false, buf[0]); - } -#endif - } - else if (type == SIMPLE_BRACKET) - { - int i, ch; - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - { - int j; - bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - if (w & ((bitset_word_t) 1 << j)) - re_set_fastmap (fastmap, icase, ch); - } - } -#ifdef RE_ENABLE_I18N - else if (type == COMPLEX_BRACKET) - { - re_charset_t *cset = dfa->nodes[node].opr.mbcset; - Idx i; - -# ifdef _LIBC - /* See if we have to try all bytes which start multiple collation - elements. - e.g. In da_DK, we want to catch 'a' since "aa" is a valid - collation element, and don't catch 'b' since 'b' is - the only collation element which starts from 'b' (and - it is caught by SIMPLE_BRACKET). */ - if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0 - && (cset->ncoll_syms || cset->nranges)) - { - const int32_t *table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - for (i = 0; i < SBC_MAX; ++i) - if (table[i] < 0) - re_set_fastmap (fastmap, icase, i); - } -# endif /* _LIBC */ - - /* See if we have to start the match at all multibyte characters, - i.e. where we would not find an invalid sequence. This only - applies to multibyte character sets; for single byte character - sets, the SIMPLE_BRACKET again suffices. */ - if (dfa->mb_cur_max > 1 - && (cset->nchar_classes || cset->non_match || cset->nranges -# ifdef _LIBC - || cset->nequiv_classes -# endif /* _LIBC */ - )) - { - unsigned char c = 0; - do - { - mbstate_t mbs; - memset (&mbs, 0, sizeof (mbs)); - if (__mbrtowc (NULL, (char *) &c, 1, &mbs) == (size_t) -2) - re_set_fastmap (fastmap, false, (int) c); - } - while (++c != 0); - } - - else - { - /* ... Else catch all bytes which can start the mbchars. */ - for (i = 0; i < cset->nmbchars; ++i) - { - char buf[256]; - mbstate_t state; - memset (&state, '\0', sizeof (state)); - if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) - re_set_fastmap (fastmap, icase, *(unsigned char *) buf); - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) - { - if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state) - != (size_t) -1) - re_set_fastmap (fastmap, false, *(unsigned char *) buf); - } - } - } - } -#endif /* RE_ENABLE_I18N */ - else if (type == OP_PERIOD -#ifdef RE_ENABLE_I18N - || type == OP_UTF8_PERIOD -#endif /* RE_ENABLE_I18N */ - || type == END_OF_RE) - { - memset (fastmap, '\1', sizeof (char) * SBC_MAX); - if (type == END_OF_RE) - bufp->can_be_null = 1; - return; - } - } -} - -/* Entry point for POSIX code. */ -/* regcomp takes a regular expression as a string and compiles it. - - PREG is a regex_t *. We do not expect any fields to be initialized, - since POSIX says we shouldn't. Thus, we set - - `buffer' to the compiled pattern; - `used' to the length of the compiled pattern; - `syntax' to RE_SYNTAX_POSIX_EXTENDED if the - REG_EXTENDED bit in CFLAGS is set; otherwise, to - RE_SYNTAX_POSIX_BASIC; - `newline_anchor' to REG_NEWLINE being set in CFLAGS; - `fastmap' to an allocated space for the fastmap; - `fastmap_accurate' to zero; - `re_nsub' to the number of subexpressions in PATTERN. - - PATTERN is the address of the pattern string. - - CFLAGS is a series of bits which affect compilation. - - If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we - use POSIX basic syntax. - - If REG_NEWLINE is set, then . and [^...] don't match newline. - Also, regexec will try a match beginning after every newline. - - If REG_ICASE is set, then we considers upper- and lowercase - versions of letters to be equivalent when matching. - - If REG_NOSUB is set, then when PREG is passed to regexec, that - routine will report only success or failure, and nothing about the - registers. - - It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for - the return codes and their meanings.) */ - -int -regcomp (preg, pattern, cflags) - regex_t *_Restrict_ preg; - const char *_Restrict_ pattern; - int cflags; -{ - reg_errcode_t ret; - reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED - : RE_SYNTAX_POSIX_BASIC); - - preg->buffer = NULL; - preg->allocated = 0; - preg->used = 0; - - /* Try to allocate space for the fastmap. */ - preg->fastmap = re_malloc (char, SBC_MAX); - if (BE (preg->fastmap == NULL, 0)) - return REG_ESPACE; - - syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; - - /* If REG_NEWLINE is set, newlines are treated differently. */ - if (cflags & REG_NEWLINE) - { /* REG_NEWLINE implies neither . nor [^...] match newline. */ - syntax &= ~RE_DOT_NEWLINE; - syntax |= RE_HAT_LISTS_NOT_NEWLINE; - /* It also changes the matching behavior. */ - preg->newline_anchor = 1; - } - else - preg->newline_anchor = 0; - preg->no_sub = !!(cflags & REG_NOSUB); - preg->translate = NULL; - - ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); - - /* POSIX doesn't distinguish between an unmatched open-group and an - unmatched close-group: both are REG_EPAREN. */ - if (ret == REG_ERPAREN) - ret = REG_EPAREN; - - /* We have already checked preg->fastmap != NULL. */ - if (BE (ret == REG_NOERROR, 1)) - /* Compute the fastmap now, since regexec cannot modify the pattern - buffer. This function never fails in this implementation. */ - (void) re_compile_fastmap (preg); - else - { - /* Some error occurred while compiling the expression. */ - re_free (preg->fastmap); - preg->fastmap = NULL; - } - - return (int) ret; -} -#ifdef _LIBC -weak_alias (__regcomp, regcomp) -#endif - -/* Returns a message corresponding to an error code, ERRCODE, returned - from either regcomp or regexec. We don't use PREG here. */ - -#ifdef _LIBC -size_t -regerror (errcode, preg, errbuf, errbuf_size) - int errcode; - const regex_t *_Restrict_ preg; - char *_Restrict_ errbuf; - size_t errbuf_size; -#else /* size_t might promote */ -size_t -regerror (int errcode, const regex_t *_Restrict_ preg, - char *_Restrict_ errbuf, size_t errbuf_size) -#endif -{ - const char *msg; - size_t msg_size; - - if (BE (errcode < 0 - || errcode >= (int) (sizeof (__re_error_msgid_idx) - / sizeof (__re_error_msgid_idx[0])), 0)) - /* Only error codes returned by the rest of the code should be passed - to this routine. If we are given anything else, or if other regex - code generates an invalid error code, then the program has a bug. - Dump core so we can fix it. */ - msg = gettext ("unknown regexp error"); - else - msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); - - msg_size = strlen (msg) + 1; /* Includes the null. */ - - if (BE (errbuf_size != 0, 1)) - { - size_t cpy_size = msg_size; - if (BE (msg_size > errbuf_size, 0)) - { - cpy_size = errbuf_size - 1; - errbuf[cpy_size] = '\0'; - } - memcpy (errbuf, msg, cpy_size); - } - - return msg_size; -} -#ifdef _LIBC -weak_alias (__regerror, regerror) -#endif - - -#ifdef RE_ENABLE_I18N -/* This static array is used for the map to single-byte characters when - UTF-8 is used. Otherwise we would allocate memory just to initialize - it the same all the time. UTF-8 is the preferred encoding so this is - a worthwhile optimization. */ -static const bitset_t utf8_sb_map = -{ - /* Set the first 128 bits. */ -# if 4 * BITSET_WORD_BITS < ASCII_CHARS -# error "bitset_word_t is narrower than 32 bits" -# elif 3 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 2 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 1 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, -# endif - (BITSET_WORD_MAX - >> (SBC_MAX % BITSET_WORD_BITS == 0 - ? 0 - : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS)) -}; -#endif - - -static void -free_dfa_content (re_dfa_t *dfa) -{ - Idx i, j; - - if (dfa->nodes) - for (i = 0; i < dfa->nodes_len; ++i) - free_token (dfa->nodes + i); - re_free (dfa->nexts); - for (i = 0; i < dfa->nodes_len; ++i) - { - if (dfa->eclosures != NULL) - re_node_set_free (dfa->eclosures + i); - if (dfa->inveclosures != NULL) - re_node_set_free (dfa->inveclosures + i); - if (dfa->edests != NULL) - re_node_set_free (dfa->edests + i); - } - re_free (dfa->edests); - re_free (dfa->eclosures); - re_free (dfa->inveclosures); - re_free (dfa->nodes); - - if (dfa->state_table) - for (i = 0; i <= dfa->state_hash_mask; ++i) - { - struct re_state_table_entry *entry = dfa->state_table + i; - for (j = 0; j < entry->num; ++j) - { - re_dfastate_t *state = entry->array[j]; - free_state (state); - } - re_free (entry->array); - } - re_free (dfa->state_table); -#ifdef RE_ENABLE_I18N - if (dfa->sb_char != utf8_sb_map) - re_free (dfa->sb_char); -#endif - re_free (dfa->subexp_map); -#ifdef DEBUG - re_free (dfa->re_str); -#endif - - re_free (dfa); -} - - -/* Free dynamically allocated space used by PREG. */ - -void -regfree (preg) - regex_t *preg; -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - if (BE (dfa != NULL, 1)) - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - - re_free (preg->fastmap); - preg->fastmap = NULL; - - re_free (preg->translate); - preg->translate = NULL; -} -#ifdef _LIBC -weak_alias (__regfree, regfree) -#endif - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined _REGEX_RE_COMP || defined _LIBC - -/* BSD has one and only one pattern buffer. */ -static struct re_pattern_buffer re_comp_buf; - -char * -# ifdef _LIBC -/* Make these definitions weak in libc, so POSIX programs can redefine - these names if they don't use our functions, and still use - regcomp/regexec above without link errors. */ -weak_function -# endif -re_comp (s) - const char *s; -{ - reg_errcode_t ret; - char *fastmap; - - if (!s) - { - if (!re_comp_buf.buffer) - return gettext ("No previous regular expression"); - return 0; - } - - if (re_comp_buf.buffer) - { - fastmap = re_comp_buf.fastmap; - re_comp_buf.fastmap = NULL; - __regfree (&re_comp_buf); - memset (&re_comp_buf, '\0', sizeof (re_comp_buf)); - re_comp_buf.fastmap = fastmap; - } - - if (re_comp_buf.fastmap == NULL) - { - re_comp_buf.fastmap = (char *) malloc (SBC_MAX); - if (re_comp_buf.fastmap == NULL) - return (char *) gettext (__re_error_msgid - + __re_error_msgid_idx[(int) REG_ESPACE]); - } - - /* Since `re_exec' always passes NULL for the `regs' argument, we - don't need to initialize the pattern buffer fields which affect it. */ - - /* Match anchors at newlines. */ - re_comp_buf.newline_anchor = 1; - - ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options); - - if (!ret) - return NULL; - - /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ - return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); -} - -#ifdef _LIBC -libc_freeres_fn (free_mem) -{ - __regfree (&re_comp_buf); -} -#endif - -#endif /* _REGEX_RE_COMP */ - -/* Internal entry point. - Compile the regular expression PATTERN, whose length is LENGTH. - SYNTAX indicate regular expression's syntax. */ - -static reg_errcode_t -re_compile_internal (regex_t *preg, const char * pattern, size_t length, - reg_syntax_t syntax) -{ - reg_errcode_t err = REG_NOERROR; - re_dfa_t *dfa; - re_string_t regexp; - - /* Initialize the pattern buffer. */ - preg->fastmap_accurate = 0; - preg->syntax = syntax; - preg->not_bol = preg->not_eol = 0; - preg->used = 0; - preg->re_nsub = 0; - preg->can_be_null = 0; - preg->regs_allocated = REGS_UNALLOCATED; - - /* Initialize the dfa. */ - dfa = (re_dfa_t *) preg->buffer; - if (BE (preg->allocated < sizeof (re_dfa_t), 0)) - { - /* If zero allocated, but buffer is non-null, try to realloc - enough space. This loses if buffer's address is bogus, but - that is the user's responsibility. If ->buffer is NULL this - is a simple allocation. */ - dfa = re_realloc (preg->buffer, re_dfa_t, 1); - if (dfa == NULL) - return REG_ESPACE; - preg->allocated = sizeof (re_dfa_t); - preg->buffer = dfa; - } - preg->used = sizeof (re_dfa_t); - - err = init_dfa (dfa, length); - if (BE (err != REG_NOERROR, 0)) - { - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - return err; - } -#ifdef DEBUG - /* Note: length+1 will not overflow since it is checked in init_dfa. */ - dfa->re_str = re_malloc (char, length + 1); - strncpy (dfa->re_str, pattern, length + 1); -#endif - - __libc_lock_init (dfa->lock); - - err = re_string_construct (®exp, pattern, length, preg->translate, - (syntax & RE_ICASE) != 0, dfa); - if (BE (err != REG_NOERROR, 0)) - { - re_compile_internal_free_return: - free_workarea_compile (preg); - re_string_destruct (®exp); - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - return err; - } - - /* Parse the regular expression, and build a structure tree. */ - preg->re_nsub = 0; - dfa->str_tree = parse (®exp, preg, syntax, &err); - if (BE (dfa->str_tree == NULL, 0)) - goto re_compile_internal_free_return; - - /* Analyze the tree and create the nfa. */ - err = analyze (preg); - if (BE (err != REG_NOERROR, 0)) - goto re_compile_internal_free_return; - -#ifdef RE_ENABLE_I18N - /* If possible, do searching in single byte encoding to speed things up. */ - if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) - optimize_utf8 (dfa); -#endif - - /* Then create the initial state of the dfa. */ - err = create_initial_state (dfa); - - /* Release work areas. */ - free_workarea_compile (preg); - re_string_destruct (®exp); - - if (BE (err != REG_NOERROR, 0)) - { - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - } - - return err; -} - -/* Initialize DFA. We use the length of the regular expression PAT_LEN - as the initial length of some arrays. */ - -static reg_errcode_t -init_dfa (re_dfa_t *dfa, size_t pat_len) -{ - __re_size_t table_size; -#ifndef _LIBC - const char *codeset_name; -#endif -#ifdef RE_ENABLE_I18N - size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t)); -#else - size_t max_i18n_object_size = 0; -#endif - size_t max_object_size = - MAX (sizeof (struct re_state_table_entry), - MAX (sizeof (re_token_t), - MAX (sizeof (re_node_set), - MAX (sizeof (regmatch_t), - max_i18n_object_size)))); - - memset (dfa, '\0', sizeof (re_dfa_t)); - - /* Force allocation of str_tree_storage the first time. */ - dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; - - /* Avoid overflows. The extra "/ 2" is for the table_size doubling - calculation below, and for similar doubling calculations - elsewhere. And it's <= rather than <, because some of the - doubling calculations add 1 afterwards. */ - if (BE (SIZE_MAX / max_object_size / 2 <= pat_len, 0)) - return REG_ESPACE; - - dfa->nodes_alloc = pat_len + 1; - dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); - - /* table_size = 2 ^ ceil(log pat_len) */ - for (table_size = 1; ; table_size <<= 1) - if (table_size > pat_len) - break; - - dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); - dfa->state_hash_mask = table_size - 1; - - dfa->mb_cur_max = MB_CUR_MAX; -#ifdef _LIBC - if (dfa->mb_cur_max == 6 - && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) - dfa->is_utf8 = 1; - dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) - != 0); -#else - codeset_name = nl_langinfo (CODESET); - if (strcasecmp (codeset_name, "UTF-8") == 0 - || strcasecmp (codeset_name, "UTF8") == 0) - dfa->is_utf8 = 1; - - /* We check exhaustively in the loop below if this charset is a - superset of ASCII. */ - dfa->map_notascii = 0; -#endif - -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - if (dfa->is_utf8) - dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; - else - { - int i, j, ch; - - dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); - if (BE (dfa->sb_char == NULL, 0)) - return REG_ESPACE; - - /* Set the bits corresponding to single byte chars. */ - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - { - wint_t wch = __btowc (ch); - if (wch != WEOF) - dfa->sb_char[i] |= (bitset_word_t) 1 << j; -# ifndef _LIBC - if (isascii (ch) && wch != ch) - dfa->map_notascii = 1; -# endif - } - } - } -#endif - - if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0)) - return REG_ESPACE; - return REG_NOERROR; -} - -/* Initialize WORD_CHAR table, which indicate which character is - "word". In this case "word" means that it is the word construction - character used by some operators like "\<", "\>", etc. */ - -static void -internal_function -init_word_char (re_dfa_t *dfa) -{ - int i, j, ch; - dfa->word_ops_used = 1; - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - if (isalnum (ch) || ch == '_') - dfa->word_char[i] |= (bitset_word_t) 1 << j; -} - -/* Free the work area which are only used while compiling. */ - -static void -free_workarea_compile (regex_t *preg) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_storage_t *storage, *next; - for (storage = dfa->str_tree_storage; storage; storage = next) - { - next = storage->next; - re_free (storage); - } - dfa->str_tree_storage = NULL; - dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; - dfa->str_tree = NULL; - re_free (dfa->org_indices); - dfa->org_indices = NULL; -} - -/* Create initial states for all contexts. */ - -static reg_errcode_t -create_initial_state (re_dfa_t *dfa) -{ - Idx first, i; - reg_errcode_t err; - re_node_set init_nodes; - - /* Initial states have the epsilon closure of the node which is - the first node of the regular expression. */ - first = dfa->str_tree->first->node_idx; - dfa->init_node = first; - err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* The back-references which are in initial states can epsilon transit, - since in this case all of the subexpressions can be null. - Then we add epsilon closures of the nodes which are the next nodes of - the back-references. */ - if (dfa->nbackref > 0) - for (i = 0; i < init_nodes.nelem; ++i) - { - Idx node_idx = init_nodes.elems[i]; - re_token_type_t type = dfa->nodes[node_idx].type; - - Idx clexp_idx; - if (type != OP_BACK_REF) - continue; - for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) - { - re_token_t *clexp_node; - clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; - if (clexp_node->type == OP_CLOSE_SUBEXP - && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) - break; - } - if (clexp_idx == init_nodes.nelem) - continue; - - if (type == OP_BACK_REF) - { - Idx dest_idx = dfa->edests[node_idx].elems[0]; - if (!re_node_set_contains (&init_nodes, dest_idx)) - { - reg_errcode_t merge_err - = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); - if (merge_err != REG_NOERROR) - return merge_err; - i = 0; - } - } - } - - /* It must be the first time to invoke acquire_state. */ - dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); - /* We don't check ERR here, since the initial state must not be NULL. */ - if (BE (dfa->init_state == NULL, 0)) - return err; - if (dfa->init_state->has_constraint) - { - dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, - CONTEXT_WORD); - dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, - CONTEXT_NEWLINE); - dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, - &init_nodes, - CONTEXT_NEWLINE - | CONTEXT_BEGBUF); - if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL, 0)) - return err; - } - else - dfa->init_state_word = dfa->init_state_nl - = dfa->init_state_begbuf = dfa->init_state; - - re_node_set_free (&init_nodes); - return REG_NOERROR; -} - -#ifdef RE_ENABLE_I18N -/* If it is possible to do searching in single byte encoding instead of UTF-8 - to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change - DFA nodes where needed. */ - -static void -optimize_utf8 (re_dfa_t *dfa) -{ - Idx node; - int i; - bool mb_chars = false; - bool has_period = false; - - for (node = 0; node < dfa->nodes_len; ++node) - switch (dfa->nodes[node].type) - { - case CHARACTER: - if (dfa->nodes[node].opr.c >= ASCII_CHARS) - mb_chars = true; - break; - case ANCHOR: - switch (dfa->nodes[node].opr.ctx_type) - { - case LINE_FIRST: - case LINE_LAST: - case BUF_FIRST: - case BUF_LAST: - break; - default: - /* Word anchors etc. cannot be handled. It's okay to test - opr.ctx_type since constraints (for all DFA nodes) are - created by ORing one or more opr.ctx_type values. */ - return; - } - break; - case OP_PERIOD: - has_period = true; - break; - case OP_BACK_REF: - case OP_ALT: - case END_OF_RE: - case OP_DUP_ASTERISK: - case OP_OPEN_SUBEXP: - case OP_CLOSE_SUBEXP: - break; - case COMPLEX_BRACKET: - return; - case SIMPLE_BRACKET: - /* Just double check. */ - { - int rshift = (ASCII_CHARS % BITSET_WORD_BITS == 0 - ? 0 - : BITSET_WORD_BITS - ASCII_CHARS % BITSET_WORD_BITS); - for (i = ASCII_CHARS / BITSET_WORD_BITS; i < BITSET_WORDS; ++i) - { - if (dfa->nodes[node].opr.sbcset[i] >> rshift != 0) - return; - rshift = 0; - } - } - break; - default: - break; - } - - if (mb_chars || has_period) - for (node = 0; node < dfa->nodes_len; ++node) - { - if (dfa->nodes[node].type == CHARACTER - && dfa->nodes[node].opr.c >= ASCII_CHARS) - dfa->nodes[node].mb_partial = 0; - else if (dfa->nodes[node].type == OP_PERIOD) - dfa->nodes[node].type = OP_UTF8_PERIOD; - } - - /* The search can be in single byte locale. */ - dfa->mb_cur_max = 1; - dfa->is_utf8 = 0; - dfa->has_mb_node = dfa->nbackref > 0 || has_period; -} -#endif - -/* Analyze the structure tree, and calculate "first", "next", "edest", - "eclosure", and "inveclosure". */ - -static reg_errcode_t -analyze (regex_t *preg) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - reg_errcode_t ret; - - /* Allocate arrays. */ - dfa->nexts = re_malloc (Idx, dfa->nodes_alloc); - dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc); - dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); - dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); - if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL - || dfa->eclosures == NULL, 0)) - return REG_ESPACE; - - dfa->subexp_map = re_malloc (Idx, preg->re_nsub); - if (dfa->subexp_map != NULL) - { - Idx i; - for (i = 0; i < preg->re_nsub; i++) - dfa->subexp_map[i] = i; - preorder (dfa->str_tree, optimize_subexps, dfa); - for (i = 0; i < preg->re_nsub; i++) - if (dfa->subexp_map[i] != i) - break; - if (i == preg->re_nsub) - { - free (dfa->subexp_map); - dfa->subexp_map = NULL; - } - } - - ret = postorder (dfa->str_tree, lower_subexps, preg); - if (BE (ret != REG_NOERROR, 0)) - return ret; - ret = postorder (dfa->str_tree, calc_first, dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - preorder (dfa->str_tree, calc_next, dfa); - ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - ret = calc_eclosure (dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - /* We only need this during the prune_impossible_nodes pass in regexec.c; - skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */ - if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match) - || dfa->nbackref) - { - dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); - if (BE (dfa->inveclosures == NULL, 0)) - return REG_ESPACE; - ret = calc_inveclosure (dfa); - } - - return ret; -} - -/* Our parse trees are very unbalanced, so we cannot use a stack to - implement parse tree visits. Instead, we use parent pointers and - some hairy code in these two functions. */ -static reg_errcode_t -postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra) -{ - bin_tree_t *node, *prev; - - for (node = root; ; ) - { - /* Descend down the tree, preferably to the left (or to the right - if that's the only child). */ - while (node->left || node->right) - if (node->left) - node = node->left; - else - node = node->right; - - do - { - reg_errcode_t err = fn (extra, node); - if (BE (err != REG_NOERROR, 0)) - return err; - if (node->parent == NULL) - return REG_NOERROR; - prev = node; - node = node->parent; - } - /* Go up while we have a node that is reached from the right. */ - while (node->right == prev || node->right == NULL); - node = node->right; - } -} - -static reg_errcode_t -preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra) -{ - bin_tree_t *node; - - for (node = root; ; ) - { - reg_errcode_t err = fn (extra, node); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* Go to the left node, or up and to the right. */ - if (node->left) - node = node->left; - else - { - bin_tree_t *prev = NULL; - while (node->right == prev || node->right == NULL) - { - prev = node; - node = node->parent; - if (!node) - return REG_NOERROR; - } - node = node->right; - } - } -} - -/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell - re_search_internal to map the inner one's opr.idx to this one's. Adjust - backreferences as well. Requires a preorder visit. */ -static reg_errcode_t -optimize_subexps (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - - if (node->token.type == OP_BACK_REF && dfa->subexp_map) - { - int idx = node->token.opr.idx; - node->token.opr.idx = dfa->subexp_map[idx]; - dfa->used_bkref_map |= 1 << node->token.opr.idx; - } - - else if (node->token.type == SUBEXP - && node->left && node->left->token.type == SUBEXP) - { - Idx other_idx = node->left->token.opr.idx; - - node->left = node->left->left; - if (node->left) - node->left->parent = node; - - dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx]; - if (other_idx < BITSET_WORD_BITS) - dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx); - } - - return REG_NOERROR; -} - -/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation - of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */ -static reg_errcode_t -lower_subexps (void *extra, bin_tree_t *node) -{ - regex_t *preg = (regex_t *) extra; - reg_errcode_t err = REG_NOERROR; - - if (node->left && node->left->token.type == SUBEXP) - { - node->left = lower_subexp (&err, preg, node->left); - if (node->left) - node->left->parent = node; - } - if (node->right && node->right->token.type == SUBEXP) - { - node->right = lower_subexp (&err, preg, node->right); - if (node->right) - node->right->parent = node; - } - - return err; -} - -static bin_tree_t * -lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *body = node->left; - bin_tree_t *op, *cls, *tree1, *tree; - - if (preg->no_sub - /* We do not optimize empty subexpressions, because otherwise we may - have bad CONCAT nodes with NULL children. This is obviously not - very common, so we do not lose much. An example that triggers - this case is the sed "script" /\(\)/x. */ - && node->left != NULL - && (node->token.opr.idx >= BITSET_WORD_BITS - || !(dfa->used_bkref_map - & ((bitset_word_t) 1 << node->token.opr.idx)))) - return node->left; - - /* Convert the SUBEXP node to the concatenation of an - OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ - op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); - cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); - tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; - tree = create_tree (dfa, op, tree1, CONCAT); - if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - - op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx; - op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp; - return tree; -} - -/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton - nodes. Requires a postorder visit. */ -static reg_errcode_t -calc_first (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - if (node->token.type == CONCAT) - { - node->first = node->left->first; - node->node_idx = node->left->node_idx; - } - else - { - node->first = node; - node->node_idx = re_dfa_add_node (dfa, node->token); - if (BE (node->node_idx == REG_MISSING, 0)) - return REG_ESPACE; - if (node->token.type == ANCHOR) - dfa->nodes[node->node_idx].constraint = node->token.opr.ctx_type; - } - return REG_NOERROR; -} - -/* Pass 2: compute NEXT on the tree. Preorder visit. */ -static reg_errcode_t -calc_next (void *extra, bin_tree_t *node) -{ - switch (node->token.type) - { - case OP_DUP_ASTERISK: - node->left->next = node; - break; - case CONCAT: - node->left->next = node->right->first; - node->right->next = node->next; - break; - default: - if (node->left) - node->left->next = node->next; - if (node->right) - node->right->next = node->next; - break; - } - return REG_NOERROR; -} - -/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */ -static reg_errcode_t -link_nfa_nodes (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - Idx idx = node->node_idx; - reg_errcode_t err = REG_NOERROR; - - switch (node->token.type) - { - case CONCAT: - break; - - case END_OF_RE: - assert (node->next == NULL); - break; - - case OP_DUP_ASTERISK: - case OP_ALT: - { - Idx left, right; - dfa->has_plural_match = 1; - if (node->left != NULL) - left = node->left->first->node_idx; - else - left = node->next->node_idx; - if (node->right != NULL) - right = node->right->first->node_idx; - else - right = node->next->node_idx; - assert (REG_VALID_INDEX (left)); - assert (REG_VALID_INDEX (right)); - err = re_node_set_init_2 (dfa->edests + idx, left, right); - } - break; - - case ANCHOR: - case OP_OPEN_SUBEXP: - case OP_CLOSE_SUBEXP: - err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx); - break; - - case OP_BACK_REF: - dfa->nexts[idx] = node->next->node_idx; - if (node->token.type == OP_BACK_REF) - err = re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); - break; - - default: - assert (!IS_EPSILON_NODE (node->token.type)); - dfa->nexts[idx] = node->next->node_idx; - break; - } - - return err; -} - -/* Duplicate the epsilon closure of the node ROOT_NODE. - Note that duplicated nodes have constraint INIT_CONSTRAINT in addition - to their own constraint. */ - -static reg_errcode_t -internal_function -duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node, - Idx root_node, unsigned int init_constraint) -{ - Idx org_node, clone_node; - bool ok; - unsigned int constraint = init_constraint; - for (org_node = top_org_node, clone_node = top_clone_node;;) - { - Idx org_dest, clone_dest; - if (dfa->nodes[org_node].type == OP_BACK_REF) - { - /* If the back reference epsilon-transit, its destination must - also have the constraint. Then duplicate the epsilon closure - of the destination of the back reference, and store it in - edests of the back reference. */ - org_dest = dfa->nexts[org_node]; - re_node_set_empty (dfa->edests + clone_node); - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - dfa->nexts[clone_node] = dfa->nexts[org_node]; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - else if (dfa->edests[org_node].nelem == 0) - { - /* In case of the node can't epsilon-transit, don't duplicate the - destination and store the original destination as the - destination of the node. */ - dfa->nexts[clone_node] = dfa->nexts[org_node]; - break; - } - else if (dfa->edests[org_node].nelem == 1) - { - /* In case of the node can epsilon-transit, and it has only one - destination. */ - org_dest = dfa->edests[org_node].elems[0]; - re_node_set_empty (dfa->edests + clone_node); - /* If the node is root_node itself, it means the epsilon closure - has a loop. Then tie it to the destination of the root_node. */ - if (org_node == root_node && clone_node != org_node) - { - ok = re_node_set_insert (dfa->edests + clone_node, org_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - break; - } - /* In case the node has another constraint, append it. */ - constraint |= dfa->nodes[org_node].constraint; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - else /* dfa->edests[org_node].nelem == 2 */ - { - /* In case of the node can epsilon-transit, and it has two - destinations. In the bin_tree_t and DFA, that's '|' and '*'. */ - org_dest = dfa->edests[org_node].elems[0]; - re_node_set_empty (dfa->edests + clone_node); - /* Search for a duplicated node which satisfies the constraint. */ - clone_dest = search_duplicated_node (dfa, org_dest, constraint); - if (clone_dest == REG_MISSING) - { - /* There is no such duplicated node, create a new one. */ - reg_errcode_t err; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - err = duplicate_node_closure (dfa, org_dest, clone_dest, - root_node, constraint); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - { - /* There is a duplicated node which satisfies the constraint, - use it to avoid infinite loop. */ - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - - org_dest = dfa->edests[org_node].elems[1]; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - org_node = org_dest; - clone_node = clone_dest; - } - return REG_NOERROR; -} - -/* Search for a node which is duplicated from the node ORG_NODE, and - satisfies the constraint CONSTRAINT. */ - -static Idx -search_duplicated_node (const re_dfa_t *dfa, Idx org_node, - unsigned int constraint) -{ - Idx idx; - for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) - { - if (org_node == dfa->org_indices[idx] - && constraint == dfa->nodes[idx].constraint) - return idx; /* Found. */ - } - return REG_MISSING; /* Not found. */ -} - -/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. - Return the index of the new node, or REG_MISSING if insufficient storage is - available. */ - -static Idx -duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint) -{ - Idx dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]); - if (BE (dup_idx != REG_MISSING, 1)) - { - dfa->nodes[dup_idx].constraint = constraint; - dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].constraint; - dfa->nodes[dup_idx].duplicated = 1; - - /* Store the index of the original node. */ - dfa->org_indices[dup_idx] = org_idx; - } - return dup_idx; -} - -static reg_errcode_t -calc_inveclosure (re_dfa_t *dfa) -{ - Idx src, idx; - bool ok; - for (idx = 0; idx < dfa->nodes_len; ++idx) - re_node_set_init_empty (dfa->inveclosures + idx); - - for (src = 0; src < dfa->nodes_len; ++src) - { - Idx *elems = dfa->eclosures[src].elems; - for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) - { - ok = re_node_set_insert_last (dfa->inveclosures + elems[idx], src); - if (BE (! ok, 0)) - return REG_ESPACE; - } - } - - return REG_NOERROR; -} - -/* Calculate "eclosure" for all the node in DFA. */ - -static reg_errcode_t -calc_eclosure (re_dfa_t *dfa) -{ - Idx node_idx; - bool incomplete; -#ifdef DEBUG - assert (dfa->nodes_len > 0); -#endif - incomplete = false; - /* For each nodes, calculate epsilon closure. */ - for (node_idx = 0; ; ++node_idx) - { - reg_errcode_t err; - re_node_set eclosure_elem; - if (node_idx == dfa->nodes_len) - { - if (!incomplete) - break; - incomplete = false; - node_idx = 0; - } - -#ifdef DEBUG - assert (dfa->eclosures[node_idx].nelem != REG_MISSING); -#endif - - /* If we have already calculated, skip it. */ - if (dfa->eclosures[node_idx].nelem != 0) - continue; - /* Calculate epsilon closure of `node_idx'. */ - err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (dfa->eclosures[node_idx].nelem == 0) - { - incomplete = true; - re_node_set_free (&eclosure_elem); - } - } - return REG_NOERROR; -} - -/* Calculate epsilon closure of NODE. */ - -static reg_errcode_t -calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) -{ - reg_errcode_t err; - Idx i; - re_node_set eclosure; - bool ok; - bool incomplete = false; - err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* This indicates that we are calculating this node now. - We reference this value to avoid infinite loop. */ - dfa->eclosures[node].nelem = REG_MISSING; - - /* If the current node has constraints, duplicate all nodes - since they must inherit the constraints. */ - if (dfa->nodes[node].constraint - && dfa->edests[node].nelem - && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) - { - err = duplicate_node_closure (dfa, node, node, node, - dfa->nodes[node].constraint); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - /* Expand each epsilon destination nodes. */ - if (IS_EPSILON_NODE(dfa->nodes[node].type)) - for (i = 0; i < dfa->edests[node].nelem; ++i) - { - re_node_set eclosure_elem; - Idx edest = dfa->edests[node].elems[i]; - /* If calculating the epsilon closure of `edest' is in progress, - return intermediate result. */ - if (dfa->eclosures[edest].nelem == REG_MISSING) - { - incomplete = true; - continue; - } - /* If we haven't calculated the epsilon closure of `edest' yet, - calculate now. Otherwise use calculated epsilon closure. */ - if (dfa->eclosures[edest].nelem == 0) - { - err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - eclosure_elem = dfa->eclosures[edest]; - /* Merge the epsilon closure of `edest'. */ - err = re_node_set_merge (&eclosure, &eclosure_elem); - if (BE (err != REG_NOERROR, 0)) - return err; - /* If the epsilon closure of `edest' is incomplete, - the epsilon closure of this node is also incomplete. */ - if (dfa->eclosures[edest].nelem == 0) - { - incomplete = true; - re_node_set_free (&eclosure_elem); - } - } - - /* An epsilon closure includes itself. */ - ok = re_node_set_insert (&eclosure, node); - if (BE (! ok, 0)) - return REG_ESPACE; - if (incomplete && !root) - dfa->eclosures[node].nelem = 0; - else - dfa->eclosures[node] = eclosure; - *new_set = eclosure; - return REG_NOERROR; -} - -/* Functions for token which are used in the parser. */ - -/* Fetch a token from INPUT. - We must not use this function inside bracket expressions. */ - -static void -internal_function -fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax) -{ - re_string_skip_bytes (input, peek_token (result, input, syntax)); -} - -/* Peek a token from INPUT, and return the length of the token. - We must not use this function inside bracket expressions. */ - -static int -internal_function -peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) -{ - unsigned char c; - - if (re_string_eoi (input)) - { - token->type = END_OF_RE; - return 0; - } - - c = re_string_peek_byte (input, 0); - token->opr.c = c; - - token->word_char = 0; -#ifdef RE_ENABLE_I18N - token->mb_partial = 0; - if (input->mb_cur_max > 1 && - !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; - token->mb_partial = 1; - return 1; - } -#endif - if (c == '\\') - { - unsigned char c2; - if (re_string_cur_idx (input) + 1 >= re_string_length (input)) - { - token->type = BACK_SLASH; - return 1; - } - - c2 = re_string_peek_byte_case (input, 1); - token->opr.c = c2; - token->type = CHARACTER; -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc = re_string_wchar_at (input, - re_string_cur_idx (input) + 1); - token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; - } - else -#endif - token->word_char = IS_WORD_CHAR (c2) != 0; - - switch (c2) - { - case '|': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) - token->type = OP_ALT; - break; - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - if (!(syntax & RE_NO_BK_REFS)) - { - token->type = OP_BACK_REF; - token->opr.idx = c2 - '1'; - } - break; - case '<': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_FIRST; - } - break; - case '>': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_LAST; - } - break; - case 'b': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_DELIM; - } - break; - case 'B': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = NOT_WORD_DELIM; - } - break; - case 'w': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_WORD; - break; - case 'W': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_NOTWORD; - break; - case 's': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_SPACE; - break; - case 'S': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_NOTSPACE; - break; - case '`': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = BUF_FIRST; - } - break; - case '\'': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = BUF_LAST; - } - break; - case '(': - if (!(syntax & RE_NO_BK_PARENS)) - token->type = OP_OPEN_SUBEXP; - break; - case ')': - if (!(syntax & RE_NO_BK_PARENS)) - token->type = OP_CLOSE_SUBEXP; - break; - case '+': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_PLUS; - break; - case '?': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_QUESTION; - break; - case '{': - if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) - token->type = OP_OPEN_DUP_NUM; - break; - case '}': - if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) - token->type = OP_CLOSE_DUP_NUM; - break; - default: - break; - } - return 2; - } - - token->type = CHARACTER; -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); - token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; - } - else -#endif - token->word_char = IS_WORD_CHAR (token->opr.c); - - switch (c) - { - case '\n': - if (syntax & RE_NEWLINE_ALT) - token->type = OP_ALT; - break; - case '|': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) - token->type = OP_ALT; - break; - case '*': - token->type = OP_DUP_ASTERISK; - break; - case '+': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_PLUS; - break; - case '?': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_QUESTION; - break; - case '{': - if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - token->type = OP_OPEN_DUP_NUM; - break; - case '}': - if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - token->type = OP_CLOSE_DUP_NUM; - break; - case '(': - if (syntax & RE_NO_BK_PARENS) - token->type = OP_OPEN_SUBEXP; - break; - case ')': - if (syntax & RE_NO_BK_PARENS) - token->type = OP_CLOSE_SUBEXP; - break; - case '[': - token->type = OP_OPEN_BRACKET; - break; - case '.': - token->type = OP_PERIOD; - break; - case '^': - if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) && - re_string_cur_idx (input) != 0) - { - char prev = re_string_peek_byte (input, -1); - if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') - break; - } - token->type = ANCHOR; - token->opr.ctx_type = LINE_FIRST; - break; - case '$': - if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) && - re_string_cur_idx (input) + 1 != re_string_length (input)) - { - re_token_t next; - re_string_skip_bytes (input, 1); - peek_token (&next, input, syntax); - re_string_skip_bytes (input, -1); - if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) - break; - } - token->type = ANCHOR; - token->opr.ctx_type = LINE_LAST; - break; - default: - break; - } - return 1; -} - -/* Peek a token from INPUT, and return the length of the token. - We must not use this function out of bracket expressions. */ - -static int -internal_function -peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) -{ - unsigned char c; - if (re_string_eoi (input)) - { - token->type = END_OF_RE; - return 0; - } - c = re_string_peek_byte (input, 0); - token->opr.c = c; - -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1 && - !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; - return 1; - } -#endif /* RE_ENABLE_I18N */ - - if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) - && re_string_cur_idx (input) + 1 < re_string_length (input)) - { - /* In this case, '\' escape a character. */ - unsigned char c2; - re_string_skip_bytes (input, 1); - c2 = re_string_peek_byte (input, 0); - token->opr.c = c2; - token->type = CHARACTER; - return 1; - } - if (c == '[') /* '[' is a special char in a bracket exps. */ - { - unsigned char c2; - int token_len; - if (re_string_cur_idx (input) + 1 < re_string_length (input)) - c2 = re_string_peek_byte (input, 1); - else - c2 = 0; - token->opr.c = c2; - token_len = 2; - switch (c2) - { - case '.': - token->type = OP_OPEN_COLL_ELEM; - break; - case '=': - token->type = OP_OPEN_EQUIV_CLASS; - break; - case ':': - if (syntax & RE_CHAR_CLASSES) - { - token->type = OP_OPEN_CHAR_CLASS; - break; - } - /* else fall through. */ - default: - token->type = CHARACTER; - token->opr.c = c; - token_len = 1; - break; - } - return token_len; - } - switch (c) - { - case '-': - token->type = OP_CHARSET_RANGE; - break; - case ']': - token->type = OP_CLOSE_BRACKET; - break; - case '^': - token->type = OP_NON_MATCH_LIST; - break; - default: - token->type = CHARACTER; - } - return 1; -} - -/* Functions for parser. */ - -/* Entry point of the parser. - Parse the regular expression REGEXP and return the structure tree. - If an error is occured, ERR is set by error code, and return NULL. - This function build the following tree, from regular expression : - CAT - / \ - / \ - EOR - - CAT means concatenation. - EOR means end of regular expression. */ - -static bin_tree_t * -parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, - reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree, *eor, *root; - re_token_t current_token; - dfa->syntax = syntax; - fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); - tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - eor = create_tree (dfa, NULL, NULL, END_OF_RE); - if (tree != NULL) - root = create_tree (dfa, tree, eor, CONCAT); - else - root = eor; - if (BE (eor == NULL || root == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - return root; -} - -/* This function build the following tree, from regular expression - |: - ALT - / \ - / \ - - - ALT means alternative, which represents the operator `|'. */ - -static bin_tree_t * -parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree, *branch = NULL; - tree = parse_branch (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - - while (token->type == OP_ALT) - { - fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); - if (token->type != OP_ALT && token->type != END_OF_RE - && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) - { - branch = parse_branch (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && branch == NULL, 0)) - return NULL; - } - else - branch = NULL; - tree = create_tree (dfa, tree, branch, OP_ALT); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - return tree; -} - -/* This function build the following tree, from regular expression - : - CAT - / \ - / \ - - - CAT means concatenation. */ - -static bin_tree_t * -parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - bin_tree_t *tree, *expr; - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - tree = parse_expression (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - - while (token->type != OP_ALT && token->type != END_OF_RE - && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) - { - expr = parse_expression (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && expr == NULL, 0)) - { - return NULL; - } - if (tree != NULL && expr != NULL) - { - tree = create_tree (dfa, tree, expr, CONCAT); - if (tree == NULL) - { - *err = REG_ESPACE; - return NULL; - } - } - else if (tree == NULL) - tree = expr; - /* Otherwise expr == NULL, we don't need to create new tree. */ - } - return tree; -} - -/* This function build the following tree, from regular expression a*: - * - | - a -*/ - -static bin_tree_t * -parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree; - switch (token->type) - { - case CHARACTER: - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - while (!re_string_eoi (regexp) - && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) - { - bin_tree_t *mbc_remain; - fetch_token (token, regexp, syntax); - mbc_remain = create_token_tree (dfa, NULL, NULL, token); - tree = create_tree (dfa, tree, mbc_remain, CONCAT); - if (BE (mbc_remain == NULL || tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - } -#endif - break; - case OP_OPEN_SUBEXP: - tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_OPEN_BRACKET: - tree = parse_bracket_exp (regexp, dfa, token, syntax, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_BACK_REF: - if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1)) - { - *err = REG_ESUBREG; - return NULL; - } - dfa->used_bkref_map |= 1 << token->opr.idx; - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - ++dfa->nbackref; - dfa->has_mb_node = 1; - break; - case OP_OPEN_DUP_NUM: - if (syntax & RE_CONTEXT_INVALID_DUP) - { - *err = REG_BADRPT; - return NULL; - } - /* FALLTHROUGH */ - case OP_DUP_ASTERISK: - case OP_DUP_PLUS: - case OP_DUP_QUESTION: - if (syntax & RE_CONTEXT_INVALID_OPS) - { - *err = REG_BADRPT; - return NULL; - } - else if (syntax & RE_CONTEXT_INDEP_OPS) - { - fetch_token (token, regexp, syntax); - return parse_expression (regexp, preg, token, syntax, nest, err); - } - /* else fall through */ - case OP_CLOSE_SUBEXP: - if ((token->type == OP_CLOSE_SUBEXP) && - !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) - { - *err = REG_ERPAREN; - return NULL; - } - /* else fall through */ - case OP_CLOSE_DUP_NUM: - /* We treat it as a normal character. */ - - /* Then we can these characters as normal characters. */ - token->type = CHARACTER; - /* mb_partial and word_char bits should be initialized already - by peek_token. */ - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - break; - case ANCHOR: - if ((token->opr.ctx_type - & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) - && dfa->word_ops_used == 0) - init_word_char (dfa); - if (token->opr.ctx_type == WORD_DELIM - || token->opr.ctx_type == NOT_WORD_DELIM) - { - bin_tree_t *tree_first, *tree_last; - if (token->opr.ctx_type == WORD_DELIM) - { - token->opr.ctx_type = WORD_FIRST; - tree_first = create_token_tree (dfa, NULL, NULL, token); - token->opr.ctx_type = WORD_LAST; - } - else - { - token->opr.ctx_type = INSIDE_WORD; - tree_first = create_token_tree (dfa, NULL, NULL, token); - token->opr.ctx_type = INSIDE_NOTWORD; - } - tree_last = create_token_tree (dfa, NULL, NULL, token); - tree = create_tree (dfa, tree_first, tree_last, OP_ALT); - if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - else - { - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - /* We must return here, since ANCHORs can't be followed - by repetition operators. - eg. RE"^*" is invalid or "", - it must not be "". */ - fetch_token (token, regexp, syntax); - return tree; - case OP_PERIOD: - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - if (dfa->mb_cur_max > 1) - dfa->has_mb_node = 1; - break; - case OP_WORD: - case OP_NOTWORD: - tree = build_charclass_op (dfa, regexp->trans, - (const unsigned char *) "alnum", - (const unsigned char *) "_", - token->type == OP_NOTWORD, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_SPACE: - case OP_NOTSPACE: - tree = build_charclass_op (dfa, regexp->trans, - (const unsigned char *) "space", - (const unsigned char *) "", - token->type == OP_NOTSPACE, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_ALT: - case END_OF_RE: - return NULL; - case BACK_SLASH: - *err = REG_EESCAPE; - return NULL; - default: - /* Must not happen? */ -#ifdef DEBUG - assert (0); -#endif - return NULL; - } - fetch_token (token, regexp, syntax); - - while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS - || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) - { - tree = parse_dup_op (tree, regexp, dfa, token, syntax, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - /* In BRE consecutive duplications are not allowed. */ - if ((syntax & RE_CONTEXT_INVALID_DUP) - && (token->type == OP_DUP_ASTERISK - || token->type == OP_OPEN_DUP_NUM)) - { - *err = REG_BADRPT; - return NULL; - } - } - - return tree; -} - -/* This function build the following tree, from regular expression - (): - SUBEXP - | - -*/ - -static bin_tree_t * -parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree; - size_t cur_nsub; - cur_nsub = preg->re_nsub++; - - fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); - - /* The subexpression may be a null string. */ - if (token->type == OP_CLOSE_SUBEXP) - tree = NULL; - else - { - tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); - if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0)) - *err = REG_EPAREN; - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } - - if (cur_nsub <= '9' - '1') - dfa->completed_bkref_map |= 1 << cur_nsub; - - tree = create_tree (dfa, tree, NULL, SUBEXP); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - tree->token.opr.idx = cur_nsub; - return tree; -} - -/* This function parse repetition operators like "*", "+", "{1,3}" etc. */ - -static bin_tree_t * -parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, - re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) -{ - bin_tree_t *tree = NULL, *old_tree = NULL; - Idx i, start, end, start_idx = re_string_cur_idx (regexp); - re_token_t start_token = *token; - - if (token->type == OP_OPEN_DUP_NUM) - { - end = 0; - start = fetch_number (regexp, token, syntax); - if (start == REG_MISSING) - { - if (token->type == CHARACTER && token->opr.c == ',') - start = 0; /* We treat "{,m}" as "{0,m}". */ - else - { - *err = REG_BADBR; /* {} is invalid. */ - return NULL; - } - } - if (BE (start != REG_ERROR, 1)) - { - /* We treat "{n}" as "{n,n}". */ - end = ((token->type == OP_CLOSE_DUP_NUM) ? start - : ((token->type == CHARACTER && token->opr.c == ',') - ? fetch_number (regexp, token, syntax) : REG_ERROR)); - } - if (BE (start == REG_ERROR || end == REG_ERROR, 0)) - { - /* Invalid sequence. */ - if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0)) - { - if (token->type == END_OF_RE) - *err = REG_EBRACE; - else - *err = REG_BADBR; - - return NULL; - } - - /* If the syntax bit is set, rollback. */ - re_string_set_index (regexp, start_idx); - *token = start_token; - token->type = CHARACTER; - /* mb_partial and word_char bits should be already initialized by - peek_token. */ - return elem; - } - - if (BE ((end != REG_MISSING && start > end) - || token->type != OP_CLOSE_DUP_NUM, 0)) - { - /* First number greater than second. */ - *err = REG_BADBR; - return NULL; - } - } - else - { - start = (token->type == OP_DUP_PLUS) ? 1 : 0; - end = (token->type == OP_DUP_QUESTION) ? 1 : REG_MISSING; - } - - fetch_token (token, regexp, syntax); - - if (BE (elem == NULL, 0)) - return NULL; - if (BE (start == 0 && end == 0, 0)) - { - postorder (elem, free_tree, NULL); - return NULL; - } - - /* Extract "{n,m}" to "...{0,}". */ - if (BE (start > 0, 0)) - { - tree = elem; - for (i = 2; i <= start; ++i) - { - elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (BE (elem == NULL || tree == NULL, 0)) - goto parse_dup_op_espace; - } - - if (start == end) - return tree; - - /* Duplicate ELEM before it is marked optional. */ - elem = duplicate_tree (elem, dfa); - old_tree = tree; - } - else - old_tree = NULL; - - if (elem->token.type == SUBEXP) - postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx); - - tree = create_tree (dfa, elem, NULL, - (end == REG_MISSING ? OP_DUP_ASTERISK : OP_ALT)); - if (BE (tree == NULL, 0)) - goto parse_dup_op_espace; - -/* From gnulib's "intprops.h": - True if the arithmetic type T is signed. */ -#define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) - - /* This loop is actually executed only when end != REG_MISSING, - to rewrite {0,n} as ((...?)?)?... We have - already created the start+1-th copy. */ - if (TYPE_SIGNED (Idx) || end != REG_MISSING) - for (i = start + 2; i <= end; ++i) - { - elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (BE (elem == NULL || tree == NULL, 0)) - goto parse_dup_op_espace; - - tree = create_tree (dfa, tree, NULL, OP_ALT); - if (BE (tree == NULL, 0)) - goto parse_dup_op_espace; - } - - if (old_tree) - tree = create_tree (dfa, old_tree, tree, CONCAT); - - return tree; - - parse_dup_op_espace: - *err = REG_ESPACE; - return NULL; -} - -/* Size of the names for collating symbol/equivalence_class/character_class. - I'm not sure, but maybe enough. */ -#define BRACKET_NAME_BUF_SIZE 32 - -#ifndef _LIBC - /* Local function for parse_bracket_exp only used in case of NOT _LIBC. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may - update it. */ - -static reg_errcode_t -internal_function -# ifdef RE_ENABLE_I18N -build_range_exp (const reg_syntax_t syntax, - bitset_t sbcset, - re_charset_t *mbcset, - Idx *range_alloc, - const bracket_elem_t *start_elem, - const bracket_elem_t *end_elem) -# else /* not RE_ENABLE_I18N */ -build_range_exp (const reg_syntax_t syntax, - bitset_t sbcset, - const bracket_elem_t *start_elem, - const bracket_elem_t *end_elem) -# endif /* not RE_ENABLE_I18N */ -{ - unsigned int start_ch, end_ch; - /* Equivalence Classes and Character Classes can't be a range start/end. */ - if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS - || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, - 0)) - return REG_ERANGE; - - /* We can handle no multi character collating elements without libc - support. */ - if (BE ((start_elem->type == COLL_SYM - && strlen ((char *) start_elem->opr.name) > 1) - || (end_elem->type == COLL_SYM - && strlen ((char *) end_elem->opr.name) > 1), 0)) - return REG_ECOLLATE; - -# ifdef RE_ENABLE_I18N - { - wchar_t wc; - wint_t start_wc; - wint_t end_wc; - wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; - - start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch - : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] - : 0)); - end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch - : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] - : 0)); - start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) - ? __btowc (start_ch) : start_elem->opr.wch); - end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) - ? __btowc (end_ch) : end_elem->opr.wch); - if (start_wc == WEOF || end_wc == WEOF) - return REG_ECOLLATE; - cmp_buf[0] = start_wc; - cmp_buf[4] = end_wc; - - if (BE ((syntax & RE_NO_EMPTY_RANGES) - && wcscoll (cmp_buf, cmp_buf + 4) > 0, 0)) - return REG_ERANGE; - - /* Got valid collation sequence values, add them as a new entry. - However, for !_LIBC we have no collation elements: if the - character set is single byte, the single byte character set - that we build below suffices. parse_bracket_exp passes - no MBCSET if dfa->mb_cur_max == 1. */ - if (mbcset) - { - /* Check the space of the arrays. */ - if (BE (*range_alloc == mbcset->nranges, 0)) - { - /* There is not enough space, need realloc. */ - wchar_t *new_array_start, *new_array_end; - Idx new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - /* Use realloc since mbcset->range_starts and mbcset->range_ends - are NULL if *range_alloc == 0. */ - new_array_start = re_realloc (mbcset->range_starts, wchar_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, wchar_t, - new_nranges); - - if (BE (new_array_start == NULL || new_array_end == NULL, 0)) - return REG_ESPACE; - - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } - - mbcset->range_starts[mbcset->nranges] = start_wc; - mbcset->range_ends[mbcset->nranges++] = end_wc; - } - - /* Build the table for single byte characters. */ - for (wc = 0; wc < SBC_MAX; ++wc) - { - cmp_buf[2] = wc; - if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 - && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) - bitset_set (sbcset, wc); - } - } -# else /* not RE_ENABLE_I18N */ - { - unsigned int ch; - start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch - : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] - : 0)); - end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch - : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] - : 0)); - if (start_ch > end_ch) - return REG_ERANGE; - /* Build the table for single byte characters. */ - for (ch = 0; ch < SBC_MAX; ++ch) - if (start_ch <= ch && ch <= end_ch) - bitset_set (sbcset, ch); - } -# endif /* not RE_ENABLE_I18N */ - return REG_NOERROR; -} -#endif /* not _LIBC */ - -#ifndef _LIBC -/* Helper function for parse_bracket_exp only used in case of NOT _LIBC.. - Build the collating element which is represented by NAME. - The result are written to MBCSET and SBCSET. - COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument since we may update it. */ - -static reg_errcode_t -internal_function -build_collating_symbol (bitset_t sbcset, -# ifdef RE_ENABLE_I18N - re_charset_t *mbcset, Idx *coll_sym_alloc, -# endif - const unsigned char *name) -{ - size_t name_len = strlen ((const char *) name); - if (BE (name_len != 1, 0)) - return REG_ECOLLATE; - else - { - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } -} -#endif /* not _LIBC */ - -/* This function parse bracket expression like "[abc]", "[a-c]", - "[[.a-a.]]" etc. */ - -static bin_tree_t * -parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, - reg_syntax_t syntax, reg_errcode_t *err) -{ -#ifdef _LIBC - const unsigned char *collseqmb; - const char *collseqwc; - uint32_t nrules; - int32_t table_size; - const int32_t *symb_table; - const unsigned char *extra; - - /* Local function for parse_bracket_exp used in _LIBC environement. - Seek the collating symbol entry correspondings to NAME. - Return the index of the symbol in the SYMB_TABLE. */ - - auto inline int32_t - __attribute ((always_inline)) - seek_collating_symbol_entry (name, name_len) - const unsigned char *name; - size_t name_len; - { - int32_t hash = elem_hash ((const char *) name, name_len); - int32_t elem = hash % table_size; - if (symb_table[2 * elem] != 0) - { - int32_t second = hash % (table_size - 2) + 1; - - do - { - /* First compare the hashing value. */ - if (symb_table[2 * elem] == hash - /* Compare the length of the name. */ - && name_len == extra[symb_table[2 * elem + 1]] - /* Compare the name. */ - && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], - name_len) == 0) - { - /* Yep, this is the entry. */ - break; - } - - /* Next entry. */ - elem += second; - } - while (symb_table[2 * elem] != 0); - } - return elem; - } - - /* Local function for parse_bracket_exp used in _LIBC environment. - Look up the collation sequence value of BR_ELEM. - Return the value if succeeded, UINT_MAX otherwise. */ - - auto inline unsigned int - __attribute ((always_inline)) - lookup_collation_sequence_value (br_elem) - bracket_elem_t *br_elem; - { - if (br_elem->type == SB_CHAR) - { - /* - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) - return collseqmb[br_elem->opr.ch]; - else - { - wint_t wc = __btowc (br_elem->opr.ch); - return __collseq_table_lookup (collseqwc, wc); - } - } - else if (br_elem->type == MB_CHAR) - { - if (nrules != 0) - return __collseq_table_lookup (collseqwc, br_elem->opr.wch); - } - else if (br_elem->type == COLL_SYM) - { - size_t sym_name_len = strlen ((char *) br_elem->opr.name); - if (nrules != 0) - { - int32_t elem, idx; - elem = seek_collating_symbol_entry (br_elem->opr.name, - sym_name_len); - if (symb_table[2 * elem] != 0) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - /* Skip the byte sequence of the collating element. */ - idx += 1 + extra[idx]; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - /* Skip the multibyte collation sequence value. */ - idx += sizeof (unsigned int); - /* Skip the wide char sequence of the collating element. */ - idx += sizeof (unsigned int) * - (1 + *(unsigned int *) (extra + idx)); - /* Return the collation sequence value. */ - return *(unsigned int *) (extra + idx); - } - else if (symb_table[2 * elem] == 0 && sym_name_len == 1) - { - /* No valid character. Match it as a single byte - character. */ - return collseqmb[br_elem->opr.name[0]]; - } - } - else if (sym_name_len == 1) - return collseqmb[br_elem->opr.name[0]]; - } - return UINT_MAX; - } - - /* Local function for parse_bracket_exp used in _LIBC environement. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may - update it. */ - - auto inline reg_errcode_t - __attribute ((always_inline)) - build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) - re_charset_t *mbcset; - Idx *range_alloc; - bitset_t sbcset; - bracket_elem_t *start_elem, *end_elem; - { - unsigned int ch; - uint32_t start_collseq; - uint32_t end_collseq; - - /* Equivalence Classes and Character Classes can't be a range - start/end. */ - if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS - || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, - 0)) - return REG_ERANGE; - - start_collseq = lookup_collation_sequence_value (start_elem); - end_collseq = lookup_collation_sequence_value (end_elem); - /* Check start/end collation sequence values. */ - if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0)) - return REG_ECOLLATE; - if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0)) - return REG_ERANGE; - - /* Got valid collation sequence values, add them as a new entry. - However, if we have no collation elements, and the character set - is single byte, the single byte character set that we - build below suffices. */ - if (nrules > 0 || dfa->mb_cur_max > 1) - { - /* Check the space of the arrays. */ - if (BE (*range_alloc == mbcset->nranges, 0)) - { - /* There is not enough space, need realloc. */ - uint32_t *new_array_start; - uint32_t *new_array_end; - Idx new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - new_array_start = re_realloc (mbcset->range_starts, uint32_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, uint32_t, - new_nranges); - - if (BE (new_array_start == NULL || new_array_end == NULL, 0)) - return REG_ESPACE; - - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } - - mbcset->range_starts[mbcset->nranges] = start_collseq; - mbcset->range_ends[mbcset->nranges++] = end_collseq; - } - - /* Build the table for single byte characters. */ - for (ch = 0; ch < SBC_MAX; ch++) - { - uint32_t ch_collseq; - /* - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) - ch_collseq = collseqmb[ch]; - else - ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); - if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) - bitset_set (sbcset, ch); - } - return REG_NOERROR; - } - - /* Local function for parse_bracket_exp used in _LIBC environement. - Build the collating element which is represented by NAME. - The result are written to MBCSET and SBCSET. - COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument sinse we may update it. */ - - auto inline reg_errcode_t - __attribute ((always_inline)) - build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) - re_charset_t *mbcset; - Idx *coll_sym_alloc; - bitset_t sbcset; - const unsigned char *name; - { - int32_t elem, idx; - size_t name_len = strlen ((const char *) name); - if (nrules != 0) - { - elem = seek_collating_symbol_entry (name, name_len); - if (symb_table[2 * elem] != 0) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - } - else if (symb_table[2 * elem] == 0 && name_len == 1) - { - /* No valid character, treat it as a normal - character. */ - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } - else - return REG_ECOLLATE; - - /* Got valid collation sequence, add it as a new entry. */ - /* Check the space of the arrays. */ - if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->ncoll_syms is 0. */ - Idx new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; - /* Use realloc since mbcset->coll_syms is NULL - if *alloc == 0. */ - int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, - new_coll_sym_alloc); - if (BE (new_coll_syms == NULL, 0)) - return REG_ESPACE; - mbcset->coll_syms = new_coll_syms; - *coll_sym_alloc = new_coll_sym_alloc; - } - mbcset->coll_syms[mbcset->ncoll_syms++] = idx; - return REG_NOERROR; - } - else - { - if (BE (name_len != 1, 0)) - return REG_ECOLLATE; - else - { - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } - } - } -#endif - - re_token_t br_token; - re_bitset_ptr_t sbcset; -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; - Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; - Idx equiv_class_alloc = 0, char_class_alloc = 0; -#endif /* not RE_ENABLE_I18N */ - bool non_match = false; - bin_tree_t *work_tree; - int token_len; - bool first_round = true; -#ifdef _LIBC - collseqmb = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules) - { - /* - if (MB_CUR_MAX > 1) - */ - collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); - table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); - symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_TABLEMB); - extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_EXTRAMB); - } -#endif - sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); -#ifdef RE_ENABLE_I18N - mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); -#endif /* RE_ENABLE_I18N */ -#ifdef RE_ENABLE_I18N - if (BE (sbcset == NULL || mbcset == NULL, 0)) -#else - if (BE (sbcset == NULL, 0)) -#endif /* RE_ENABLE_I18N */ - { - *err = REG_ESPACE; - return NULL; - } - - token_len = peek_token_bracket (token, regexp, syntax); - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_BADPAT; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_NON_MATCH_LIST) - { -#ifdef RE_ENABLE_I18N - mbcset->non_match = 1; -#endif /* not RE_ENABLE_I18N */ - non_match = true; - if (syntax & RE_HAT_LISTS_NOT_NEWLINE) - bitset_set (sbcset, '\n'); - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - token_len = peek_token_bracket (token, regexp, syntax); - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_BADPAT; - goto parse_bracket_exp_free_return; - } - } - - /* We treat the first ']' as a normal character. */ - if (token->type == OP_CLOSE_BRACKET) - token->type = CHARACTER; - - while (1) - { - bracket_elem_t start_elem, end_elem; - unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; - unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; - reg_errcode_t ret; - int token_len2 = 0; - bool is_range_exp = false; - re_token_t token2; - - start_elem.opr.name = start_name_buf; - ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, - syntax, first_round); - if (BE (ret != REG_NOERROR, 0)) - { - *err = ret; - goto parse_bracket_exp_free_return; - } - first_round = false; - - /* Get information about the next token. We need it in any case. */ - token_len = peek_token_bracket (token, regexp, syntax); - - /* Do not check for ranges if we know they are not allowed. */ - if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) - { - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_CHARSET_RANGE) - { - re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ - token_len2 = peek_token_bracket (&token2, regexp, syntax); - if (BE (token2.type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token2.type == OP_CLOSE_BRACKET) - { - /* We treat the last '-' as a normal character. */ - re_string_skip_bytes (regexp, -token_len); - token->type = CHARACTER; - } - else - is_range_exp = true; - } - } - - if (is_range_exp == true) - { - end_elem.opr.name = end_name_buf; - ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, - dfa, syntax, true); - if (BE (ret != REG_NOERROR, 0)) - { - *err = ret; - goto parse_bracket_exp_free_return; - } - - token_len = peek_token_bracket (token, regexp, syntax); - -#ifdef _LIBC - *err = build_range_exp (sbcset, mbcset, &range_alloc, - &start_elem, &end_elem); -#else -# ifdef RE_ENABLE_I18N - *err = build_range_exp (syntax, sbcset, - dfa->mb_cur_max > 1 ? mbcset : NULL, - &range_alloc, &start_elem, &end_elem); -# else - *err = build_range_exp (syntax, sbcset, &start_elem, &end_elem); -# endif -#endif /* RE_ENABLE_I18N */ - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - } - else - { - switch (start_elem.type) - { - case SB_CHAR: - bitset_set (sbcset, start_elem.opr.ch); - break; -#ifdef RE_ENABLE_I18N - case MB_CHAR: - /* Check whether the array has enough space. */ - if (BE (mbchar_alloc == mbcset->nmbchars, 0)) - { - wchar_t *new_mbchars; - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nmbchars is 0. */ - mbchar_alloc = 2 * mbcset->nmbchars + 1; - /* Use realloc since array is NULL if *alloc == 0. */ - new_mbchars = re_realloc (mbcset->mbchars, wchar_t, - mbchar_alloc); - if (BE (new_mbchars == NULL, 0)) - goto parse_bracket_exp_espace; - mbcset->mbchars = new_mbchars; - } - mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; - break; -#endif /* RE_ENABLE_I18N */ - case EQUIV_CLASS: - *err = build_equiv_class (sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &equiv_class_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - case COLL_SYM: - *err = build_collating_symbol (sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &coll_sym_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - case CHAR_CLASS: - *err = build_charclass (regexp->trans, sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &char_class_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name, syntax); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - default: - assert (0); - break; - } - } - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_CLOSE_BRACKET) - break; - } - - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - - /* If it is non-matching list. */ - if (non_match) - bitset_not (sbcset); - -#ifdef RE_ENABLE_I18N - /* Ensure only single byte characters are set. */ - if (dfa->mb_cur_max > 1) - bitset_mask (sbcset, dfa->sb_char); - - if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes - || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes - || mbcset->non_match))) - { - bin_tree_t *mbc_tree; - int sbc_idx; - /* Build a tree for complex bracket. */ - dfa->has_mb_node = 1; - br_token.type = COMPLEX_BRACKET; - br_token.opr.mbcset = mbcset; - mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (mbc_tree == NULL, 0)) - goto parse_bracket_exp_espace; - for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx) - if (sbcset[sbc_idx]) - break; - /* If there are no bits set in sbcset, there is no point - of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ - if (sbc_idx < BITSET_WORDS) - { - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - work_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - - /* Then join them by ALT node. */ - work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - } - else - { - re_free (sbcset); - work_tree = mbc_tree; - } - } - else -#endif /* not RE_ENABLE_I18N */ - { -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - work_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - } - return work_tree; - - parse_bracket_exp_espace: - *err = REG_ESPACE; - parse_bracket_exp_free_return: - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - return NULL; -} - -/* Parse an element in the bracket expression. */ - -static reg_errcode_t -parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, - re_token_t *token, int token_len, re_dfa_t *dfa, - reg_syntax_t syntax, bool accept_hyphen) -{ -#ifdef RE_ENABLE_I18N - int cur_char_size; - cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); - if (cur_char_size > 1) - { - elem->type = MB_CHAR; - elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); - re_string_skip_bytes (regexp, cur_char_size); - return REG_NOERROR; - } -#endif /* RE_ENABLE_I18N */ - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS - || token->type == OP_OPEN_EQUIV_CLASS) - return parse_bracket_symbol (elem, regexp, token); - if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen) - { - /* A '-' must only appear as anything but a range indicator before - the closing bracket. Everything else is an error. */ - re_token_t token2; - (void) peek_token_bracket (&token2, regexp, syntax); - if (token2.type != OP_CLOSE_BRACKET) - /* The actual error value is not standardized since this whole - case is undefined. But ERANGE makes good sense. */ - return REG_ERANGE; - } - elem->type = SB_CHAR; - elem->opr.ch = token->opr.c; - return REG_NOERROR; -} - -/* Parse a bracket symbol in the bracket expression. Bracket symbols are - such as [::], [..], and - [==]. */ - -static reg_errcode_t -parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, - re_token_t *token) -{ - unsigned char ch, delim = token->opr.c; - int i = 0; - if (re_string_eoi(regexp)) - return REG_EBRACK; - for (;; ++i) - { - if (i >= BRACKET_NAME_BUF_SIZE) - return REG_EBRACK; - if (token->type == OP_OPEN_CHAR_CLASS) - ch = re_string_fetch_byte_case (regexp); - else - ch = re_string_fetch_byte (regexp); - if (re_string_eoi(regexp)) - return REG_EBRACK; - if (ch == delim && re_string_peek_byte (regexp, 0) == ']') - break; - elem->opr.name[i] = ch; - } - re_string_skip_bytes (regexp, 1); - elem->opr.name[i] = '\0'; - switch (token->type) - { - case OP_OPEN_COLL_ELEM: - elem->type = COLL_SYM; - break; - case OP_OPEN_EQUIV_CLASS: - elem->type = EQUIV_CLASS; - break; - case OP_OPEN_CHAR_CLASS: - elem->type = CHAR_CLASS; - break; - default: - break; - } - return REG_NOERROR; -} - - /* Helper function for parse_bracket_exp. - Build the equivalence class which is represented by NAME. - The result are written to MBCSET and SBCSET. - EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, - is a pointer argument sinse we may update it. */ - -static reg_errcode_t -#ifdef RE_ENABLE_I18N -build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, - Idx *equiv_class_alloc, const unsigned char *name) -#else /* not RE_ENABLE_I18N */ -build_equiv_class (bitset_t sbcset, const unsigned char *name) -#endif /* not RE_ENABLE_I18N */ -{ -#ifdef _LIBC - uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { - const int32_t *table, *indirect; - const unsigned char *weights, *extra, *cp; - unsigned char char_buf[2]; - int32_t idx1, idx2; - unsigned int ch; - size_t len; - /* This #include defines a local function! */ -# include - /* Calculate the index for equivalence class. */ - cp = name; - table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_WEIGHTMB); - extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_INDIRECTMB); - idx1 = findidx (&cp); - if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) - /* This isn't a valid character. */ - return REG_ECOLLATE; - - /* Build single byte matcing table for this equivalence class. */ - char_buf[1] = (unsigned char) '\0'; - len = weights[idx1 & 0xffffff]; - for (ch = 0; ch < SBC_MAX; ++ch) - { - char_buf[0] = ch; - cp = char_buf; - idx2 = findidx (&cp); -/* - idx2 = table[ch]; -*/ - if (idx2 == 0) - /* This isn't a valid character. */ - continue; - /* Compare only if the length matches and the collation rule - index is the same. */ - if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24)) - { - int cnt = 0; - - while (cnt <= len && - weights[(idx1 & 0xffffff) + 1 + cnt] - == weights[(idx2 & 0xffffff) + 1 + cnt]) - ++cnt; - - if (cnt > len) - bitset_set (sbcset, ch); - } - } - /* Check whether the array has enough space. */ - if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nequiv_classes is 0. */ - Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; - /* Use realloc since the array is NULL if *alloc == 0. */ - int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, - int32_t, - new_equiv_class_alloc); - if (BE (new_equiv_classes == NULL, 0)) - return REG_ESPACE; - mbcset->equiv_classes = new_equiv_classes; - *equiv_class_alloc = new_equiv_class_alloc; - } - mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; - } - else -#endif /* _LIBC */ - { - if (BE (strlen ((const char *) name) != 1, 0)) - return REG_ECOLLATE; - bitset_set (sbcset, *name); - } - return REG_NOERROR; -} - - /* Helper function for parse_bracket_exp. - Build the character class which is represented by NAME. - The result are written to MBCSET and SBCSET. - CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, - is a pointer argument sinse we may update it. */ - -static reg_errcode_t -#ifdef RE_ENABLE_I18N -build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - re_charset_t *mbcset, Idx *char_class_alloc, - const unsigned char *class_name, reg_syntax_t syntax) -#else /* not RE_ENABLE_I18N */ -build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - const unsigned char *class_name, reg_syntax_t syntax) -#endif /* not RE_ENABLE_I18N */ -{ - int i; - const char *name = (const char *) class_name; - - /* In case of REG_ICASE "upper" and "lower" match the both of - upper and lower cases. */ - if ((syntax & RE_ICASE) - && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) - name = "alpha"; - -#ifdef RE_ENABLE_I18N - /* Check the space of the arrays. */ - if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nchar_classes is 0. */ - Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1; - /* Use realloc since array is NULL if *alloc == 0. */ - wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, - new_char_class_alloc); - if (BE (new_char_classes == NULL, 0)) - return REG_ESPACE; - mbcset->char_classes = new_char_classes; - *char_class_alloc = new_char_class_alloc; - } - mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); -#endif /* RE_ENABLE_I18N */ - -#define BUILD_CHARCLASS_LOOP(ctype_func) \ - do { \ - if (BE (trans != NULL, 0)) \ - { \ - for (i = 0; i < SBC_MAX; ++i) \ - if (ctype_func (i)) \ - bitset_set (sbcset, trans[i]); \ - } \ - else \ - { \ - for (i = 0; i < SBC_MAX; ++i) \ - if (ctype_func (i)) \ - bitset_set (sbcset, i); \ - } \ - } while (0) - - if (strcmp (name, "alnum") == 0) - BUILD_CHARCLASS_LOOP (isalnum); - else if (strcmp (name, "cntrl") == 0) - BUILD_CHARCLASS_LOOP (iscntrl); - else if (strcmp (name, "lower") == 0) - BUILD_CHARCLASS_LOOP (islower); - else if (strcmp (name, "space") == 0) - BUILD_CHARCLASS_LOOP (isspace); - else if (strcmp (name, "alpha") == 0) - BUILD_CHARCLASS_LOOP (isalpha); - else if (strcmp (name, "digit") == 0) - BUILD_CHARCLASS_LOOP (isdigit); - else if (strcmp (name, "print") == 0) - BUILD_CHARCLASS_LOOP (isprint); - else if (strcmp (name, "upper") == 0) - BUILD_CHARCLASS_LOOP (isupper); - else if (strcmp (name, "blank") == 0) - BUILD_CHARCLASS_LOOP (isblank); - else if (strcmp (name, "graph") == 0) - BUILD_CHARCLASS_LOOP (isgraph); - else if (strcmp (name, "punct") == 0) - BUILD_CHARCLASS_LOOP (ispunct); - else if (strcmp (name, "xdigit") == 0) - BUILD_CHARCLASS_LOOP (isxdigit); - else - return REG_ECTYPE; - - return REG_NOERROR; -} - -static bin_tree_t * -build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, - const unsigned char *class_name, - const unsigned char *extra, bool non_match, - reg_errcode_t *err) -{ - re_bitset_ptr_t sbcset; -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; - Idx alloc = 0; -#endif /* not RE_ENABLE_I18N */ - reg_errcode_t ret; - re_token_t br_token; - bin_tree_t *tree; - - sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); -#ifdef RE_ENABLE_I18N - mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); -#endif /* RE_ENABLE_I18N */ - -#ifdef RE_ENABLE_I18N - if (BE (sbcset == NULL || mbcset == NULL, 0)) -#else /* not RE_ENABLE_I18N */ - if (BE (sbcset == NULL, 0)) -#endif /* not RE_ENABLE_I18N */ - { - *err = REG_ESPACE; - return NULL; - } - - if (non_match) - { -#ifdef RE_ENABLE_I18N - mbcset->non_match = 1; -#endif /* not RE_ENABLE_I18N */ - } - - /* We don't care the syntax in this case. */ - ret = build_charclass (trans, sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &alloc, -#endif /* RE_ENABLE_I18N */ - class_name, 0); - - if (BE (ret != REG_NOERROR, 0)) - { - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - *err = ret; - return NULL; - } - /* \w match '_' also. */ - for (; *extra; extra++) - bitset_set (sbcset, *extra); - - /* If it is non-matching list. */ - if (non_match) - bitset_not (sbcset); - -#ifdef RE_ENABLE_I18N - /* Ensure only single byte characters are set. */ - if (dfa->mb_cur_max > 1) - bitset_mask (sbcset, dfa->sb_char); -#endif - - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (tree == NULL, 0)) - goto build_word_op_espace; - -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - bin_tree_t *mbc_tree; - /* Build a tree for complex bracket. */ - br_token.type = COMPLEX_BRACKET; - br_token.opr.mbcset = mbcset; - dfa->has_mb_node = 1; - mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (mbc_tree == NULL, 0)) - goto build_word_op_espace; - /* Then join them by ALT node. */ - tree = create_tree (dfa, tree, mbc_tree, OP_ALT); - if (BE (mbc_tree != NULL, 1)) - return tree; - } - else - { - free_charset (mbcset); - return tree; - } -#else /* not RE_ENABLE_I18N */ - return tree; -#endif /* not RE_ENABLE_I18N */ - - build_word_op_espace: - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - *err = REG_ESPACE; - return NULL; -} - -/* This is intended for the expressions like "a{1,3}". - Fetch a number from `input', and return the number. - Return REG_MISSING if the number field is empty like "{,1}". - Return REG_ERROR if an error occurred. */ - -static Idx -fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) -{ - Idx num = REG_MISSING; - unsigned char c; - while (1) - { - fetch_token (token, input, syntax); - c = token->opr.c; - if (BE (token->type == END_OF_RE, 0)) - return REG_ERROR; - if (token->type == OP_CLOSE_DUP_NUM || c == ',') - break; - num = ((token->type != CHARACTER || c < '0' || '9' < c - || num == REG_ERROR) - ? REG_ERROR - : ((num == REG_MISSING) ? c - '0' : num * 10 + c - '0')); - num = (num > RE_DUP_MAX) ? REG_ERROR : num; - } - return num; -} - -#ifdef RE_ENABLE_I18N -static void -free_charset (re_charset_t *cset) -{ - re_free (cset->mbchars); -# ifdef _LIBC - re_free (cset->coll_syms); - re_free (cset->equiv_classes); - re_free (cset->range_starts); - re_free (cset->range_ends); -# endif - re_free (cset->char_classes); - re_free (cset); -} -#endif /* RE_ENABLE_I18N */ - -/* Functions for binary tree operation. */ - -/* Create a tree node. */ - -static bin_tree_t * -create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, - re_token_type_t type) -{ - re_token_t t; - t.type = type; - return create_token_tree (dfa, left, right, &t); -} - -static bin_tree_t * -create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, - const re_token_t *token) -{ - bin_tree_t *tree; - if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0)) - { - bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); - - if (storage == NULL) - return NULL; - storage->next = dfa->str_tree_storage; - dfa->str_tree_storage = storage; - dfa->str_tree_storage_idx = 0; - } - tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; - - tree->parent = NULL; - tree->left = left; - tree->right = right; - tree->token = *token; - tree->token.duplicated = 0; - tree->token.opt_subexp = 0; - tree->first = NULL; - tree->next = NULL; - tree->node_idx = REG_MISSING; - - if (left != NULL) - left->parent = tree; - if (right != NULL) - right->parent = tree; - return tree; -} - -/* Mark the tree SRC as an optional subexpression. - To be called from preorder or postorder. */ - -static reg_errcode_t -mark_opt_subexp (void *extra, bin_tree_t *node) -{ - Idx idx = (Idx) (long) extra; - if (node->token.type == SUBEXP && node->token.opr.idx == idx) - node->token.opt_subexp = 1; - - return REG_NOERROR; -} - -/* Free the allocated memory inside NODE. */ - -static void -free_token (re_token_t *node) -{ -#ifdef RE_ENABLE_I18N - if (node->type == COMPLEX_BRACKET && node->duplicated == 0) - free_charset (node->opr.mbcset); - else -#endif /* RE_ENABLE_I18N */ - if (node->type == SIMPLE_BRACKET && node->duplicated == 0) - re_free (node->opr.sbcset); -} - -/* Worker function for tree walking. Free the allocated memory inside NODE - and its children. */ - -static reg_errcode_t -free_tree (void *extra, bin_tree_t *node) -{ - free_token (&node->token); - return REG_NOERROR; -} - - -/* Duplicate the node SRC, and return new node. This is a preorder - visit similar to the one implemented by the generic visitor, but - we need more infrastructure to maintain two parallel trees --- so, - it's easier to duplicate. */ - -static bin_tree_t * -duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa) -{ - const bin_tree_t *node; - bin_tree_t *dup_root; - bin_tree_t **p_new = &dup_root, *dup_node = root->parent; - - for (node = root; ; ) - { - /* Create a new tree and link it back to the current parent. */ - *p_new = create_token_tree (dfa, NULL, NULL, &node->token); - if (*p_new == NULL) - return NULL; - (*p_new)->parent = dup_node; - (*p_new)->token.duplicated = 1; - dup_node = *p_new; - - /* Go to the left node, or up and to the right. */ - if (node->left) - { - node = node->left; - p_new = &dup_node->left; - } - else - { - const bin_tree_t *prev = NULL; - while (node->right == prev || node->right == NULL) - { - prev = node; - node = node->parent; - dup_node = dup_node->parent; - if (!node) - return dup_root; - } - node = node->right; - p_new = &dup_node->right; - } - } -} diff --git a/grub-core/gnulib/regex.c b/grub-core/gnulib/regex.c deleted file mode 100644 index ba0eebee7..000000000 --- a/grub-core/gnulib/regex.c +++ /dev/null @@ -1,72 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2005, 2006, 2009, 2010 Free Software Foundation, - Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Make sure noone compiles this code with a C++ compiler. */ -#if defined __cplusplus && defined _LIBC -# error "This is C code, use a C compiler" -#endif - -#ifdef _LIBC -/* We have to keep the namespace clean. */ -# define regfree(preg) __regfree (preg) -# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) -# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) -# define regerror(errcode, preg, errbuf, errbuf_size) \ - __regerror(errcode, preg, errbuf, errbuf_size) -# define re_set_registers(bu, re, nu, st, en) \ - __re_set_registers (bu, re, nu, st, en) -# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ - __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) -# define re_match(bufp, string, size, pos, regs) \ - __re_match (bufp, string, size, pos, regs) -# define re_search(bufp, string, size, startpos, range, regs) \ - __re_search (bufp, string, size, startpos, range, regs) -# define re_compile_pattern(pattern, length, bufp) \ - __re_compile_pattern (pattern, length, bufp) -# define re_set_syntax(syntax) __re_set_syntax (syntax) -# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ - __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) -# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) - -# include "../locale/localeinfo.h" -#endif - -/* On some systems, limits.h sets RE_DUP_MAX to a lower value than - GNU regex allows. Include it before , which correctly - #undefs RE_DUP_MAX and sets it to the right value. */ -#include - -#include -#include "regex_internal.h" - -#include "regex_internal.c" -#include "regcomp.c" -#include "regexec.c" - -/* Binary backward compatibility. */ -#if _LIBC -# include -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) -link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") -int re_max_failures = 2000; -# endif -#endif diff --git a/grub-core/gnulib/regex.h b/grub-core/gnulib/regex.h deleted file mode 100644 index 1c139d680..000000000 --- a/grub-core/gnulib/regex.h +++ /dev/null @@ -1,679 +0,0 @@ -/* Definitions for data structures and routines for the regular - expression library. - Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993, 1995, 1996, 1997, 1998, - 2000, 2001, 2002, 2003, 2005, 2006, 2009, 2010 Free Software Foundation, - Inc. - This file is part of the GNU C Library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _REGEX_H -#define _REGEX_H 1 - -#include - -/* Allow the use in C++ code. */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Define __USE_GNU_REGEX to declare GNU extensions that violate the - POSIX name space rules. */ -#undef __USE_GNU_REGEX -#if (defined _GNU_SOURCE \ - || (!defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE \ - && !defined _XOPEN_SOURCE)) -# define __USE_GNU_REGEX 1 -#endif - -#ifdef _REGEX_LARGE_OFFSETS - -/* Use types and values that are wide enough to represent signed and - unsigned byte offsets in memory. This currently works only when - the regex code is used outside of the GNU C library; it is not yet - supported within glibc itself, and glibc users should not define - _REGEX_LARGE_OFFSETS. */ - -/* The type of the offset of a byte within a string. - For historical reasons POSIX 1003.1-2004 requires that regoff_t be - at least as wide as off_t. However, many common POSIX platforms set - regoff_t to the more-sensible ssize_t and the Open Group has - signalled its intention to change the requirement to be that - regoff_t be at least as wide as ptrdiff_t and ssize_t; see XBD ERN - 60 (2005-08-25). We don't know of any hosts where ssize_t or - ptrdiff_t is wider than ssize_t, so ssize_t is safe. */ -typedef ssize_t regoff_t; - -/* The type of nonnegative object indexes. Traditionally, GNU regex - uses 'int' for these. Code that uses __re_idx_t should work - regardless of whether the type is signed. */ -typedef size_t __re_idx_t; - -/* The type of object sizes. */ -typedef size_t __re_size_t; - -/* The type of object sizes, in places where the traditional code - uses unsigned long int. */ -typedef size_t __re_long_size_t; - -#else - -/* Use types that are binary-compatible with the traditional GNU regex - implementation, which mishandles strings longer than INT_MAX. */ - -typedef int regoff_t; -typedef int __re_idx_t; -typedef unsigned int __re_size_t; -typedef unsigned long int __re_long_size_t; - -#endif - -/* The following two types have to be signed and unsigned integer type - wide enough to hold a value of a pointer. For most ANSI compilers - ptrdiff_t and size_t should be likely OK. Still size of these two - types is 2 for Microsoft C. Ugh... */ -typedef long int s_reg_t; -typedef unsigned long int active_reg_t; - -/* The following bits are used to determine the regexp syntax we - recognize. The set/not-set meanings are chosen so that Emacs syntax - remains the value 0. The bits are given in alphabetical order, and - the definitions shifted by one from the previous bit; thus, when we - add or remove a bit, only one other definition need change. */ -typedef unsigned long int reg_syntax_t; - -#ifdef __USE_GNU_REGEX - -/* If this bit is not set, then \ inside a bracket expression is literal. - If set, then such a \ quotes the following character. */ -# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) - -/* If this bit is not set, then + and ? are operators, and \+ and \? are - literals. - If set, then \+ and \? are operators and + and ? are literals. */ -# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) - -/* If this bit is set, then character classes are supported. They are: - [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], - [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. - If not set, then character classes are not supported. */ -# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) - -/* If this bit is set, then ^ and $ are always anchors (outside bracket - expressions, of course). - If this bit is not set, then it depends: - ^ is an anchor if it is at the beginning of a regular - expression or after an open-group or an alternation operator; - $ is an anchor if it is at the end of a regular expression, or - before a close-group or an alternation operator. - - This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because - POSIX draft 11.2 says that * etc. in leading positions is undefined. - We already implemented a previous draft which made those constructs - invalid, though, so we haven't changed the code back. */ -# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) - -/* If this bit is set, then special characters are always special - regardless of where they are in the pattern. - If this bit is not set, then special characters are special only in - some contexts; otherwise they are ordinary. Specifically, - * + ? and intervals are only special when not after the beginning, - open-group, or alternation operator. */ -# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) - -/* If this bit is set, then *, +, ?, and { cannot be first in an re or - immediately after an alternation or begin-group operator. */ -# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) - -/* If this bit is set, then . matches newline. - If not set, then it doesn't. */ -# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) - -/* If this bit is set, then . doesn't match NUL. - If not set, then it does. */ -# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) - -/* If this bit is set, nonmatching lists [^...] do not match newline. - If not set, they do. */ -# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) - -/* If this bit is set, either \{...\} or {...} defines an - interval, depending on RE_NO_BK_BRACES. - If not set, \{, \}, {, and } are literals. */ -# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) - -/* If this bit is set, +, ? and | aren't recognized as operators. - If not set, they are. */ -# define RE_LIMITED_OPS (RE_INTERVALS << 1) - -/* If this bit is set, newline is an alternation operator. - If not set, newline is literal. */ -# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) - -/* If this bit is set, then `{...}' defines an interval, and \{ and \} - are literals. - If not set, then `\{...\}' defines an interval. */ -# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) - -/* If this bit is set, (...) defines a group, and \( and \) are literals. - If not set, \(...\) defines a group, and ( and ) are literals. */ -# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) - -/* If this bit is set, then \ matches . - If not set, then \ is a back-reference. */ -# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) - -/* If this bit is set, then | is an alternation operator, and \| is literal. - If not set, then \| is an alternation operator, and | is literal. */ -# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) - -/* If this bit is set, then an ending range point collating higher - than the starting range point, as in [z-a], is invalid. - If not set, then when ending range point collates higher than the - starting range point, the range is ignored. */ -# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) - -/* If this bit is set, then an unmatched ) is ordinary. - If not set, then an unmatched ) is invalid. */ -# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) - -/* If this bit is set, succeed as soon as we match the whole pattern, - without further backtracking. */ -# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) - -/* If this bit is set, do not process the GNU regex operators. - If not set, then the GNU regex operators are recognized. */ -# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) - -/* If this bit is set, turn on internal regex debugging. - If not set, and debugging was on, turn it off. - This only works if regex.c is compiled -DDEBUG. - We define this bit always, so that all that's needed to turn on - debugging is to recompile regex.c; the calling code can always have - this bit set, and it won't affect anything in the normal case. */ -# define RE_DEBUG (RE_NO_GNU_OPS << 1) - -/* If this bit is set, a syntactically invalid interval is treated as - a string of ordinary characters. For example, the ERE 'a{1' is - treated as 'a\{1'. */ -# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) - -/* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ -# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) - -/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only - for ^, because it is difficult to scan the regex backwards to find - whether ^ should be special. */ -# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) - -/* If this bit is set, then \{ cannot be first in a regex or - immediately after an alternation, open-group or \} operator. */ -# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) - -/* If this bit is set, then no_sub will be set to 1 during - re_compile_pattern. */ -# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) - -#endif /* defined __USE_GNU_REGEX */ - -/* This global variable defines the particular regexp syntax to use (for - some interfaces). When a regexp is compiled, the syntax used is - stored in the pattern buffer, so changing this does not affect - already-compiled regexps. */ -extern reg_syntax_t re_syntax_options; - -#ifdef __USE_GNU_REGEX -/* Define combinations of the above bits for the standard possibilities. - (The [[[ comments delimit what gets put into the Texinfo file, so - don't delete them!) */ -/* [[[begin syntaxes]]] */ -# define RE_SYNTAX_EMACS 0 - -# define RE_SYNTAX_AWK \ - (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ - | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ - | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) - -# define RE_SYNTAX_GNU_AWK \ - ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ - & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ - | RE_CONTEXT_INVALID_OPS )) - -# define RE_SYNTAX_POSIX_AWK \ - (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ - | RE_INTERVALS | RE_NO_GNU_OPS) - -# define RE_SYNTAX_GREP \ - (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ - | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ - | RE_NEWLINE_ALT) - -# define RE_SYNTAX_EGREP \ - (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ - | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ - | RE_NO_BK_VBAR) - -# define RE_SYNTAX_POSIX_EGREP \ - (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \ - | RE_INVALID_INTERVAL_ORD) - -/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ -# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC - -# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC - -/* Syntax bits common to both basic and extended POSIX regex syntax. */ -# define _RE_SYNTAX_POSIX_COMMON \ - (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ - | RE_INTERVALS | RE_NO_EMPTY_RANGES) - -# define RE_SYNTAX_POSIX_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) - -/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes - RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this - isn't minimal, since other operators, such as \`, aren't disabled. */ -# define RE_SYNTAX_POSIX_MINIMAL_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) - -# define RE_SYNTAX_POSIX_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ - | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) - -/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is - removed and RE_NO_BK_REFS is added. */ -# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) -/* [[[end syntaxes]]] */ - -#endif /* defined __USE_GNU_REGEX */ - -#ifdef __USE_GNU_REGEX - -/* Maximum number of duplicates an interval can allow. POSIX-conforming - systems might define this in , but we want our - value, so remove any previous define. */ -# ifdef RE_DUP_MAX -# undef RE_DUP_MAX -# endif - -/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored - the counter as a 2-byte signed integer. This is no longer true, so - RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to - ((SIZE_MAX - 2) / 10 - 1) if _REGEX_LARGE_OFFSETS is defined. - However, there would be a huge performance problem if someone - actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains - its historical value. */ -# define RE_DUP_MAX (0x7fff) - -#endif /* defined __USE_GNU_REGEX */ - - -/* POSIX `cflags' bits (i.e., information for `regcomp'). */ - -/* If this bit is set, then use extended regular expression syntax. - If not set, then use basic regular expression syntax. */ -#define REG_EXTENDED 1 - -/* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ -#define REG_ICASE (1 << 1) - -/* If this bit is set, then anchors do not match at newline - characters in the string. - If not set, then anchors do match at newlines. */ -#define REG_NEWLINE (1 << 2) - -/* If this bit is set, then report only success or fail in regexec. - If not set, then returns differ between not matching and errors. */ -#define REG_NOSUB (1 << 3) - - -/* POSIX `eflags' bits (i.e., information for regexec). */ - -/* If this bit is set, then the beginning-of-line operator doesn't match - the beginning of the string (presumably because it's not the - beginning of a line). - If not set, then the beginning-of-line operator does match the - beginning of the string. */ -#define REG_NOTBOL 1 - -/* Like REG_NOTBOL, except for the end-of-line. */ -#define REG_NOTEOL (1 << 1) - -/* Use PMATCH[0] to delimit the start and end of the search in the - buffer. */ -#define REG_STARTEND (1 << 2) - - -/* If any error codes are removed, changed, or added, update the - `__re_error_msgid' table in regcomp.c. */ - -typedef enum -{ - _REG_ENOSYS = -1, /* This will never happen for this implementation. */ - _REG_NOERROR = 0, /* Success. */ - _REG_NOMATCH, /* Didn't find a match (for regexec). */ - - /* POSIX regcomp return error codes. (In the order listed in the - standard.) */ - _REG_BADPAT, /* Invalid pattern. */ - _REG_ECOLLATE, /* Invalid collating element. */ - _REG_ECTYPE, /* Invalid character class name. */ - _REG_EESCAPE, /* Trailing backslash. */ - _REG_ESUBREG, /* Invalid back reference. */ - _REG_EBRACK, /* Unmatched left bracket. */ - _REG_EPAREN, /* Parenthesis imbalance. */ - _REG_EBRACE, /* Unmatched \{. */ - _REG_BADBR, /* Invalid contents of \{\}. */ - _REG_ERANGE, /* Invalid range end. */ - _REG_ESPACE, /* Ran out of memory. */ - _REG_BADRPT, /* No preceding re for repetition op. */ - - /* Error codes we've added. */ - _REG_EEND, /* Premature end. */ - _REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ - _REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ -} reg_errcode_t; - -#ifdef _XOPEN_SOURCE -# define REG_ENOSYS _REG_ENOSYS -#endif -#define REG_NOERROR _REG_NOERROR -#define REG_NOMATCH _REG_NOMATCH -#define REG_BADPAT _REG_BADPAT -#define REG_ECOLLATE _REG_ECOLLATE -#define REG_ECTYPE _REG_ECTYPE -#define REG_EESCAPE _REG_EESCAPE -#define REG_ESUBREG _REG_ESUBREG -#define REG_EBRACK _REG_EBRACK -#define REG_EPAREN _REG_EPAREN -#define REG_EBRACE _REG_EBRACE -#define REG_BADBR _REG_BADBR -#define REG_ERANGE _REG_ERANGE -#define REG_ESPACE _REG_ESPACE -#define REG_BADRPT _REG_BADRPT -#define REG_EEND _REG_EEND -#define REG_ESIZE _REG_ESIZE -#define REG_ERPAREN _REG_ERPAREN - -/* struct re_pattern_buffer normally uses member names like `buffer' - that POSIX does not allow. In POSIX mode these members have names - with leading `re_' (e.g., `re_buffer'). */ -#ifdef __USE_GNU_REGEX -# define _REG_RE_NAME(id) id -# define _REG_RM_NAME(id) id -#else -# define _REG_RE_NAME(id) re_##id -# define _REG_RM_NAME(id) rm_##id -#endif - -/* The user can specify the type of the re_translate member by - defining the macro RE_TRANSLATE_TYPE, which defaults to unsigned - char *. This pollutes the POSIX name space, so in POSIX mode just - use unsigned char *. */ -#ifdef __USE_GNU_REGEX -# ifndef RE_TRANSLATE_TYPE -# define RE_TRANSLATE_TYPE unsigned char * -# endif -# define REG_TRANSLATE_TYPE RE_TRANSLATE_TYPE -#else -# define REG_TRANSLATE_TYPE unsigned char * -#endif - -/* This data structure represents a compiled pattern. Before calling - the pattern compiler, the fields `buffer', `allocated', `fastmap', - `translate', and `no_sub' can be set. After the pattern has been - compiled, the `re_nsub' field is available. All other fields are - private to the regex routines. */ - -struct re_dfa_t; -typedef struct re_dfa_t re_dfa_t; - -struct re_pattern_buffer -{ - /* Space that holds the compiled pattern. It is declared as - `unsigned char *' because its elements are sometimes used as - array indexes. */ - re_dfa_t *_REG_RE_NAME (buffer); - - /* Number of bytes to which `buffer' points. */ - __re_long_size_t _REG_RE_NAME (allocated); - - /* Number of bytes actually used in `buffer'. */ - __re_long_size_t _REG_RE_NAME (used); - - /* Syntax setting with which the pattern was compiled. */ - reg_syntax_t _REG_RE_NAME (syntax); - - /* Pointer to a fastmap, if any, otherwise zero. re_search uses the - fastmap, if there is one, to skip over impossible starting points - for matches. */ - char *_REG_RE_NAME (fastmap); - - /* Either a translate table to apply to all characters before - comparing them, or zero for no translation. The translation is - applied to a pattern when it is compiled and to a string when it - is matched. */ - REG_TRANSLATE_TYPE _REG_RE_NAME (translate); - - /* Number of subexpressions found by the compiler. */ - size_t re_nsub; - - /* Zero if this pattern cannot match the empty string, one else. - Well, in truth it's used only in `re_search_2', to see whether or - not we should use the fastmap, so we don't set this absolutely - perfectly; see `re_compile_fastmap' (the `duplicate' case). */ - unsigned int _REG_RE_NAME (can_be_null) : 1; - - /* If REGS_UNALLOCATED, allocate space in the `regs' structure - for `max (RE_NREGS, re_nsub + 1)' groups. - If REGS_REALLOCATE, reallocate space if necessary. - If REGS_FIXED, use what's there. */ -#ifdef __USE_GNU_REGEX -# define REGS_UNALLOCATED 0 -# define REGS_REALLOCATE 1 -# define REGS_FIXED 2 -#endif - unsigned int _REG_RE_NAME (regs_allocated) : 2; - - /* Set to zero when `re_compile_pattern' compiles a pattern; set to - one by `re_compile_fastmap' if it updates the fastmap. */ - unsigned int _REG_RE_NAME (fastmap_accurate) : 1; - - /* If set, `re_match_2' does not return information about - subexpressions. */ - unsigned int _REG_RE_NAME (no_sub) : 1; - - /* If set, a beginning-of-line anchor doesn't match at the beginning - of the string. */ - unsigned int _REG_RE_NAME (not_bol) : 1; - - /* Similarly for an end-of-line anchor. */ - unsigned int _REG_RE_NAME (not_eol) : 1; - - /* If true, an anchor at a newline matches. */ - unsigned int _REG_RE_NAME (newline_anchor) : 1; - -/* [[[end pattern_buffer]]] */ -}; - -typedef struct re_pattern_buffer regex_t; - -/* This is the structure we store register match data in. See - regex.texinfo for a full description of what registers match. */ -struct re_registers -{ - __re_size_t _REG_RM_NAME (num_regs); - regoff_t *_REG_RM_NAME (start); - regoff_t *_REG_RM_NAME (end); -}; - - -/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, - `re_match_2' returns information about at least this many registers - the first time a `regs' structure is passed. */ -#if !defined RE_NREGS && defined __USE_GNU_REGEX -# define RE_NREGS 30 -#endif - - -/* POSIX specification for registers. Aside from the different names than - `re_registers', POSIX uses an array of structures, instead of a - structure of arrays. */ -typedef struct -{ - regoff_t rm_so; /* Byte offset from string's start to substring's start. */ - regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ -} regmatch_t; - -/* Declarations for routines. */ - -/* Sets the current default syntax to SYNTAX, and return the old syntax. - You can also simply assign to the `re_syntax_options' variable. */ -extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); - -/* Compile the regular expression PATTERN, with length LENGTH - and syntax given by the global `re_syntax_options', into the buffer - BUFFER. Return NULL if successful, and an error string if not. */ -extern const char *re_compile_pattern (const char *__pattern, size_t __length, - struct re_pattern_buffer *__buffer); - - -/* Compile a fastmap for the compiled pattern in BUFFER; used to - accelerate searches. Return 0 if successful and -2 if was an - internal error. */ -extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); - - -/* Search in the string STRING (with length LENGTH) for the pattern - compiled into BUFFER. Start searching at position START, for RANGE - characters. Return the starting position of the match, -1 for no - match, or -2 for an internal error. Also return register - information in REGS (if REGS and BUFFER->no_sub are nonzero). */ -extern regoff_t re_search (struct re_pattern_buffer *__buffer, - const char *__string, __re_idx_t __length, - __re_idx_t __start, regoff_t __range, - struct re_registers *__regs); - - -/* Like `re_search', but search in the concatenation of STRING1 and - STRING2. Also, stop searching at index START + STOP. */ -extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, - const char *__string1, __re_idx_t __length1, - const char *__string2, __re_idx_t __length2, - __re_idx_t __start, regoff_t __range, - struct re_registers *__regs, - __re_idx_t __stop); - - -/* Like `re_search', but return how many characters in STRING the regexp - in BUFFER matched, starting at position START. */ -extern regoff_t re_match (struct re_pattern_buffer *__buffer, - const char *__string, __re_idx_t __length, - __re_idx_t __start, struct re_registers *__regs); - - -/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ -extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, - const char *__string1, __re_idx_t __length1, - const char *__string2, __re_idx_t __length2, - __re_idx_t __start, struct re_registers *__regs, - __re_idx_t __stop); - - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using BUFFER and REGS will use this memory - for recording register information. STARTS and ENDS must be - allocated with malloc, and must each be at least `NUM_REGS * sizeof - (regoff_t)' bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - BUFFER will allocate its own register data, without freeing the old - data. */ -extern void re_set_registers (struct re_pattern_buffer *__buffer, - struct re_registers *__regs, - __re_size_t __num_regs, - regoff_t *__starts, regoff_t *__ends); - -#if defined _REGEX_RE_COMP || defined _LIBC -# ifndef _CRAY -/* 4.2 bsd compatibility. */ -extern char *re_comp (const char *); -extern int re_exec (const char *); -# endif -#endif - -/* GCC 2.95 and later have "__restrict"; C99 compilers have - "restrict", and "configure" may have defined "restrict". - Other compilers use __restrict, __restrict__, and _Restrict, and - 'configure' might #define 'restrict' to those words, so pick a - different name. */ -#ifndef _Restrict_ -# if 199901L <= __STDC_VERSION__ -# define _Restrict_ restrict -# elif 2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__) -# define _Restrict_ __restrict -# else -# define _Restrict_ -# endif -#endif -/* gcc 3.1 and up support the [restrict] syntax. Don't trust - sys/cdefs.h's definition of __restrict_arr, though, as it - mishandles gcc -ansi -pedantic. */ -#ifndef _Restrict_arr_ -# if ((199901L <= __STDC_VERSION__ \ - || ((3 < __GNUC__ || (3 == __GNUC__ && 1 <= __GNUC_MINOR__)) \ - && !__STRICT_ANSI__)) \ - && !defined __GNUG__) -# define _Restrict_arr_ _Restrict_ -# else -# define _Restrict_arr_ -# endif -#endif - -/* POSIX compatibility. */ -extern int regcomp (regex_t *_Restrict_ __preg, - const char *_Restrict_ __pattern, - int __cflags); - -extern int regexec (const regex_t *_Restrict_ __preg, - const char *_Restrict_ __string, size_t __nmatch, - regmatch_t __pmatch[_Restrict_arr_], - int __eflags); - -extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg, - char *_Restrict_ __errbuf, size_t __errbuf_size); - -extern void regfree (regex_t *__preg); - - -#ifdef __cplusplus -} -#endif /* C++ */ - -#endif /* regex.h */ diff --git a/grub-core/gnulib/regex_internal.c b/grub-core/gnulib/regex_internal.c deleted file mode 100644 index 98b8d5d21..000000000 --- a/grub-core/gnulib/regex_internal.c +++ /dev/null @@ -1,1742 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free - Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -static void re_string_construct_common (const char *str, Idx len, - re_string_t *pstr, - RE_TRANSLATE_TYPE trans, bool icase, - const re_dfa_t *dfa) internal_function; -static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, - const re_node_set *nodes, - re_hashval_t hash) internal_function; -static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, - const re_node_set *nodes, - unsigned int context, - re_hashval_t hash) internal_function; - -/* Functions for string operation. */ - -/* This function allocate the buffers. It is necessary to call - re_string_reconstruct before using the object. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len, - RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) -{ - reg_errcode_t ret; - Idx init_buf_len; - - /* Ensure at least one character fits into the buffers. */ - if (init_len < dfa->mb_cur_max) - init_len = dfa->mb_cur_max; - init_buf_len = (len + 1 < init_len) ? len + 1: init_len; - re_string_construct_common (str, len, pstr, trans, icase, dfa); - - ret = re_string_realloc_buffers (pstr, init_buf_len); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - pstr->word_char = dfa->word_char; - pstr->word_ops_used = dfa->word_ops_used; - pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; - pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; - pstr->valid_raw_len = pstr->valid_len; - return REG_NOERROR; -} - -/* This function allocate the buffers, and initialize them. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_string_construct (re_string_t *pstr, const char *str, Idx len, - RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) -{ - reg_errcode_t ret; - memset (pstr, '\0', sizeof (re_string_t)); - re_string_construct_common (str, len, pstr, trans, icase, dfa); - - if (len > 0) - { - ret = re_string_realloc_buffers (pstr, len + 1); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; - - if (icase) - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - while (1) - { - ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - if (pstr->valid_raw_len >= len) - break; - if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) - break; - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - } - else -#endif /* RE_ENABLE_I18N */ - build_upper_buffer (pstr); - } - else - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - build_wcs_buffer (pstr); - else -#endif /* RE_ENABLE_I18N */ - { - if (trans != NULL) - re_string_translate_buffer (pstr); - else - { - pstr->valid_len = pstr->bufs_len; - pstr->valid_raw_len = pstr->bufs_len; - } - } - } - - return REG_NOERROR; -} - -/* Helper functions for re_string_allocate, and re_string_construct. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) -{ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - wint_t *new_wcs; - - /* Avoid overflow. */ - size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); - if (BE (SIZE_MAX / max_object_size < new_buf_len, 0)) - return REG_ESPACE; - - new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); - if (BE (new_wcs == NULL, 0)) - return REG_ESPACE; - pstr->wcs = new_wcs; - if (pstr->offsets != NULL) - { - Idx *new_offsets = re_realloc (pstr->offsets, Idx, new_buf_len); - if (BE (new_offsets == NULL, 0)) - return REG_ESPACE; - pstr->offsets = new_offsets; - } - } -#endif /* RE_ENABLE_I18N */ - if (pstr->mbs_allocated) - { - unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, - new_buf_len); - if (BE (new_mbs == NULL, 0)) - return REG_ESPACE; - pstr->mbs = new_mbs; - } - pstr->bufs_len = new_buf_len; - return REG_NOERROR; -} - - -static void -internal_function -re_string_construct_common (const char *str, Idx len, re_string_t *pstr, - RE_TRANSLATE_TYPE trans, bool icase, - const re_dfa_t *dfa) -{ - pstr->raw_mbs = (const unsigned char *) str; - pstr->len = len; - pstr->raw_len = len; - pstr->trans = trans; - pstr->icase = icase; - pstr->mbs_allocated = (trans != NULL || icase); - pstr->mb_cur_max = dfa->mb_cur_max; - pstr->is_utf8 = dfa->is_utf8; - pstr->map_notascii = dfa->map_notascii; - pstr->stop = pstr->len; - pstr->raw_stop = pstr->stop; -} - -#ifdef RE_ENABLE_I18N - -/* Build wide character buffer PSTR->WCS. - If the byte sequence of the string are: - (0), (1), (0), (1), - Then wide character buffer will be: - , WEOF , , WEOF , - We use WEOF for padding, they indicate that the position isn't - a first byte of a multibyte character. - - Note that this function assumes PSTR->VALID_LEN elements are already - built and starts from PSTR->VALID_LEN. */ - -static void -internal_function -build_wcs_buffer (re_string_t *pstr) -{ -#ifdef _LIBC - unsigned char buf[MB_LEN_MAX]; - assert (MB_LEN_MAX >= pstr->mb_cur_max); -#else - unsigned char buf[64]; -#endif - mbstate_t prev_st; - Idx byte_idx, end_idx, remain_len; - size_t mbclen; - - /* Build the buffers from pstr->valid_len to either pstr->len or - pstr->bufs_len. */ - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - for (byte_idx = pstr->valid_len; byte_idx < end_idx;) - { - wchar_t wc; - const char *p; - - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - /* Apply the translation if we need. */ - if (BE (pstr->trans != NULL, 0)) - { - int i, ch; - - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; - buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; - } - p = (const char *) buf; - } - else - p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; - mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (BE (mbclen == (size_t) -2, 0)) - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) - { - /* We treat these cases as a singlebyte character. */ - mbclen = 1; - wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; - if (BE (pstr->trans != NULL, 0)) - wc = pstr->trans[wc]; - pstr->cur_state = prev_st; - } - - /* Write wide character and padding. */ - pstr->wcs[byte_idx++] = wc; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = byte_idx; -} - -/* Build wide character buffer PSTR->WCS like build_wcs_buffer, - but for REG_ICASE. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -build_wcs_upper_buffer (re_string_t *pstr) -{ - mbstate_t prev_st; - Idx src_idx, byte_idx, end_idx, remain_len; - size_t mbclen; -#ifdef _LIBC - char buf[MB_LEN_MAX]; - assert (MB_LEN_MAX >= pstr->mb_cur_max); -#else - char buf[64]; -#endif - - byte_idx = pstr->valid_len; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - /* The following optimization assumes that ASCII characters can be - mapped to wide characters with a simple cast. */ - if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) - { - while (byte_idx < end_idx) - { - wchar_t wc; - - if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]) - && mbsinit (&pstr->cur_state)) - { - /* In case of a singlebyte character. */ - pstr->mbs[byte_idx] - = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]); - /* The next step uses the assumption that wchar_t is encoded - ASCII-safe: all ASCII values can be converted like this. */ - pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx]; - ++byte_idx; - continue; - } - - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - mbclen = __mbrtowc (&wc, - ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx - + byte_idx), remain_len, &pstr->cur_state); - if (BE (mbclen < (size_t) -2, 1)) - { - wchar_t wcu = wc; - if (iswlower (wc)) - { - size_t mbcdlen; - - wcu = towupper (wc); - mbcdlen = wcrtomb (buf, wcu, &prev_st); - if (BE (mbclen == mbcdlen, 1)) - memcpy (pstr->mbs + byte_idx, buf, mbclen); - else - { - src_idx = byte_idx; - goto offsets_needed; - } - } - else - memcpy (pstr->mbs + byte_idx, - pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); - pstr->wcs[byte_idx++] = wcu; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - else if (mbclen == (size_t) -1 || mbclen == 0) - { - /* It is an invalid character or '\0'. Just use the byte. */ - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; - pstr->mbs[byte_idx] = ch; - /* And also cast it to wide char. */ - pstr->wcs[byte_idx++] = (wchar_t) ch; - if (BE (mbclen == (size_t) -1, 0)) - pstr->cur_state = prev_st; - } - else - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = byte_idx; - return REG_NOERROR; - } - else - for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) - { - wchar_t wc; - const char *p; - offsets_needed: - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - if (BE (pstr->trans != NULL, 0)) - { - int i, ch; - - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; - buf[i] = pstr->trans[ch]; - } - p = (const char *) buf; - } - else - p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; - mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (BE (mbclen < (size_t) -2, 1)) - { - wchar_t wcu = wc; - if (iswlower (wc)) - { - size_t mbcdlen; - - wcu = towupper (wc); - mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st); - if (BE (mbclen == mbcdlen, 1)) - memcpy (pstr->mbs + byte_idx, buf, mbclen); - else if (mbcdlen != (size_t) -1) - { - size_t i; - - if (byte_idx + mbcdlen > pstr->bufs_len) - { - pstr->cur_state = prev_st; - break; - } - - if (pstr->offsets == NULL) - { - pstr->offsets = re_malloc (Idx, pstr->bufs_len); - - if (pstr->offsets == NULL) - return REG_ESPACE; - } - if (!pstr->offsets_needed) - { - for (i = 0; i < (size_t) byte_idx; ++i) - pstr->offsets[i] = i; - pstr->offsets_needed = 1; - } - - memcpy (pstr->mbs + byte_idx, buf, mbcdlen); - pstr->wcs[byte_idx] = wcu; - pstr->offsets[byte_idx] = src_idx; - for (i = 1; i < mbcdlen; ++i) - { - pstr->offsets[byte_idx + i] - = src_idx + (i < mbclen ? i : mbclen - 1); - pstr->wcs[byte_idx + i] = WEOF; - } - pstr->len += mbcdlen - mbclen; - if (pstr->raw_stop > src_idx) - pstr->stop += mbcdlen - mbclen; - end_idx = (pstr->bufs_len > pstr->len) - ? pstr->len : pstr->bufs_len; - byte_idx += mbcdlen; - src_idx += mbclen; - continue; - } - else - memcpy (pstr->mbs + byte_idx, p, mbclen); - } - else - memcpy (pstr->mbs + byte_idx, p, mbclen); - - if (BE (pstr->offsets_needed != 0, 0)) - { - size_t i; - for (i = 0; i < mbclen; ++i) - pstr->offsets[byte_idx + i] = src_idx + i; - } - src_idx += mbclen; - - pstr->wcs[byte_idx++] = wcu; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - else if (mbclen == (size_t) -1 || mbclen == 0) - { - /* It is an invalid character or '\0'. Just use the byte. */ - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; - - if (BE (pstr->trans != NULL, 0)) - ch = pstr->trans [ch]; - pstr->mbs[byte_idx] = ch; - - if (BE (pstr->offsets_needed != 0, 0)) - pstr->offsets[byte_idx] = src_idx; - ++src_idx; - - /* And also cast it to wide char. */ - pstr->wcs[byte_idx++] = (wchar_t) ch; - if (BE (mbclen == (size_t) -1, 0)) - pstr->cur_state = prev_st; - } - else - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = src_idx; - return REG_NOERROR; -} - -/* Skip characters until the index becomes greater than NEW_RAW_IDX. - Return the index. */ - -static Idx -internal_function -re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc) -{ - mbstate_t prev_st; - Idx rawbuf_idx; - size_t mbclen; - wint_t wc = WEOF; - - /* Skip the characters which are not necessary to check. */ - for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; - rawbuf_idx < new_raw_idx;) - { - wchar_t wc2; - Idx remain_len; - remain_len = pstr->len - rawbuf_idx; - prev_st = pstr->cur_state; - mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx, - remain_len, &pstr->cur_state); - if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0)) - { - /* We treat these cases as a single byte character. */ - if (mbclen == 0 || remain_len == 0) - wc = L'\0'; - else - wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx); - mbclen = 1; - pstr->cur_state = prev_st; - } - else - wc = wc2; - /* Then proceed the next character. */ - rawbuf_idx += mbclen; - } - *last_wc = wc; - return rawbuf_idx; -} -#endif /* RE_ENABLE_I18N */ - -/* Build the buffer PSTR->MBS, and apply the translation if we need. - This function is used in case of REG_ICASE. */ - -static void -internal_function -build_upper_buffer (re_string_t *pstr) -{ - Idx char_idx, end_idx; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) - { - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; - if (BE (pstr->trans != NULL, 0)) - ch = pstr->trans[ch]; - if (islower (ch)) - pstr->mbs[char_idx] = toupper (ch); - else - pstr->mbs[char_idx] = ch; - } - pstr->valid_len = char_idx; - pstr->valid_raw_len = char_idx; -} - -/* Apply TRANS to the buffer in PSTR. */ - -static void -internal_function -re_string_translate_buffer (re_string_t *pstr) -{ - Idx buf_idx, end_idx; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) - { - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; - pstr->mbs[buf_idx] = pstr->trans[ch]; - } - - pstr->valid_len = buf_idx; - pstr->valid_raw_len = buf_idx; -} - -/* This function re-construct the buffers. - Concretely, convert to wide character in case of pstr->mb_cur_max > 1, - convert to upper case in case of REG_ICASE, apply translation. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) -{ - Idx offset; - - if (BE (pstr->raw_mbs_idx <= idx, 0)) - offset = idx - pstr->raw_mbs_idx; - else - { - /* Reset buffer. */ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); -#endif /* RE_ENABLE_I18N */ - pstr->len = pstr->raw_len; - pstr->stop = pstr->raw_stop; - pstr->valid_len = 0; - pstr->raw_mbs_idx = 0; - pstr->valid_raw_len = 0; - pstr->offsets_needed = 0; - pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF - : CONTEXT_NEWLINE | CONTEXT_BEGBUF); - if (!pstr->mbs_allocated) - pstr->mbs = (unsigned char *) pstr->raw_mbs; - offset = idx; - } - - if (BE (offset != 0, 1)) - { - /* Should the already checked characters be kept? */ - if (BE (offset < pstr->valid_raw_len, 1)) - { - /* Yes, move them to the front of the buffer. */ -#ifdef RE_ENABLE_I18N - if (BE (pstr->offsets_needed, 0)) - { - Idx low = 0, high = pstr->valid_len, mid; - do - { - mid = (high + low) / 2; - if (pstr->offsets[mid] > offset) - high = mid; - else if (pstr->offsets[mid] < offset) - low = mid + 1; - else - break; - } - while (low < high); - if (pstr->offsets[mid] < offset) - ++mid; - pstr->tip_context = re_string_context_at (pstr, mid - 1, - eflags); - /* This can be quite complicated, so handle specially - only the common and easy case where the character with - different length representation of lower and upper - case is present at or after offset. */ - if (pstr->valid_len > offset - && mid == offset && pstr->offsets[mid] == offset) - { - memmove (pstr->wcs, pstr->wcs + offset, - (pstr->valid_len - offset) * sizeof (wint_t)); - memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); - pstr->valid_len -= offset; - pstr->valid_raw_len -= offset; - for (low = 0; low < pstr->valid_len; low++) - pstr->offsets[low] = pstr->offsets[low + offset] - offset; - } - else - { - /* Otherwise, just find out how long the partial multibyte - character at offset is and fill it with WEOF/255. */ - pstr->len = pstr->raw_len - idx + offset; - pstr->stop = pstr->raw_stop - idx + offset; - pstr->offsets_needed = 0; - while (mid > 0 && pstr->offsets[mid - 1] == offset) - --mid; - while (mid < pstr->valid_len) - if (pstr->wcs[mid] != WEOF) - break; - else - ++mid; - if (mid == pstr->valid_len) - pstr->valid_len = 0; - else - { - pstr->valid_len = pstr->offsets[mid] - offset; - if (pstr->valid_len) - { - for (low = 0; low < pstr->valid_len; ++low) - pstr->wcs[low] = WEOF; - memset (pstr->mbs, 255, pstr->valid_len); - } - } - pstr->valid_raw_len = pstr->valid_len; - } - } - else -#endif - { - pstr->tip_context = re_string_context_at (pstr, offset - 1, - eflags); -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - memmove (pstr->wcs, pstr->wcs + offset, - (pstr->valid_len - offset) * sizeof (wint_t)); -#endif /* RE_ENABLE_I18N */ - if (BE (pstr->mbs_allocated, 0)) - memmove (pstr->mbs, pstr->mbs + offset, - pstr->valid_len - offset); - pstr->valid_len -= offset; - pstr->valid_raw_len -= offset; -#if DEBUG - assert (pstr->valid_len > 0); -#endif - } - } - else - { -#ifdef RE_ENABLE_I18N - /* No, skip all characters until IDX. */ - Idx prev_valid_len = pstr->valid_len; - - if (BE (pstr->offsets_needed, 0)) - { - pstr->len = pstr->raw_len - idx + offset; - pstr->stop = pstr->raw_stop - idx + offset; - pstr->offsets_needed = 0; - } -#endif - pstr->valid_len = 0; -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - Idx wcs_idx; - wint_t wc = WEOF; - - if (pstr->is_utf8) - { - const unsigned char *raw, *p, *end; - - /* Special case UTF-8. Multi-byte chars start with any - byte other than 0x80 - 0xbf. */ - raw = pstr->raw_mbs + pstr->raw_mbs_idx; - end = raw + (offset - pstr->mb_cur_max); - if (end < pstr->raw_mbs) - end = pstr->raw_mbs; - p = raw + offset - 1; -#ifdef _LIBC - /* We know the wchar_t encoding is UCS4, so for the simple - case, ASCII characters, skip the conversion step. */ - if (isascii (*p) && BE (pstr->trans == NULL, 1)) - { - memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); - /* pstr->valid_len = 0; */ - wc = (wchar_t) *p; - } - else -#endif - for (; p >= end; --p) - if ((*p & 0xc0) != 0x80) - { - mbstate_t cur_state; - wchar_t wc2; - Idx mlen = raw + pstr->len - p; - size_t mbclen; - -#if 0 /* dead code: buf is set but never used */ - unsigned char buf[6]; - if (BE (pstr->trans != NULL, 0)) - { - int i = mlen < 6 ? mlen : 6; - while (--i >= 0) - buf[i] = pstr->trans[p[i]]; - } -#endif - /* XXX Don't use mbrtowc, we know which conversion - to use (UTF-8 -> UCS4). */ - memset (&cur_state, 0, sizeof (cur_state)); - mbclen = __mbrtowc (&wc2, (const char *) p, mlen, - &cur_state); - if (raw + offset - p <= mbclen - && mbclen < (size_t) -2) - { - memset (&pstr->cur_state, '\0', - sizeof (mbstate_t)); - pstr->valid_len = mbclen - (raw + offset - p); - wc = wc2; - } - break; - } - } - - if (wc == WEOF) - pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; - if (wc == WEOF) - pstr->tip_context - = re_string_context_at (pstr, prev_valid_len - 1, eflags); - else - pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0) - && IS_WIDE_WORD_CHAR (wc)) - ? CONTEXT_WORD - : ((IS_WIDE_NEWLINE (wc) - && pstr->newline_anchor) - ? CONTEXT_NEWLINE : 0)); - if (BE (pstr->valid_len, 0)) - { - for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) - pstr->wcs[wcs_idx] = WEOF; - if (pstr->mbs_allocated) - memset (pstr->mbs, 255, pstr->valid_len); - } - pstr->valid_raw_len = pstr->valid_len; - } - else -#endif /* RE_ENABLE_I18N */ - { - int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; - pstr->valid_raw_len = 0; - if (pstr->trans) - c = pstr->trans[c]; - pstr->tip_context = (bitset_contain (pstr->word_char, c) - ? CONTEXT_WORD - : ((IS_NEWLINE (c) && pstr->newline_anchor) - ? CONTEXT_NEWLINE : 0)); - } - } - if (!BE (pstr->mbs_allocated, 0)) - pstr->mbs += offset; - } - pstr->raw_mbs_idx = idx; - pstr->len -= offset; - pstr->stop -= offset; - - /* Then build the buffers. */ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - if (pstr->icase) - { - reg_errcode_t ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - else - build_wcs_buffer (pstr); - } - else -#endif /* RE_ENABLE_I18N */ - if (BE (pstr->mbs_allocated, 0)) - { - if (pstr->icase) - build_upper_buffer (pstr); - else if (pstr->trans != NULL) - re_string_translate_buffer (pstr); - } - else - pstr->valid_len = pstr->len; - - pstr->cur_idx = 0; - return REG_NOERROR; -} - -static unsigned char -internal_function __attribute ((pure)) -re_string_peek_byte_case (const re_string_t *pstr, Idx idx) -{ - int ch; - Idx off; - - /* Handle the common (easiest) cases first. */ - if (BE (!pstr->mbs_allocated, 1)) - return re_string_peek_byte (pstr, idx); - -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1 - && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) - return re_string_peek_byte (pstr, idx); -#endif - - off = pstr->cur_idx + idx; -#ifdef RE_ENABLE_I18N - if (pstr->offsets_needed) - off = pstr->offsets[off]; -#endif - - ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; - -#ifdef RE_ENABLE_I18N - /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I - this function returns CAPITAL LETTER I instead of first byte of - DOTLESS SMALL LETTER I. The latter would confuse the parser, - since peek_byte_case doesn't advance cur_idx in any way. */ - if (pstr->offsets_needed && !isascii (ch)) - return re_string_peek_byte (pstr, idx); -#endif - - return ch; -} - -static unsigned char -internal_function __attribute ((pure)) -re_string_fetch_byte_case (re_string_t *pstr) -{ - if (BE (!pstr->mbs_allocated, 1)) - return re_string_fetch_byte (pstr); - -#ifdef RE_ENABLE_I18N - if (pstr->offsets_needed) - { - Idx off; - int ch; - - /* For tr_TR.UTF-8 [[:islower:]] there is - [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip - in that case the whole multi-byte character and return - the original letter. On the other side, with - [[: DOTLESS SMALL LETTER I return [[:I, as doing - anything else would complicate things too much. */ - - if (!re_string_first_byte (pstr, pstr->cur_idx)) - return re_string_fetch_byte (pstr); - - off = pstr->offsets[pstr->cur_idx]; - ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; - - if (! isascii (ch)) - return re_string_fetch_byte (pstr); - - re_string_skip_bytes (pstr, - re_string_char_size_at (pstr, pstr->cur_idx)); - return ch; - } -#endif - - return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; -} - -static void -internal_function -re_string_destruct (re_string_t *pstr) -{ -#ifdef RE_ENABLE_I18N - re_free (pstr->wcs); - re_free (pstr->offsets); -#endif /* RE_ENABLE_I18N */ - if (pstr->mbs_allocated) - re_free (pstr->mbs); -} - -/* Return the context at IDX in INPUT. */ - -static unsigned int -internal_function -re_string_context_at (const re_string_t *input, Idx idx, int eflags) -{ - int c; - if (BE (! REG_VALID_INDEX (idx), 0)) - /* In this case, we use the value stored in input->tip_context, - since we can't know the character in input->mbs[-1] here. */ - return input->tip_context; - if (BE (idx == input->len, 0)) - return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF - : CONTEXT_NEWLINE | CONTEXT_ENDBUF); -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc; - Idx wc_idx = idx; - while(input->wcs[wc_idx] == WEOF) - { -#ifdef DEBUG - /* It must not happen. */ - assert (REG_VALID_INDEX (wc_idx)); -#endif - --wc_idx; - if (! REG_VALID_INDEX (wc_idx)) - return input->tip_context; - } - wc = input->wcs[wc_idx]; - if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) - return CONTEXT_WORD; - return (IS_WIDE_NEWLINE (wc) && input->newline_anchor - ? CONTEXT_NEWLINE : 0); - } - else -#endif - { - c = re_string_byte_at (input, idx); - if (bitset_contain (input->word_char, c)) - return CONTEXT_WORD; - return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; - } -} - -/* Functions for set operation. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_node_set_alloc (re_node_set *set, Idx size) -{ - set->alloc = size; - set->nelem = 0; - set->elems = re_malloc (Idx, size); - if (BE (set->elems == NULL, 0)) - return REG_ESPACE; - return REG_NOERROR; -} - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_node_set_init_1 (re_node_set *set, Idx elem) -{ - set->alloc = 1; - set->nelem = 1; - set->elems = re_malloc (Idx, 1); - if (BE (set->elems == NULL, 0)) - { - set->alloc = set->nelem = 0; - return REG_ESPACE; - } - set->elems[0] = elem; - return REG_NOERROR; -} - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2) -{ - set->alloc = 2; - set->elems = re_malloc (Idx, 2); - if (BE (set->elems == NULL, 0)) - return REG_ESPACE; - if (elem1 == elem2) - { - set->nelem = 1; - set->elems[0] = elem1; - } - else - { - set->nelem = 2; - if (elem1 < elem2) - { - set->elems[0] = elem1; - set->elems[1] = elem2; - } - else - { - set->elems[0] = elem2; - set->elems[1] = elem1; - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_node_set_init_copy (re_node_set *dest, const re_node_set *src) -{ - dest->nelem = src->nelem; - if (src->nelem > 0) - { - dest->alloc = dest->nelem; - dest->elems = re_malloc (Idx, dest->alloc); - if (BE (dest->elems == NULL, 0)) - { - dest->alloc = dest->nelem = 0; - return REG_ESPACE; - } - memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); - } - else - re_node_set_init_empty (dest); - return REG_NOERROR; -} - -/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. - Note: We assume dest->elems is NULL, when dest->alloc is 0. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, - const re_node_set *src2) -{ - Idx i1, i2, is, id, delta, sbase; - if (src1->nelem == 0 || src2->nelem == 0) - return REG_NOERROR; - - /* We need dest->nelem + 2 * elems_in_intersection; this is a - conservative estimate. */ - if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) - { - Idx new_alloc = src1->nelem + src2->nelem + dest->alloc; - Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc); - if (BE (new_elems == NULL, 0)) - return REG_ESPACE; - dest->elems = new_elems; - dest->alloc = new_alloc; - } - - /* Find the items in the intersection of SRC1 and SRC2, and copy - into the top of DEST those that are not already in DEST itself. */ - sbase = dest->nelem + src1->nelem + src2->nelem; - i1 = src1->nelem - 1; - i2 = src2->nelem - 1; - id = dest->nelem - 1; - for (;;) - { - if (src1->elems[i1] == src2->elems[i2]) - { - /* Try to find the item in DEST. Maybe we could binary search? */ - while (REG_VALID_INDEX (id) && dest->elems[id] > src1->elems[i1]) - --id; - - if (! REG_VALID_INDEX (id) || dest->elems[id] != src1->elems[i1]) - dest->elems[--sbase] = src1->elems[i1]; - - if (! REG_VALID_INDEX (--i1) || ! REG_VALID_INDEX (--i2)) - break; - } - - /* Lower the highest of the two items. */ - else if (src1->elems[i1] < src2->elems[i2]) - { - if (! REG_VALID_INDEX (--i2)) - break; - } - else - { - if (! REG_VALID_INDEX (--i1)) - break; - } - } - - id = dest->nelem - 1; - is = dest->nelem + src1->nelem + src2->nelem - 1; - delta = is - sbase + 1; - - /* Now copy. When DELTA becomes zero, the remaining - DEST elements are already in place; this is more or - less the same loop that is in re_node_set_merge. */ - dest->nelem += delta; - if (delta > 0 && REG_VALID_INDEX (id)) - for (;;) - { - if (dest->elems[is] > dest->elems[id]) - { - /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; - if (delta == 0) - break; - } - else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; - if (! REG_VALID_INDEX (--id)) - break; - } - } - - /* Copy remaining SRC elements. */ - memcpy (dest->elems, dest->elems + sbase, delta * sizeof (Idx)); - - return REG_NOERROR; -} - -/* Calculate the union set of the sets SRC1 and SRC2. And store it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_node_set_init_union (re_node_set *dest, const re_node_set *src1, - const re_node_set *src2) -{ - Idx i1, i2, id; - if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) - { - dest->alloc = src1->nelem + src2->nelem; - dest->elems = re_malloc (Idx, dest->alloc); - if (BE (dest->elems == NULL, 0)) - return REG_ESPACE; - } - else - { - if (src1 != NULL && src1->nelem > 0) - return re_node_set_init_copy (dest, src1); - else if (src2 != NULL && src2->nelem > 0) - return re_node_set_init_copy (dest, src2); - else - re_node_set_init_empty (dest); - return REG_NOERROR; - } - for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) - { - if (src1->elems[i1] > src2->elems[i2]) - { - dest->elems[id++] = src2->elems[i2++]; - continue; - } - if (src1->elems[i1] == src2->elems[i2]) - ++i2; - dest->elems[id++] = src1->elems[i1++]; - } - if (i1 < src1->nelem) - { - memcpy (dest->elems + id, src1->elems + i1, - (src1->nelem - i1) * sizeof (Idx)); - id += src1->nelem - i1; - } - else if (i2 < src2->nelem) - { - memcpy (dest->elems + id, src2->elems + i2, - (src2->nelem - i2) * sizeof (Idx)); - id += src2->nelem - i2; - } - dest->nelem = id; - return REG_NOERROR; -} - -/* Calculate the union set of the sets DEST and SRC. And store it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_node_set_merge (re_node_set *dest, const re_node_set *src) -{ - Idx is, id, sbase, delta; - if (src == NULL || src->nelem == 0) - return REG_NOERROR; - if (dest->alloc < 2 * src->nelem + dest->nelem) - { - Idx new_alloc = 2 * (src->nelem + dest->alloc); - Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc); - if (BE (new_buffer == NULL, 0)) - return REG_ESPACE; - dest->elems = new_buffer; - dest->alloc = new_alloc; - } - - if (BE (dest->nelem == 0, 0)) - { - dest->nelem = src->nelem; - memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); - return REG_NOERROR; - } - - /* Copy into the top of DEST the items of SRC that are not - found in DEST. Maybe we could binary search in DEST? */ - for (sbase = dest->nelem + 2 * src->nelem, - is = src->nelem - 1, id = dest->nelem - 1; - REG_VALID_INDEX (is) && REG_VALID_INDEX (id); ) - { - if (dest->elems[id] == src->elems[is]) - is--, id--; - else if (dest->elems[id] < src->elems[is]) - dest->elems[--sbase] = src->elems[is--]; - else /* if (dest->elems[id] > src->elems[is]) */ - --id; - } - - if (REG_VALID_INDEX (is)) - { - /* If DEST is exhausted, the remaining items of SRC must be unique. */ - sbase -= is + 1; - memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (Idx)); - } - - id = dest->nelem - 1; - is = dest->nelem + 2 * src->nelem - 1; - delta = is - sbase + 1; - if (delta == 0) - return REG_NOERROR; - - /* Now copy. When DELTA becomes zero, the remaining - DEST elements are already in place. */ - dest->nelem += delta; - for (;;) - { - if (dest->elems[is] > dest->elems[id]) - { - /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; - if (delta == 0) - break; - } - else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; - if (! REG_VALID_INDEX (--id)) - { - /* Copy remaining SRC elements. */ - memcpy (dest->elems, dest->elems + sbase, - delta * sizeof (Idx)); - break; - } - } - } - - return REG_NOERROR; -} - -/* Insert the new element ELEM to the re_node_set* SET. - SET should not already have ELEM. - Return true if successful. */ - -static bool -internal_function __attribute_warn_unused_result__ -re_node_set_insert (re_node_set *set, Idx elem) -{ - Idx idx; - /* In case the set is empty. */ - if (set->alloc == 0) - return BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1); - - if (BE (set->nelem, 0) == 0) - { - /* We already guaranteed above that set->alloc != 0. */ - set->elems[0] = elem; - ++set->nelem; - return true; - } - - /* Realloc if we need. */ - if (set->alloc == set->nelem) - { - Idx *new_elems; - set->alloc = set->alloc * 2; - new_elems = re_realloc (set->elems, Idx, set->alloc); - if (BE (new_elems == NULL, 0)) - return false; - set->elems = new_elems; - } - - /* Move the elements which follows the new element. Test the - first element separately to skip a check in the inner loop. */ - if (elem < set->elems[0]) - { - idx = 0; - for (idx = set->nelem; idx > 0; idx--) - set->elems[idx] = set->elems[idx - 1]; - } - else - { - for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) - set->elems[idx] = set->elems[idx - 1]; - } - - /* Insert the new element. */ - set->elems[idx] = elem; - ++set->nelem; - return true; -} - -/* Insert the new element ELEM to the re_node_set* SET. - SET should not already have any element greater than or equal to ELEM. - Return true if successful. */ - -static bool -internal_function __attribute_warn_unused_result__ -re_node_set_insert_last (re_node_set *set, Idx elem) -{ - /* Realloc if we need. */ - if (set->alloc == set->nelem) - { - Idx *new_elems; - set->alloc = (set->alloc + 1) * 2; - new_elems = re_realloc (set->elems, Idx, set->alloc); - if (BE (new_elems == NULL, 0)) - return false; - set->elems = new_elems; - } - - /* Insert the new element. */ - set->elems[set->nelem++] = elem; - return true; -} - -/* Compare two node sets SET1 and SET2. - Return true if SET1 and SET2 are equivalent. */ - -static bool -internal_function __attribute ((pure)) -re_node_set_compare (const re_node_set *set1, const re_node_set *set2) -{ - Idx i; - if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) - return false; - for (i = set1->nelem ; REG_VALID_INDEX (--i) ; ) - if (set1->elems[i] != set2->elems[i]) - return false; - return true; -} - -/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ - -static Idx -internal_function __attribute ((pure)) -re_node_set_contains (const re_node_set *set, Idx elem) -{ - __re_size_t idx, right, mid; - if (! REG_VALID_NONZERO_INDEX (set->nelem)) - return 0; - - /* Binary search the element. */ - idx = 0; - right = set->nelem - 1; - while (idx < right) - { - mid = (idx + right) / 2; - if (set->elems[mid] < elem) - idx = mid + 1; - else - right = mid; - } - return set->elems[idx] == elem ? idx + 1 : 0; -} - -static void -internal_function -re_node_set_remove_at (re_node_set *set, Idx idx) -{ - if (idx < 0 || idx >= set->nelem) - return; - --set->nelem; - for (; idx < set->nelem; idx++) - set->elems[idx] = set->elems[idx + 1]; -} - - -/* Add the token TOKEN to dfa->nodes, and return the index of the token. - Or return REG_MISSING if an error occurred. */ - -static Idx -internal_function -re_dfa_add_node (re_dfa_t *dfa, re_token_t token) -{ - if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0)) - { - size_t new_nodes_alloc = dfa->nodes_alloc * 2; - Idx *new_nexts, *new_indices; - re_node_set *new_edests, *new_eclosures; - re_token_t *new_nodes; - size_t max_object_size = - MAX (sizeof (re_token_t), - MAX (sizeof (re_node_set), - sizeof (Idx))); - - /* Avoid overflows. */ - if (BE (SIZE_MAX / 2 / max_object_size < dfa->nodes_alloc, 0)) - return REG_MISSING; - - new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); - if (BE (new_nodes == NULL, 0)) - return REG_MISSING; - dfa->nodes = new_nodes; - new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc); - new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc); - new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); - new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); - if (BE (new_nexts == NULL || new_indices == NULL - || new_edests == NULL || new_eclosures == NULL, 0)) - return REG_MISSING; - dfa->nexts = new_nexts; - dfa->org_indices = new_indices; - dfa->edests = new_edests; - dfa->eclosures = new_eclosures; - dfa->nodes_alloc = new_nodes_alloc; - } - dfa->nodes[dfa->nodes_len] = token; - dfa->nodes[dfa->nodes_len].constraint = 0; -#ifdef RE_ENABLE_I18N - { - int type = token.type; - dfa->nodes[dfa->nodes_len].accept_mb = - (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; - } -#endif - dfa->nexts[dfa->nodes_len] = REG_MISSING; - re_node_set_init_empty (dfa->edests + dfa->nodes_len); - re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); - return dfa->nodes_len++; -} - -static inline re_hashval_t -internal_function -calc_state_hash (const re_node_set *nodes, unsigned int context) -{ - re_hashval_t hash = nodes->nelem + context; - Idx i; - for (i = 0 ; i < nodes->nelem ; i++) - hash += nodes->elems[i]; - return hash; -} - -/* Search for the state whose node_set is equivalent to NODES. - Return the pointer to the state, if we found it in the DFA. - Otherwise create the new one and return it. In case of an error - return NULL and set the error code in ERR. - Note: - We assume NULL as the invalid state, then it is possible that - return value is NULL and ERR is REG_NOERROR. - - We never return non-NULL value in case of any errors, it is for - optimization. */ - -static re_dfastate_t * -internal_function __attribute_warn_unused_result__ -re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, - const re_node_set *nodes) -{ - re_hashval_t hash; - re_dfastate_t *new_state; - struct re_state_table_entry *spot; - Idx i; -#ifdef lint - /* Suppress bogus uninitialized-variable warnings. */ - *err = REG_NOERROR; -#endif - if (BE (nodes->nelem == 0, 0)) - { - *err = REG_NOERROR; - return NULL; - } - hash = calc_state_hash (nodes, 0); - spot = dfa->state_table + (hash & dfa->state_hash_mask); - - for (i = 0 ; i < spot->num ; i++) - { - re_dfastate_t *state = spot->array[i]; - if (hash != state->hash) - continue; - if (re_node_set_compare (&state->nodes, nodes)) - return state; - } - - /* There are no appropriate state in the dfa, create the new one. */ - new_state = create_ci_newstate (dfa, nodes, hash); - if (BE (new_state == NULL, 0)) - *err = REG_ESPACE; - - return new_state; -} - -/* Search for the state whose node_set is equivalent to NODES and - whose context is equivalent to CONTEXT. - Return the pointer to the state, if we found it in the DFA. - Otherwise create the new one and return it. In case of an error - return NULL and set the error code in ERR. - Note: - We assume NULL as the invalid state, then it is possible that - return value is NULL and ERR is REG_NOERROR. - - We never return non-NULL value in case of any errors, it is for - optimization. */ - -static re_dfastate_t * -internal_function __attribute_warn_unused_result__ -re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, - const re_node_set *nodes, unsigned int context) -{ - re_hashval_t hash; - re_dfastate_t *new_state; - struct re_state_table_entry *spot; - Idx i; -#ifdef lint - /* Suppress bogus uninitialized-variable warnings. */ - *err = REG_NOERROR; -#endif - if (nodes->nelem == 0) - { - *err = REG_NOERROR; - return NULL; - } - hash = calc_state_hash (nodes, context); - spot = dfa->state_table + (hash & dfa->state_hash_mask); - - for (i = 0 ; i < spot->num ; i++) - { - re_dfastate_t *state = spot->array[i]; - if (state->hash == hash - && state->context == context - && re_node_set_compare (state->entrance_nodes, nodes)) - return state; - } - /* There are no appropriate state in `dfa', create the new one. */ - new_state = create_cd_newstate (dfa, nodes, context, hash); - if (BE (new_state == NULL, 0)) - *err = REG_ESPACE; - - return new_state; -} - -/* Finish initialization of the new state NEWSTATE, and using its hash value - HASH put in the appropriate bucket of DFA's state table. Return value - indicates the error code if failed. */ - -static reg_errcode_t -__attribute_warn_unused_result__ -register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, - re_hashval_t hash) -{ - struct re_state_table_entry *spot; - reg_errcode_t err; - Idx i; - - newstate->hash = hash; - err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); - if (BE (err != REG_NOERROR, 0)) - return REG_ESPACE; - for (i = 0; i < newstate->nodes.nelem; i++) - { - Idx elem = newstate->nodes.elems[i]; - if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) - if (BE (! re_node_set_insert_last (&newstate->non_eps_nodes, elem), 0)) - return REG_ESPACE; - } - - spot = dfa->state_table + (hash & dfa->state_hash_mask); - if (BE (spot->alloc <= spot->num, 0)) - { - Idx new_alloc = 2 * spot->num + 2; - re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, - new_alloc); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - spot->array = new_array; - spot->alloc = new_alloc; - } - spot->array[spot->num++] = newstate; - return REG_NOERROR; -} - -static void -free_state (re_dfastate_t *state) -{ - re_node_set_free (&state->non_eps_nodes); - re_node_set_free (&state->inveclosure); - if (state->entrance_nodes != &state->nodes) - { - re_node_set_free (state->entrance_nodes); - re_free (state->entrance_nodes); - } - re_node_set_free (&state->nodes); - re_free (state->word_trtable); - re_free (state->trtable); - re_free (state); -} - -/* Create the new state which is independ of contexts. - Return the new state if succeeded, otherwise return NULL. */ - -static re_dfastate_t * -internal_function __attribute_warn_unused_result__ -create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, - re_hashval_t hash) -{ - Idx i; - reg_errcode_t err; - re_dfastate_t *newstate; - - newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); - if (BE (newstate == NULL, 0)) - return NULL; - err = re_node_set_init_copy (&newstate->nodes, nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_free (newstate); - return NULL; - } - - newstate->entrance_nodes = &newstate->nodes; - for (i = 0 ; i < nodes->nelem ; i++) - { - re_token_t *node = dfa->nodes + nodes->elems[i]; - re_token_type_t type = node->type; - if (type == CHARACTER && !node->constraint) - continue; -#ifdef RE_ENABLE_I18N - newstate->accept_mb |= node->accept_mb; -#endif /* RE_ENABLE_I18N */ - - /* If the state has the halt node, the state is a halt state. */ - if (type == END_OF_RE) - newstate->halt = 1; - else if (type == OP_BACK_REF) - newstate->has_backref = 1; - else if (type == ANCHOR || node->constraint) - newstate->has_constraint = 1; - } - err = register_state (dfa, newstate, hash); - if (BE (err != REG_NOERROR, 0)) - { - free_state (newstate); - newstate = NULL; - } - return newstate; -} - -/* Create the new state which is depend on the context CONTEXT. - Return the new state if succeeded, otherwise return NULL. */ - -static re_dfastate_t * -internal_function __attribute_warn_unused_result__ -create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, - unsigned int context, re_hashval_t hash) -{ - Idx i, nctx_nodes = 0; - reg_errcode_t err; - re_dfastate_t *newstate; - - newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); - if (BE (newstate == NULL, 0)) - return NULL; - err = re_node_set_init_copy (&newstate->nodes, nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_free (newstate); - return NULL; - } - - newstate->context = context; - newstate->entrance_nodes = &newstate->nodes; - - for (i = 0 ; i < nodes->nelem ; i++) - { - re_token_t *node = dfa->nodes + nodes->elems[i]; - re_token_type_t type = node->type; - unsigned int constraint = node->constraint; - - if (type == CHARACTER && !constraint) - continue; -#ifdef RE_ENABLE_I18N - newstate->accept_mb |= node->accept_mb; -#endif /* RE_ENABLE_I18N */ - - /* If the state has the halt node, the state is a halt state. */ - if (type == END_OF_RE) - newstate->halt = 1; - else if (type == OP_BACK_REF) - newstate->has_backref = 1; - - if (constraint) - { - if (newstate->entrance_nodes == &newstate->nodes) - { - newstate->entrance_nodes = re_malloc (re_node_set, 1); - if (BE (newstate->entrance_nodes == NULL, 0)) - { - free_state (newstate); - return NULL; - } - if (re_node_set_init_copy (newstate->entrance_nodes, nodes) - != REG_NOERROR) - return NULL; - nctx_nodes = 0; - newstate->has_constraint = 1; - } - - if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) - { - re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); - ++nctx_nodes; - } - } - } - err = register_state (dfa, newstate, hash); - if (BE (err != REG_NOERROR, 0)) - { - free_state (newstate); - newstate = NULL; - } - return newstate; -} diff --git a/grub-core/gnulib/regex_internal.h b/grub-core/gnulib/regex_internal.h deleted file mode 100644 index e5b6679d1..000000000 --- a/grub-core/gnulib/regex_internal.h +++ /dev/null @@ -1,869 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free - Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _REGEX_INTERNAL_H -#define _REGEX_INTERNAL_H 1 - -#include -#include -#include -#include -#include -#include - -#include -#ifndef _LIBC -# include "localcharset.h" -#endif -#if defined HAVE_LOCALE_H || defined _LIBC -# include -#endif - -#include -#include -#include -#if defined _LIBC -# include -#else -# define __libc_lock_init(NAME) do { } while (0) -# define __libc_lock_lock(NAME) do { } while (0) -# define __libc_lock_unlock(NAME) do { } while (0) -#endif - -/* In case that the system doesn't have isblank(). */ -#if !defined _LIBC && ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK)) -# define isblank(ch) ((ch) == ' ' || (ch) == '\t') -#endif - -#ifdef _LIBC -# ifndef _RE_DEFINE_LOCALE_FUNCTIONS -# define _RE_DEFINE_LOCALE_FUNCTIONS 1 -# include -# include -# include -# endif -#endif - -/* This is for other GNU distributions with internationalized messages. */ -#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC -# include -# ifdef _LIBC -# undef gettext -# define gettext(msgid) \ - INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES) -# endif -#else -# define gettext(msgid) (msgid) -#endif - -#ifndef gettext_noop -/* This define is so xgettext can find the internationalizable - strings. */ -# define gettext_noop(String) String -#endif - -/* For loser systems without the definition. */ -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_ISWCTYPE && HAVE_WCSCOLL) || _LIBC -# define RE_ENABLE_I18N -#endif - -#if __GNUC__ >= 3 -# define BE(expr, val) __builtin_expect (expr, val) -#else -# define BE(expr, val) (expr) -# ifdef _LIBC -# define inline -# endif -#endif - -/* Number of ASCII characters. */ -#define ASCII_CHARS 0x80 - -/* Number of single byte characters. */ -#define SBC_MAX (UCHAR_MAX + 1) - -#define COLL_ELEM_LEN_MAX 8 - -/* The character which represents newline. */ -#define NEWLINE_CHAR '\n' -#define WIDE_NEWLINE_CHAR L'\n' - -/* Rename to standard API for using out of glibc. */ -#ifndef _LIBC -# define __wctype wctype -# define __iswctype iswctype -# define __btowc btowc -# define __wcrtomb wcrtomb -# define __mbrtowc mbrtowc -# define __regfree regfree -# define attribute_hidden -#endif /* not _LIBC */ - -#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) -# define __attribute(arg) __attribute__ (arg) -#else -# define __attribute(arg) -#endif - -typedef __re_idx_t Idx; - -/* Special return value for failure to match. */ -#define REG_MISSING ((Idx) -1) - -/* Special return value for internal error. */ -#define REG_ERROR ((Idx) -2) - -/* Test whether N is a valid index, and is not one of the above. */ -#ifdef _REGEX_LARGE_OFFSETS -# define REG_VALID_INDEX(n) ((Idx) (n) < REG_ERROR) -#else -# define REG_VALID_INDEX(n) (0 <= (n)) -#endif - -/* Test whether N is a valid nonzero index. */ -#ifdef _REGEX_LARGE_OFFSETS -# define REG_VALID_NONZERO_INDEX(n) ((Idx) ((n) - 1) < (Idx) (REG_ERROR - 1)) -#else -# define REG_VALID_NONZERO_INDEX(n) (0 < (n)) -#endif - -/* A hash value, suitable for computing hash tables. */ -typedef __re_size_t re_hashval_t; - -/* An integer used to represent a set of bits. It must be unsigned, - and must be at least as wide as unsigned int. */ -typedef unsigned long int bitset_word_t; -/* All bits set in a bitset_word_t. */ -#define BITSET_WORD_MAX ULONG_MAX - -/* Number of bits in a bitset_word_t. For portability to hosts with - padding bits, do not use '(sizeof (bitset_word_t) * CHAR_BIT)'; - instead, deduce it directly from BITSET_WORD_MAX. Avoid - greater-than-32-bit integers and unconditional shifts by more than - 31 bits, as they're not portable. */ -#if BITSET_WORD_MAX == 0xffffffffUL -# define BITSET_WORD_BITS 32 -#elif BITSET_WORD_MAX >> 31 >> 4 == 1 -# define BITSET_WORD_BITS 36 -#elif BITSET_WORD_MAX >> 31 >> 16 == 1 -# define BITSET_WORD_BITS 48 -#elif BITSET_WORD_MAX >> 31 >> 28 == 1 -# define BITSET_WORD_BITS 60 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1 -# define BITSET_WORD_BITS 64 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1 -# define BITSET_WORD_BITS 72 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1 -# define BITSET_WORD_BITS 128 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1 -# define BITSET_WORD_BITS 256 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1 -# define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */ -# if BITSET_WORD_BITS <= SBC_MAX -# error "Invalid SBC_MAX" -# endif -#else -# error "Add case for new bitset_word_t size" -#endif - -/* Number of bitset_word_t values in a bitset_t. */ -#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS) - -typedef bitset_word_t bitset_t[BITSET_WORDS]; -typedef bitset_word_t *re_bitset_ptr_t; -typedef const bitset_word_t *re_const_bitset_ptr_t; - -#define PREV_WORD_CONSTRAINT 0x0001 -#define PREV_NOTWORD_CONSTRAINT 0x0002 -#define NEXT_WORD_CONSTRAINT 0x0004 -#define NEXT_NOTWORD_CONSTRAINT 0x0008 -#define PREV_NEWLINE_CONSTRAINT 0x0010 -#define NEXT_NEWLINE_CONSTRAINT 0x0020 -#define PREV_BEGBUF_CONSTRAINT 0x0040 -#define NEXT_ENDBUF_CONSTRAINT 0x0080 -#define WORD_DELIM_CONSTRAINT 0x0100 -#define NOT_WORD_DELIM_CONSTRAINT 0x0200 - -typedef enum -{ - INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, - WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, - WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, - INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, - LINE_FIRST = PREV_NEWLINE_CONSTRAINT, - LINE_LAST = NEXT_NEWLINE_CONSTRAINT, - BUF_FIRST = PREV_BEGBUF_CONSTRAINT, - BUF_LAST = NEXT_ENDBUF_CONSTRAINT, - WORD_DELIM = WORD_DELIM_CONSTRAINT, - NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT -} re_context_type; - -typedef struct -{ - Idx alloc; - Idx nelem; - Idx *elems; -} re_node_set; - -typedef enum -{ - NON_TYPE = 0, - - /* Node type, These are used by token, node, tree. */ - CHARACTER = 1, - END_OF_RE = 2, - SIMPLE_BRACKET = 3, - OP_BACK_REF = 4, - OP_PERIOD = 5, -#ifdef RE_ENABLE_I18N - COMPLEX_BRACKET = 6, - OP_UTF8_PERIOD = 7, -#endif /* RE_ENABLE_I18N */ - - /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used - when the debugger shows values of this enum type. */ -#define EPSILON_BIT 8 - OP_OPEN_SUBEXP = EPSILON_BIT | 0, - OP_CLOSE_SUBEXP = EPSILON_BIT | 1, - OP_ALT = EPSILON_BIT | 2, - OP_DUP_ASTERISK = EPSILON_BIT | 3, - ANCHOR = EPSILON_BIT | 4, - - /* Tree type, these are used only by tree. */ - CONCAT = 16, - SUBEXP = 17, - - /* Token type, these are used only by token. */ - OP_DUP_PLUS = 18, - OP_DUP_QUESTION, - OP_OPEN_BRACKET, - OP_CLOSE_BRACKET, - OP_CHARSET_RANGE, - OP_OPEN_DUP_NUM, - OP_CLOSE_DUP_NUM, - OP_NON_MATCH_LIST, - OP_OPEN_COLL_ELEM, - OP_CLOSE_COLL_ELEM, - OP_OPEN_EQUIV_CLASS, - OP_CLOSE_EQUIV_CLASS, - OP_OPEN_CHAR_CLASS, - OP_CLOSE_CHAR_CLASS, - OP_WORD, - OP_NOTWORD, - OP_SPACE, - OP_NOTSPACE, - BACK_SLASH - -} re_token_type_t; - -#ifdef RE_ENABLE_I18N -typedef struct -{ - /* Multibyte characters. */ - wchar_t *mbchars; - - /* Collating symbols. */ -# ifdef _LIBC - int32_t *coll_syms; -# endif - - /* Equivalence classes. */ -# ifdef _LIBC - int32_t *equiv_classes; -# endif - - /* Range expressions. */ -# ifdef _LIBC - uint32_t *range_starts; - uint32_t *range_ends; -# else /* not _LIBC */ - wchar_t *range_starts; - wchar_t *range_ends; -# endif /* not _LIBC */ - - /* Character classes. */ - wctype_t *char_classes; - - /* If this character set is the non-matching list. */ - unsigned int non_match : 1; - - /* # of multibyte characters. */ - Idx nmbchars; - - /* # of collating symbols. */ - Idx ncoll_syms; - - /* # of equivalence classes. */ - Idx nequiv_classes; - - /* # of range expressions. */ - Idx nranges; - - /* # of character classes. */ - Idx nchar_classes; -} re_charset_t; -#endif /* RE_ENABLE_I18N */ - -typedef struct -{ - union - { - unsigned char c; /* for CHARACTER */ - re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; /* for COMPLEX_BRACKET */ -#endif /* RE_ENABLE_I18N */ - Idx idx; /* for BACK_REF */ - re_context_type ctx_type; /* for ANCHOR */ - } opr; -#if __GNUC__ >= 2 && !__STRICT_ANSI__ - re_token_type_t type : 8; -#else - re_token_type_t type; -#endif - unsigned int constraint : 10; /* context constraint */ - unsigned int duplicated : 1; - unsigned int opt_subexp : 1; -#ifdef RE_ENABLE_I18N - unsigned int accept_mb : 1; - /* These 2 bits can be moved into the union if needed (e.g. if running out - of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ - unsigned int mb_partial : 1; -#endif - unsigned int word_char : 1; -} re_token_t; - -#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) - -struct re_string_t -{ - /* Indicate the raw buffer which is the original string passed as an - argument of regexec(), re_search(), etc.. */ - const unsigned char *raw_mbs; - /* Store the multibyte string. In case of "case insensitive mode" like - REG_ICASE, upper cases of the string are stored, otherwise MBS points - the same address that RAW_MBS points. */ - unsigned char *mbs; -#ifdef RE_ENABLE_I18N - /* Store the wide character string which is corresponding to MBS. */ - wint_t *wcs; - Idx *offsets; - mbstate_t cur_state; -#endif - /* Index in RAW_MBS. Each character mbs[i] corresponds to - raw_mbs[raw_mbs_idx + i]. */ - Idx raw_mbs_idx; - /* The length of the valid characters in the buffers. */ - Idx valid_len; - /* The corresponding number of bytes in raw_mbs array. */ - Idx valid_raw_len; - /* The length of the buffers MBS and WCS. */ - Idx bufs_len; - /* The index in MBS, which is updated by re_string_fetch_byte. */ - Idx cur_idx; - /* length of RAW_MBS array. */ - Idx raw_len; - /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ - Idx len; - /* End of the buffer may be shorter than its length in the cases such - as re_match_2, re_search_2. Then, we use STOP for end of the buffer - instead of LEN. */ - Idx raw_stop; - /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ - Idx stop; - - /* The context of mbs[0]. We store the context independently, since - the context of mbs[0] may be different from raw_mbs[0], which is - the beginning of the input string. */ - unsigned int tip_context; - /* The translation passed as a part of an argument of re_compile_pattern. */ - RE_TRANSLATE_TYPE trans; - /* Copy of re_dfa_t's word_char. */ - re_const_bitset_ptr_t word_char; - /* true if REG_ICASE. */ - unsigned char icase; - unsigned char is_utf8; - unsigned char map_notascii; - unsigned char mbs_allocated; - unsigned char offsets_needed; - unsigned char newline_anchor; - unsigned char word_ops_used; - int mb_cur_max; -}; -typedef struct re_string_t re_string_t; - -#ifndef _LIBC -# if defined __i386__ && !defined __EMX__ -# define internal_function __attribute ((regparm (3), stdcall)) -# else -# define internal_function -# endif -#endif - -static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, - Idx new_buf_len) - internal_function; -#ifdef RE_ENABLE_I18N -static void build_wcs_buffer (re_string_t *pstr) internal_function; -static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr) - internal_function; -#endif /* RE_ENABLE_I18N */ -static void build_upper_buffer (re_string_t *pstr) internal_function; -static void re_string_translate_buffer (re_string_t *pstr) internal_function; -static unsigned int re_string_context_at (const re_string_t *input, Idx idx, - int eflags) - internal_function __attribute ((pure)); -#define re_string_peek_byte(pstr, offset) \ - ((pstr)->mbs[(pstr)->cur_idx + offset]) -#define re_string_fetch_byte(pstr) \ - ((pstr)->mbs[(pstr)->cur_idx++]) -#define re_string_first_byte(pstr, idx) \ - ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) -#define re_string_is_single_byte_char(pstr, idx) \ - ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ - || (pstr)->wcs[(idx) + 1] != WEOF)) -#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) -#define re_string_cur_idx(pstr) ((pstr)->cur_idx) -#define re_string_get_buffer(pstr) ((pstr)->mbs) -#define re_string_length(pstr) ((pstr)->len) -#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) -#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) -#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) - -#include - -#ifndef _LIBC -# if HAVE_ALLOCA -/* The OS usually guarantees only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - allocate anything larger than 4096 bytes. Also care for the possibility - of a few compiler-allocated temporary stack slots. */ -# define __libc_use_alloca(n) ((n) < 4032) -# else -/* alloca is implemented with malloc, so just use malloc. */ -# define __libc_use_alloca(n) 0 -# undef alloca -# define alloca(n) malloc (n) -# endif -#endif - -#ifndef MAX -# define MAX(a,b) ((a) < (b) ? (b) : (a)) -#endif - -#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) -#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) -#define re_free(p) free (p) - -struct bin_tree_t -{ - struct bin_tree_t *parent; - struct bin_tree_t *left; - struct bin_tree_t *right; - struct bin_tree_t *first; - struct bin_tree_t *next; - - re_token_t token; - - /* `node_idx' is the index in dfa->nodes, if `type' == 0. - Otherwise `type' indicate the type of this node. */ - Idx node_idx; -}; -typedef struct bin_tree_t bin_tree_t; - -#define BIN_TREE_STORAGE_SIZE \ - ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) - -struct bin_tree_storage_t -{ - struct bin_tree_storage_t *next; - bin_tree_t data[BIN_TREE_STORAGE_SIZE]; -}; -typedef struct bin_tree_storage_t bin_tree_storage_t; - -#define CONTEXT_WORD 1 -#define CONTEXT_NEWLINE (CONTEXT_WORD << 1) -#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) -#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) - -#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) -#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) -#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) -#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) -#define IS_ORDINARY_CONTEXT(c) ((c) == 0) - -#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') -#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) -#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_') -#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) - -#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ - ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ - || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ - || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ - || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) - -#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ - ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ - || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ - || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ - || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) - -struct re_dfastate_t -{ - re_hashval_t hash; - re_node_set nodes; - re_node_set non_eps_nodes; - re_node_set inveclosure; - re_node_set *entrance_nodes; - struct re_dfastate_t **trtable, **word_trtable; - unsigned int context : 4; - unsigned int halt : 1; - /* If this state can accept `multi byte'. - Note that we refer to multibyte characters, and multi character - collating elements as `multi byte'. */ - unsigned int accept_mb : 1; - /* If this state has backreference node(s). */ - unsigned int has_backref : 1; - unsigned int has_constraint : 1; -}; -typedef struct re_dfastate_t re_dfastate_t; - -struct re_state_table_entry -{ - Idx num; - Idx alloc; - re_dfastate_t **array; -}; - -/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ - -typedef struct -{ - Idx next_idx; - Idx alloc; - re_dfastate_t **array; -} state_array_t; - -/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ - -typedef struct -{ - Idx node; - Idx str_idx; /* The position NODE match at. */ - state_array_t path; -} re_sub_match_last_t; - -/* Store information about the node NODE whose type is OP_OPEN_SUBEXP. - And information about the node, whose type is OP_CLOSE_SUBEXP, - corresponding to NODE is stored in LASTS. */ - -typedef struct -{ - Idx str_idx; - Idx node; - state_array_t *path; - Idx alasts; /* Allocation size of LASTS. */ - Idx nlasts; /* The number of LASTS. */ - re_sub_match_last_t **lasts; -} re_sub_match_top_t; - -struct re_backref_cache_entry -{ - Idx node; - Idx str_idx; - Idx subexp_from; - Idx subexp_to; - char more; - char unused; - unsigned short int eps_reachable_subexps_map; -}; - -typedef struct -{ - /* The string object corresponding to the input string. */ - re_string_t input; -#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) - const re_dfa_t *const dfa; -#else - const re_dfa_t *dfa; -#endif - /* EFLAGS of the argument of regexec. */ - int eflags; - /* Where the matching ends. */ - Idx match_last; - Idx last_node; - /* The state log used by the matcher. */ - re_dfastate_t **state_log; - Idx state_log_top; - /* Back reference cache. */ - Idx nbkref_ents; - Idx abkref_ents; - struct re_backref_cache_entry *bkref_ents; - int max_mb_elem_len; - Idx nsub_tops; - Idx asub_tops; - re_sub_match_top_t **sub_tops; -} re_match_context_t; - -typedef struct -{ - re_dfastate_t **sifted_states; - re_dfastate_t **limited_states; - Idx last_node; - Idx last_str_idx; - re_node_set limits; -} re_sift_context_t; - -struct re_fail_stack_ent_t -{ - Idx idx; - Idx node; - regmatch_t *regs; - re_node_set eps_via_nodes; -}; - -struct re_fail_stack_t -{ - Idx num; - Idx alloc; - struct re_fail_stack_ent_t *stack; -}; - -struct re_dfa_t -{ - re_token_t *nodes; - size_t nodes_alloc; - size_t nodes_len; - Idx *nexts; - Idx *org_indices; - re_node_set *edests; - re_node_set *eclosures; - re_node_set *inveclosures; - struct re_state_table_entry *state_table; - re_dfastate_t *init_state; - re_dfastate_t *init_state_word; - re_dfastate_t *init_state_nl; - re_dfastate_t *init_state_begbuf; - bin_tree_t *str_tree; - bin_tree_storage_t *str_tree_storage; - re_bitset_ptr_t sb_char; - int str_tree_storage_idx; - - /* number of subexpressions `re_nsub' is in regex_t. */ - re_hashval_t state_hash_mask; - Idx init_node; - Idx nbackref; /* The number of backreference in this dfa. */ - - /* Bitmap expressing which backreference is used. */ - bitset_word_t used_bkref_map; - bitset_word_t completed_bkref_map; - - unsigned int has_plural_match : 1; - /* If this dfa has "multibyte node", which is a backreference or - a node which can accept multibyte character or multi character - collating element. */ - unsigned int has_mb_node : 1; - unsigned int is_utf8 : 1; - unsigned int map_notascii : 1; - unsigned int word_ops_used : 1; - int mb_cur_max; - bitset_t word_char; - reg_syntax_t syntax; - Idx *subexp_map; -#ifdef DEBUG - char* re_str; -#endif -#ifdef _LIBC - __libc_lock_define (, lock) -#endif -}; - -#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) -#define re_node_set_remove(set,id) \ - (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) -#define re_node_set_empty(p) ((p)->nelem = 0) -#define re_node_set_free(set) re_free ((set)->elems) - - -typedef enum -{ - SB_CHAR, - MB_CHAR, - EQUIV_CLASS, - COLL_SYM, - CHAR_CLASS -} bracket_elem_type; - -typedef struct -{ - bracket_elem_type type; - union - { - unsigned char ch; - unsigned char *name; - wchar_t wch; - } opr; -} bracket_elem_t; - - -/* Inline functions for bitset_t operation. */ - -static inline void -bitset_set (bitset_t set, Idx i) -{ - set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS; -} - -static inline void -bitset_clear (bitset_t set, Idx i) -{ - set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS); -} - -static inline bool -bitset_contain (const bitset_t set, Idx i) -{ - return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1; -} - -static inline void -bitset_empty (bitset_t set) -{ - memset (set, '\0', sizeof (bitset_t)); -} - -static inline void -bitset_set_all (bitset_t set) -{ - memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS)); - if (SBC_MAX % BITSET_WORD_BITS != 0) - set[BITSET_WORDS - 1] = - ((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1; -} - -static inline void -bitset_copy (bitset_t dest, const bitset_t src) -{ - memcpy (dest, src, sizeof (bitset_t)); -} - -static inline void -bitset_not (bitset_t set) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i) - set[bitset_i] = ~set[bitset_i]; - if (SBC_MAX % BITSET_WORD_BITS != 0) - set[BITSET_WORDS - 1] = - ((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1) - & ~set[BITSET_WORDS - 1]); -} - -static inline void -bitset_merge (bitset_t dest, const bitset_t src) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) - dest[bitset_i] |= src[bitset_i]; -} - -static inline void -bitset_mask (bitset_t dest, const bitset_t src) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) - dest[bitset_i] &= src[bitset_i]; -} - -#ifdef RE_ENABLE_I18N -/* Inline functions for re_string. */ -static inline int -internal_function __attribute ((pure)) -re_string_char_size_at (const re_string_t *pstr, Idx idx) -{ - int byte_idx; - if (pstr->mb_cur_max == 1) - return 1; - for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) - if (pstr->wcs[idx + byte_idx] != WEOF) - break; - return byte_idx; -} - -static inline wint_t -internal_function __attribute ((pure)) -re_string_wchar_at (const re_string_t *pstr, Idx idx) -{ - if (pstr->mb_cur_max == 1) - return (wint_t) pstr->mbs[idx]; - return (wint_t) pstr->wcs[idx]; -} - -static int -internal_function __attribute ((pure)) -re_string_elem_size_at (const re_string_t *pstr, Idx idx) -{ -# ifdef _LIBC - const unsigned char *p, *extra; - const int32_t *table, *indirect; - int32_t tmp; -# include - uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - - if (nrules != 0) - { - table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_INDIRECTMB); - p = pstr->mbs + idx; - tmp = findidx (&p); - return p - pstr->mbs - idx; - } - else -# endif /* _LIBC */ - return 1; -} -#endif /* RE_ENABLE_I18N */ - -#ifndef __GNUC_PREREQ -# if defined __GNUC__ && defined __GNUC_MINOR__ -# define __GNUC_PREREQ(maj, min) \ - ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) -# else -# define __GNUC_PREREQ(maj, min) 0 -# endif -#endif - -#if __GNUC_PREREQ (3,4) -# undef __attribute_warn_unused_result__ -# define __attribute_warn_unused_result__ \ - __attribute__ ((__warn_unused_result__)) -#else -# define __attribute_warn_unused_result__ /* empty */ -#endif - -#endif /* _REGEX_INTERNAL_H */ diff --git a/grub-core/gnulib/regexec.c b/grub-core/gnulib/regexec.c deleted file mode 100644 index dc449ce52..000000000 --- a/grub-core/gnulib/regexec.c +++ /dev/null @@ -1,4416 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free - Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, - Idx n) internal_function; -static void match_ctx_clean (re_match_context_t *mctx) internal_function; -static void match_ctx_free (re_match_context_t *cache) internal_function; -static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, Idx node, - Idx str_idx, Idx from, Idx to) - internal_function; -static Idx search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx) - internal_function; -static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, Idx node, - Idx str_idx) internal_function; -static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, - Idx node, Idx str_idx) - internal_function; -static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, - re_dfastate_t **limited_sts, Idx last_node, - Idx last_str_idx) - internal_function; -static reg_errcode_t re_search_internal (const regex_t *preg, - const char *string, Idx length, - Idx start, Idx last_start, Idx stop, - size_t nmatch, regmatch_t pmatch[], - int eflags) internal_function; -static regoff_t re_search_2_stub (struct re_pattern_buffer *bufp, - const char *string1, Idx length1, - const char *string2, Idx length2, - Idx start, regoff_t range, - struct re_registers *regs, - Idx stop, bool ret_len) internal_function; -static regoff_t re_search_stub (struct re_pattern_buffer *bufp, - const char *string, Idx length, Idx start, - regoff_t range, Idx stop, - struct re_registers *regs, - bool ret_len) internal_function; -static unsigned int re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, - Idx nregs, int regs_allocated) - internal_function; -static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx) - internal_function; -static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match, - Idx *p_match_first) internal_function; -static Idx check_halt_state_context (const re_match_context_t *mctx, - const re_dfastate_t *state, Idx idx) - internal_function; -static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, - regmatch_t *prev_idx_match, Idx cur_node, - Idx cur_idx, Idx nmatch) internal_function; -static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, - Idx str_idx, Idx dest_node, Idx nregs, - regmatch_t *regs, - re_node_set *eps_via_nodes) - internal_function; -static reg_errcode_t set_regs (const regex_t *preg, - const re_match_context_t *mctx, - size_t nmatch, regmatch_t *pmatch, - bool fl_backtrack) internal_function; -static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs) - internal_function; - -#ifdef RE_ENABLE_I18N -static int sift_states_iter_mb (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx node_idx, Idx str_idx, Idx max_str_idx) - internal_function; -#endif /* RE_ENABLE_I18N */ -static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, - re_sift_context_t *sctx) - internal_function; -static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, - re_sift_context_t *sctx, Idx str_idx, - re_node_set *cur_dest) - internal_function; -static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx str_idx, - re_node_set *dest_nodes) - internal_function; -static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa, - re_node_set *dest_nodes, - const re_node_set *candidates) - internal_function; -static bool check_dst_limits (const re_match_context_t *mctx, - const re_node_set *limits, - Idx dst_node, Idx dst_idx, Idx src_node, - Idx src_idx) internal_function; -static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, - int boundaries, Idx subexp_idx, - Idx from_node, Idx bkref_idx) - internal_function; -static int check_dst_limits_calc_pos (const re_match_context_t *mctx, - Idx limit, Idx subexp_idx, - Idx node, Idx str_idx, - Idx bkref_idx) internal_function; -static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa, - re_node_set *dest_nodes, - const re_node_set *candidates, - re_node_set *limits, - struct re_backref_cache_entry *bkref_ents, - Idx str_idx) internal_function; -static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx str_idx, const re_node_set *candidates) - internal_function; -static reg_errcode_t merge_state_array (const re_dfa_t *dfa, - re_dfastate_t **dst, - re_dfastate_t **src, Idx num) - internal_function; -static re_dfastate_t *find_recover_state (reg_errcode_t *err, - re_match_context_t *mctx) internal_function; -static re_dfastate_t *transit_state (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *state) internal_function; -static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *next_state) - internal_function; -static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, - re_node_set *cur_nodes, - Idx str_idx) internal_function; -#if 0 -static re_dfastate_t *transit_state_sb (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *pstate) - internal_function; -#endif -#ifdef RE_ENABLE_I18N -static reg_errcode_t transit_state_mb (re_match_context_t *mctx, - re_dfastate_t *pstate) - internal_function; -#endif /* RE_ENABLE_I18N */ -static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, - const re_node_set *nodes) - internal_function; -static reg_errcode_t get_subexp (re_match_context_t *mctx, - Idx bkref_node, Idx bkref_str_idx) - internal_function; -static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, - const re_sub_match_top_t *sub_top, - re_sub_match_last_t *sub_last, - Idx bkref_node, Idx bkref_str) - internal_function; -static Idx find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, - Idx subexp_idx, int type) internal_function; -static reg_errcode_t check_arrival (re_match_context_t *mctx, - state_array_t *path, Idx top_node, - Idx top_str, Idx last_node, Idx last_str, - int type) internal_function; -static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, - Idx str_idx, - re_node_set *cur_nodes, - re_node_set *next_nodes) - internal_function; -static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa, - re_node_set *cur_nodes, - Idx ex_subexp, int type) - internal_function; -static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa, - re_node_set *dst_nodes, - Idx target, Idx ex_subexp, - int type) internal_function; -static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, - re_node_set *cur_nodes, Idx cur_str, - Idx subexp_num, int type) - internal_function; -static bool build_trtable (const re_dfa_t *dfa, - re_dfastate_t *state) internal_function; -#ifdef RE_ENABLE_I18N -static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, - const re_string_t *input, Idx idx) - internal_function; -# ifdef _LIBC -static unsigned int find_collation_sequence_value (const unsigned char *mbs, - size_t name_len) - internal_function; -# endif /* _LIBC */ -#endif /* RE_ENABLE_I18N */ -static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa, - const re_dfastate_t *state, - re_node_set *states_node, - bitset_t *states_ch) internal_function; -static bool check_node_accept (const re_match_context_t *mctx, - const re_token_t *node, Idx idx) - internal_function; -static reg_errcode_t extend_buffers (re_match_context_t *mctx) - internal_function; - -/* Entry point for POSIX code. */ - -/* regexec searches for a given pattern, specified by PREG, in the - string STRING. - - If NMATCH is zero or REG_NOSUB was set in the cflags argument to - `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at - least NMATCH elements, and we set them to the offsets of the - corresponding matched substrings. - - EFLAGS specifies `execution flags' which affect matching: if - REG_NOTBOL is set, then ^ does not match at the beginning of the - string; if REG_NOTEOL is set, then $ does not match at the end. - - We return 0 if we find a match and REG_NOMATCH if not. */ - -int -regexec (preg, string, nmatch, pmatch, eflags) - const regex_t *_Restrict_ preg; - const char *_Restrict_ string; - size_t nmatch; - regmatch_t pmatch[_Restrict_arr_]; - int eflags; -{ - reg_errcode_t err; - Idx start, length; -#ifdef _LIBC - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; -#endif - - if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) - return REG_BADPAT; - - if (eflags & REG_STARTEND) - { - start = pmatch[0].rm_so; - length = pmatch[0].rm_eo; - } - else - { - start = 0; - length = strlen (string); - } - - __libc_lock_lock (dfa->lock); - if (preg->no_sub) - err = re_search_internal (preg, string, length, start, length, - length, 0, NULL, eflags); - else - err = re_search_internal (preg, string, length, start, length, - length, nmatch, pmatch, eflags); - __libc_lock_unlock (dfa->lock); - return err != REG_NOERROR; -} - -#ifdef _LIBC -# include -versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); - -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) -__typeof__ (__regexec) __compat_regexec; - -int -attribute_compat_text_section -__compat_regexec (const regex_t *_Restrict_ preg, - const char *_Restrict_ string, size_t nmatch, - regmatch_t pmatch[], int eflags) -{ - return regexec (preg, string, nmatch, pmatch, - eflags & (REG_NOTBOL | REG_NOTEOL)); -} -compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); -# endif -#endif - -/* Entry points for GNU code. */ - -/* re_match, re_search, re_match_2, re_search_2 - - The former two functions operate on STRING with length LENGTH, - while the later two operate on concatenation of STRING1 and STRING2 - with lengths LENGTH1 and LENGTH2, respectively. - - re_match() matches the compiled pattern in BUFP against the string, - starting at index START. - - re_search() first tries matching at index START, then it tries to match - starting from index START + 1, and so on. The last start position tried - is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same - way as re_match().) - - The parameter STOP of re_{match,search}_2 specifies that no match exceeding - the first STOP characters of the concatenation of the strings should be - concerned. - - If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match - and all groups is stored in REGS. (For the "_2" variants, the offsets are - computed relative to the concatenation, not relative to the individual - strings.) - - On success, re_match* functions return the length of the match, re_search* - return the position of the start of the match. Return value -1 means no - match was found and -2 indicates an internal error. */ - -regoff_t -re_match (bufp, string, length, start, regs) - struct re_pattern_buffer *bufp; - const char *string; - Idx length, start; - struct re_registers *regs; -{ - return re_search_stub (bufp, string, length, start, 0, length, regs, true); -} -#ifdef _LIBC -weak_alias (__re_match, re_match) -#endif - -regoff_t -re_search (bufp, string, length, start, range, regs) - struct re_pattern_buffer *bufp; - const char *string; - Idx length, start; - regoff_t range; - struct re_registers *regs; -{ - return re_search_stub (bufp, string, length, start, range, length, regs, - false); -} -#ifdef _LIBC -weak_alias (__re_search, re_search) -#endif - -regoff_t -re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - Idx length1, length2, start, stop; - struct re_registers *regs; -{ - return re_search_2_stub (bufp, string1, length1, string2, length2, - start, 0, regs, stop, true); -} -#ifdef _LIBC -weak_alias (__re_match_2, re_match_2) -#endif - -regoff_t -re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - Idx length1, length2, start, stop; - regoff_t range; - struct re_registers *regs; -{ - return re_search_2_stub (bufp, string1, length1, string2, length2, - start, range, regs, stop, false); -} -#ifdef _LIBC -weak_alias (__re_search_2, re_search_2) -#endif - -static regoff_t -internal_function -re_search_2_stub (struct re_pattern_buffer *bufp, - const char *string1, Idx length1, - const char *string2, Idx length2, - Idx start, regoff_t range, struct re_registers *regs, - Idx stop, bool ret_len) -{ - const char *str; - regoff_t rval; - Idx len = length1 + length2; - char *s = NULL; - - if (BE (length1 < 0 || length2 < 0 || stop < 0 || len < length1, 0)) - return -2; - - /* Concatenate the strings. */ - if (length2 > 0) - if (length1 > 0) - { - s = re_malloc (char, len); - - if (BE (s == NULL, 0)) - return -2; -#ifdef _LIBC - memcpy (__mempcpy (s, string1, length1), string2, length2); -#else - memcpy (s, string1, length1); - memcpy (s + length1, string2, length2); -#endif - str = s; - } - else - str = string2; - else - str = string1; - - rval = re_search_stub (bufp, str, len, start, range, stop, regs, - ret_len); - re_free (s); - return rval; -} - -/* The parameters have the same meaning as those of re_search. - Additional parameters: - If RET_LEN is true the length of the match is returned (re_match style); - otherwise the position of the match is returned. */ - -static regoff_t -internal_function -re_search_stub (struct re_pattern_buffer *bufp, - const char *string, Idx length, - Idx start, regoff_t range, Idx stop, struct re_registers *regs, - bool ret_len) -{ - reg_errcode_t result; - regmatch_t *pmatch; - Idx nregs; - regoff_t rval; - int eflags = 0; -#ifdef _LIBC - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; -#endif - Idx last_start = start + range; - - /* Check for out-of-range. */ - if (BE (start < 0 || start > length, 0)) - return -1; - if (BE (length < last_start || (0 <= range && last_start < start), 0)) - last_start = length; - else if (BE (last_start < 0 || (range < 0 && start <= last_start), 0)) - last_start = 0; - - __libc_lock_lock (dfa->lock); - - eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; - eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; - - /* Compile fastmap if we haven't yet. */ - if (start < last_start && bufp->fastmap != NULL && !bufp->fastmap_accurate) - re_compile_fastmap (bufp); - - if (BE (bufp->no_sub, 0)) - regs = NULL; - - /* We need at least 1 register. */ - if (regs == NULL) - nregs = 1; - else if (BE (bufp->regs_allocated == REGS_FIXED - && regs->num_regs <= bufp->re_nsub, 0)) - { - nregs = regs->num_regs; - if (BE (nregs < 1, 0)) - { - /* Nothing can be copied to regs. */ - regs = NULL; - nregs = 1; - } - } - else - nregs = bufp->re_nsub + 1; - pmatch = re_malloc (regmatch_t, nregs); - if (BE (pmatch == NULL, 0)) - { - rval = -2; - goto out; - } - - result = re_search_internal (bufp, string, length, start, last_start, stop, - nregs, pmatch, eflags); - - rval = 0; - - /* I hope we needn't fill ther regs with -1's when no match was found. */ - if (result != REG_NOERROR) - rval = -1; - else if (regs != NULL) - { - /* If caller wants register contents data back, copy them. */ - bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, - bufp->regs_allocated); - if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0)) - rval = -2; - } - - if (BE (rval == 0, 1)) - { - if (ret_len) - { - assert (pmatch[0].rm_so == start); - rval = pmatch[0].rm_eo - start; - } - else - rval = pmatch[0].rm_so; - } - re_free (pmatch); - out: - __libc_lock_unlock (dfa->lock); - return rval; -} - -static unsigned int -internal_function -re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs, - int regs_allocated) -{ - int rval = REGS_REALLOCATE; - Idx i; - Idx need_regs = nregs + 1; - /* We need one extra element beyond `num_regs' for the `-1' marker GNU code - uses. */ - - /* Have the register data arrays been allocated? */ - if (regs_allocated == REGS_UNALLOCATED) - { /* No. So allocate them with malloc. */ - regs->start = re_malloc (regoff_t, need_regs); - if (BE (regs->start == NULL, 0)) - return REGS_UNALLOCATED; - regs->end = re_malloc (regoff_t, need_regs); - if (BE (regs->end == NULL, 0)) - { - re_free (regs->start); - return REGS_UNALLOCATED; - } - regs->num_regs = need_regs; - } - else if (regs_allocated == REGS_REALLOCATE) - { /* Yes. If we need more elements than were already - allocated, reallocate them. If we need fewer, just - leave it alone. */ - if (BE (need_regs > regs->num_regs, 0)) - { - regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); - regoff_t *new_end; - if (BE (new_start == NULL, 0)) - return REGS_UNALLOCATED; - new_end = re_realloc (regs->end, regoff_t, need_regs); - if (BE (new_end == NULL, 0)) - { - re_free (new_start); - return REGS_UNALLOCATED; - } - regs->start = new_start; - regs->end = new_end; - regs->num_regs = need_regs; - } - } - else - { - assert (regs_allocated == REGS_FIXED); - /* This function may not be called with REGS_FIXED and nregs too big. */ - assert (regs->num_regs >= nregs); - rval = REGS_FIXED; - } - - /* Copy the regs. */ - for (i = 0; i < nregs; ++i) - { - regs->start[i] = pmatch[i].rm_so; - regs->end[i] = pmatch[i].rm_eo; - } - for ( ; i < regs->num_regs; ++i) - regs->start[i] = regs->end[i] = -1; - - return rval; -} - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use - this memory for recording register information. STARTS and ENDS - must be allocated using the malloc library routine, and must each - be at least NUM_REGS * sizeof (regoff_t) bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ - -void -re_set_registers (bufp, regs, num_regs, starts, ends) - struct re_pattern_buffer *bufp; - struct re_registers *regs; - __re_size_t num_regs; - regoff_t *starts, *ends; -{ - if (num_regs) - { - bufp->regs_allocated = REGS_REALLOCATE; - regs->num_regs = num_regs; - regs->start = starts; - regs->end = ends; - } - else - { - bufp->regs_allocated = REGS_UNALLOCATED; - regs->num_regs = 0; - regs->start = regs->end = NULL; - } -} -#ifdef _LIBC -weak_alias (__re_set_registers, re_set_registers) -#endif - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined _REGEX_RE_COMP || defined _LIBC -int -# ifdef _LIBC -weak_function -# endif -re_exec (s) - const char *s; -{ - return 0 == regexec (&re_comp_buf, s, 0, NULL, 0); -} -#endif /* _REGEX_RE_COMP */ - -/* Internal entry point. */ - -/* Searches for a compiled pattern PREG in the string STRING, whose - length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same - meaning as with regexec. LAST_START is START + RANGE, where - START and RANGE have the same meaning as with re_search. - Return REG_NOERROR if we find a match, and REG_NOMATCH if not, - otherwise return the error code. - Note: We assume front end functions already check ranges. - (0 <= LAST_START && LAST_START <= LENGTH) */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -re_search_internal (const regex_t *preg, - const char *string, Idx length, - Idx start, Idx last_start, Idx stop, - size_t nmatch, regmatch_t pmatch[], - int eflags) -{ - reg_errcode_t err; - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; - Idx left_lim, right_lim; - int incr; - bool fl_longest_match; - int match_kind; - Idx match_first; - Idx match_last = REG_MISSING; - Idx extra_nmatch; - bool sb; - int ch; -#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) - re_match_context_t mctx = { .dfa = dfa }; -#else - re_match_context_t mctx; -#endif - char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate - && start != last_start && !preg->can_be_null) - ? preg->fastmap : NULL); - RE_TRANSLATE_TYPE t = preg->translate; - -#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) - memset (&mctx, '\0', sizeof (re_match_context_t)); - mctx.dfa = dfa; -#endif - - extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0; - nmatch -= extra_nmatch; - - /* Check if the DFA haven't been compiled. */ - if (BE (preg->used == 0 || dfa->init_state == NULL - || dfa->init_state_word == NULL || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL, 0)) - return REG_NOMATCH; - -#ifdef DEBUG - /* We assume front-end functions already check them. */ - assert (0 <= last_start && last_start <= length); -#endif - - /* If initial states with non-begbuf contexts have no elements, - the regex must be anchored. If preg->newline_anchor is set, - we'll never use init_state_nl, so do not check it. */ - if (dfa->init_state->nodes.nelem == 0 - && dfa->init_state_word->nodes.nelem == 0 - && (dfa->init_state_nl->nodes.nelem == 0 - || !preg->newline_anchor)) - { - if (start != 0 && last_start != 0) - return REG_NOMATCH; - start = last_start = 0; - } - - /* We must check the longest matching, if nmatch > 0. */ - fl_longest_match = (nmatch != 0 || dfa->nbackref); - - err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, - preg->translate, (preg->syntax & RE_ICASE) != 0, - dfa); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - mctx.input.stop = stop; - mctx.input.raw_stop = stop; - mctx.input.newline_anchor = preg->newline_anchor; - - err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* We will log all the DFA states through which the dfa pass, - if nmatch > 1, or this dfa has "multibyte node", which is a - back-reference or a node which can accept multibyte character or - multi character collating element. */ - if (nmatch > 1 || dfa->has_mb_node) - { - /* Avoid overflow. */ - if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= mctx.input.bufs_len, 0)) - { - err = REG_ESPACE; - goto free_return; - } - - mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); - if (BE (mctx.state_log == NULL, 0)) - { - err = REG_ESPACE; - goto free_return; - } - } - else - mctx.state_log = NULL; - - match_first = start; - mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF - : CONTEXT_NEWLINE | CONTEXT_BEGBUF; - - /* Check incrementally whether of not the input string match. */ - incr = (last_start < start) ? -1 : 1; - left_lim = (last_start < start) ? last_start : start; - right_lim = (last_start < start) ? start : last_start; - sb = dfa->mb_cur_max == 1; - match_kind = - (fastmap - ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) - | (start <= last_start ? 2 : 0) - | (t != NULL ? 1 : 0)) - : 8); - - for (;; match_first += incr) - { - err = REG_NOMATCH; - if (match_first < left_lim || right_lim < match_first) - goto free_return; - - /* Advance as rapidly as possible through the string, until we - find a plausible place to start matching. This may be done - with varying efficiency, so there are various possibilities: - only the most common of them are specialized, in order to - save on code size. We use a switch statement for speed. */ - switch (match_kind) - { - case 8: - /* No fastmap. */ - break; - - case 7: - /* Fastmap with single-byte translation, match forward. */ - while (BE (match_first < right_lim, 1) - && !fastmap[t[(unsigned char) string[match_first]]]) - ++match_first; - goto forward_match_found_start_or_reached_end; - - case 6: - /* Fastmap without translation, match forward. */ - while (BE (match_first < right_lim, 1) - && !fastmap[(unsigned char) string[match_first]]) - ++match_first; - - forward_match_found_start_or_reached_end: - if (BE (match_first == right_lim, 0)) - { - ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (!fastmap[t ? t[ch] : ch]) - goto free_return; - } - break; - - case 4: - case 5: - /* Fastmap without multi-byte translation, match backwards. */ - while (match_first >= left_lim) - { - ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (fastmap[t ? t[ch] : ch]) - break; - --match_first; - } - if (match_first < left_lim) - goto free_return; - break; - - default: - /* In this case, we can't determine easily the current byte, - since it might be a component byte of a multibyte - character. Then we use the constructed buffer instead. */ - for (;;) - { - /* If MATCH_FIRST is out of the valid range, reconstruct the - buffers. */ - __re_size_t offset = match_first - mctx.input.raw_mbs_idx; - if (BE (offset >= (__re_size_t) mctx.input.valid_raw_len, 0)) - { - err = re_string_reconstruct (&mctx.input, match_first, - eflags); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - offset = match_first - mctx.input.raw_mbs_idx; - } - /* If MATCH_FIRST is out of the buffer, leave it as '\0'. - Note that MATCH_FIRST must not be smaller than 0. */ - ch = (match_first >= length - ? 0 : re_string_byte_at (&mctx.input, offset)); - if (fastmap[ch]) - break; - match_first += incr; - if (match_first < left_lim || match_first > right_lim) - { - err = REG_NOMATCH; - goto free_return; - } - } - break; - } - - /* Reconstruct the buffers so that the matcher can assume that - the matching starts from the beginning of the buffer. */ - err = re_string_reconstruct (&mctx.input, match_first, eflags); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - -#ifdef RE_ENABLE_I18N - /* Don't consider this char as a possible match start if it part, - yet isn't the head, of a multibyte character. */ - if (!sb && !re_string_first_byte (&mctx.input, 0)) - continue; -#endif - - /* It seems to be appropriate one, then use the matcher. */ - /* We assume that the matching starts from 0. */ - mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; - match_last = check_matching (&mctx, fl_longest_match, - start <= last_start ? &match_first : NULL); - if (match_last != REG_MISSING) - { - if (BE (match_last == REG_ERROR, 0)) - { - err = REG_ESPACE; - goto free_return; - } - else - { - mctx.match_last = match_last; - if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) - { - re_dfastate_t *pstate = mctx.state_log[match_last]; - mctx.last_node = check_halt_state_context (&mctx, pstate, - match_last); - } - if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) - || dfa->nbackref) - { - err = prune_impossible_nodes (&mctx); - if (err == REG_NOERROR) - break; - if (BE (err != REG_NOMATCH, 0)) - goto free_return; - match_last = REG_MISSING; - } - else - break; /* We found a match. */ - } - } - - match_ctx_clean (&mctx); - } - -#ifdef DEBUG - assert (match_last != REG_MISSING); - assert (err == REG_NOERROR); -#endif - - /* Set pmatch[] if we need. */ - if (nmatch > 0) - { - Idx reg_idx; - - /* Initialize registers. */ - for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) - pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; - - /* Set the points where matching start/end. */ - pmatch[0].rm_so = 0; - pmatch[0].rm_eo = mctx.match_last; - /* FIXME: This function should fail if mctx.match_last exceeds - the maximum possible regoff_t value. We need a new error - code REG_OVERFLOW. */ - - if (!preg->no_sub && nmatch > 1) - { - err = set_regs (preg, &mctx, nmatch, pmatch, - dfa->has_plural_match && dfa->nbackref > 0); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - - /* At last, add the offset to the each registers, since we slided - the buffers so that we could assume that the matching starts - from 0. */ - for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) - if (pmatch[reg_idx].rm_so != -1) - { -#ifdef RE_ENABLE_I18N - if (BE (mctx.input.offsets_needed != 0, 0)) - { - pmatch[reg_idx].rm_so = - (pmatch[reg_idx].rm_so == mctx.input.valid_len - ? mctx.input.valid_raw_len - : mctx.input.offsets[pmatch[reg_idx].rm_so]); - pmatch[reg_idx].rm_eo = - (pmatch[reg_idx].rm_eo == mctx.input.valid_len - ? mctx.input.valid_raw_len - : mctx.input.offsets[pmatch[reg_idx].rm_eo]); - } -#else - assert (mctx.input.offsets_needed == 0); -#endif - pmatch[reg_idx].rm_so += match_first; - pmatch[reg_idx].rm_eo += match_first; - } - for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx) - { - pmatch[nmatch + reg_idx].rm_so = -1; - pmatch[nmatch + reg_idx].rm_eo = -1; - } - - if (dfa->subexp_map) - for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++) - if (dfa->subexp_map[reg_idx] != reg_idx) - { - pmatch[reg_idx + 1].rm_so - = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; - pmatch[reg_idx + 1].rm_eo - = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; - } - } - - free_return: - re_free (mctx.state_log); - if (dfa->nbackref) - match_ctx_free (&mctx); - re_string_destruct (&mctx.input); - return err; -} - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -prune_impossible_nodes (re_match_context_t *mctx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx halt_node, match_last; - reg_errcode_t ret; - re_dfastate_t **sifted_states; - re_dfastate_t **lim_states = NULL; - re_sift_context_t sctx; -#ifdef DEBUG - assert (mctx->state_log != NULL); -#endif - match_last = mctx->match_last; - halt_node = mctx->last_node; - - /* Avoid overflow. */ - if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= match_last, 0)) - return REG_ESPACE; - - sifted_states = re_malloc (re_dfastate_t *, match_last + 1); - if (BE (sifted_states == NULL, 0)) - { - ret = REG_ESPACE; - goto free_return; - } - if (dfa->nbackref) - { - lim_states = re_malloc (re_dfastate_t *, match_last + 1); - if (BE (lim_states == NULL, 0)) - { - ret = REG_ESPACE; - goto free_return; - } - while (1) - { - memset (lim_states, '\0', - sizeof (re_dfastate_t *) * (match_last + 1)); - sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, - match_last); - ret = sift_states_backward (mctx, &sctx); - re_node_set_free (&sctx.limits); - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - if (sifted_states[0] != NULL || lim_states[0] != NULL) - break; - do - { - --match_last; - if (! REG_VALID_INDEX (match_last)) - { - ret = REG_NOMATCH; - goto free_return; - } - } while (mctx->state_log[match_last] == NULL - || !mctx->state_log[match_last]->halt); - halt_node = check_halt_state_context (mctx, - mctx->state_log[match_last], - match_last); - } - ret = merge_state_array (dfa, sifted_states, lim_states, - match_last + 1); - re_free (lim_states); - lim_states = NULL; - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - } - else - { - sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); - ret = sift_states_backward (mctx, &sctx); - re_node_set_free (&sctx.limits); - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - if (sifted_states[0] == NULL) - { - ret = REG_NOMATCH; - goto free_return; - } - } - re_free (mctx->state_log); - mctx->state_log = sifted_states; - sifted_states = NULL; - mctx->last_node = halt_node; - mctx->match_last = match_last; - ret = REG_NOERROR; - free_return: - re_free (sifted_states); - re_free (lim_states); - return ret; -} - -/* Acquire an initial state and return it. - We must select appropriate initial state depending on the context, - since initial states may have constraints like "\<", "^", etc.. */ - -static inline re_dfastate_t * -__attribute ((always_inline)) internal_function -acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, - Idx idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - if (dfa->init_state->has_constraint) - { - unsigned int context; - context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); - if (IS_WORD_CONTEXT (context)) - return dfa->init_state_word; - else if (IS_ORDINARY_CONTEXT (context)) - return dfa->init_state; - else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) - return dfa->init_state_begbuf; - else if (IS_NEWLINE_CONTEXT (context)) - return dfa->init_state_nl; - else if (IS_BEGBUF_CONTEXT (context)) - { - /* It is relatively rare case, then calculate on demand. */ - return re_acquire_state_context (err, dfa, - dfa->init_state->entrance_nodes, - context); - } - else - /* Must not happen? */ - return dfa->init_state; - } - else - return dfa->init_state; -} - -/* Check whether the regular expression match input string INPUT or not, - and return the index where the matching end. Return REG_MISSING if - there is no match, and return REG_ERROR in case of an error. - FL_LONGEST_MATCH means we want the POSIX longest matching. - If P_MATCH_FIRST is not NULL, and the match fails, it is set to the - next place where we may want to try matching. - Note that the matcher assume that the maching starts from the current - index of the buffer. */ - -static Idx -internal_function __attribute_warn_unused_result__ -check_matching (re_match_context_t *mctx, bool fl_longest_match, - Idx *p_match_first) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx match = 0; - Idx match_last = REG_MISSING; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - re_dfastate_t *cur_state; - bool at_init_state = p_match_first != NULL; - Idx next_start_idx = cur_str_idx; - - err = REG_NOERROR; - cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); - /* An initial state must not be NULL (invalid). */ - if (BE (cur_state == NULL, 0)) - { - assert (err == REG_ESPACE); - return REG_ERROR; - } - - if (mctx->state_log != NULL) - { - mctx->state_log[cur_str_idx] = cur_state; - - /* Check OP_OPEN_SUBEXP in the initial state in case that we use them - later. E.g. Processing back references. */ - if (BE (dfa->nbackref, 0)) - { - at_init_state = false; - err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (cur_state->has_backref) - { - err = transit_state_bkref (mctx, &cur_state->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - } - - /* If the RE accepts NULL string. */ - if (BE (cur_state->halt, 0)) - { - if (!cur_state->has_constraint - || check_halt_state_context (mctx, cur_state, cur_str_idx)) - { - if (!fl_longest_match) - return cur_str_idx; - else - { - match_last = cur_str_idx; - match = 1; - } - } - } - - while (!re_string_eoi (&mctx->input)) - { - re_dfastate_t *old_state = cur_state; - Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1; - - if (BE (next_char_idx >= mctx->input.bufs_len, 0) - || (BE (next_char_idx >= mctx->input.valid_len, 0) - && mctx->input.valid_len < mctx->input.len)) - { - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - { - assert (err == REG_ESPACE); - return REG_ERROR; - } - } - - cur_state = transit_state (&err, mctx, cur_state); - if (mctx->state_log != NULL) - cur_state = merge_state_with_log (&err, mctx, cur_state); - - if (cur_state == NULL) - { - /* Reached the invalid state or an error. Try to recover a valid - state using the state log, if available and if we have not - already found a valid (even if not the longest) match. */ - if (BE (err != REG_NOERROR, 0)) - return REG_ERROR; - - if (mctx->state_log == NULL - || (match && !fl_longest_match) - || (cur_state = find_recover_state (&err, mctx)) == NULL) - break; - } - - if (BE (at_init_state, 0)) - { - if (old_state == cur_state) - next_start_idx = next_char_idx; - else - at_init_state = false; - } - - if (cur_state->halt) - { - /* Reached a halt state. - Check the halt state can satisfy the current context. */ - if (!cur_state->has_constraint - || check_halt_state_context (mctx, cur_state, - re_string_cur_idx (&mctx->input))) - { - /* We found an appropriate halt state. */ - match_last = re_string_cur_idx (&mctx->input); - match = 1; - - /* We found a match, do not modify match_first below. */ - p_match_first = NULL; - if (!fl_longest_match) - break; - } - } - } - - if (p_match_first) - *p_match_first += next_start_idx; - - return match_last; -} - -/* Check NODE match the current context. */ - -static bool -internal_function -check_halt_node_context (const re_dfa_t *dfa, Idx node, unsigned int context) -{ - re_token_type_t type = dfa->nodes[node].type; - unsigned int constraint = dfa->nodes[node].constraint; - if (type != END_OF_RE) - return false; - if (!constraint) - return true; - if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) - return false; - return true; -} - -/* Check the halt state STATE match the current context. - Return 0 if not match, if the node, STATE has, is a halt node and - match the context, return the node. */ - -static Idx -internal_function -check_halt_state_context (const re_match_context_t *mctx, - const re_dfastate_t *state, Idx idx) -{ - Idx i; - unsigned int context; -#ifdef DEBUG - assert (state->halt); -#endif - context = re_string_context_at (&mctx->input, idx, mctx->eflags); - for (i = 0; i < state->nodes.nelem; ++i) - if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) - return state->nodes.elems[i]; - return 0; -} - -/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA - corresponding to the DFA). - Return the destination node, and update EPS_VIA_NODES; - return REG_MISSING in case of errors. */ - -static Idx -internal_function -proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, - Idx *pidx, Idx node, re_node_set *eps_via_nodes, - struct re_fail_stack_t *fs) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx i; - bool ok; - if (IS_EPSILON_NODE (dfa->nodes[node].type)) - { - re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; - re_node_set *edests = &dfa->edests[node]; - Idx dest_node; - ok = re_node_set_insert (eps_via_nodes, node); - if (BE (! ok, 0)) - return REG_ERROR; - /* Pick up a valid destination, or return REG_MISSING if none - is found. */ - for (dest_node = REG_MISSING, i = 0; i < edests->nelem; ++i) - { - Idx candidate = edests->elems[i]; - if (!re_node_set_contains (cur_nodes, candidate)) - continue; - if (dest_node == REG_MISSING) - dest_node = candidate; - - else - { - /* In order to avoid infinite loop like "(a*)*", return the second - epsilon-transition if the first was already considered. */ - if (re_node_set_contains (eps_via_nodes, dest_node)) - return candidate; - - /* Otherwise, push the second epsilon-transition on the fail stack. */ - else if (fs != NULL - && push_fail_stack (fs, *pidx, candidate, nregs, regs, - eps_via_nodes)) - return REG_ERROR; - - /* We know we are going to exit. */ - break; - } - } - return dest_node; - } - else - { - Idx naccepted = 0; - re_token_type_t type = dfa->nodes[node].type; - -#ifdef RE_ENABLE_I18N - if (dfa->nodes[node].accept_mb) - naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); - else -#endif /* RE_ENABLE_I18N */ - if (type == OP_BACK_REF) - { - Idx subexp_idx = dfa->nodes[node].opr.idx + 1; - naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; - if (fs != NULL) - { - if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1) - return REG_MISSING; - else if (naccepted) - { - char *buf = (char *) re_string_get_buffer (&mctx->input); - if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, - naccepted) != 0) - return REG_MISSING; - } - } - - if (naccepted == 0) - { - Idx dest_node; - ok = re_node_set_insert (eps_via_nodes, node); - if (BE (! ok, 0)) - return REG_ERROR; - dest_node = dfa->edests[node].elems[0]; - if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, - dest_node)) - return dest_node; - } - } - - if (naccepted != 0 - || check_node_accept (mctx, dfa->nodes + node, *pidx)) - { - Idx dest_node = dfa->nexts[node]; - *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; - if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL - || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, - dest_node))) - return REG_MISSING; - re_node_set_empty (eps_via_nodes); - return dest_node; - } - } - return REG_MISSING; -} - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node, - Idx nregs, regmatch_t *regs, re_node_set *eps_via_nodes) -{ - reg_errcode_t err; - Idx num = fs->num++; - if (fs->num == fs->alloc) - { - struct re_fail_stack_ent_t *new_array; - new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t) - * fs->alloc * 2)); - if (new_array == NULL) - return REG_ESPACE; - fs->alloc *= 2; - fs->stack = new_array; - } - fs->stack[num].idx = str_idx; - fs->stack[num].node = dest_node; - fs->stack[num].regs = re_malloc (regmatch_t, nregs); - if (fs->stack[num].regs == NULL) - return REG_ESPACE; - memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); - err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); - return err; -} - -static Idx -internal_function -pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs, - regmatch_t *regs, re_node_set *eps_via_nodes) -{ - Idx num = --fs->num; - assert (REG_VALID_INDEX (num)); - *pidx = fs->stack[num].idx; - memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); - re_node_set_free (eps_via_nodes); - re_free (fs->stack[num].regs); - *eps_via_nodes = fs->stack[num].eps_via_nodes; - return fs->stack[num].node; -} - -/* Set the positions where the subexpressions are starts/ends to registers - PMATCH. - Note: We assume that pmatch[0] is already set, and - pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, - regmatch_t *pmatch, bool fl_backtrack) -{ - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; - Idx idx, cur_node; - re_node_set eps_via_nodes; - struct re_fail_stack_t *fs; - struct re_fail_stack_t fs_body = { 0, 2, NULL }; - regmatch_t *prev_idx_match; - bool prev_idx_match_malloced = false; - -#ifdef DEBUG - assert (nmatch > 1); - assert (mctx->state_log != NULL); -#endif - if (fl_backtrack) - { - fs = &fs_body; - fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); - if (fs->stack == NULL) - return REG_ESPACE; - } - else - fs = NULL; - - cur_node = dfa->init_node; - re_node_set_init_empty (&eps_via_nodes); - - if (__libc_use_alloca (nmatch * sizeof (regmatch_t))) - prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t)); - else - { - prev_idx_match = re_malloc (regmatch_t, nmatch); - if (prev_idx_match == NULL) - { - free_fail_stack_return (fs); - return REG_ESPACE; - } - prev_idx_match_malloced = true; - } - memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); - - for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) - { - update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); - - if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) - { - Idx reg_idx; - if (fs) - { - for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) - if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) - break; - if (reg_idx == nmatch) - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return free_fail_stack_return (fs); - } - cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, - &eps_via_nodes); - } - else - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return REG_NOERROR; - } - } - - /* Proceed to next node. */ - cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node, - &eps_via_nodes, fs); - - if (BE (! REG_VALID_INDEX (cur_node), 0)) - { - if (BE (cur_node == REG_ERROR, 0)) - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - free_fail_stack_return (fs); - return REG_ESPACE; - } - if (fs) - cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, - &eps_via_nodes); - else - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return REG_NOMATCH; - } - } - } - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return free_fail_stack_return (fs); -} - -static reg_errcode_t -internal_function -free_fail_stack_return (struct re_fail_stack_t *fs) -{ - if (fs) - { - Idx fs_idx; - for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) - { - re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); - re_free (fs->stack[fs_idx].regs); - } - re_free (fs->stack); - } - return REG_NOERROR; -} - -static void -internal_function -update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, - regmatch_t *prev_idx_match, Idx cur_node, Idx cur_idx, Idx nmatch) -{ - int type = dfa->nodes[cur_node].type; - if (type == OP_OPEN_SUBEXP) - { - Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; - - /* We are at the first node of this sub expression. */ - if (reg_num < nmatch) - { - pmatch[reg_num].rm_so = cur_idx; - pmatch[reg_num].rm_eo = -1; - } - } - else if (type == OP_CLOSE_SUBEXP) - { - Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; - if (reg_num < nmatch) - { - /* We are at the last node of this sub expression. */ - if (pmatch[reg_num].rm_so < cur_idx) - { - pmatch[reg_num].rm_eo = cur_idx; - /* This is a non-empty match or we are not inside an optional - subexpression. Accept this right away. */ - memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); - } - else - { - if (dfa->nodes[cur_node].opt_subexp - && prev_idx_match[reg_num].rm_so != -1) - /* We transited through an empty match for an optional - subexpression, like (a?)*, and this is not the subexp's - first match. Copy back the old content of the registers - so that matches of an inner subexpression are undone as - well, like in ((a?))*. */ - memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); - else - /* We completed a subexpression, but it may be part of - an optional one, so do not update PREV_IDX_MATCH. */ - pmatch[reg_num].rm_eo = cur_idx; - } - } - } -} - -/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 - and sift the nodes in each states according to the following rules. - Updated state_log will be wrote to STATE_LOG. - - Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if... - 1. When STR_IDX == MATCH_LAST(the last index in the state_log): - If `a' isn't the LAST_NODE and `a' can't epsilon transit to - the LAST_NODE, we throw away the node `a'. - 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts - string `s' and transit to `b': - i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw - away the node `a'. - ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is - thrown away, we throw away the node `a'. - 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': - i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the - node `a'. - ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, - we throw away the node `a'. */ - -#define STATE_NODE_CONTAINS(state,node) \ - ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) - -static reg_errcode_t -internal_function -sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) -{ - reg_errcode_t err; - int null_cnt = 0; - Idx str_idx = sctx->last_str_idx; - re_node_set cur_dest; - -#ifdef DEBUG - assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); -#endif - - /* Build sifted state_log[str_idx]. It has the nodes which can epsilon - transit to the last_node and the last_node itself. */ - err = re_node_set_init_1 (&cur_dest, sctx->last_node); - if (BE (err != REG_NOERROR, 0)) - return err; - err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* Then check each states in the state_log. */ - while (str_idx > 0) - { - /* Update counters. */ - null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; - if (null_cnt > mctx->max_mb_elem_len) - { - memset (sctx->sifted_states, '\0', - sizeof (re_dfastate_t *) * str_idx); - re_node_set_free (&cur_dest); - return REG_NOERROR; - } - re_node_set_empty (&cur_dest); - --str_idx; - - if (mctx->state_log[str_idx]) - { - err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - - /* Add all the nodes which satisfy the following conditions: - - It can epsilon transit to a node in CUR_DEST. - - It is in CUR_SRC. - And update state_log. */ - err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - err = REG_NOERROR; - free_return: - re_node_set_free (&cur_dest); - return err; -} - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx str_idx, re_node_set *cur_dest) -{ - const re_dfa_t *const dfa = mctx->dfa; - const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; - Idx i; - - /* Then build the next sifted state. - We build the next sifted state on `cur_dest', and update - `sifted_states[str_idx]' with `cur_dest'. - Note: - `cur_dest' is the sifted state from `state_log[str_idx + 1]'. - `cur_src' points the node_set of the old `state_log[str_idx]' - (with the epsilon nodes pre-filtered out). */ - for (i = 0; i < cur_src->nelem; i++) - { - Idx prev_node = cur_src->elems[i]; - int naccepted = 0; - bool ok; - -#ifdef DEBUG - re_token_type_t type = dfa->nodes[prev_node].type; - assert (!IS_EPSILON_NODE (type)); -#endif -#ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ - if (dfa->nodes[prev_node].accept_mb) - naccepted = sift_states_iter_mb (mctx, sctx, prev_node, - str_idx, sctx->last_str_idx); -#endif /* RE_ENABLE_I18N */ - - /* We don't check backreferences here. - See update_cur_sifted_state(). */ - if (!naccepted - && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) - && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], - dfa->nexts[prev_node])) - naccepted = 1; - - if (naccepted == 0) - continue; - - if (sctx->limits.nelem) - { - Idx to_idx = str_idx + naccepted; - if (check_dst_limits (mctx, &sctx->limits, - dfa->nexts[prev_node], to_idx, - prev_node, str_idx)) - continue; - } - ok = re_node_set_insert (cur_dest, prev_node); - if (BE (! ok, 0)) - return REG_ESPACE; - } - - return REG_NOERROR; -} - -/* Helper functions. */ - -static reg_errcode_t -internal_function -clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx) -{ - Idx top = mctx->state_log_top; - - if (next_state_log_idx >= mctx->input.bufs_len - || (next_state_log_idx >= mctx->input.valid_len - && mctx->input.valid_len < mctx->input.len)) - { - reg_errcode_t err; - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (top < next_state_log_idx) - { - memset (mctx->state_log + top + 1, '\0', - sizeof (re_dfastate_t *) * (next_state_log_idx - top)); - mctx->state_log_top = next_state_log_idx; - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, - re_dfastate_t **src, Idx num) -{ - Idx st_idx; - reg_errcode_t err; - for (st_idx = 0; st_idx < num; ++st_idx) - { - if (dst[st_idx] == NULL) - dst[st_idx] = src[st_idx]; - else if (src[st_idx] != NULL) - { - re_node_set merged_set; - err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, - &src[st_idx]->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); - re_node_set_free (&merged_set); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -update_cur_sifted_state (const re_match_context_t *mctx, - re_sift_context_t *sctx, Idx str_idx, - re_node_set *dest_nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err = REG_NOERROR; - const re_node_set *candidates; - candidates = ((mctx->state_log[str_idx] == NULL) ? NULL - : &mctx->state_log[str_idx]->nodes); - - if (dest_nodes->nelem == 0) - sctx->sifted_states[str_idx] = NULL; - else - { - if (candidates) - { - /* At first, add the nodes which can epsilon transit to a node in - DEST_NODE. */ - err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* Then, check the limitations in the current sift_context. */ - if (sctx->limits.nelem) - { - err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, - mctx->bkref_ents, str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - - sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (candidates && mctx->state_log[str_idx]->has_backref) - { - err = sift_states_bkref (mctx, sctx, str_idx, candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, - const re_node_set *candidates) -{ - reg_errcode_t err = REG_NOERROR; - Idx i; - - re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (!state->inveclosure.alloc) - { - err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); - if (BE (err != REG_NOERROR, 0)) - return REG_ESPACE; - for (i = 0; i < dest_nodes->nelem; i++) - { - err = re_node_set_merge (&state->inveclosure, - dfa->inveclosures + dest_nodes->elems[i]); - if (BE (err != REG_NOERROR, 0)) - return REG_ESPACE; - } - } - return re_node_set_add_intersect (dest_nodes, candidates, - &state->inveclosure); -} - -static reg_errcode_t -internal_function -sub_epsilon_src_nodes (const re_dfa_t *dfa, Idx node, re_node_set *dest_nodes, - const re_node_set *candidates) -{ - Idx ecl_idx; - reg_errcode_t err; - re_node_set *inv_eclosure = dfa->inveclosures + node; - re_node_set except_nodes; - re_node_set_init_empty (&except_nodes); - for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) - { - Idx cur_node = inv_eclosure->elems[ecl_idx]; - if (cur_node == node) - continue; - if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) - { - Idx edst1 = dfa->edests[cur_node].elems[0]; - Idx edst2 = ((dfa->edests[cur_node].nelem > 1) - ? dfa->edests[cur_node].elems[1] : REG_MISSING); - if ((!re_node_set_contains (inv_eclosure, edst1) - && re_node_set_contains (dest_nodes, edst1)) - || (REG_VALID_NONZERO_INDEX (edst2) - && !re_node_set_contains (inv_eclosure, edst2) - && re_node_set_contains (dest_nodes, edst2))) - { - err = re_node_set_add_intersect (&except_nodes, candidates, - dfa->inveclosures + cur_node); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&except_nodes); - return err; - } - } - } - } - for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) - { - Idx cur_node = inv_eclosure->elems[ecl_idx]; - if (!re_node_set_contains (&except_nodes, cur_node)) - { - Idx idx = re_node_set_contains (dest_nodes, cur_node) - 1; - re_node_set_remove_at (dest_nodes, idx); - } - } - re_node_set_free (&except_nodes); - return REG_NOERROR; -} - -static bool -internal_function -check_dst_limits (const re_match_context_t *mctx, const re_node_set *limits, - Idx dst_node, Idx dst_idx, Idx src_node, Idx src_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx lim_idx, src_pos, dst_pos; - - Idx dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); - Idx src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); - for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) - { - Idx subexp_idx; - struct re_backref_cache_entry *ent; - ent = mctx->bkref_ents + limits->elems[lim_idx]; - subexp_idx = dfa->nodes[ent->node].opr.idx; - - dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - subexp_idx, dst_node, dst_idx, - dst_bkref_idx); - src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - subexp_idx, src_node, src_idx, - src_bkref_idx); - - /* In case of: - ( ) - ( ) - ( ) */ - if (src_pos == dst_pos) - continue; /* This is unrelated limitation. */ - else - return true; - } - return false; -} - -static int -internal_function -check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, - Idx subexp_idx, Idx from_node, Idx bkref_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - const re_node_set *eclosures = dfa->eclosures + from_node; - Idx node_idx; - - /* Else, we are on the boundary: examine the nodes on the epsilon - closure. */ - for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) - { - Idx node = eclosures->elems[node_idx]; - switch (dfa->nodes[node].type) - { - case OP_BACK_REF: - if (bkref_idx != REG_MISSING) - { - struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; - do - { - Idx dst; - int cpos; - - if (ent->node != node) - continue; - - if (subexp_idx < BITSET_WORD_BITS - && !(ent->eps_reachable_subexps_map - & ((bitset_word_t) 1 << subexp_idx))) - continue; - - /* Recurse trying to reach the OP_OPEN_SUBEXP and - OP_CLOSE_SUBEXP cases below. But, if the - destination node is the same node as the source - node, don't recurse because it would cause an - infinite loop: a regex that exhibits this behavior - is ()\1*\1* */ - dst = dfa->edests[node].elems[0]; - if (dst == from_node) - { - if (boundaries & 1) - return -1; - else /* if (boundaries & 2) */ - return 0; - } - - cpos = - check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, - dst, bkref_idx); - if (cpos == -1 /* && (boundaries & 1) */) - return -1; - if (cpos == 0 && (boundaries & 2)) - return 0; - - if (subexp_idx < BITSET_WORD_BITS) - ent->eps_reachable_subexps_map - &= ~((bitset_word_t) 1 << subexp_idx); - } - while (ent++->more); - } - break; - - case OP_OPEN_SUBEXP: - if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) - return -1; - break; - - case OP_CLOSE_SUBEXP: - if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) - return 0; - break; - - default: - break; - } - } - - return (boundaries & 2) ? 1 : 0; -} - -static int -internal_function -check_dst_limits_calc_pos (const re_match_context_t *mctx, Idx limit, - Idx subexp_idx, Idx from_node, Idx str_idx, - Idx bkref_idx) -{ - struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; - int boundaries; - - /* If we are outside the range of the subexpression, return -1 or 1. */ - if (str_idx < lim->subexp_from) - return -1; - - if (lim->subexp_to < str_idx) - return 1; - - /* If we are within the subexpression, return 0. */ - boundaries = (str_idx == lim->subexp_from); - boundaries |= (str_idx == lim->subexp_to) << 1; - if (boundaries == 0) - return 0; - - /* Else, examine epsilon closure. */ - return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, - from_node, bkref_idx); -} - -/* Check the limitations of sub expressions LIMITS, and remove the nodes - which are against limitations from DEST_NODES. */ - -static reg_errcode_t -internal_function -check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, - const re_node_set *candidates, re_node_set *limits, - struct re_backref_cache_entry *bkref_ents, Idx str_idx) -{ - reg_errcode_t err; - Idx node_idx, lim_idx; - - for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) - { - Idx subexp_idx; - struct re_backref_cache_entry *ent; - ent = bkref_ents + limits->elems[lim_idx]; - - if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) - continue; /* This is unrelated limitation. */ - - subexp_idx = dfa->nodes[ent->node].opr.idx; - if (ent->subexp_to == str_idx) - { - Idx ops_node = REG_MISSING; - Idx cls_node = REG_MISSING; - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - re_token_type_t type = dfa->nodes[node].type; - if (type == OP_OPEN_SUBEXP - && subexp_idx == dfa->nodes[node].opr.idx) - ops_node = node; - else if (type == OP_CLOSE_SUBEXP - && subexp_idx == dfa->nodes[node].opr.idx) - cls_node = node; - } - - /* Check the limitation of the open subexpression. */ - /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ - if (REG_VALID_INDEX (ops_node)) - { - err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - /* Check the limitation of the close subexpression. */ - if (REG_VALID_INDEX (cls_node)) - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - if (!re_node_set_contains (dfa->inveclosures + node, - cls_node) - && !re_node_set_contains (dfa->eclosures + node, - cls_node)) - { - /* It is against this limitation. - Remove it form the current sifted state. */ - err = sub_epsilon_src_nodes (dfa, node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - --node_idx; - } - } - } - else /* (ent->subexp_to != str_idx) */ - { - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - re_token_type_t type = dfa->nodes[node].type; - if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) - { - if (subexp_idx != dfa->nodes[node].opr.idx) - continue; - /* It is against this limitation. - Remove it form the current sifted state. */ - err = sub_epsilon_src_nodes (dfa, node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx str_idx, const re_node_set *candidates) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx node_idx, node; - re_sift_context_t local_sctx; - Idx first_idx = search_cur_bkref_entry (mctx, str_idx); - - if (first_idx == REG_MISSING) - return REG_NOERROR; - - local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ - - for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) - { - Idx enabled_idx; - re_token_type_t type; - struct re_backref_cache_entry *entry; - node = candidates->elems[node_idx]; - type = dfa->nodes[node].type; - /* Avoid infinite loop for the REs like "()\1+". */ - if (node == sctx->last_node && str_idx == sctx->last_str_idx) - continue; - if (type != OP_BACK_REF) - continue; - - entry = mctx->bkref_ents + first_idx; - enabled_idx = first_idx; - do - { - Idx subexp_len; - Idx to_idx; - Idx dst_node; - bool ok; - re_dfastate_t *cur_state; - - if (entry->node != node) - continue; - subexp_len = entry->subexp_to - entry->subexp_from; - to_idx = str_idx + subexp_len; - dst_node = (subexp_len ? dfa->nexts[node] - : dfa->edests[node].elems[0]); - - if (to_idx > sctx->last_str_idx - || sctx->sifted_states[to_idx] == NULL - || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) - || check_dst_limits (mctx, &sctx->limits, node, - str_idx, dst_node, to_idx)) - continue; - - if (local_sctx.sifted_states == NULL) - { - local_sctx = *sctx; - err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - local_sctx.last_node = node; - local_sctx.last_str_idx = str_idx; - ok = re_node_set_insert (&local_sctx.limits, enabled_idx); - if (BE (! ok, 0)) - { - err = REG_ESPACE; - goto free_return; - } - cur_state = local_sctx.sifted_states[str_idx]; - err = sift_states_backward (mctx, &local_sctx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - if (sctx->limited_states != NULL) - { - err = merge_state_array (dfa, sctx->limited_states, - local_sctx.sifted_states, - str_idx + 1); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - local_sctx.sifted_states[str_idx] = cur_state; - re_node_set_remove (&local_sctx.limits, enabled_idx); - - /* mctx->bkref_ents may have changed, reload the pointer. */ - entry = mctx->bkref_ents + enabled_idx; - } - while (enabled_idx++, entry++->more); - } - err = REG_NOERROR; - free_return: - if (local_sctx.sifted_states != NULL) - { - re_node_set_free (&local_sctx.limits); - } - - return err; -} - - -#ifdef RE_ENABLE_I18N -static int -internal_function -sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx node_idx, Idx str_idx, Idx max_str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - int naccepted; - /* Check the node can accept `multi byte'. */ - naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); - if (naccepted > 0 && str_idx + naccepted <= max_str_idx && - !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], - dfa->nexts[node_idx])) - /* The node can't accept the `multi byte', or the - destination was already thrown away, then the node - could't accept the current input `multi byte'. */ - naccepted = 0; - /* Otherwise, it is sure that the node could accept - `naccepted' bytes input. */ - return naccepted; -} -#endif /* RE_ENABLE_I18N */ - - -/* Functions for state transition. */ - -/* Return the next state to which the current state STATE will transit by - accepting the current input byte, and update STATE_LOG if necessary. - If STATE can accept a multibyte char/collating element/back reference - update the destination of STATE_LOG. */ - -static re_dfastate_t * -internal_function __attribute_warn_unused_result__ -transit_state (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *state) -{ - re_dfastate_t **trtable; - unsigned char ch; - -#ifdef RE_ENABLE_I18N - /* If the current state can accept multibyte. */ - if (BE (state->accept_mb, 0)) - { - *err = transit_state_mb (mctx, state); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } -#endif /* RE_ENABLE_I18N */ - - /* Then decide the next state with the single byte. */ -#if 0 - if (0) - /* don't use transition table */ - return transit_state_sb (err, mctx, state); -#endif - - /* Use transition table */ - ch = re_string_fetch_byte (&mctx->input); - for (;;) - { - trtable = state->trtable; - if (BE (trtable != NULL, 1)) - return trtable[ch]; - - trtable = state->word_trtable; - if (BE (trtable != NULL, 1)) - { - unsigned int context; - context - = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input) - 1, - mctx->eflags); - if (IS_WORD_CONTEXT (context)) - return trtable[ch + SBC_MAX]; - else - return trtable[ch]; - } - - if (!build_trtable (mctx->dfa, state)) - { - *err = REG_ESPACE; - return NULL; - } - - /* Retry, we now have a transition table. */ - } -} - -/* Update the state_log if we need */ -static re_dfastate_t * -internal_function -merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *next_state) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx cur_idx = re_string_cur_idx (&mctx->input); - - if (cur_idx > mctx->state_log_top) - { - mctx->state_log[cur_idx] = next_state; - mctx->state_log_top = cur_idx; - } - else if (mctx->state_log[cur_idx] == 0) - { - mctx->state_log[cur_idx] = next_state; - } - else - { - re_dfastate_t *pstate; - unsigned int context; - re_node_set next_nodes, *log_nodes, *table_nodes = NULL; - /* If (state_log[cur_idx] != 0), it implies that cur_idx is - the destination of a multibyte char/collating element/ - back reference. Then the next state is the union set of - these destinations and the results of the transition table. */ - pstate = mctx->state_log[cur_idx]; - log_nodes = pstate->entrance_nodes; - if (next_state != NULL) - { - table_nodes = next_state->entrance_nodes; - *err = re_node_set_init_union (&next_nodes, table_nodes, - log_nodes); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } - else - next_nodes = *log_nodes; - /* Note: We already add the nodes of the initial state, - then we don't need to add them here. */ - - context = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input) - 1, - mctx->eflags); - next_state = mctx->state_log[cur_idx] - = re_acquire_state_context (err, dfa, &next_nodes, context); - /* We don't need to check errors here, since the return value of - this function is next_state and ERR is already set. */ - - if (table_nodes != NULL) - re_node_set_free (&next_nodes); - } - - if (BE (dfa->nbackref, 0) && next_state != NULL) - { - /* Check OP_OPEN_SUBEXP in the current state in case that we use them - later. We must check them here, since the back references in the - next state might use them. */ - *err = check_subexp_matching_top (mctx, &next_state->nodes, - cur_idx); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - - /* If the next state has back references. */ - if (next_state->has_backref) - { - *err = transit_state_bkref (mctx, &next_state->nodes); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - next_state = mctx->state_log[cur_idx]; - } - } - - return next_state; -} - -/* Skip bytes in the input that correspond to part of a - multi-byte match, then look in the log for a state - from which to restart matching. */ -static re_dfastate_t * -internal_function -find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) -{ - re_dfastate_t *cur_state; - do - { - Idx max = mctx->state_log_top; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - - do - { - if (++cur_str_idx > max) - return NULL; - re_string_skip_bytes (&mctx->input, 1); - } - while (mctx->state_log[cur_str_idx] == NULL); - - cur_state = merge_state_with_log (err, mctx, NULL); - } - while (*err == REG_NOERROR && cur_state == NULL); - return cur_state; -} - -/* Helper functions for transit_state. */ - -/* From the node set CUR_NODES, pick up the nodes whose types are - OP_OPEN_SUBEXP and which have corresponding back references in the regular - expression. And register them to use them later for evaluating the - correspoding back references. */ - -static reg_errcode_t -internal_function -check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, - Idx str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx node_idx; - reg_errcode_t err; - - /* TODO: This isn't efficient. - Because there might be more than one nodes whose types are - OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all - nodes. - E.g. RE: (a){2} */ - for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) - { - Idx node = cur_nodes->elems[node_idx]; - if (dfa->nodes[node].type == OP_OPEN_SUBEXP - && dfa->nodes[node].opr.idx < BITSET_WORD_BITS - && (dfa->used_bkref_map - & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx))) - { - err = match_ctx_add_subtop (mctx, node, str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - return REG_NOERROR; -} - -#if 0 -/* Return the next state to which the current state STATE will transit by - accepting the current input byte. */ - -static re_dfastate_t * -transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *state) -{ - const re_dfa_t *const dfa = mctx->dfa; - re_node_set next_nodes; - re_dfastate_t *next_state; - Idx node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); - unsigned int context; - - *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) - { - Idx cur_node = state->nodes.elems[node_cnt]; - if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) - { - *err = re_node_set_merge (&next_nodes, - dfa->eclosures + dfa->nexts[cur_node]); - if (BE (*err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return NULL; - } - } - } - context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); - next_state = re_acquire_state_context (err, dfa, &next_nodes, context); - /* We don't need to check errors here, since the return value of - this function is next_state and ERR is already set. */ - - re_node_set_free (&next_nodes); - re_string_skip_bytes (&mctx->input, 1); - return next_state; -} -#endif - -#ifdef RE_ENABLE_I18N -static reg_errcode_t -internal_function -transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx i; - - for (i = 0; i < pstate->nodes.nelem; ++i) - { - re_node_set dest_nodes, *new_nodes; - Idx cur_node_idx = pstate->nodes.elems[i]; - int naccepted; - Idx dest_idx; - unsigned int context; - re_dfastate_t *dest_state; - - if (!dfa->nodes[cur_node_idx].accept_mb) - continue; - - if (dfa->nodes[cur_node_idx].constraint) - { - context = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input), - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, - context)) - continue; - } - - /* How many bytes the node can accept? */ - naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, - re_string_cur_idx (&mctx->input)); - if (naccepted == 0) - continue; - - /* The node can accepts `naccepted' bytes. */ - dest_idx = re_string_cur_idx (&mctx->input) + naccepted; - mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted - : mctx->max_mb_elem_len); - err = clean_state_log_if_needed (mctx, dest_idx); - if (BE (err != REG_NOERROR, 0)) - return err; -#ifdef DEBUG - assert (dfa->nexts[cur_node_idx] != REG_MISSING); -#endif - new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx]; - - dest_state = mctx->state_log[dest_idx]; - if (dest_state == NULL) - dest_nodes = *new_nodes; - else - { - err = re_node_set_init_union (&dest_nodes, - dest_state->entrance_nodes, new_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - context = re_string_context_at (&mctx->input, dest_idx - 1, - mctx->eflags); - mctx->state_log[dest_idx] - = re_acquire_state_context (&err, dfa, &dest_nodes, context); - if (dest_state != NULL) - re_node_set_free (&dest_nodes); - if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0)) - return err; - } - return REG_NOERROR; -} -#endif /* RE_ENABLE_I18N */ - -static reg_errcode_t -internal_function -transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx i; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - - for (i = 0; i < nodes->nelem; ++i) - { - Idx dest_str_idx, prev_nelem, bkc_idx; - Idx node_idx = nodes->elems[i]; - unsigned int context; - const re_token_t *node = dfa->nodes + node_idx; - re_node_set *new_dest_nodes; - - /* Check whether `node' is a backreference or not. */ - if (node->type != OP_BACK_REF) - continue; - - if (node->constraint) - { - context = re_string_context_at (&mctx->input, cur_str_idx, - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) - continue; - } - - /* `node' is a backreference. - Check the substring which the substring matched. */ - bkc_idx = mctx->nbkref_ents; - err = get_subexp (mctx, node_idx, cur_str_idx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* And add the epsilon closures (which is `new_dest_nodes') of - the backreference to appropriate state_log. */ -#ifdef DEBUG - assert (dfa->nexts[node_idx] != REG_MISSING); -#endif - for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) - { - Idx subexp_len; - re_dfastate_t *dest_state; - struct re_backref_cache_entry *bkref_ent; - bkref_ent = mctx->bkref_ents + bkc_idx; - if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) - continue; - subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; - new_dest_nodes = (subexp_len == 0 - ? dfa->eclosures + dfa->edests[node_idx].elems[0] - : dfa->eclosures + dfa->nexts[node_idx]); - dest_str_idx = (cur_str_idx + bkref_ent->subexp_to - - bkref_ent->subexp_from); - context = re_string_context_at (&mctx->input, dest_str_idx - 1, - mctx->eflags); - dest_state = mctx->state_log[dest_str_idx]; - prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 - : mctx->state_log[cur_str_idx]->nodes.nelem); - /* Add `new_dest_node' to state_log. */ - if (dest_state == NULL) - { - mctx->state_log[dest_str_idx] - = re_acquire_state_context (&err, dfa, new_dest_nodes, - context); - if (BE (mctx->state_log[dest_str_idx] == NULL - && err != REG_NOERROR, 0)) - goto free_return; - } - else - { - re_node_set dest_nodes; - err = re_node_set_init_union (&dest_nodes, - dest_state->entrance_nodes, - new_dest_nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&dest_nodes); - goto free_return; - } - mctx->state_log[dest_str_idx] - = re_acquire_state_context (&err, dfa, &dest_nodes, context); - re_node_set_free (&dest_nodes); - if (BE (mctx->state_log[dest_str_idx] == NULL - && err != REG_NOERROR, 0)) - goto free_return; - } - /* We need to check recursively if the backreference can epsilon - transit. */ - if (subexp_len == 0 - && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) - { - err = check_subexp_matching_top (mctx, new_dest_nodes, - cur_str_idx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - err = transit_state_bkref (mctx, new_dest_nodes); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - } - } - err = REG_NOERROR; - free_return: - return err; -} - -/* Enumerate all the candidates which the backreference BKREF_NODE can match - at BKREF_STR_IDX, and register them by match_ctx_add_entry(). - Note that we might collect inappropriate candidates here. - However, the cost of checking them strictly here is too high, then we - delay these checking for prune_impossible_nodes(). */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -get_subexp (re_match_context_t *mctx, Idx bkref_node, Idx bkref_str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx subexp_num, sub_top_idx; - const char *buf = (const char *) re_string_get_buffer (&mctx->input); - /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ - Idx cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); - if (cache_idx != REG_MISSING) - { - const struct re_backref_cache_entry *entry - = mctx->bkref_ents + cache_idx; - do - if (entry->node == bkref_node) - return REG_NOERROR; /* We already checked it. */ - while (entry++->more); - } - - subexp_num = dfa->nodes[bkref_node].opr.idx; - - /* For each sub expression */ - for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) - { - reg_errcode_t err; - re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; - re_sub_match_last_t *sub_last; - Idx sub_last_idx, sl_str, bkref_str_off; - - if (dfa->nodes[sub_top->node].opr.idx != subexp_num) - continue; /* It isn't related. */ - - sl_str = sub_top->str_idx; - bkref_str_off = bkref_str_idx; - /* At first, check the last node of sub expressions we already - evaluated. */ - for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) - { - regoff_t sl_str_diff; - sub_last = sub_top->lasts[sub_last_idx]; - sl_str_diff = sub_last->str_idx - sl_str; - /* The matched string by the sub expression match with the substring - at the back reference? */ - if (sl_str_diff > 0) - { - if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0)) - { - /* Not enough chars for a successful match. */ - if (bkref_str_off + sl_str_diff > mctx->input.len) - break; - - err = clean_state_log_if_needed (mctx, - bkref_str_off - + sl_str_diff); - if (BE (err != REG_NOERROR, 0)) - return err; - buf = (const char *) re_string_get_buffer (&mctx->input); - } - if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) - /* We don't need to search this sub expression any more. */ - break; - } - bkref_str_off += sl_str_diff; - sl_str += sl_str_diff; - err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, - bkref_str_idx); - - /* Reload buf, since the preceding call might have reallocated - the buffer. */ - buf = (const char *) re_string_get_buffer (&mctx->input); - - if (err == REG_NOMATCH) - continue; - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (sub_last_idx < sub_top->nlasts) - continue; - if (sub_last_idx > 0) - ++sl_str; - /* Then, search for the other last nodes of the sub expression. */ - for (; sl_str <= bkref_str_idx; ++sl_str) - { - Idx cls_node; - regoff_t sl_str_off; - const re_node_set *nodes; - sl_str_off = sl_str - sub_top->str_idx; - /* The matched string by the sub expression match with the substring - at the back reference? */ - if (sl_str_off > 0) - { - if (BE (bkref_str_off >= mctx->input.valid_len, 0)) - { - /* If we are at the end of the input, we cannot match. */ - if (bkref_str_off >= mctx->input.len) - break; - - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - return err; - - buf = (const char *) re_string_get_buffer (&mctx->input); - } - if (buf [bkref_str_off++] != buf[sl_str - 1]) - break; /* We don't need to search this sub expression - any more. */ - } - if (mctx->state_log[sl_str] == NULL) - continue; - /* Does this state have a ')' of the sub expression? */ - nodes = &mctx->state_log[sl_str]->nodes; - cls_node = find_subexp_node (dfa, nodes, subexp_num, - OP_CLOSE_SUBEXP); - if (cls_node == REG_MISSING) - continue; /* No. */ - if (sub_top->path == NULL) - { - sub_top->path = calloc (sizeof (state_array_t), - sl_str - sub_top->str_idx + 1); - if (sub_top->path == NULL) - return REG_ESPACE; - } - /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node - in the current context? */ - err = check_arrival (mctx, sub_top->path, sub_top->node, - sub_top->str_idx, cls_node, sl_str, - OP_CLOSE_SUBEXP); - if (err == REG_NOMATCH) - continue; - if (BE (err != REG_NOERROR, 0)) - return err; - sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); - if (BE (sub_last == NULL, 0)) - return REG_ESPACE; - err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, - bkref_str_idx); - if (err == REG_NOMATCH) - continue; - } - } - return REG_NOERROR; -} - -/* Helper functions for get_subexp(). */ - -/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. - If it can arrive, register the sub expression expressed with SUB_TOP - and SUB_LAST. */ - -static reg_errcode_t -internal_function -get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, - re_sub_match_last_t *sub_last, Idx bkref_node, Idx bkref_str) -{ - reg_errcode_t err; - Idx to_idx; - /* Can the subexpression arrive the back reference? */ - err = check_arrival (mctx, &sub_last->path, sub_last->node, - sub_last->str_idx, bkref_node, bkref_str, - OP_OPEN_SUBEXP); - if (err != REG_NOERROR) - return err; - err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, - sub_last->str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; - return clean_state_log_if_needed (mctx, to_idx); -} - -/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. - Search '(' if FL_OPEN, or search ')' otherwise. - TODO: This function isn't efficient... - Because there might be more than one nodes whose types are - OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all - nodes. - E.g. RE: (a){2} */ - -static Idx -internal_function -find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, - Idx subexp_idx, int type) -{ - Idx cls_idx; - for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) - { - Idx cls_node = nodes->elems[cls_idx]; - const re_token_t *node = dfa->nodes + cls_node; - if (node->type == type - && node->opr.idx == subexp_idx) - return cls_node; - } - return REG_MISSING; -} - -/* Check whether the node TOP_NODE at TOP_STR can arrive to the node - LAST_NODE at LAST_STR. We record the path onto PATH since it will be - heavily reused. - Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node, - Idx top_str, Idx last_node, Idx last_str, int type) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err = REG_NOERROR; - Idx subexp_num, backup_cur_idx, str_idx, null_cnt; - re_dfastate_t *cur_state = NULL; - re_node_set *cur_nodes, next_nodes; - re_dfastate_t **backup_state_log; - unsigned int context; - - subexp_num = dfa->nodes[top_node].opr.idx; - /* Extend the buffer if we need. */ - if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0)) - { - re_dfastate_t **new_array; - Idx old_alloc = path->alloc; - Idx new_alloc = old_alloc + last_str + mctx->max_mb_elem_len + 1; - if (BE (new_alloc < old_alloc, 0) - || BE (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc, 0)) - return REG_ESPACE; - new_array = re_realloc (path->array, re_dfastate_t *, new_alloc); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - path->array = new_array; - path->alloc = new_alloc; - memset (new_array + old_alloc, '\0', - sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); - } - - str_idx = path->next_idx ? path->next_idx : top_str; - - /* Temporary modify MCTX. */ - backup_state_log = mctx->state_log; - backup_cur_idx = mctx->input.cur_idx; - mctx->state_log = path->array; - mctx->input.cur_idx = str_idx; - - /* Setup initial node set. */ - context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); - if (str_idx == top_str) - { - err = re_node_set_init_1 (&next_nodes, top_node); - if (BE (err != REG_NOERROR, 0)) - return err; - err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - else - { - cur_state = mctx->state_log[str_idx]; - if (cur_state && cur_state->has_backref) - { - err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - re_node_set_init_empty (&next_nodes); - } - if (str_idx == top_str || (cur_state && cur_state->has_backref)) - { - if (next_nodes.nelem) - { - err = expand_bkref_cache (mctx, &next_nodes, str_idx, - subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); - if (BE (cur_state == NULL && err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - mctx->state_log[str_idx] = cur_state; - } - - for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) - { - re_node_set_empty (&next_nodes); - if (mctx->state_log[str_idx + 1]) - { - err = re_node_set_merge (&next_nodes, - &mctx->state_log[str_idx + 1]->nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - if (cur_state) - { - err = check_arrival_add_next_nodes (mctx, str_idx, - &cur_state->non_eps_nodes, - &next_nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - ++str_idx; - if (next_nodes.nelem) - { - err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - err = expand_bkref_cache (mctx, &next_nodes, str_idx, - subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); - cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); - if (BE (cur_state == NULL && err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - mctx->state_log[str_idx] = cur_state; - null_cnt = cur_state == NULL ? null_cnt + 1 : 0; - } - re_node_set_free (&next_nodes); - cur_nodes = (mctx->state_log[last_str] == NULL ? NULL - : &mctx->state_log[last_str]->nodes); - path->next_idx = str_idx; - - /* Fix MCTX. */ - mctx->state_log = backup_state_log; - mctx->input.cur_idx = backup_cur_idx; - - /* Then check the current node set has the node LAST_NODE. */ - if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) - return REG_NOERROR; - - return REG_NOMATCH; -} - -/* Helper functions for check_arrival. */ - -/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them - to NEXT_NODES. - TODO: This function is similar to the functions transit_state*(), - however this function has many additional works. - Can't we unify them? */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx, - re_node_set *cur_nodes, re_node_set *next_nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - bool ok; - Idx cur_idx; -#ifdef RE_ENABLE_I18N - reg_errcode_t err = REG_NOERROR; -#endif - re_node_set union_set; - re_node_set_init_empty (&union_set); - for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) - { - int naccepted = 0; - Idx cur_node = cur_nodes->elems[cur_idx]; -#ifdef DEBUG - re_token_type_t type = dfa->nodes[cur_node].type; - assert (!IS_EPSILON_NODE (type)); -#endif -#ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ - if (dfa->nodes[cur_node].accept_mb) - { - naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, - str_idx); - if (naccepted > 1) - { - re_dfastate_t *dest_state; - Idx next_node = dfa->nexts[cur_node]; - Idx next_idx = str_idx + naccepted; - dest_state = mctx->state_log[next_idx]; - re_node_set_empty (&union_set); - if (dest_state) - { - err = re_node_set_merge (&union_set, &dest_state->nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&union_set); - return err; - } - } - ok = re_node_set_insert (&union_set, next_node); - if (BE (! ok, 0)) - { - re_node_set_free (&union_set); - return REG_ESPACE; - } - mctx->state_log[next_idx] = re_acquire_state (&err, dfa, - &union_set); - if (BE (mctx->state_log[next_idx] == NULL - && err != REG_NOERROR, 0)) - { - re_node_set_free (&union_set); - return err; - } - } - } -#endif /* RE_ENABLE_I18N */ - if (naccepted - || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) - { - ok = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); - if (BE (! ok, 0)) - { - re_node_set_free (&union_set); - return REG_ESPACE; - } - } - } - re_node_set_free (&union_set); - return REG_NOERROR; -} - -/* For all the nodes in CUR_NODES, add the epsilon closures of them to - CUR_NODES, however exclude the nodes which are: - - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. - - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. -*/ - -static reg_errcode_t -internal_function -check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, - Idx ex_subexp, int type) -{ - reg_errcode_t err; - Idx idx, outside_node; - re_node_set new_nodes; -#ifdef DEBUG - assert (cur_nodes->nelem); -#endif - err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); - if (BE (err != REG_NOERROR, 0)) - return err; - /* Create a new node set NEW_NODES with the nodes which are epsilon - closures of the node in CUR_NODES. */ - - for (idx = 0; idx < cur_nodes->nelem; ++idx) - { - Idx cur_node = cur_nodes->elems[idx]; - const re_node_set *eclosure = dfa->eclosures + cur_node; - outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); - if (outside_node == REG_MISSING) - { - /* There are no problematic nodes, just merge them. */ - err = re_node_set_merge (&new_nodes, eclosure); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&new_nodes); - return err; - } - } - else - { - /* There are problematic nodes, re-calculate incrementally. */ - err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, - ex_subexp, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&new_nodes); - return err; - } - } - } - re_node_set_free (cur_nodes); - *cur_nodes = new_nodes; - return REG_NOERROR; -} - -/* Helper function for check_arrival_expand_ecl. - Check incrementally the epsilon closure of TARGET, and if it isn't - problematic append it to DST_NODES. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, - Idx target, Idx ex_subexp, int type) -{ - Idx cur_node; - for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) - { - bool ok; - - if (dfa->nodes[cur_node].type == type - && dfa->nodes[cur_node].opr.idx == ex_subexp) - { - if (type == OP_CLOSE_SUBEXP) - { - ok = re_node_set_insert (dst_nodes, cur_node); - if (BE (! ok, 0)) - return REG_ESPACE; - } - break; - } - ok = re_node_set_insert (dst_nodes, cur_node); - if (BE (! ok, 0)) - return REG_ESPACE; - if (dfa->edests[cur_node].nelem == 0) - break; - if (dfa->edests[cur_node].nelem == 2) - { - reg_errcode_t err; - err = check_arrival_expand_ecl_sub (dfa, dst_nodes, - dfa->edests[cur_node].elems[1], - ex_subexp, type); - if (BE (err != REG_NOERROR, 0)) - return err; - } - cur_node = dfa->edests[cur_node].elems[0]; - } - return REG_NOERROR; -} - - -/* For all the back references in the current state, calculate the - destination of the back references by the appropriate entry - in MCTX->BKREF_ENTS. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, - Idx cur_str, Idx subexp_num, int type) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx cache_idx_start = search_cur_bkref_entry (mctx, cur_str); - struct re_backref_cache_entry *ent; - - if (cache_idx_start == REG_MISSING) - return REG_NOERROR; - - restart: - ent = mctx->bkref_ents + cache_idx_start; - do - { - Idx to_idx, next_node; - - /* Is this entry ENT is appropriate? */ - if (!re_node_set_contains (cur_nodes, ent->node)) - continue; /* No. */ - - to_idx = cur_str + ent->subexp_to - ent->subexp_from; - /* Calculate the destination of the back reference, and append it - to MCTX->STATE_LOG. */ - if (to_idx == cur_str) - { - /* The backreference did epsilon transit, we must re-check all the - node in the current state. */ - re_node_set new_dests; - reg_errcode_t err2, err3; - next_node = dfa->edests[ent->node].elems[0]; - if (re_node_set_contains (cur_nodes, next_node)) - continue; - err = re_node_set_init_1 (&new_dests, next_node); - err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); - err3 = re_node_set_merge (cur_nodes, &new_dests); - re_node_set_free (&new_dests); - if (BE (err != REG_NOERROR || err2 != REG_NOERROR - || err3 != REG_NOERROR, 0)) - { - err = (err != REG_NOERROR ? err - : (err2 != REG_NOERROR ? err2 : err3)); - return err; - } - /* TODO: It is still inefficient... */ - goto restart; - } - else - { - re_node_set union_set; - next_node = dfa->nexts[ent->node]; - if (mctx->state_log[to_idx]) - { - bool ok; - if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, - next_node)) - continue; - err = re_node_set_init_copy (&union_set, - &mctx->state_log[to_idx]->nodes); - ok = re_node_set_insert (&union_set, next_node); - if (BE (err != REG_NOERROR || ! ok, 0)) - { - re_node_set_free (&union_set); - err = err != REG_NOERROR ? err : REG_ESPACE; - return err; - } - } - else - { - err = re_node_set_init_1 (&union_set, next_node); - if (BE (err != REG_NOERROR, 0)) - return err; - } - mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); - re_node_set_free (&union_set); - if (BE (mctx->state_log[to_idx] == NULL - && err != REG_NOERROR, 0)) - return err; - } - } - while (ent++->more); - return REG_NOERROR; -} - -/* Build transition table for the state. - Return true if successful. */ - -static bool -internal_function -build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) -{ - reg_errcode_t err; - Idx i, j; - int ch; - bool need_word_trtable = false; - bitset_word_t elem, mask; - bool dests_node_malloced = false; - bool dest_states_malloced = false; - Idx ndests; /* Number of the destination states from `state'. */ - re_dfastate_t **trtable; - re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; - re_node_set follows, *dests_node; - bitset_t *dests_ch; - bitset_t acceptable; - - struct dests_alloc - { - re_node_set dests_node[SBC_MAX]; - bitset_t dests_ch[SBC_MAX]; - } *dests_alloc; - - /* We build DFA states which corresponds to the destination nodes - from `state'. `dests_node[i]' represents the nodes which i-th - destination state contains, and `dests_ch[i]' represents the - characters which i-th destination state accepts. */ - if (__libc_use_alloca (sizeof (struct dests_alloc))) - dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc)); - else - { - dests_alloc = re_malloc (struct dests_alloc, 1); - if (BE (dests_alloc == NULL, 0)) - return false; - dests_node_malloced = true; - } - dests_node = dests_alloc->dests_node; - dests_ch = dests_alloc->dests_ch; - - /* Initialize transiton table. */ - state->word_trtable = state->trtable = NULL; - - /* At first, group all nodes belonging to `state' into several - destinations. */ - ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); - if (BE (! REG_VALID_NONZERO_INDEX (ndests), 0)) - { - if (dests_node_malloced) - free (dests_alloc); - if (ndests == 0) - { - state->trtable = (re_dfastate_t **) - calloc (sizeof (re_dfastate_t *), SBC_MAX); - return true; - } - return false; - } - - err = re_node_set_alloc (&follows, ndests + 1); - if (BE (err != REG_NOERROR, 0)) - goto out_free; - - /* Avoid arithmetic overflow in size calculation. */ - if (BE ((((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX) - / (3 * sizeof (re_dfastate_t *))) - < ndests), - 0)) - goto out_free; - - if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX - + ndests * 3 * sizeof (re_dfastate_t *))) - dest_states = (re_dfastate_t **) - alloca (ndests * 3 * sizeof (re_dfastate_t *)); - else - { - dest_states = (re_dfastate_t **) - malloc (ndests * 3 * sizeof (re_dfastate_t *)); - if (BE (dest_states == NULL, 0)) - { -out_free: - if (dest_states_malloced) - free (dest_states); - re_node_set_free (&follows); - for (i = 0; i < ndests; ++i) - re_node_set_free (dests_node + i); - if (dests_node_malloced) - free (dests_alloc); - return false; - } - dest_states_malloced = true; - } - dest_states_word = dest_states + ndests; - dest_states_nl = dest_states_word + ndests; - bitset_empty (acceptable); - - /* Then build the states for all destinations. */ - for (i = 0; i < ndests; ++i) - { - Idx next_node; - re_node_set_empty (&follows); - /* Merge the follows of this destination states. */ - for (j = 0; j < dests_node[i].nelem; ++j) - { - next_node = dfa->nexts[dests_node[i].elems[j]]; - if (next_node != REG_MISSING) - { - err = re_node_set_merge (&follows, dfa->eclosures + next_node); - if (BE (err != REG_NOERROR, 0)) - goto out_free; - } - } - dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); - if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - /* If the new state has context constraint, - build appropriate states for these contexts. */ - if (dest_states[i]->has_constraint) - { - dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, - CONTEXT_WORD); - if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - - if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) - need_word_trtable = true; - - dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, - CONTEXT_NEWLINE); - if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - } - else - { - dest_states_word[i] = dest_states[i]; - dest_states_nl[i] = dest_states[i]; - } - bitset_merge (acceptable, dests_ch[i]); - } - - if (!BE (need_word_trtable, 0)) - { - /* We don't care about whether the following character is a word - character, or we are in a single-byte character set so we can - discern by looking at the character code: allocate a - 256-entry transition table. */ - trtable = state->trtable = - (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); - if (BE (trtable == NULL, 0)) - goto out_free; - - /* For all characters ch...: */ - for (i = 0; i < BITSET_WORDS; ++i) - for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; - elem; - mask <<= 1, elem >>= 1, ++ch) - if (BE (elem & 1, 0)) - { - /* There must be exactly one destination which accepts - character ch. See group_nodes_into_DFAstates. */ - for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) - ; - - /* j-th destination accepts the word character ch. */ - if (dfa->word_char[i] & mask) - trtable[ch] = dest_states_word[j]; - else - trtable[ch] = dest_states[j]; - } - } - else - { - /* We care about whether the following character is a word - character, and we are in a multi-byte character set: discern - by looking at the character code: build two 256-entry - transition tables, one starting at trtable[0] and one - starting at trtable[SBC_MAX]. */ - trtable = state->word_trtable = - (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); - if (BE (trtable == NULL, 0)) - goto out_free; - - /* For all characters ch...: */ - for (i = 0; i < BITSET_WORDS; ++i) - for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; - elem; - mask <<= 1, elem >>= 1, ++ch) - if (BE (elem & 1, 0)) - { - /* There must be exactly one destination which accepts - character ch. See group_nodes_into_DFAstates. */ - for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) - ; - - /* j-th destination accepts the word character ch. */ - trtable[ch] = dest_states[j]; - trtable[ch + SBC_MAX] = dest_states_word[j]; - } - } - - /* new line */ - if (bitset_contain (acceptable, NEWLINE_CHAR)) - { - /* The current state accepts newline character. */ - for (j = 0; j < ndests; ++j) - if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) - { - /* k-th destination accepts newline character. */ - trtable[NEWLINE_CHAR] = dest_states_nl[j]; - if (need_word_trtable) - trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; - /* There must be only one destination which accepts - newline. See group_nodes_into_DFAstates. */ - break; - } - } - - if (dest_states_malloced) - free (dest_states); - - re_node_set_free (&follows); - for (i = 0; i < ndests; ++i) - re_node_set_free (dests_node + i); - - if (dests_node_malloced) - free (dests_alloc); - - return true; -} - -/* Group all nodes belonging to STATE into several destinations. - Then for all destinations, set the nodes belonging to the destination - to DESTS_NODE[i] and set the characters accepted by the destination - to DEST_CH[i]. This function return the number of destinations. */ - -static Idx -internal_function -group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, - re_node_set *dests_node, bitset_t *dests_ch) -{ - reg_errcode_t err; - bool ok; - Idx i, j, k; - Idx ndests; /* Number of the destinations from `state'. */ - bitset_t accepts; /* Characters a node can accept. */ - const re_node_set *cur_nodes = &state->nodes; - bitset_empty (accepts); - ndests = 0; - - /* For all the nodes belonging to `state', */ - for (i = 0; i < cur_nodes->nelem; ++i) - { - re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; - re_token_type_t type = node->type; - unsigned int constraint = node->constraint; - - /* Enumerate all single byte character this node can accept. */ - if (type == CHARACTER) - bitset_set (accepts, node->opr.c); - else if (type == SIMPLE_BRACKET) - { - bitset_merge (accepts, node->opr.sbcset); - } - else if (type == OP_PERIOD) - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - bitset_merge (accepts, dfa->sb_char); - else -#endif - bitset_set_all (accepts); - if (!(dfa->syntax & RE_DOT_NEWLINE)) - bitset_clear (accepts, '\n'); - if (dfa->syntax & RE_DOT_NOT_NULL) - bitset_clear (accepts, '\0'); - } -#ifdef RE_ENABLE_I18N - else if (type == OP_UTF8_PERIOD) - { - if (ASCII_CHARS % BITSET_WORD_BITS == 0) - memset (accepts, -1, ASCII_CHARS / CHAR_BIT); - else - bitset_merge (accepts, utf8_sb_map); - if (!(dfa->syntax & RE_DOT_NEWLINE)) - bitset_clear (accepts, '\n'); - if (dfa->syntax & RE_DOT_NOT_NULL) - bitset_clear (accepts, '\0'); - } -#endif - else - continue; - - /* Check the `accepts' and sift the characters which are not - match it the context. */ - if (constraint) - { - if (constraint & NEXT_NEWLINE_CONSTRAINT) - { - bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); - bitset_empty (accepts); - if (accepts_newline) - bitset_set (accepts, NEWLINE_CHAR); - else - continue; - } - if (constraint & NEXT_ENDBUF_CONSTRAINT) - { - bitset_empty (accepts); - continue; - } - - if (constraint & NEXT_WORD_CONSTRAINT) - { - bitset_word_t any_set = 0; - if (type == CHARACTER && !node->word_char) - { - bitset_empty (accepts); - continue; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); - else -#endif - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= dfa->word_char[j]); - if (!any_set) - continue; - } - if (constraint & NEXT_NOTWORD_CONSTRAINT) - { - bitset_word_t any_set = 0; - if (type == CHARACTER && node->word_char) - { - bitset_empty (accepts); - continue; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); - else -#endif - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= ~dfa->word_char[j]); - if (!any_set) - continue; - } - } - - /* Then divide `accepts' into DFA states, or create a new - state. Above, we make sure that accepts is not empty. */ - for (j = 0; j < ndests; ++j) - { - bitset_t intersec; /* Intersection sets, see below. */ - bitset_t remains; - /* Flags, see below. */ - bitset_word_t has_intersec, not_subset, not_consumed; - - /* Optimization, skip if this state doesn't accept the character. */ - if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) - continue; - - /* Enumerate the intersection set of this state and `accepts'. */ - has_intersec = 0; - for (k = 0; k < BITSET_WORDS; ++k) - has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; - /* And skip if the intersection set is empty. */ - if (!has_intersec) - continue; - - /* Then check if this state is a subset of `accepts'. */ - not_subset = not_consumed = 0; - for (k = 0; k < BITSET_WORDS; ++k) - { - not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; - not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; - } - - /* If this state isn't a subset of `accepts', create a - new group state, which has the `remains'. */ - if (not_subset) - { - bitset_copy (dests_ch[ndests], remains); - bitset_copy (dests_ch[j], intersec); - err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); - if (BE (err != REG_NOERROR, 0)) - goto error_return; - ++ndests; - } - - /* Put the position in the current group. */ - ok = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); - if (BE (! ok, 0)) - goto error_return; - - /* If all characters are consumed, go to next node. */ - if (!not_consumed) - break; - } - /* Some characters remain, create a new group. */ - if (j == ndests) - { - bitset_copy (dests_ch[ndests], accepts); - err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); - if (BE (err != REG_NOERROR, 0)) - goto error_return; - ++ndests; - bitset_empty (accepts); - } - } - return ndests; - error_return: - for (j = 0; j < ndests; ++j) - re_node_set_free (dests_node + j); - return REG_MISSING; -} - -#ifdef RE_ENABLE_I18N -/* Check how many bytes the node `dfa->nodes[node_idx]' accepts. - Return the number of the bytes the node accepts. - STR_IDX is the current index of the input string. - - This function handles the nodes which can accept one character, or - one collating element like '.', '[a-z]', opposite to the other nodes - can only accept one byte. */ - -static int -internal_function -check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, - const re_string_t *input, Idx str_idx) -{ - const re_token_t *node = dfa->nodes + node_idx; - int char_len, elem_len; - Idx i; - - if (BE (node->type == OP_UTF8_PERIOD, 0)) - { - unsigned char c = re_string_byte_at (input, str_idx), d; - if (BE (c < 0xc2, 1)) - return 0; - - if (str_idx + 2 > input->len) - return 0; - - d = re_string_byte_at (input, str_idx + 1); - if (c < 0xe0) - return (d < 0x80 || d > 0xbf) ? 0 : 2; - else if (c < 0xf0) - { - char_len = 3; - if (c == 0xe0 && d < 0xa0) - return 0; - } - else if (c < 0xf8) - { - char_len = 4; - if (c == 0xf0 && d < 0x90) - return 0; - } - else if (c < 0xfc) - { - char_len = 5; - if (c == 0xf8 && d < 0x88) - return 0; - } - else if (c < 0xfe) - { - char_len = 6; - if (c == 0xfc && d < 0x84) - return 0; - } - else - return 0; - - if (str_idx + char_len > input->len) - return 0; - - for (i = 1; i < char_len; ++i) - { - d = re_string_byte_at (input, str_idx + i); - if (d < 0x80 || d > 0xbf) - return 0; - } - return char_len; - } - - char_len = re_string_char_size_at (input, str_idx); - if (node->type == OP_PERIOD) - { - if (char_len <= 1) - return 0; - /* FIXME: I don't think this if is needed, as both '\n' - and '\0' are char_len == 1. */ - /* '.' accepts any one character except the following two cases. */ - if ((!(dfa->syntax & RE_DOT_NEWLINE) && - re_string_byte_at (input, str_idx) == '\n') || - ((dfa->syntax & RE_DOT_NOT_NULL) && - re_string_byte_at (input, str_idx) == '\0')) - return 0; - return char_len; - } - - elem_len = re_string_elem_size_at (input, str_idx); - if ((elem_len <= 1 && char_len <= 1) || char_len == 0) - return 0; - - if (node->type == COMPLEX_BRACKET) - { - const re_charset_t *cset = node->opr.mbcset; -# ifdef _LIBC - const unsigned char *pin - = ((const unsigned char *) re_string_get_buffer (input) + str_idx); - Idx j; - uint32_t nrules; -# endif /* _LIBC */ - int match_len = 0; - wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) - ? re_string_wchar_at (input, str_idx) : 0); - - /* match with multibyte character? */ - for (i = 0; i < cset->nmbchars; ++i) - if (wc == cset->mbchars[i]) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - /* match with character_class? */ - for (i = 0; i < cset->nchar_classes; ++i) - { - wctype_t wt = cset->char_classes[i]; - if (__iswctype (wc, wt)) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - } - -# ifdef _LIBC - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { - unsigned int in_collseq = 0; - const int32_t *table, *indirect; - const unsigned char *weights, *extra; - const char *collseqwc; - int32_t idx; - /* This #include defines a local function! */ -# include - - /* match with collating_symbol? */ - if (cset->ncoll_syms) - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); - for (i = 0; i < cset->ncoll_syms; ++i) - { - const unsigned char *coll_sym = extra + cset->coll_syms[i]; - /* Compare the length of input collating element and - the length of current collating element. */ - if (*coll_sym != elem_len) - continue; - /* Compare each bytes. */ - for (j = 0; j < *coll_sym; j++) - if (pin[j] != coll_sym[1 + j]) - break; - if (j == *coll_sym) - { - /* Match if every bytes is equal. */ - match_len = j; - goto check_node_accept_bytes_match; - } - } - - if (cset->nranges) - { - if (elem_len <= char_len) - { - collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); - in_collseq = __collseq_table_lookup (collseqwc, wc); - } - else - in_collseq = find_collation_sequence_value (pin, elem_len); - } - /* match with range expression? */ - for (i = 0; i < cset->nranges; ++i) - if (cset->range_starts[i] <= in_collseq - && in_collseq <= cset->range_ends[i]) - { - match_len = elem_len; - goto check_node_accept_bytes_match; - } - - /* match with equivalence_class? */ - if (cset->nequiv_classes) - { - const unsigned char *cp = pin; - table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - weights = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); - int32_t idx = findidx (&cp); - if (idx > 0) - for (i = 0; i < cset->nequiv_classes; ++i) - { - int32_t equiv_class_idx = cset->equiv_classes[i]; - size_t weight_len = weights[idx & 0xffffff]; - if (weight_len == weights[equiv_class_idx & 0xffffff] - && (idx >> 24) == (equiv_class_idx >> 24)) - { - Idx cnt = 0; - - idx &= 0xffffff; - equiv_class_idx &= 0xffffff; - - while (cnt <= weight_len - && (weights[equiv_class_idx + 1 + cnt] - == weights[idx + 1 + cnt])) - ++cnt; - if (cnt > weight_len) - { - match_len = elem_len; - goto check_node_accept_bytes_match; - } - } - } - } - } - else -# endif /* _LIBC */ - { - /* match with range expression? */ -#if __GNUC__ >= 2 && ! (__STDC_VERSION__ < 199901L && __STRICT_ANSI__) - wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; -#else - wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; - cmp_buf[2] = wc; -#endif - for (i = 0; i < cset->nranges; ++i) - { - cmp_buf[0] = cset->range_starts[i]; - cmp_buf[4] = cset->range_ends[i]; - if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 - && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - } - } - check_node_accept_bytes_match: - if (!cset->non_match) - return match_len; - else - { - if (match_len > 0) - return 0; - else - return (elem_len > char_len) ? elem_len : char_len; - } - } - return 0; -} - -# ifdef _LIBC -static unsigned int -internal_function -find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) -{ - uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules == 0) - { - if (mbs_len == 1) - { - /* No valid character. Match it as a single byte character. */ - const unsigned char *collseq = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); - return collseq[mbs[0]]; - } - return UINT_MAX; - } - else - { - int32_t idx; - const unsigned char *extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); - int32_t extrasize = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; - - for (idx = 0; idx < extrasize;) - { - int mbs_cnt; - bool found = false; - int32_t elem_mbs_len; - /* Skip the name of collating element name. */ - idx = idx + extra[idx] + 1; - elem_mbs_len = extra[idx++]; - if (mbs_len == elem_mbs_len) - { - for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) - if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) - break; - if (mbs_cnt == elem_mbs_len) - /* Found the entry. */ - found = true; - } - /* Skip the byte sequence of the collating element. */ - idx += elem_mbs_len; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - /* Skip the collation sequence value. */ - idx += sizeof (uint32_t); - /* Skip the wide char sequence of the collating element. */ - idx = idx + sizeof (uint32_t) * (extra[idx] + 1); - /* If we found the entry, return the sequence value. */ - if (found) - return *(uint32_t *) (extra + idx); - /* Skip the collation sequence value. */ - idx += sizeof (uint32_t); - } - return UINT_MAX; - } -} -# endif /* _LIBC */ -#endif /* RE_ENABLE_I18N */ - -/* Check whether the node accepts the byte which is IDX-th - byte of the INPUT. */ - -static bool -internal_function -check_node_accept (const re_match_context_t *mctx, const re_token_t *node, - Idx idx) -{ - unsigned char ch; - ch = re_string_byte_at (&mctx->input, idx); - switch (node->type) - { - case CHARACTER: - if (node->opr.c != ch) - return false; - break; - - case SIMPLE_BRACKET: - if (!bitset_contain (node->opr.sbcset, ch)) - return false; - break; - -#ifdef RE_ENABLE_I18N - case OP_UTF8_PERIOD: - if (ch >= ASCII_CHARS) - return false; - /* FALLTHROUGH */ -#endif - case OP_PERIOD: - if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) - || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) - return false; - break; - - default: - return false; - } - - if (node->constraint) - { - /* The node has constraints. Check whether the current context - satisfies the constraints. */ - unsigned int context = re_string_context_at (&mctx->input, idx, - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) - return false; - } - - return true; -} - -/* Extend the buffers, if the buffers have run out. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -extend_buffers (re_match_context_t *mctx) -{ - reg_errcode_t ret; - re_string_t *pstr = &mctx->input; - - /* Avoid overflow. */ - if (BE (SIZE_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0)) - return REG_ESPACE; - - /* Double the lengthes of the buffers. */ - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - if (mctx->state_log != NULL) - { - /* And double the length of state_log. */ - /* XXX We have no indication of the size of this buffer. If this - allocation fail we have no indication that the state_log array - does not have the right size. */ - re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, - pstr->bufs_len + 1); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - mctx->state_log = new_array; - } - - /* Then reconstruct the buffers. */ - if (pstr->icase) - { -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - else -#endif /* RE_ENABLE_I18N */ - build_upper_buffer (pstr); - } - else - { -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - build_wcs_buffer (pstr); - else -#endif /* RE_ENABLE_I18N */ - { - if (pstr->trans != NULL) - re_string_translate_buffer (pstr); - } - } - return REG_NOERROR; -} - - -/* Functions for matching context. */ - -/* Initialize MCTX. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -match_ctx_init (re_match_context_t *mctx, int eflags, Idx n) -{ - mctx->eflags = eflags; - mctx->match_last = REG_MISSING; - if (n > 0) - { - /* Avoid overflow. */ - size_t max_object_size = - MAX (sizeof (struct re_backref_cache_entry), - sizeof (re_sub_match_top_t *)); - if (BE (SIZE_MAX / max_object_size < n, 0)) - return REG_ESPACE; - - mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); - mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); - if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0)) - return REG_ESPACE; - } - /* Already zero-ed by the caller. - else - mctx->bkref_ents = NULL; - mctx->nbkref_ents = 0; - mctx->nsub_tops = 0; */ - mctx->abkref_ents = n; - mctx->max_mb_elem_len = 1; - mctx->asub_tops = n; - return REG_NOERROR; -} - -/* Clean the entries which depend on the current input in MCTX. - This function must be invoked when the matcher changes the start index - of the input, or changes the input string. */ - -static void -internal_function -match_ctx_clean (re_match_context_t *mctx) -{ - Idx st_idx; - for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) - { - Idx sl_idx; - re_sub_match_top_t *top = mctx->sub_tops[st_idx]; - for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) - { - re_sub_match_last_t *last = top->lasts[sl_idx]; - re_free (last->path.array); - re_free (last); - } - re_free (top->lasts); - if (top->path) - { - re_free (top->path->array); - re_free (top->path); - } - free (top); - } - - mctx->nsub_tops = 0; - mctx->nbkref_ents = 0; -} - -/* Free all the memory associated with MCTX. */ - -static void -internal_function -match_ctx_free (re_match_context_t *mctx) -{ - /* First, free all the memory associated with MCTX->SUB_TOPS. */ - match_ctx_clean (mctx); - re_free (mctx->sub_tops); - re_free (mctx->bkref_ents); -} - -/* Add a new backreference entry to MCTX. - Note that we assume that caller never call this function with duplicate - entry, and call with STR_IDX which isn't smaller than any existing entry. -*/ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from, - Idx to) -{ - if (mctx->nbkref_ents >= mctx->abkref_ents) - { - struct re_backref_cache_entry* new_entry; - new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, - mctx->abkref_ents * 2); - if (BE (new_entry == NULL, 0)) - { - re_free (mctx->bkref_ents); - return REG_ESPACE; - } - mctx->bkref_ents = new_entry; - memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', - sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); - mctx->abkref_ents *= 2; - } - if (mctx->nbkref_ents > 0 - && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) - mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; - - mctx->bkref_ents[mctx->nbkref_ents].node = node; - mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; - mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; - mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; - - /* This is a cache that saves negative results of check_dst_limits_calc_pos. - If bit N is clear, means that this entry won't epsilon-transition to - an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If - it is set, check_dst_limits_calc_pos_1 will recurse and try to find one - such node. - - A backreference does not epsilon-transition unless it is empty, so set - to all zeros if FROM != TO. */ - mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map - = (from == to ? -1 : 0); - - mctx->bkref_ents[mctx->nbkref_ents++].more = 0; - if (mctx->max_mb_elem_len < to - from) - mctx->max_mb_elem_len = to - from; - return REG_NOERROR; -} - -/* Return the first entry with the same str_idx, or REG_MISSING if none is - found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ - -static Idx -internal_function -search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx) -{ - Idx left, right, mid, last; - last = right = mctx->nbkref_ents; - for (left = 0; left < right;) - { - mid = (left + right) / 2; - if (mctx->bkref_ents[mid].str_idx < str_idx) - left = mid + 1; - else - right = mid; - } - if (left < last && mctx->bkref_ents[left].str_idx == str_idx) - return left; - else - return REG_MISSING; -} - -/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches - at STR_IDX. */ - -static reg_errcode_t -internal_function __attribute_warn_unused_result__ -match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx) -{ -#ifdef DEBUG - assert (mctx->sub_tops != NULL); - assert (mctx->asub_tops > 0); -#endif - if (BE (mctx->nsub_tops == mctx->asub_tops, 0)) - { - Idx new_asub_tops = mctx->asub_tops * 2; - re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, - re_sub_match_top_t *, - new_asub_tops); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - mctx->sub_tops = new_array; - mctx->asub_tops = new_asub_tops; - } - mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); - if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0)) - return REG_ESPACE; - mctx->sub_tops[mctx->nsub_tops]->node = node; - mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; - return REG_NOERROR; -} - -/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches - at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */ - -static re_sub_match_last_t * -internal_function -match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx) -{ - re_sub_match_last_t *new_entry; - if (BE (subtop->nlasts == subtop->alasts, 0)) - { - Idx new_alasts = 2 * subtop->alasts + 1; - re_sub_match_last_t **new_array = re_realloc (subtop->lasts, - re_sub_match_last_t *, - new_alasts); - if (BE (new_array == NULL, 0)) - return NULL; - subtop->lasts = new_array; - subtop->alasts = new_alasts; - } - new_entry = calloc (1, sizeof (re_sub_match_last_t)); - if (BE (new_entry != NULL, 1)) - { - subtop->lasts[subtop->nlasts] = new_entry; - new_entry->node = node; - new_entry->str_idx = str_idx; - ++subtop->nlasts; - } - return new_entry; -} - -static void -internal_function -sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, - re_dfastate_t **limited_sts, Idx last_node, Idx last_str_idx) -{ - sctx->sifted_states = sifted_sts; - sctx->limited_states = limited_sts; - sctx->last_node = last_node; - sctx->last_str_idx = last_str_idx; - re_node_set_init_empty (&sctx->limits); -} diff --git a/grub-core/gnulib/size_max.h b/grub-core/gnulib/size_max.h deleted file mode 100644 index 56d5a9b1c..000000000 --- a/grub-core/gnulib/size_max.h +++ /dev/null @@ -1,31 +0,0 @@ -/* size_max.h -- declare SIZE_MAX through system headers - Copyright (C) 2005-2006, 2009-2010 Free Software Foundation, Inc. - Written by Simon Josefsson. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef GNULIB_SIZE_MAX_H -#define GNULIB_SIZE_MAX_H - -/* Get SIZE_MAX declaration on systems like Solaris 7/8/9. */ -# include -/* Get SIZE_MAX declaration on systems like glibc 2. */ -# if HAVE_STDINT_H -# include -# endif -/* On systems where these include files don't define it, SIZE_MAX is defined - in config.h. */ - -#endif /* GNULIB_SIZE_MAX_H */ diff --git a/grub-core/gnulib/sleep.c b/grub-core/gnulib/sleep.c deleted file mode 100644 index 213e5bd29..000000000 --- a/grub-core/gnulib/sleep.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Pausing execution of the current thread. - Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2007. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -#include - -#include "verify.h" - -#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - -# define WIN32_LEAN_AND_MEAN /* avoid including junk */ -# include - -unsigned int -sleep (unsigned int seconds) -{ - unsigned int remaining; - - /* Sleep for 1 second many times, because - 1. Sleep is not interruptiple by Ctrl-C, - 2. we want to avoid arithmetic overflow while multiplying with 1000. */ - for (remaining = seconds; remaining > 0; remaining--) - Sleep (1000); - - return remaining; -} - -#elif HAVE_SLEEP - -# undef sleep - -/* Guarantee unlimited sleep and a reasonable return value. Cygwin - 1.5.x rejects attempts to sleep more than 49.7 days (2**32 - milliseconds), but uses uninitialized memory which results in a - garbage answer. */ -unsigned int -rpl_sleep (unsigned int seconds) -{ - /* This requires int larger than 16 bits. */ - verify (UINT_MAX / 49 / 24 / 60 / 60); - const unsigned int limit = 49 * 24 * 60 * 60; - while (limit < seconds) - { - unsigned int result; - seconds -= limit; - result = sleep (limit); - if (result) - return seconds + result; - } - return sleep (seconds); -} - -#else /* !HAVE_SLEEP */ - - #error "Please port gnulib sleep.c to your platform, possibly using usleep() or select(), then report this to bug-gnulib." - -#endif diff --git a/grub-core/gnulib/stdbool.in.h b/grub-core/gnulib/stdbool.in.h deleted file mode 100644 index 574c281a8..000000000 --- a/grub-core/gnulib/stdbool.in.h +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright (C) 2001-2003, 2006-2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2001. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GL_STDBOOL_H -#define _GL_STDBOOL_H - -/* ISO C 99 for platforms that lack it. */ - -/* Usage suggestions: - - Programs that use should be aware of some limitations - and standards compliance issues. - - Standards compliance: - - - must be #included before 'bool', 'false', 'true' - can be used. - - - You cannot assume that sizeof (bool) == 1. - - - Programs should not undefine the macros bool, true, and false, - as C99 lists that as an "obsolescent feature". - - Limitations of this substitute, when used in a C89 environment: - - - must be #included before the '_Bool' type can be used. - - - You cannot assume that _Bool is a typedef; it might be a macro. - - - Bit-fields of type 'bool' are not supported. Portable code - should use 'unsigned int foo : 1;' rather than 'bool foo : 1;'. - - - In C99, casts and automatic conversions to '_Bool' or 'bool' are - performed in such a way that every nonzero value gets converted - to 'true', and zero gets converted to 'false'. This doesn't work - with this substitute. With this substitute, only the values 0 and 1 - give the expected result when converted to _Bool' or 'bool'. - - - C99 allows the use of (_Bool)0.0 in constant expressions, but - this substitute cannot always provide this property. - - Also, it is suggested that programs use 'bool' rather than '_Bool'; - this isn't required, but 'bool' is more common. */ - - -/* 7.16. Boolean type and values */ - -/* BeOS already #defines false 0, true 1. We use the same - definitions below, but temporarily we have to #undef them. */ -#if defined __BEOS__ && !defined __HAIKU__ -# include /* defines bool but not _Bool */ -# undef false -# undef true -#endif - -/* For the sake of symbolic names in gdb, we define true and false as - enum constants, not only as macros. - It is tempting to write - typedef enum { false = 0, true = 1 } _Bool; - so that gdb prints values of type 'bool' symbolically. But if we do - this, values of type '_Bool' may promote to 'int' or 'unsigned int' - (see ISO C 99 6.7.2.2.(4)); however, '_Bool' must promote to 'int' - (see ISO C 99 6.3.1.1.(2)). So we add a negative value to the - enum; this ensures that '_Bool' promotes to 'int'. */ -#if defined __cplusplus || (defined __BEOS__ && !defined __HAIKU__) - /* A compiler known to have 'bool'. */ - /* If the compiler already has both 'bool' and '_Bool', we can assume they - are the same types. */ -# if !@HAVE__BOOL@ -typedef bool _Bool; -# endif -#else -# if !defined __GNUC__ - /* If @HAVE__BOOL@: - Some HP-UX cc and AIX IBM C compiler versions have compiler bugs when - the built-in _Bool type is used. See - http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html - http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html - http://lists.gnu.org/archive/html/bug-coreutils/2005-10/msg00086.html - Similar bugs are likely with other compilers as well; this file - wouldn't be used if was working. - So we override the _Bool type. - If !@HAVE__BOOL@: - Need to define _Bool ourselves. As 'signed char' or as an enum type? - Use of a typedef, with SunPRO C, leads to a stupid - "warning: _Bool is a keyword in ISO C99". - Use of an enum type, with IRIX cc, leads to a stupid - "warning(1185): enumerated type mixed with another type". - Even the existence of an enum type, without a typedef, - "Invalid enumerator. (badenum)" with HP-UX cc on Tru64. - The only benefit of the enum, debuggability, is not important - with these compilers. So use 'signed char' and no enum. */ -# define _Bool signed char -# else - /* With this compiler, trust the _Bool type if the compiler has it. */ -# if !@HAVE__BOOL@ -typedef enum { _Bool_must_promote_to_int = -1, false = 0, true = 1 } _Bool; -# endif -# endif -#endif -#define bool _Bool - -/* The other macros must be usable in preprocessor directives. */ -#define false 0 -#define true 1 -#define __bool_true_false_are_defined 1 - -#endif /* _GL_STDBOOL_H */ diff --git a/grub-core/gnulib/stddef.in.h b/grub-core/gnulib/stddef.in.h deleted file mode 100644 index 08778a233..000000000 --- a/grub-core/gnulib/stddef.in.h +++ /dev/null @@ -1,86 +0,0 @@ -/* A substitute for POSIX 2008 , for platforms that have issues. - - Copyright (C) 2009, 2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Eric Blake. */ - -/* - * POSIX 2008 for platforms that have issues. - * - */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -#if defined __need_wchar_t || defined __need_size_t \ - || defined __need_ptrdiff_t || defined __need_NULL \ - || defined __need_wint_t -/* Special invocation convention inside gcc header files. In - particular, gcc provides a version of that blindly - redefines NULL even when __need_wint_t was defined, even though - wint_t is not normally provided by . Hence, we must - remember if special invocation has ever been used to obtain wint_t, - in which case we need to clean up NULL yet again. */ - -# if !(defined _GL_STDDEF_H && defined _GL_STDDEF_WINT_T) -# ifdef __need_wint_t -# undef _GL_STDDEF_H -# define _GL_STDDEF_WINT_T -# endif -# @INCLUDE_NEXT@ @NEXT_STDDEF_H@ -# endif - -#else -/* Normal invocation convention. */ - -# ifndef _GL_STDDEF_H - -/* The include_next requires a split double-inclusion guard. */ - -# @INCLUDE_NEXT@ @NEXT_STDDEF_H@ - -# ifndef _GL_STDDEF_H -# define _GL_STDDEF_H - -/* On NetBSD 5.0, the definition of NULL lacks proper parentheses. */ -#if @REPLACE_NULL@ -# undef NULL -# ifdef __cplusplus - /* ISO C++ says that the macro NULL must expand to an integer constant - expression, hence '((void *) 0)' is not allowed in C++. */ -# if __GNUG__ >= 3 - /* GNU C++ has a __null macro that behaves like an integer ('int' or - 'long') but has the same size as a pointer. Use that, to avoid - warnings. */ -# define NULL __null -# else -# define NULL 0L -# endif -# else -# define NULL ((void *) 0) -# endif -#endif - -/* Some platforms lack wchar_t. */ -#if !@HAVE_WCHAR_T@ -# define wchar_t int -#endif - -# endif /* _GL_STDDEF_H */ -# endif /* _GL_STDDEF_H */ -#endif /* __need_XXX */ diff --git a/grub-core/gnulib/stdint.in.h b/grub-core/gnulib/stdint.in.h deleted file mode 100644 index 5da5f1788..000000000 --- a/grub-core/gnulib/stdint.in.h +++ /dev/null @@ -1,568 +0,0 @@ -/* Copyright (C) 2001-2002, 2004-2010 Free Software Foundation, Inc. - Written by Paul Eggert, Bruno Haible, Sam Steingold, Peter Burwood. - This file is part of gnulib. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* - * ISO C 99 for platforms that lack it. - * - */ - -#ifndef _GL_STDINT_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -/* When including a system file that in turn includes , - use the system , not our substitute. This avoids - problems with (for example) VMS, whose includes - . */ -#define _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H - -/* Get those types that are already defined in other system include - files, so that we can "#define int8_t signed char" below without - worrying about a later system include file containing a "typedef - signed char int8_t;" that will get messed up by our macro. Our - macros should all be consistent with the system versions, except - for the "fast" types and macros, which we recommend against using - in public interfaces due to compiler differences. */ - -#if @HAVE_STDINT_H@ -# if defined __sgi && ! defined __c99 - /* Bypass IRIX's if in C89 mode, since it merely annoys users - with "This header file is to be used only for c99 mode compilations" - diagnostics. */ -# define __STDINT_H__ -# endif - /* Other systems may have an incomplete or buggy . - Include it before , since any "#include " - in would reinclude us, skipping our contents because - _GL_STDINT_H is defined. - The include_next requires a split double-inclusion guard. */ -# @INCLUDE_NEXT@ @NEXT_STDINT_H@ -#endif - -#if ! defined _GL_STDINT_H && ! defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H -#define _GL_STDINT_H - -/* defines some of the stdint.h types as well, on glibc, - IRIX 6.5, and OpenBSD 3.8 (via ). - AIX 5.2 isn't needed and causes troubles. - MacOS X 10.4.6 includes (which is us), but - relies on the system definitions, so include - after @NEXT_STDINT_H@. */ -#if @HAVE_SYS_TYPES_H@ && ! defined _AIX -# include -#endif - -/* Get LONG_MIN, LONG_MAX, ULONG_MAX. */ -#include - -#if @HAVE_INTTYPES_H@ - /* In OpenBSD 3.8, includes , which defines - int{8,16,32,64}_t, uint{8,16,32,64}_t and __BIT_TYPES_DEFINED__. - also defines intptr_t and uintptr_t. */ -# include -#elif @HAVE_SYS_INTTYPES_H@ - /* Solaris 7 has the types except the *_fast*_t types, and - the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX. */ -# include -#endif - -#if @HAVE_SYS_BITYPES_H@ && ! defined __BIT_TYPES_DEFINED__ - /* Linux libc4 >= 4.6.7 and libc5 have a that defines - int{8,16,32,64}_t and __BIT_TYPES_DEFINED__. In libc5 >= 5.2.2 it is - included by . */ -# include -#endif - -#undef _GL_JUST_INCLUDE_SYSTEM_INTTYPES_H - -/* Minimum and maximum values for a integer type under the usual assumption. - Return an unspecified value if BITS == 0, adding a check to pacify - picky compilers. */ - -#define _STDINT_MIN(signed, bits, zero) \ - ((signed) ? (- ((zero) + 1) << ((bits) ? (bits) - 1 : 0)) : (zero)) - -#define _STDINT_MAX(signed, bits, zero) \ - ((signed) \ - ? ~ _STDINT_MIN (signed, bits, zero) \ - : /* The expression for the unsigned case. The subtraction of (signed) \ - is a nop in the unsigned case and avoids "signed integer overflow" \ - warnings in the signed case. */ \ - ((((zero) + 1) << ((bits) ? (bits) - 1 - (signed) : 0)) - 1) * 2 + 1) - -/* 7.18.1.1. Exact-width integer types */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. */ - -#undef int8_t -#undef uint8_t -typedef signed char gl_int8_t; -typedef unsigned char gl_uint8_t; -#define int8_t gl_int8_t -#define uint8_t gl_uint8_t - -#undef int16_t -#undef uint16_t -typedef short int gl_int16_t; -typedef unsigned short int gl_uint16_t; -#define int16_t gl_int16_t -#define uint16_t gl_uint16_t - -#undef int32_t -#undef uint32_t -typedef int gl_int32_t; -typedef unsigned int gl_uint32_t; -#define int32_t gl_int32_t -#define uint32_t gl_uint32_t - -/* Do not undefine int64_t if gnulib is not being used with 64-bit - types, since otherwise it breaks platforms like Tandem/NSK. */ -#if LONG_MAX >> 31 >> 31 == 1 -# undef int64_t -typedef long int gl_int64_t; -# define int64_t gl_int64_t -# define GL_INT64_T -#elif defined _MSC_VER -# undef int64_t -typedef __int64 gl_int64_t; -# define int64_t gl_int64_t -# define GL_INT64_T -#elif @HAVE_LONG_LONG_INT@ -# undef int64_t -typedef long long int gl_int64_t; -# define int64_t gl_int64_t -# define GL_INT64_T -#endif - -#if ULONG_MAX >> 31 >> 31 >> 1 == 1 -# undef uint64_t -typedef unsigned long int gl_uint64_t; -# define uint64_t gl_uint64_t -# define GL_UINT64_T -#elif defined _MSC_VER -# undef uint64_t -typedef unsigned __int64 gl_uint64_t; -# define uint64_t gl_uint64_t -# define GL_UINT64_T -#elif @HAVE_UNSIGNED_LONG_LONG_INT@ -# undef uint64_t -typedef unsigned long long int gl_uint64_t; -# define uint64_t gl_uint64_t -# define GL_UINT64_T -#endif - -/* Avoid collision with Solaris 2.5.1 etc. */ -#define _UINT8_T -#define _UINT32_T -#define _UINT64_T - - -/* 7.18.1.2. Minimum-width integer types */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types - are the same as the corresponding N_t types. */ - -#undef int_least8_t -#undef uint_least8_t -#undef int_least16_t -#undef uint_least16_t -#undef int_least32_t -#undef uint_least32_t -#undef int_least64_t -#undef uint_least64_t -#define int_least8_t int8_t -#define uint_least8_t uint8_t -#define int_least16_t int16_t -#define uint_least16_t uint16_t -#define int_least32_t int32_t -#define uint_least32_t uint32_t -#ifdef GL_INT64_T -# define int_least64_t int64_t -#endif -#ifdef GL_UINT64_T -# define uint_least64_t uint64_t -#endif - -/* 7.18.1.3. Fastest minimum-width integer types */ - -/* Note: Other substitutes may define these types differently. - It is not recommended to use these types in public header files. */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types - are taken from the same list of types. Assume that 'long int' - is fast enough for all narrower integers. */ - -#undef int_fast8_t -#undef uint_fast8_t -#undef int_fast16_t -#undef uint_fast16_t -#undef int_fast32_t -#undef uint_fast32_t -#undef int_fast64_t -#undef uint_fast64_t -typedef long int gl_int_fast8_t; -typedef unsigned long int gl_uint_fast8_t; -typedef long int gl_int_fast16_t; -typedef unsigned long int gl_uint_fast16_t; -typedef long int gl_int_fast32_t; -typedef unsigned long int gl_uint_fast32_t; -#define int_fast8_t gl_int_fast8_t -#define uint_fast8_t gl_uint_fast8_t -#define int_fast16_t gl_int_fast16_t -#define uint_fast16_t gl_uint_fast16_t -#define int_fast32_t gl_int_fast32_t -#define uint_fast32_t gl_uint_fast32_t -#ifdef GL_INT64_T -# define int_fast64_t int64_t -#endif -#ifdef GL_UINT64_T -# define uint_fast64_t uint64_t -#endif - -/* 7.18.1.4. Integer types capable of holding object pointers */ - -#undef intptr_t -#undef uintptr_t -typedef long int gl_intptr_t; -typedef unsigned long int gl_uintptr_t; -#define intptr_t gl_intptr_t -#define uintptr_t gl_uintptr_t - -/* 7.18.1.5. Greatest-width integer types */ - -/* Note: These types are compiler dependent. It may be unwise to use them in - public header files. */ - -#undef intmax_t -#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 -typedef long long int gl_intmax_t; -# define intmax_t gl_intmax_t -#elif defined GL_INT64_T -# define intmax_t int64_t -#else -typedef long int gl_intmax_t; -# define intmax_t gl_intmax_t -#endif - -#undef uintmax_t -#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 -typedef unsigned long long int gl_uintmax_t; -# define uintmax_t gl_uintmax_t -#elif defined GL_UINT64_T -# define uintmax_t uint64_t -#else -typedef unsigned long int gl_uintmax_t; -# define uintmax_t gl_uintmax_t -#endif - -/* Verify that intmax_t and uintmax_t have the same size. Too much code - breaks if this is not the case. If this check fails, the reason is likely - to be found in the autoconf macros. */ -typedef int _verify_intmax_size[2 * (sizeof (intmax_t) == sizeof (uintmax_t)) - 1]; - -/* 7.18.2. Limits of specified-width integer types */ - -#if ! defined __cplusplus || defined __STDC_LIMIT_MACROS - -/* 7.18.2.1. Limits of exact-width integer types */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. */ - -#undef INT8_MIN -#undef INT8_MAX -#undef UINT8_MAX -#define INT8_MIN (~ INT8_MAX) -#define INT8_MAX 127 -#define UINT8_MAX 255 - -#undef INT16_MIN -#undef INT16_MAX -#undef UINT16_MAX -#define INT16_MIN (~ INT16_MAX) -#define INT16_MAX 32767 -#define UINT16_MAX 65535 - -#undef INT32_MIN -#undef INT32_MAX -#undef UINT32_MAX -#define INT32_MIN (~ INT32_MAX) -#define INT32_MAX 2147483647 -#define UINT32_MAX 4294967295U - -#undef INT64_MIN -#undef INT64_MAX -#ifdef GL_INT64_T -/* Prefer (- INTMAX_C (1) << 63) over (~ INT64_MAX) because SunPRO C 5.0 - evaluates the latter incorrectly in preprocessor expressions. */ -# define INT64_MIN (- INTMAX_C (1) << 63) -# define INT64_MAX INTMAX_C (9223372036854775807) -#endif - -#undef UINT64_MAX -#ifdef GL_UINT64_T -# define UINT64_MAX UINTMAX_C (18446744073709551615) -#endif - -/* 7.18.2.2. Limits of minimum-width integer types */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. Therefore the leastN_t types - are the same as the corresponding N_t types. */ - -#undef INT_LEAST8_MIN -#undef INT_LEAST8_MAX -#undef UINT_LEAST8_MAX -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define UINT_LEAST8_MAX UINT8_MAX - -#undef INT_LEAST16_MIN -#undef INT_LEAST16_MAX -#undef UINT_LEAST16_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define UINT_LEAST16_MAX UINT16_MAX - -#undef INT_LEAST32_MIN -#undef INT_LEAST32_MAX -#undef UINT_LEAST32_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define UINT_LEAST32_MAX UINT32_MAX - -#undef INT_LEAST64_MIN -#undef INT_LEAST64_MAX -#ifdef GL_INT64_T -# define INT_LEAST64_MIN INT64_MIN -# define INT_LEAST64_MAX INT64_MAX -#endif - -#undef UINT_LEAST64_MAX -#ifdef GL_UINT64_T -# define UINT_LEAST64_MAX UINT64_MAX -#endif - -/* 7.18.2.3. Limits of fastest minimum-width integer types */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits. Therefore the fastN_t types - are taken from the same list of types. */ - -#undef INT_FAST8_MIN -#undef INT_FAST8_MAX -#undef UINT_FAST8_MAX -#define INT_FAST8_MIN LONG_MIN -#define INT_FAST8_MAX LONG_MAX -#define UINT_FAST8_MAX ULONG_MAX - -#undef INT_FAST16_MIN -#undef INT_FAST16_MAX -#undef UINT_FAST16_MAX -#define INT_FAST16_MIN LONG_MIN -#define INT_FAST16_MAX LONG_MAX -#define UINT_FAST16_MAX ULONG_MAX - -#undef INT_FAST32_MIN -#undef INT_FAST32_MAX -#undef UINT_FAST32_MAX -#define INT_FAST32_MIN LONG_MIN -#define INT_FAST32_MAX LONG_MAX -#define UINT_FAST32_MAX ULONG_MAX - -#undef INT_FAST64_MIN -#undef INT_FAST64_MAX -#ifdef GL_INT64_T -# define INT_FAST64_MIN INT64_MIN -# define INT_FAST64_MAX INT64_MAX -#endif - -#undef UINT_FAST64_MAX -#ifdef GL_UINT64_T -# define UINT_FAST64_MAX UINT64_MAX -#endif - -/* 7.18.2.4. Limits of integer types capable of holding object pointers */ - -#undef INTPTR_MIN -#undef INTPTR_MAX -#undef UINTPTR_MAX -#define INTPTR_MIN LONG_MIN -#define INTPTR_MAX LONG_MAX -#define UINTPTR_MAX ULONG_MAX - -/* 7.18.2.5. Limits of greatest-width integer types */ - -#undef INTMAX_MIN -#undef INTMAX_MAX -#ifdef INT64_MAX -# define INTMAX_MIN INT64_MIN -# define INTMAX_MAX INT64_MAX -#else -# define INTMAX_MIN INT32_MIN -# define INTMAX_MAX INT32_MAX -#endif - -#undef UINTMAX_MAX -#ifdef UINT64_MAX -# define UINTMAX_MAX UINT64_MAX -#else -# define UINTMAX_MAX UINT32_MAX -#endif - -/* 7.18.3. Limits of other integer types */ - -/* ptrdiff_t limits */ -#undef PTRDIFF_MIN -#undef PTRDIFF_MAX -#if @APPLE_UNIVERSAL_BUILD@ -# ifdef _LP64 -# define PTRDIFF_MIN _STDINT_MIN (1, 64, 0l) -# define PTRDIFF_MAX _STDINT_MAX (1, 64, 0l) -# else -# define PTRDIFF_MIN _STDINT_MIN (1, 32, 0) -# define PTRDIFF_MAX _STDINT_MAX (1, 32, 0) -# endif -#else -# define PTRDIFF_MIN \ - _STDINT_MIN (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) -# define PTRDIFF_MAX \ - _STDINT_MAX (1, @BITSIZEOF_PTRDIFF_T@, 0@PTRDIFF_T_SUFFIX@) -#endif - -/* sig_atomic_t limits */ -#undef SIG_ATOMIC_MIN -#undef SIG_ATOMIC_MAX -#define SIG_ATOMIC_MIN \ - _STDINT_MIN (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ - 0@SIG_ATOMIC_T_SUFFIX@) -#define SIG_ATOMIC_MAX \ - _STDINT_MAX (@HAVE_SIGNED_SIG_ATOMIC_T@, @BITSIZEOF_SIG_ATOMIC_T@, \ - 0@SIG_ATOMIC_T_SUFFIX@) - - -/* size_t limit */ -#undef SIZE_MAX -#if @APPLE_UNIVERSAL_BUILD@ -# ifdef _LP64 -# define SIZE_MAX _STDINT_MAX (0, 64, 0ul) -# else -# define SIZE_MAX _STDINT_MAX (0, 32, 0ul) -# endif -#else -# define SIZE_MAX _STDINT_MAX (0, @BITSIZEOF_SIZE_T@, 0@SIZE_T_SUFFIX@) -#endif - -/* wchar_t limits */ -/* Get WCHAR_MIN, WCHAR_MAX. - This include is not on the top, above, because on OSF/1 4.0 we have a sequence of nested - includes -> -> -> , and the latter includes - and assumes its types are already defined. */ -#if ! (defined WCHAR_MIN && defined WCHAR_MAX) -# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H -# include -# undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H -#endif -#undef WCHAR_MIN -#undef WCHAR_MAX -#define WCHAR_MIN \ - _STDINT_MIN (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) -#define WCHAR_MAX \ - _STDINT_MAX (@HAVE_SIGNED_WCHAR_T@, @BITSIZEOF_WCHAR_T@, 0@WCHAR_T_SUFFIX@) - -/* wint_t limits */ -#undef WINT_MIN -#undef WINT_MAX -#define WINT_MIN \ - _STDINT_MIN (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) -#define WINT_MAX \ - _STDINT_MAX (@HAVE_SIGNED_WINT_T@, @BITSIZEOF_WINT_T@, 0@WINT_T_SUFFIX@) - -#endif /* !defined __cplusplus || defined __STDC_LIMIT_MACROS */ - -/* 7.18.4. Macros for integer constants */ - -#if ! defined __cplusplus || defined __STDC_CONSTANT_MACROS - -/* 7.18.4.1. Macros for minimum-width integer constants */ -/* According to ISO C 99 Technical Corrigendum 1 */ - -/* Here we assume a standard architecture where the hardware integer - types have 8, 16, 32, optionally 64 bits, and int is 32 bits. */ - -#undef INT8_C -#undef UINT8_C -#define INT8_C(x) x -#define UINT8_C(x) x - -#undef INT16_C -#undef UINT16_C -#define INT16_C(x) x -#define UINT16_C(x) x - -#undef INT32_C -#undef UINT32_C -#define INT32_C(x) x -#define UINT32_C(x) x ## U - -#undef INT64_C -#undef UINT64_C -#if LONG_MAX >> 31 >> 31 == 1 -# define INT64_C(x) x##L -#elif defined _MSC_VER -# define INT64_C(x) x##i64 -#elif @HAVE_LONG_LONG_INT@ -# define INT64_C(x) x##LL -#endif -#if ULONG_MAX >> 31 >> 31 >> 1 == 1 -# define UINT64_C(x) x##UL -#elif defined _MSC_VER -# define UINT64_C(x) x##ui64 -#elif @HAVE_UNSIGNED_LONG_LONG_INT@ -# define UINT64_C(x) x##ULL -#endif - -/* 7.18.4.2. Macros for greatest-width integer constants */ - -#undef INTMAX_C -#if @HAVE_LONG_LONG_INT@ && LONG_MAX >> 30 == 1 -# define INTMAX_C(x) x##LL -#elif defined GL_INT64_T -# define INTMAX_C(x) INT64_C(x) -#else -# define INTMAX_C(x) x##L -#endif - -#undef UINTMAX_C -#if @HAVE_UNSIGNED_LONG_LONG_INT@ && ULONG_MAX >> 31 == 1 -# define UINTMAX_C(x) x##ULL -#elif defined GL_UINT64_T -# define UINTMAX_C(x) UINT64_C(x) -#else -# define UINTMAX_C(x) x##UL -#endif - -#endif /* !defined __cplusplus || defined __STDC_CONSTANT_MACROS */ - -#endif /* _GL_STDINT_H */ -#endif /* !defined _GL_STDINT_H && !defined _GL_JUST_INCLUDE_SYSTEM_STDINT_H */ diff --git a/grub-core/gnulib/stdio-write.c b/grub-core/gnulib/stdio-write.c deleted file mode 100644 index a6a0eb143..000000000 --- a/grub-core/gnulib/stdio-write.c +++ /dev/null @@ -1,148 +0,0 @@ -/* POSIX compatible FILE stream write function. - Copyright (C) 2008-2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -/* Replace these functions only if module 'sigpipe' is requested. */ -#if GNULIB_SIGPIPE - -/* On native Windows platforms, SIGPIPE does not exist. When write() is - called on a pipe with no readers, WriteFile() fails with error - GetLastError() = ERROR_NO_DATA, and write() in consequence fails with - error EINVAL. This write() function is at the basis of the function - which flushes the buffer of a FILE stream. */ - -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - -# include -# include -# include - -# define WIN32_LEAN_AND_MEAN /* avoid including junk */ -# include - -# define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \ - if (ferror (stream)) \ - return (EXPRESSION); \ - else \ - { \ - RETTYPE ret; \ - SetLastError (0); \ - ret = (EXPRESSION); \ - if (FAILED && GetLastError () == ERROR_NO_DATA && ferror (stream)) \ - { \ - int fd = fileno (stream); \ - if (fd >= 0 \ - && GetFileType ((HANDLE) _get_osfhandle (fd)) == FILE_TYPE_PIPE)\ - { \ - /* Try to raise signal SIGPIPE. */ \ - raise (SIGPIPE); \ - /* If it is currently blocked or ignored, change errno from \ - EINVAL to EPIPE. */ \ - errno = EPIPE; \ - } \ - } \ - return ret; \ - } - -# if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */ -int -printf (const char *format, ...) -{ - int retval; - va_list args; - - va_start (args, format); - retval = vfprintf (stdout, format, args); - va_end (args); - - return retval; -} -# endif - -# if !REPLACE_FPRINTF_POSIX /* avoid collision with fprintf.c */ -int -fprintf (FILE *stream, const char *format, ...) -{ - int retval; - va_list args; - - va_start (args, format); - retval = vfprintf (stream, format, args); - va_end (args); - - return retval; -} -# endif - -# if !REPLACE_VPRINTF_POSIX /* avoid collision with vprintf.c */ -int -vprintf (const char *format, va_list args) -{ - return vfprintf (stdout, format, args); -} -# endif - -# if !REPLACE_VFPRINTF_POSIX /* avoid collision with vfprintf.c */ -int -vfprintf (FILE *stream, const char *format, va_list args) -#undef vfprintf -{ - CALL_WITH_SIGPIPE_EMULATION (int, vfprintf (stream, format, args), ret == EOF) -} -# endif - -int -putchar (int c) -{ - return fputc (c, stdout); -} - -int -fputc (int c, FILE *stream) -#undef fputc -{ - CALL_WITH_SIGPIPE_EMULATION (int, fputc (c, stream), ret == EOF) -} - -int -fputs (const char *string, FILE *stream) -#undef fputs -{ - CALL_WITH_SIGPIPE_EMULATION (int, fputs (string, stream), ret == EOF) -} - -int -puts (const char *string) -#undef puts -{ - FILE *stream = stdout; - CALL_WITH_SIGPIPE_EMULATION (int, puts (string), ret == EOF) -} - -size_t -fwrite (const void *ptr, size_t s, size_t n, FILE *stream) -#undef fwrite -{ - CALL_WITH_SIGPIPE_EMULATION (size_t, fwrite (ptr, s, n, stream), ret < n) -} - -# endif -#endif diff --git a/grub-core/gnulib/stdio.in.h b/grub-core/gnulib/stdio.in.h deleted file mode 100644 index 80b9dbfda..000000000 --- a/grub-core/gnulib/stdio.in.h +++ /dev/null @@ -1,1071 +0,0 @@ -/* A GNU-like . - - Copyright (C) 2004, 2007-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -#if defined __need_FILE || defined __need___FILE -/* Special invocation convention inside glibc header files. */ - -#@INCLUDE_NEXT@ @NEXT_STDIO_H@ - -#else -/* Normal invocation convention. */ - -#ifndef _GL_STDIO_H - -/* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_STDIO_H@ - -#ifndef _GL_STDIO_H -#define _GL_STDIO_H - -/* Get va_list. Needed on many systems, including glibc 2.8. */ -#include - -#include - -/* Get off_t and ssize_t. Needed on many systems, including glibc 2.8. */ -#include - -#ifndef __attribute__ -/* The __attribute__ feature is available in gcc versions 2.5 and later. - The __-protected variants of the attributes 'format' and 'printf' are - accepted by gcc versions 2.6.4 (effectively 2.7) and later. - We enable __attribute__ only if these are supported too, because - gnulib and libintl do '#define printf __printf__' when they override - the 'printf' function. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __attribute__(Spec) /* empty */ -# endif -#endif - - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - -/* Macros for stringification. */ -#define _GL_STDIO_STRINGIZE(token) #token -#define _GL_STDIO_MACROEXPAND_AND_STRINGIZE(token) _GL_STDIO_STRINGIZE(token) - - -#if @GNULIB_DPRINTF@ -# if @REPLACE_DPRINTF@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define dprintf rpl_dprintf -# endif -_GL_FUNCDECL_RPL (dprintf, int, (int fd, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (dprintf, int, (int fd, const char *format, ...)); -# else -# if !@HAVE_DPRINTF@ -_GL_FUNCDECL_SYS (dprintf, int, (int fd, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (dprintf, int, (int fd, const char *format, ...)); -# endif -_GL_CXXALIASWARN (dprintf); -#elif defined GNULIB_POSIXCHECK -# undef dprintf -# if HAVE_RAW_DECL_DPRINTF -_GL_WARN_ON_USE (dprintf, "dprintf is unportable - " - "use gnulib module dprintf for portability"); -# endif -#endif - -#if @GNULIB_FCLOSE@ -/* Close STREAM and its underlying file descriptor. */ -# if @REPLACE_FCLOSE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define fclose rpl_fclose -# endif -_GL_FUNCDECL_RPL (fclose, int, (FILE *stream) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (fclose, int, (FILE *stream)); -# else -_GL_CXXALIAS_SYS (fclose, int, (FILE *stream)); -# endif -_GL_CXXALIASWARN (fclose); -#elif defined GNULIB_POSIXCHECK -# undef fclose -/* Assume fclose is always declared. */ -_GL_WARN_ON_USE (fclose, "fclose is not always POSIX compliant - " - "use gnulib module fclose for portable POSIX compliance"); -#endif - -#if @GNULIB_FFLUSH@ -/* Flush all pending data on STREAM according to POSIX rules. Both - output and seekable input streams are supported. - Note! LOSS OF DATA can occur if fflush is applied on an input stream - that is _not_seekable_ or on an update stream that is _not_seekable_ - and in which the most recent operation was input. Seekability can - be tested with lseek(fileno(fp),0,SEEK_CUR). */ -# if @REPLACE_FFLUSH@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define fflush rpl_fflush -# endif -_GL_FUNCDECL_RPL (fflush, int, (FILE *gl_stream)); -_GL_CXXALIAS_RPL (fflush, int, (FILE *gl_stream)); -# else -_GL_CXXALIAS_SYS (fflush, int, (FILE *gl_stream)); -# endif -_GL_CXXALIASWARN (fflush); -#elif defined GNULIB_POSIXCHECK -# undef fflush -/* Assume fflush is always declared. */ -_GL_WARN_ON_USE (fflush, "fflush is not always POSIX compliant - " - "use gnulib module fflush for portable POSIX compliance"); -#endif - -/* It is very rare that the developer ever has full control of stdin, - so any use of gets warrants an unconditional warning. Assume it is - always declared, since it is required by C89. */ -#undef gets -_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); - -#if @GNULIB_FOPEN@ -# if @REPLACE_FOPEN@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fopen -# define fopen rpl_fopen -# endif -_GL_FUNCDECL_RPL (fopen, FILE *, (const char *filename, const char *mode) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (fopen, FILE *, (const char *filename, const char *mode)); -# else -_GL_CXXALIAS_SYS (fopen, FILE *, (const char *filename, const char *mode)); -# endif -_GL_CXXALIASWARN (fopen); -#elif defined GNULIB_POSIXCHECK -# undef fopen -/* Assume fopen is always declared. */ -_GL_WARN_ON_USE (fopen, "fopen on Win32 platforms is not POSIX compatible - " - "use gnulib module fopen for portability"); -#endif - -#if @GNULIB_FPRINTF_POSIX@ || @GNULIB_FPRINTF@ -# if (@GNULIB_FPRINTF_POSIX@ && @REPLACE_FPRINTF@) \ - || (@GNULIB_FPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define fprintf rpl_fprintf -# endif -# define GNULIB_overrides_fprintf 1 -_GL_FUNCDECL_RPL (fprintf, int, (FILE *fp, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (fprintf, int, (FILE *fp, const char *format, ...)); -# else -_GL_CXXALIAS_SYS (fprintf, int, (FILE *fp, const char *format, ...)); -# endif -_GL_CXXALIASWARN (fprintf); -#endif -#if !@GNULIB_FPRINTF_POSIX@ && defined GNULIB_POSIXCHECK -# if !GNULIB_overrides_fprintf -# undef fprintf -# endif -/* Assume fprintf is always declared. */ -_GL_WARN_ON_USE (fprintf, "fprintf is not always POSIX compliant - " - "use gnulib module fprintf-posix for portable " - "POSIX compliance"); -#endif - -#if @GNULIB_FPURGE@ -/* Discard all pending buffered I/O data on STREAM. - STREAM must not be wide-character oriented. - When discarding pending output, the file position is set back to where it - was before the write calls. When discarding pending input, the file - position is advanced to match the end of the previously read input. - Return 0 if successful. Upon error, return -1 and set errno. */ -# if @REPLACE_FPURGE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define fpurge rpl_fpurge -# endif -_GL_FUNCDECL_RPL (fpurge, int, (FILE *gl_stream) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (fpurge, int, (FILE *gl_stream)); -# else -# if !@HAVE_DECL_FPURGE@ -_GL_FUNCDECL_SYS (fpurge, int, (FILE *gl_stream) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (fpurge, int, (FILE *gl_stream)); -# endif -_GL_CXXALIASWARN (fpurge); -#elif defined GNULIB_POSIXCHECK -# undef fpurge -# if HAVE_RAW_DECL_FPURGE -_GL_WARN_ON_USE (fpurge, "fpurge is not always present - " - "use gnulib module fpurge for portability"); -# endif -#endif - -#if @GNULIB_FPUTC@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fputc -# define fputc rpl_fputc -# endif -_GL_FUNCDECL_RPL (fputc, int, (int c, FILE *stream) _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (fputc, int, (int c, FILE *stream)); -# else -_GL_CXXALIAS_SYS (fputc, int, (int c, FILE *stream)); -# endif -_GL_CXXALIASWARN (fputc); -#endif - -#if @GNULIB_FPUTS@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fputs -# define fputs rpl_fputs -# endif -_GL_FUNCDECL_RPL (fputs, int, (const char *string, FILE *stream) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (fputs, int, (const char *string, FILE *stream)); -# else -_GL_CXXALIAS_SYS (fputs, int, (const char *string, FILE *stream)); -# endif -_GL_CXXALIASWARN (fputs); -#endif - -#if @GNULIB_FREOPEN@ -# if @REPLACE_FREOPEN@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef freopen -# define freopen rpl_freopen -# endif -_GL_FUNCDECL_RPL (freopen, FILE *, - (const char *filename, const char *mode, FILE *stream) - _GL_ARG_NONNULL ((2, 3))); -_GL_CXXALIAS_RPL (freopen, FILE *, - (const char *filename, const char *mode, FILE *stream)); -# else -_GL_CXXALIAS_SYS (freopen, FILE *, - (const char *filename, const char *mode, FILE *stream)); -# endif -_GL_CXXALIASWARN (freopen); -#elif defined GNULIB_POSIXCHECK -# undef freopen -/* Assume freopen is always declared. */ -_GL_WARN_ON_USE (freopen, "freopen on Win32 platforms is not POSIX compatible - " - "use gnulib module freopen for portability"); -#endif - - -/* Set up the following warnings, based on which modules are in use. - GNU Coding Standards discourage the use of fseek, since it imposes - an arbitrary limitation on some 32-bit hosts. Remember that the - fseek module depends on the fseeko module, so we only have three - cases to consider: - - 1. The developer is not using either module. Issue a warning under - GNULIB_POSIXCHECK for both functions, to remind them that both - functions have bugs on some systems. _GL_NO_LARGE_FILES has no - impact on this warning. - - 2. The developer is using both modules. They may be unaware of the - arbitrary limitations of fseek, so issue a warning under - GNULIB_POSIXCHECK. On the other hand, they may be using both - modules intentionally, so the developer can define - _GL_NO_LARGE_FILES in the compilation units where the use of fseek - is safe, to silence the warning. - - 3. The developer is using the fseeko module, but not fseek. Gnulib - guarantees that fseek will still work around platform bugs in that - case, but we presume that the developer is aware of the pitfalls of - fseek and was trying to avoid it, so issue a warning even when - GNULIB_POSIXCHECK is undefined. Again, _GL_NO_LARGE_FILES can be - defined to silence the warning in particular compilation units. - In C++ compilations with GNULIB_NAMESPACE, in order to avoid that - fseek gets defined as a macro, it is recommended that the developer - uses the fseek module, even if he is not calling the fseek function. - - Most gnulib clients that perform stream operations should fall into - category 3. */ - -#if @GNULIB_FSEEK@ -# if defined GNULIB_POSIXCHECK && !defined _GL_NO_LARGE_FILES -# define _GL_FSEEK_WARN /* Category 2, above. */ -# undef fseek -# endif -# if @REPLACE_FSEEK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fseek -# define fseek rpl_fseek -# endif -_GL_FUNCDECL_RPL (fseek, int, (FILE *fp, long offset, int whence) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (fseek, int, (FILE *fp, long offset, int whence)); -# else -_GL_CXXALIAS_SYS (fseek, int, (FILE *fp, long offset, int whence)); -# endif -_GL_CXXALIASWARN (fseek); -#endif - -#if @GNULIB_FSEEKO@ -# if !@GNULIB_FSEEK@ && !defined _GL_NO_LARGE_FILES -# define _GL_FSEEK_WARN /* Category 3, above. */ -# undef fseek -# endif -# if @REPLACE_FSEEKO@ -/* Provide an fseeko function that is aware of a preceding fflush(), and which - detects pipes. */ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fseeko -# define fseeko rpl_fseeko -# endif -_GL_FUNCDECL_RPL (fseeko, int, (FILE *fp, off_t offset, int whence) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (fseeko, int, (FILE *fp, off_t offset, int whence)); -# else -# if ! @HAVE_FSEEKO@ -_GL_FUNCDECL_SYS (fseeko, int, (FILE *fp, off_t offset, int whence) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (fseeko, int, (FILE *fp, off_t offset, int whence)); -# endif -_GL_CXXALIASWARN (fseeko); -# if (@REPLACE_FSEEKO@ || !@HAVE_FSEEKO@) && !@GNULIB_FSEEK@ - /* Provide an fseek function that is consistent with fseeko. */ - /* In order to avoid that fseek gets defined as a macro here, the - developer can request the 'fseek' module. */ -# undef fseek -# define fseek rpl_fseek -static inline int _GL_ARG_NONNULL ((1)) -rpl_fseek (FILE *fp, long offset, int whence) -{ -# if @REPLACE_FSEEKO@ - return rpl_fseeko (fp, offset, whence); -# else - return fseeko (fp, offset, whence); -# endif -} -# endif -#elif defined GNULIB_POSIXCHECK -# define _GL_FSEEK_WARN /* Category 1, above. */ -# undef fseek -# undef fseeko -# if HAVE_RAW_DECL_FSEEKO -_GL_WARN_ON_USE (fseeko, "fseeko is unportable - " - "use gnulib module fseeko for portability"); -# endif -#endif - -#ifdef _GL_FSEEK_WARN -# undef _GL_FSEEK_WARN -/* Here, either fseek is undefined (but C89 guarantees that it is - declared), or it is defined as rpl_fseek (declared above). */ -_GL_WARN_ON_USE (fseek, "fseek cannot handle files larger than 4 GB " - "on 32-bit platforms - " - "use fseeko function for handling of large files"); -#endif - - -/* ftell, ftello. See the comments on fseek/fseeko. */ - -#if @GNULIB_FTELL@ -# if defined GNULIB_POSIXCHECK && !defined _GL_NO_LARGE_FILES -# define _GL_FTELL_WARN /* Category 2, above. */ -# undef ftell -# endif -# if @REPLACE_FTELL@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef ftell -# define ftell rpl_ftell -# endif -_GL_FUNCDECL_RPL (ftell, long, (FILE *fp) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (ftell, long, (FILE *fp)); -# else -_GL_CXXALIAS_SYS (ftell, long, (FILE *fp)); -# endif -_GL_CXXALIASWARN (ftell); -#endif - -#if @GNULIB_FTELLO@ -# if !@GNULIB_FTELL@ && !defined _GL_NO_LARGE_FILES -# define _GL_FTELL_WARN /* Category 3, above. */ -# undef ftell -# endif -# if @REPLACE_FTELLO@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef ftello -# define ftello rpl_ftello -# endif -_GL_FUNCDECL_RPL (ftello, off_t, (FILE *fp) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (ftello, off_t, (FILE *fp)); -# else -# if ! @HAVE_FTELLO@ -_GL_FUNCDECL_SYS (ftello, off_t, (FILE *fp) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (ftello, off_t, (FILE *fp)); -# endif -_GL_CXXALIASWARN (ftello); -# if (@REPLACE_FTELLO@ || !@HAVE_FTELLO@) && !@GNULIB_FTELL@ - /* Provide an ftell function that is consistent with ftello. */ - /* In order to avoid that ftell gets defined as a macro here, the - developer can request the 'ftell' module. */ -# undef ftell -# define ftell rpl_ftell -static inline long _GL_ARG_NONNULL ((1)) -rpl_ftell (FILE *f) -{ -# if @REPLACE_FTELLO@ - return rpl_ftello (f); -# else - return ftello (f); -# endif -} -# endif -#elif defined GNULIB_POSIXCHECK -# define _GL_FTELL_WARN /* Category 1, above. */ -# undef ftell -# undef ftello -# if HAVE_RAW_DECL_FTELLO -_GL_WARN_ON_USE (ftello, "ftello is unportable - " - "use gnulib module ftello for portability"); -# endif -#endif - -#ifdef _GL_FTELL_WARN -# undef _GL_FTELL_WARN -/* Here, either ftell is undefined (but C89 guarantees that it is - declared), or it is defined as rpl_ftell (declared above). */ -_GL_WARN_ON_USE (ftell, "ftell cannot handle files larger than 4 GB " - "on 32-bit platforms - " - "use ftello function for handling of large files"); -#endif - - -#if @GNULIB_FWRITE@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fwrite -# define fwrite rpl_fwrite -# endif -_GL_FUNCDECL_RPL (fwrite, size_t, - (const void *ptr, size_t s, size_t n, FILE *stream) - _GL_ARG_NONNULL ((1, 4))); -_GL_CXXALIAS_RPL (fwrite, size_t, - (const void *ptr, size_t s, size_t n, FILE *stream)); -# else -_GL_CXXALIAS_SYS (fwrite, size_t, - (const void *ptr, size_t s, size_t n, FILE *stream)); -# endif -_GL_CXXALIASWARN (fwrite); -#endif - -#if @GNULIB_GETDELIM@ -/* Read input, up to (and including) the next occurrence of DELIMITER, from - STREAM, store it in *LINEPTR (and NUL-terminate it). - *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE - bytes of space. It is realloc'd as necessary. - Return the number of bytes read and stored at *LINEPTR (not including the - NUL terminator), or -1 on error or EOF. */ -# if @REPLACE_GETDELIM@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef getdelim -# define getdelim rpl_getdelim -# endif -_GL_FUNCDECL_RPL (getdelim, ssize_t, - (char **lineptr, size_t *linesize, int delimiter, - FILE *stream) - _GL_ARG_NONNULL ((1, 2, 4))); -_GL_CXXALIAS_RPL (getdelim, ssize_t, - (char **lineptr, size_t *linesize, int delimiter, - FILE *stream)); -# else -# if !@HAVE_DECL_GETDELIM@ -_GL_FUNCDECL_SYS (getdelim, ssize_t, - (char **lineptr, size_t *linesize, int delimiter, - FILE *stream) - _GL_ARG_NONNULL ((1, 2, 4))); -# endif -_GL_CXXALIAS_SYS (getdelim, ssize_t, - (char **lineptr, size_t *linesize, int delimiter, - FILE *stream)); -# endif -_GL_CXXALIASWARN (getdelim); -#elif defined GNULIB_POSIXCHECK -# undef getdelim -# if HAVE_RAW_DECL_GETDELIM -_GL_WARN_ON_USE (getdelim, "getdelim is unportable - " - "use gnulib module getdelim for portability"); -# endif -#endif - -#if @GNULIB_GETLINE@ -/* Read a line, up to (and including) the next newline, from STREAM, store it - in *LINEPTR (and NUL-terminate it). - *LINEPTR is a pointer returned from malloc (or NULL), pointing to *LINESIZE - bytes of space. It is realloc'd as necessary. - Return the number of bytes read and stored at *LINEPTR (not including the - NUL terminator), or -1 on error or EOF. */ -# if @REPLACE_GETLINE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef getline -# define getline rpl_getline -# endif -_GL_FUNCDECL_RPL (getline, ssize_t, - (char **lineptr, size_t *linesize, FILE *stream) - _GL_ARG_NONNULL ((1, 2, 3))); -_GL_CXXALIAS_RPL (getline, ssize_t, - (char **lineptr, size_t *linesize, FILE *stream)); -# else -# if !@HAVE_DECL_GETLINE@ -_GL_FUNCDECL_SYS (getline, ssize_t, - (char **lineptr, size_t *linesize, FILE *stream) - _GL_ARG_NONNULL ((1, 2, 3))); -# endif -_GL_CXXALIAS_SYS (getline, ssize_t, - (char **lineptr, size_t *linesize, FILE *stream)); -# endif -# if @HAVE_DECL_GETLINE@ -_GL_CXXALIASWARN (getline); -# endif -#elif defined GNULIB_POSIXCHECK -# undef getline -# if HAVE_RAW_DECL_GETLINE -_GL_WARN_ON_USE (getline, "getline is unportable - " - "use gnulib module getline for portability"); -# endif -#endif - -#if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@ -struct obstack; -/* Grow an obstack with formatted output. Return the number of - bytes added to OBS. No trailing nul byte is added, and the - object should be closed with obstack_finish before use. Upon - memory allocation error, call obstack_alloc_failed_handler. Upon - other error, return -1. */ -# if @REPLACE_OBSTACK_PRINTF@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define obstack_printf rpl_obstack_printf -# endif -_GL_FUNCDECL_RPL (obstack_printf, int, - (struct obstack *obs, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (obstack_printf, int, - (struct obstack *obs, const char *format, ...)); -# else -# if !@HAVE_DECL_OBSTACK_PRINTF@ -_GL_FUNCDECL_SYS (obstack_printf, int, - (struct obstack *obs, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (obstack_printf, int, - (struct obstack *obs, const char *format, ...)); -# endif -_GL_CXXALIASWARN (obstack_printf); -# if @REPLACE_OBSTACK_PRINTF@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define obstack_vprintf rpl_obstack_vprintf -# endif -_GL_FUNCDECL_RPL (obstack_vprintf, int, - (struct obstack *obs, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (obstack_vprintf, int, - (struct obstack *obs, const char *format, va_list args)); -# else -# if !@HAVE_DECL_OBSTACK_PRINTF@ -_GL_FUNCDECL_SYS (obstack_vprintf, int, - (struct obstack *obs, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (obstack_vprintf, int, - (struct obstack *obs, const char *format, va_list args)); -# endif -_GL_CXXALIASWARN (obstack_vprintf); -#endif - -#if @GNULIB_PERROR@ -/* Print a message to standard error, describing the value of ERRNO, - (if STRING is not NULL and not empty) prefixed with STRING and ": ", - and terminated with a newline. */ -# if @REPLACE_PERROR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define perror rpl_perror -# endif -_GL_FUNCDECL_RPL (perror, void, (const char *string)); -_GL_CXXALIAS_RPL (perror, void, (const char *string)); -# else -_GL_CXXALIAS_SYS (perror, void, (const char *string)); -# endif -_GL_CXXALIASWARN (perror); -#elif defined GNULIB_POSIXCHECK -# undef perror -/* Assume perror is always declared. */ -_GL_WARN_ON_USE (perror, "perror is not always POSIX compliant - " - "use gnulib module perror for portability"); -#endif - -#if @GNULIB_POPEN@ -# if @REPLACE_POPEN@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef popen -# define popen rpl_popen -# endif -_GL_FUNCDECL_RPL (popen, FILE *, (const char *cmd, const char *mode) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (popen, FILE *, (const char *cmd, const char *mode)); -# else -_GL_CXXALIAS_SYS (popen, FILE *, (const char *cmd, const char *mode)); -# endif -_GL_CXXALIASWARN (popen); -#elif defined GNULIB_POSIXCHECK -# undef popen -# if HAVE_RAW_DECL_POPEN -_GL_WARN_ON_USE (popen, "popen is buggy on some platforms - " - "use gnulib module popen or pipe for more portability"); -# endif -#endif - -#if @GNULIB_PRINTF_POSIX@ || @GNULIB_PRINTF@ -# if (@GNULIB_PRINTF_POSIX@ && @REPLACE_PRINTF@) \ - || (@GNULIB_PRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) -# if defined __GNUC__ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -/* Don't break __attribute__((format(printf,M,N))). */ -# define printf __printf__ -# endif -_GL_FUNCDECL_RPL_1 (__printf__, int, - (const char *format, ...) - __asm__ (@ASM_SYMBOL_PREFIX@ - _GL_STDIO_MACROEXPAND_AND_STRINGIZE(rpl_printf)) - __attribute__ ((__format__ (__printf__, 1, 2))) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL_1 (printf, __printf__, int, (const char *format, ...)); -# else -_GL_FUNCDECL_RPL (printf, int, - (const char *format, ...) - __attribute__ ((__format__ (__printf__, 1, 2))) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (printf, int, (const char *format, ...)); -# endif -# define GNULIB_overrides_printf 1 -# else -_GL_CXXALIAS_SYS (printf, int, (const char *format, ...)); -# endif -_GL_CXXALIASWARN (printf); -#endif -#if !@GNULIB_PRINTF_POSIX@ && defined GNULIB_POSIXCHECK -# if !GNULIB_overrides_printf -# undef printf -# endif -/* Assume printf is always declared. */ -_GL_WARN_ON_USE (printf, "printf is not always POSIX compliant - " - "use gnulib module printf-posix for portable " - "POSIX compliance"); -#endif - -#if @GNULIB_PUTC@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef putc -# define putc rpl_fputc -# endif -_GL_FUNCDECL_RPL (fputc, int, (int c, FILE *stream) _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL_1 (putc, rpl_fputc, int, (int c, FILE *stream)); -# else -_GL_CXXALIAS_SYS (putc, int, (int c, FILE *stream)); -# endif -_GL_CXXALIASWARN (putc); -#endif - -#if @GNULIB_PUTCHAR@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef putchar -# define putchar rpl_putchar -# endif -_GL_FUNCDECL_RPL (putchar, int, (int c)); -_GL_CXXALIAS_RPL (putchar, int, (int c)); -# else -_GL_CXXALIAS_SYS (putchar, int, (int c)); -# endif -_GL_CXXALIASWARN (putchar); -#endif - -#if @GNULIB_PUTS@ -# if @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef puts -# define puts rpl_puts -# endif -_GL_FUNCDECL_RPL (puts, int, (const char *string) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (puts, int, (const char *string)); -# else -_GL_CXXALIAS_SYS (puts, int, (const char *string)); -# endif -_GL_CXXALIASWARN (puts); -#endif - -#if @GNULIB_REMOVE@ -# if @REPLACE_REMOVE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef remove -# define remove rpl_remove -# endif -_GL_FUNCDECL_RPL (remove, int, (const char *name) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (remove, int, (const char *name)); -# else -_GL_CXXALIAS_SYS (remove, int, (const char *name)); -# endif -_GL_CXXALIASWARN (remove); -#elif defined GNULIB_POSIXCHECK -# undef remove -/* Assume remove is always declared. */ -_GL_WARN_ON_USE (remove, "remove cannot handle directories on some platforms - " - "use gnulib module remove for more portability"); -#endif - -#if @GNULIB_RENAME@ -# if @REPLACE_RENAME@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef rename -# define rename rpl_rename -# endif -_GL_FUNCDECL_RPL (rename, int, - (const char *old_filename, const char *new_filename) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (rename, int, - (const char *old_filename, const char *new_filename)); -# else -_GL_CXXALIAS_SYS (rename, int, - (const char *old_filename, const char *new_filename)); -# endif -_GL_CXXALIASWARN (rename); -#elif defined GNULIB_POSIXCHECK -# undef rename -/* Assume rename is always declared. */ -_GL_WARN_ON_USE (rename, "rename is buggy on some platforms - " - "use gnulib module rename for more portability"); -#endif - -#if @GNULIB_RENAMEAT@ -# if @REPLACE_RENAMEAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef renameat -# define renameat rpl_renameat -# endif -_GL_FUNCDECL_RPL (renameat, int, - (int fd1, char const *file1, int fd2, char const *file2) - _GL_ARG_NONNULL ((2, 4))); -_GL_CXXALIAS_RPL (renameat, int, - (int fd1, char const *file1, int fd2, char const *file2)); -# else -# if !@HAVE_RENAMEAT@ -_GL_FUNCDECL_SYS (renameat, int, - (int fd1, char const *file1, int fd2, char const *file2) - _GL_ARG_NONNULL ((2, 4))); -# endif -_GL_CXXALIAS_SYS (renameat, int, - (int fd1, char const *file1, int fd2, char const *file2)); -# endif -_GL_CXXALIASWARN (renameat); -#elif defined GNULIB_POSIXCHECK -# undef renameat -# if HAVE_RAW_DECL_RENAMEAT -_GL_WARN_ON_USE (renameat, "renameat is not portable - " - "use gnulib module renameat for portability"); -# endif -#endif - -#if @GNULIB_SNPRINTF@ -# if @REPLACE_SNPRINTF@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define snprintf rpl_snprintf -# endif -_GL_FUNCDECL_RPL (snprintf, int, - (char *str, size_t size, const char *format, ...) - __attribute__ ((__format__ (__printf__, 3, 4))) - _GL_ARG_NONNULL ((3))); -_GL_CXXALIAS_RPL (snprintf, int, - (char *str, size_t size, const char *format, ...)); -# else -# if !@HAVE_DECL_SNPRINTF@ -_GL_FUNCDECL_SYS (snprintf, int, - (char *str, size_t size, const char *format, ...) - __attribute__ ((__format__ (__printf__, 3, 4))) - _GL_ARG_NONNULL ((3))); -# endif -_GL_CXXALIAS_SYS (snprintf, int, - (char *str, size_t size, const char *format, ...)); -# endif -_GL_CXXALIASWARN (snprintf); -#elif defined GNULIB_POSIXCHECK -# undef snprintf -# if HAVE_RAW_DECL_SNPRINTF -_GL_WARN_ON_USE (snprintf, "snprintf is unportable - " - "use gnulib module snprintf for portability"); -# endif -#endif - -/* Some people would argue that sprintf should be handled like gets - (for example, OpenBSD issues a link warning for both functions), - since both can cause security holes due to buffer overruns. - However, we believe that sprintf can be used safely, and is more - efficient than snprintf in those safe cases; and as proof of our - belief, we use sprintf in several gnulib modules. So this header - intentionally avoids adding a warning to sprintf except when - GNULIB_POSIXCHECK is defined. */ - -#if @GNULIB_SPRINTF_POSIX@ -# if @REPLACE_SPRINTF@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define sprintf rpl_sprintf -# endif -_GL_FUNCDECL_RPL (sprintf, int, (char *str, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (sprintf, int, (char *str, const char *format, ...)); -# else -_GL_CXXALIAS_SYS (sprintf, int, (char *str, const char *format, ...)); -# endif -_GL_CXXALIASWARN (sprintf); -#elif defined GNULIB_POSIXCHECK -# undef sprintf -/* Assume sprintf is always declared. */ -_GL_WARN_ON_USE (sprintf, "sprintf is not always POSIX compliant - " - "use gnulib module sprintf-posix for portable " - "POSIX compliance"); -#endif - -#if @GNULIB_TMPFILE@ -# if @REPLACE_TMPFILE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define tmpfile rpl_tmpfile -# endif -_GL_FUNCDECL_RPL (tmpfile, FILE *, (void)); -_GL_CXXALIAS_RPL (tmpfile, FILE *, (void)); -# else -_GL_CXXALIAS_SYS (tmpfile, FILE *, (void)); -# endif -_GL_CXXALIASWARN (tmpfile); -#elif defined GNULIB_POSIXCHECK -# undef tmpfile -# if HAVE_RAW_DECL_TMPFILE -_GL_WARN_ON_USE (tmpfile, "tmpfile is not usable on mingw - " - "use gnulib module tmpfile for portability"); -# endif -#endif - -#if @GNULIB_VASPRINTF@ -/* Write formatted output to a string dynamically allocated with malloc(). - If the memory allocation succeeds, store the address of the string in - *RESULT and return the number of resulting bytes, excluding the trailing - NUL. Upon memory allocation error, or some other error, return -1. */ -# if @REPLACE_VASPRINTF@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define asprintf rpl_asprintf -# endif -_GL_FUNCDECL_RPL (asprintf, int, - (char **result, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (asprintf, int, - (char **result, const char *format, ...)); -# else -# if !@HAVE_VASPRINTF@ -_GL_FUNCDECL_SYS (asprintf, int, - (char **result, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (asprintf, int, - (char **result, const char *format, ...)); -# endif -_GL_CXXALIASWARN (asprintf); -# if @REPLACE_VASPRINTF@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define vasprintf rpl_vasprintf -# endif -_GL_FUNCDECL_RPL (vasprintf, int, - (char **result, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (vasprintf, int, - (char **result, const char *format, va_list args)); -# else -# if !@HAVE_VASPRINTF@ -_GL_FUNCDECL_SYS (vasprintf, int, - (char **result, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (vasprintf, int, - (char **result, const char *format, va_list args)); -# endif -_GL_CXXALIASWARN (vasprintf); -#endif - -#if @GNULIB_VDPRINTF@ -# if @REPLACE_VDPRINTF@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define vdprintf rpl_vdprintf -# endif -_GL_FUNCDECL_RPL (vdprintf, int, (int fd, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (vdprintf, int, (int fd, const char *format, va_list args)); -# else -# if !@HAVE_VDPRINTF@ -_GL_FUNCDECL_SYS (vdprintf, int, (int fd, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) - _GL_ARG_NONNULL ((2))); -# endif -/* Need to cast, because on Solaris, the third parameter will likely be - __va_list args. */ -_GL_CXXALIAS_SYS_CAST (vdprintf, int, - (int fd, const char *format, va_list args)); -# endif -_GL_CXXALIASWARN (vdprintf); -#elif defined GNULIB_POSIXCHECK -# undef vdprintf -# if HAVE_RAW_DECL_VDPRINTF -_GL_WARN_ON_USE (vdprintf, "vdprintf is unportable - " - "use gnulib module vdprintf for portability"); -# endif -#endif - -#if @GNULIB_VFPRINTF_POSIX@ || @GNULIB_VFPRINTF@ -# if (@GNULIB_VFPRINTF_POSIX@ && @REPLACE_VFPRINTF@) \ - || (@GNULIB_VFPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define vfprintf rpl_vfprintf -# endif -# define GNULIB_overrides_vfprintf 1 -_GL_FUNCDECL_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (vfprintf, int, (FILE *fp, const char *format, va_list args)); -# else -/* Need to cast, because on Solaris, the third parameter is - __va_list args - and GCC's fixincludes did not change this to __gnuc_va_list. */ -_GL_CXXALIAS_SYS_CAST (vfprintf, int, - (FILE *fp, const char *format, va_list args)); -# endif -_GL_CXXALIASWARN (vfprintf); -#endif -#if !@GNULIB_VFPRINTF_POSIX@ && defined GNULIB_POSIXCHECK -# if !GNULIB_overrides_vfprintf -# undef vfprintf -# endif -/* Assume vfprintf is always declared. */ -_GL_WARN_ON_USE (vfprintf, "vfprintf is not always POSIX compliant - " - "use gnulib module vfprintf-posix for portable " - "POSIX compliance"); -#endif - -#if @GNULIB_VPRINTF_POSIX@ || @GNULIB_VPRINTF@ -# if (@GNULIB_VPRINTF_POSIX@ && @REPLACE_VPRINTF@) \ - || (@GNULIB_VPRINTF@ && @REPLACE_STDIO_WRITE_FUNCS@ && @GNULIB_STDIO_H_SIGPIPE@) -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define vprintf rpl_vprintf -# endif -# define GNULIB_overrides_vprintf 1 -_GL_FUNCDECL_RPL (vprintf, int, (const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 1, 0))) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (vprintf, int, (const char *format, va_list args)); -# else -/* Need to cast, because on Solaris, the second parameter is - __va_list args - and GCC's fixincludes did not change this to __gnuc_va_list. */ -_GL_CXXALIAS_SYS_CAST (vprintf, int, (const char *format, va_list args)); -# endif -_GL_CXXALIASWARN (vprintf); -#endif -#if !@GNULIB_VPRINTF_POSIX@ && defined GNULIB_POSIXCHECK -# if !GNULIB_overrides_vprintf -# undef vprintf -# endif -/* Assume vprintf is always declared. */ -_GL_WARN_ON_USE (vprintf, "vprintf is not always POSIX compliant - " - "use gnulib module vprintf-posix for portable " - "POSIX compliance"); -#endif - -#if @GNULIB_VSNPRINTF@ -# if @REPLACE_VSNPRINTF@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define vsnprintf rpl_vsnprintf -# endif -_GL_FUNCDECL_RPL (vsnprintf, int, - (char *str, size_t size, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 3, 0))) - _GL_ARG_NONNULL ((3))); -_GL_CXXALIAS_RPL (vsnprintf, int, - (char *str, size_t size, const char *format, va_list args)); -# else -# if !@HAVE_DECL_VSNPRINTF@ -_GL_FUNCDECL_SYS (vsnprintf, int, - (char *str, size_t size, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 3, 0))) - _GL_ARG_NONNULL ((3))); -# endif -_GL_CXXALIAS_SYS (vsnprintf, int, - (char *str, size_t size, const char *format, va_list args)); -# endif -_GL_CXXALIASWARN (vsnprintf); -#elif defined GNULIB_POSIXCHECK -# undef vsnprintf -# if HAVE_RAW_DECL_VSNPRINTF -_GL_WARN_ON_USE (vsnprintf, "vsnprintf is unportable - " - "use gnulib module vsnprintf for portability"); -# endif -#endif - -#if @GNULIB_VSPRINTF_POSIX@ -# if @REPLACE_VSPRINTF@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define vsprintf rpl_vsprintf -# endif -_GL_FUNCDECL_RPL (vsprintf, int, - (char *str, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 2, 0))) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (vsprintf, int, - (char *str, const char *format, va_list args)); -# else -/* Need to cast, because on Solaris, the third parameter is - __va_list args - and GCC's fixincludes did not change this to __gnuc_va_list. */ -_GL_CXXALIAS_SYS_CAST (vsprintf, int, - (char *str, const char *format, va_list args)); -# endif -_GL_CXXALIASWARN (vsprintf); -#elif defined GNULIB_POSIXCHECK -# undef vsprintf -/* Assume vsprintf is always declared. */ -_GL_WARN_ON_USE (vsprintf, "vsprintf is not always POSIX compliant - " - "use gnulib module vsprintf-posix for portable " - "POSIX compliance"); -#endif - - -#endif /* _GL_STDIO_H */ -#endif /* _GL_STDIO_H */ -#endif diff --git a/grub-core/gnulib/stdlib.in.h b/grub-core/gnulib/stdlib.in.h deleted file mode 100644 index f4309ed73..000000000 --- a/grub-core/gnulib/stdlib.in.h +++ /dev/null @@ -1,715 +0,0 @@ -/* A GNU-like . - - Copyright (C) 1995, 2001-2004, 2006-2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -#if defined __need_malloc_and_calloc -/* Special invocation convention inside glibc header files. */ - -#@INCLUDE_NEXT@ @NEXT_STDLIB_H@ - -#else -/* Normal invocation convention. */ - -#ifndef _GL_STDLIB_H - -/* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_STDLIB_H@ - -#ifndef _GL_STDLIB_H -#define _GL_STDLIB_H - -/* NetBSD 5.0 mis-defines NULL. */ -#include - -/* MirBSD 10 defines WEXITSTATUS in , not in . */ -#ifndef WEXITSTATUS -# include -#endif - -/* Solaris declares getloadavg() in . */ -#if (@GNULIB_GETLOADAVG@ || defined GNULIB_POSIXCHECK) && @HAVE_SYS_LOADAVG_H@ -# include -#endif - -/* OSF/1 5.1 declares 'struct random_data' in , which is included - from if _REENTRANT is defined. Include it always. */ -#if @HAVE_RANDOM_H@ -# include -#endif - -#if !@HAVE_STRUCT_RANDOM_DATA@ || (@GNULIB_RANDOM_R@ && !@HAVE_RANDOM_R@) \ - || defined GNULIB_POSIXCHECK -# include -#endif - -#if !@HAVE_STRUCT_RANDOM_DATA@ -struct random_data -{ - int32_t *fptr; /* Front pointer. */ - int32_t *rptr; /* Rear pointer. */ - int32_t *state; /* Array of state values. */ - int rand_type; /* Type of random number generator. */ - int rand_deg; /* Degree of random number generator. */ - int rand_sep; /* Distance between front and rear. */ - int32_t *end_ptr; /* Pointer behind state table. */ -}; -#endif - -#if (@GNULIB_MKSTEMP@ || @GNULIB_GETSUBOPT@ || defined GNULIB_POSIXCHECK) && ! defined __GLIBC__ && !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) -/* On MacOS X 10.3, only declares mkstemp. */ -/* On Cygwin 1.7.1, only declares getsubopt. */ -/* But avoid namespace pollution on glibc systems and native Windows. */ -# include -#endif - -#ifndef __attribute__ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) -# define __attribute__(Spec) /* empty */ -# endif -#endif - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - - -/* Some systems do not define EXIT_*, despite otherwise supporting C89. */ -#ifndef EXIT_SUCCESS -# define EXIT_SUCCESS 0 -#endif -/* Tandem/NSK and other platforms that define EXIT_FAILURE as -1 interfere - with proper operation of xargs. */ -#ifndef EXIT_FAILURE -# define EXIT_FAILURE 1 -#elif EXIT_FAILURE != 1 -# undef EXIT_FAILURE -# define EXIT_FAILURE 1 -#endif - - -#if @GNULIB__EXIT@ -/* Terminate the current process with the given return code, without running - the 'atexit' handlers. */ -# if !@HAVE__EXIT@ -_GL_FUNCDECL_SYS (_Exit, void, (int status) __attribute__ ((__noreturn__))); -# endif -_GL_CXXALIAS_SYS (_Exit, void, (int status)); -_GL_CXXALIASWARN (_Exit); -#elif defined GNULIB_POSIXCHECK -# undef _Exit -# if HAVE_RAW_DECL__EXIT -_GL_WARN_ON_USE (_Exit, "_Exit is unportable - " - "use gnulib module _Exit for portability"); -# endif -#endif - - -#if @GNULIB_ATOLL@ -/* Parse a signed decimal integer. - Returns the value of the integer. Errors are not detected. */ -# if !@HAVE_ATOLL@ -_GL_FUNCDECL_SYS (atoll, long long, (const char *string) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (atoll, long long, (const char *string)); -_GL_CXXALIASWARN (atoll); -#elif defined GNULIB_POSIXCHECK -# undef atoll -# if HAVE_RAW_DECL_ATOLL -_GL_WARN_ON_USE (atoll, "atoll is unportable - " - "use gnulib module atoll for portability"); -# endif -#endif - -#if @GNULIB_CALLOC_POSIX@ -# if @REPLACE_CALLOC@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef calloc -# define calloc rpl_calloc -# endif -_GL_FUNCDECL_RPL (calloc, void *, (size_t nmemb, size_t size)); -_GL_CXXALIAS_RPL (calloc, void *, (size_t nmemb, size_t size)); -# else -_GL_CXXALIAS_SYS (calloc, void *, (size_t nmemb, size_t size)); -# endif -_GL_CXXALIASWARN (calloc); -#elif defined GNULIB_POSIXCHECK -# undef calloc -/* Assume calloc is always declared. */ -_GL_WARN_ON_USE (calloc, "calloc is not POSIX compliant everywhere - " - "use gnulib module calloc-posix for portability"); -#endif - -#if @GNULIB_CANONICALIZE_FILE_NAME@ -# if @REPLACE_CANONICALIZE_FILE_NAME@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define canonicalize_file_name rpl_canonicalize_file_name -# endif -_GL_FUNCDECL_RPL (canonicalize_file_name, char *, (const char *name) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (canonicalize_file_name, char *, (const char *name)); -# else -# if !@HAVE_CANONICALIZE_FILE_NAME@ -_GL_FUNCDECL_SYS (canonicalize_file_name, char *, (const char *name) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (canonicalize_file_name, char *, (const char *name)); -# endif -_GL_CXXALIASWARN (canonicalize_file_name); -#elif defined GNULIB_POSIXCHECK -# undef canonicalize_file_name -# if HAVE_RAW_DECL_CANONICALIZE_FILE_NAME -_GL_WARN_ON_USE (canonicalize_file_name, "canonicalize_file_name is unportable - " - "use gnulib module canonicalize-lgpl for portability"); -# endif -#endif - -#if @GNULIB_GETLOADAVG@ -/* Store max(NELEM,3) load average numbers in LOADAVG[]. - The three numbers are the load average of the last 1 minute, the last 5 - minutes, and the last 15 minutes, respectively. - LOADAVG is an array of NELEM numbers. */ -# if !@HAVE_DECL_GETLOADAVG@ -_GL_FUNCDECL_SYS (getloadavg, int, (double loadavg[], int nelem) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (getloadavg, int, (double loadavg[], int nelem)); -_GL_CXXALIASWARN (getloadavg); -#elif defined GNULIB_POSIXCHECK -# undef getloadavg -# if HAVE_RAW_DECL_GETLOADAVG -_GL_WARN_ON_USE (getloadavg, "getloadavg is not portable - " - "use gnulib module getloadavg for portability"); -# endif -#endif - -#if @GNULIB_GETSUBOPT@ -/* Assuming *OPTIONP is a comma separated list of elements of the form - "token" or "token=value", getsubopt parses the first of these elements. - If the first element refers to a "token" that is member of the given - NULL-terminated array of tokens: - - It replaces the comma with a NUL byte, updates *OPTIONP to point past - the first option and the comma, sets *VALUEP to the value of the - element (or NULL if it doesn't contain an "=" sign), - - It returns the index of the "token" in the given array of tokens. - Otherwise it returns -1, and *OPTIONP and *VALUEP are undefined. - For more details see the POSIX:2001 specification. - http://www.opengroup.org/susv3xsh/getsubopt.html */ -# if !@HAVE_GETSUBOPT@ -_GL_FUNCDECL_SYS (getsubopt, int, - (char **optionp, char *const *tokens, char **valuep) - _GL_ARG_NONNULL ((1, 2, 3))); -# endif -_GL_CXXALIAS_SYS (getsubopt, int, - (char **optionp, char *const *tokens, char **valuep)); -_GL_CXXALIASWARN (getsubopt); -#elif defined GNULIB_POSIXCHECK -# undef getsubopt -# if HAVE_RAW_DECL_GETSUBOPT -_GL_WARN_ON_USE (getsubopt, "getsubopt is unportable - " - "use gnulib module getsubopt for portability"); -# endif -#endif - -#if @GNULIB_GRANTPT@ -/* Change the ownership and access permission of the slave side of the - pseudo-terminal whose master side is specified by FD. */ -# if !@HAVE_GRANTPT@ -_GL_FUNCDECL_SYS (grantpt, int, (int fd)); -# endif -_GL_CXXALIAS_SYS (grantpt, int, (int fd)); -_GL_CXXALIASWARN (grantpt); -#elif defined GNULIB_POSIXCHECK -# undef grantpt -# if HAVE_RAW_DECL_GRANTPT -_GL_WARN_ON_USE (ptsname, "grantpt is not portable - " - "use gnulib module grantpt for portability"); -# endif -#endif - -#if @GNULIB_MALLOC_POSIX@ -# if @REPLACE_MALLOC@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef malloc -# define malloc rpl_malloc -# endif -_GL_FUNCDECL_RPL (malloc, void *, (size_t size)); -_GL_CXXALIAS_RPL (malloc, void *, (size_t size)); -# else -_GL_CXXALIAS_SYS (malloc, void *, (size_t size)); -# endif -_GL_CXXALIASWARN (malloc); -#elif defined GNULIB_POSIXCHECK -# undef malloc -/* Assume malloc is always declared. */ -_GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - " - "use gnulib module malloc-posix for portability"); -#endif - -#if @GNULIB_MKDTEMP@ -/* Create a unique temporary directory from TEMPLATE. - The last six characters of TEMPLATE must be "XXXXXX"; - they are replaced with a string that makes the directory name unique. - Returns TEMPLATE, or a null pointer if it cannot get a unique name. - The directory is created mode 700. */ -# if !@HAVE_MKDTEMP@ -_GL_FUNCDECL_SYS (mkdtemp, char *, (char * /*template*/) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (mkdtemp, char *, (char * /*template*/)); -_GL_CXXALIASWARN (mkdtemp); -#elif defined GNULIB_POSIXCHECK -# undef mkdtemp -# if HAVE_RAW_DECL_MKDTEMP -_GL_WARN_ON_USE (mkdtemp, "mkdtemp is unportable - " - "use gnulib module mkdtemp for portability"); -# endif -#endif - -#if @GNULIB_MKOSTEMP@ -/* Create a unique temporary file from TEMPLATE. - The last six characters of TEMPLATE must be "XXXXXX"; - they are replaced with a string that makes the file name unique. - The flags are a bitmask, possibly including O_CLOEXEC (defined in ) - and O_TEXT, O_BINARY (defined in "binary-io.h"). - The file is then created, with the specified flags, ensuring it didn't exist - before. - The file is created read-write (mask at least 0600 & ~umask), but it may be - world-readable and world-writable (mask 0666 & ~umask), depending on the - implementation. - Returns the open file descriptor if successful, otherwise -1 and errno - set. */ -# if !@HAVE_MKOSTEMP@ -_GL_FUNCDECL_SYS (mkostemp, int, (char * /*template*/, int /*flags*/) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (mkostemp, int, (char * /*template*/, int /*flags*/)); -_GL_CXXALIASWARN (mkostemp); -#elif defined GNULIB_POSIXCHECK -# undef mkostemp -# if HAVE_RAW_DECL_MKOSTEMP -_GL_WARN_ON_USE (mkostemp, "mkostemp is unportable - " - "use gnulib module mkostemp for portability"); -# endif -#endif - -#if @GNULIB_MKOSTEMPS@ -/* Create a unique temporary file from TEMPLATE. - The last six characters of TEMPLATE before a suffix of length - SUFFIXLEN must be "XXXXXX"; - they are replaced with a string that makes the file name unique. - The flags are a bitmask, possibly including O_CLOEXEC (defined in ) - and O_TEXT, O_BINARY (defined in "binary-io.h"). - The file is then created, with the specified flags, ensuring it didn't exist - before. - The file is created read-write (mask at least 0600 & ~umask), but it may be - world-readable and world-writable (mask 0666 & ~umask), depending on the - implementation. - Returns the open file descriptor if successful, otherwise -1 and errno - set. */ -# if !@HAVE_MKOSTEMPS@ -_GL_FUNCDECL_SYS (mkostemps, int, - (char * /*template*/, int /*suffixlen*/, int /*flags*/) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (mkostemps, int, - (char * /*template*/, int /*suffixlen*/, int /*flags*/)); -_GL_CXXALIASWARN (mkostemps); -#elif defined GNULIB_POSIXCHECK -# undef mkostemps -# if HAVE_RAW_DECL_MKOSTEMPS -_GL_WARN_ON_USE (mkostemps, "mkostemps is unportable - " - "use gnulib module mkostemps for portability"); -# endif -#endif - -#if @GNULIB_MKSTEMP@ -/* Create a unique temporary file from TEMPLATE. - The last six characters of TEMPLATE must be "XXXXXX"; - they are replaced with a string that makes the file name unique. - The file is then created, ensuring it didn't exist before. - The file is created read-write (mask at least 0600 & ~umask), but it may be - world-readable and world-writable (mask 0666 & ~umask), depending on the - implementation. - Returns the open file descriptor if successful, otherwise -1 and errno - set. */ -# if @REPLACE_MKSTEMP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define mkstemp rpl_mkstemp -# endif -_GL_FUNCDECL_RPL (mkstemp, int, (char * /*template*/) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (mkstemp, int, (char * /*template*/)); -# else -# if ! @HAVE_MKSTEMP@ -_GL_FUNCDECL_SYS (mkstemp, int, (char * /*template*/) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (mkstemp, int, (char * /*template*/)); -# endif -_GL_CXXALIASWARN (mkstemp); -#elif defined GNULIB_POSIXCHECK -# undef mkstemp -# if HAVE_RAW_DECL_MKSTEMP -_GL_WARN_ON_USE (mkstemp, "mkstemp is unportable - " - "use gnulib module mkstemp for portability"); -# endif -#endif - -#if @GNULIB_MKSTEMPS@ -/* Create a unique temporary file from TEMPLATE. - The last six characters of TEMPLATE prior to a suffix of length - SUFFIXLEN must be "XXXXXX"; - they are replaced with a string that makes the file name unique. - The file is then created, ensuring it didn't exist before. - The file is created read-write (mask at least 0600 & ~umask), but it may be - world-readable and world-writable (mask 0666 & ~umask), depending on the - implementation. - Returns the open file descriptor if successful, otherwise -1 and errno - set. */ -# if !@HAVE_MKSTEMPS@ -_GL_FUNCDECL_SYS (mkstemps, int, (char * /*template*/, int /*suffixlen*/) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (mkstemps, int, (char * /*template*/, int /*suffixlen*/)); -_GL_CXXALIASWARN (mkstemps); -#elif defined GNULIB_POSIXCHECK -# undef mkstemps -# if HAVE_RAW_DECL_MKSTEMPS -_GL_WARN_ON_USE (mkstemps, "mkstemps is unportable - " - "use gnulib module mkstemps for portability"); -# endif -#endif - -#if @GNULIB_PTSNAME@ -/* Return the pathname of the pseudo-terminal slave associated with - the master FD is open on, or NULL on errors. */ -# if !@HAVE_PTSNAME@ -_GL_FUNCDECL_SYS (ptsname, char *, (int fd)); -# endif -_GL_CXXALIAS_SYS (ptsname, char *, (int fd)); -_GL_CXXALIASWARN (ptsname); -#elif defined GNULIB_POSIXCHECK -# undef ptsname -# if HAVE_RAW_DECL_PTSNAME -_GL_WARN_ON_USE (ptsname, "ptsname is not portable - " - "use gnulib module ptsname for portability"); -# endif -#endif - -#if @GNULIB_PUTENV@ -# if @REPLACE_PUTENV@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef putenv -# define putenv rpl_putenv -# endif -_GL_FUNCDECL_RPL (putenv, int, (char *string) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (putenv, int, (char *string)); -# else -_GL_CXXALIAS_SYS (putenv, int, (char *string)); -# endif -_GL_CXXALIASWARN (putenv); -#endif - - -#if @GNULIB_RANDOM_R@ -# if !@HAVE_RANDOM_R@ -# ifndef RAND_MAX -# define RAND_MAX 2147483647 -# endif -# endif -#endif - -#if @GNULIB_RANDOM_R@ -# if !@HAVE_RANDOM_R@ -_GL_FUNCDECL_SYS (random_r, int, (struct random_data *buf, int32_t *result) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (random_r, int, (struct random_data *buf, int32_t *result)); -_GL_CXXALIASWARN (random_r); -#elif defined GNULIB_POSIXCHECK -# undef random_r -# if HAVE_RAW_DECL_RANDOM_R -_GL_WARN_ON_USE (random_r, "random_r is unportable - " - "use gnulib module random_r for portability"); -# endif -#endif - -#if @GNULIB_RANDOM_R@ -# if !@HAVE_RANDOM_R@ -_GL_FUNCDECL_SYS (srandom_r, int, - (unsigned int seed, struct random_data *rand_state) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (srandom_r, int, - (unsigned int seed, struct random_data *rand_state)); -_GL_CXXALIASWARN (srandom_r); -#elif defined GNULIB_POSIXCHECK -# undef srandom_r -# if HAVE_RAW_DECL_SRANDOM_R -_GL_WARN_ON_USE (srandom_r, "srandom_r is unportable - " - "use gnulib module random_r for portability"); -# endif -#endif - -#if @GNULIB_RANDOM_R@ -# if !@HAVE_RANDOM_R@ -_GL_FUNCDECL_SYS (initstate_r, int, - (unsigned int seed, char *buf, size_t buf_size, - struct random_data *rand_state) - _GL_ARG_NONNULL ((2, 4))); -# endif -_GL_CXXALIAS_SYS (initstate_r, int, - (unsigned int seed, char *buf, size_t buf_size, - struct random_data *rand_state)); -_GL_CXXALIASWARN (initstate_r); -#elif defined GNULIB_POSIXCHECK -# undef initstate_r -# if HAVE_RAW_DECL_INITSTATE_R -_GL_WARN_ON_USE (initstate_r, "initstate_r is unportable - " - "use gnulib module random_r for portability"); -# endif -#endif - -#if @GNULIB_RANDOM_R@ -# if !@HAVE_RANDOM_R@ -_GL_FUNCDECL_SYS (setstate_r, int, - (char *arg_state, struct random_data *rand_state) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (setstate_r, int, - (char *arg_state, struct random_data *rand_state)); -_GL_CXXALIASWARN (setstate_r); -#elif defined GNULIB_POSIXCHECK -# undef setstate_r -# if HAVE_RAW_DECL_SETSTATE_R -_GL_WARN_ON_USE (setstate_r, "setstate_r is unportable - " - "use gnulib module random_r for portability"); -# endif -#endif - - -#if @GNULIB_REALLOC_POSIX@ -# if @REPLACE_REALLOC@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef realloc -# define realloc rpl_realloc -# endif -_GL_FUNCDECL_RPL (realloc, void *, (void *ptr, size_t size)); -_GL_CXXALIAS_RPL (realloc, void *, (void *ptr, size_t size)); -# else -_GL_CXXALIAS_SYS (realloc, void *, (void *ptr, size_t size)); -# endif -_GL_CXXALIASWARN (realloc); -#elif defined GNULIB_POSIXCHECK -# undef realloc -/* Assume realloc is always declared. */ -_GL_WARN_ON_USE (realloc, "realloc is not POSIX compliant everywhere - " - "use gnulib module realloc-posix for portability"); -#endif - -#if @GNULIB_REALPATH@ -# if @REPLACE_REALPATH@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define realpath rpl_realpath -# endif -_GL_FUNCDECL_RPL (realpath, char *, (const char *name, char *resolved) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (realpath, char *, (const char *name, char *resolved)); -# else -# if !@HAVE_REALPATH@ -_GL_FUNCDECL_SYS (realpath, char *, (const char *name, char *resolved) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (realpath, char *, (const char *name, char *resolved)); -# endif -_GL_CXXALIASWARN (realpath); -#elif defined GNULIB_POSIXCHECK -# undef realpath -# if HAVE_RAW_DECL_REALPATH -_GL_WARN_ON_USE (realpath, "realpath is unportable - use gnulib module " - "canonicalize or canonicalize-lgpl for portability"); -# endif -#endif - -#if @GNULIB_RPMATCH@ -/* Test a user response to a question. - Return 1 if it is affirmative, 0 if it is negative, or -1 if not clear. */ -# if !@HAVE_RPMATCH@ -_GL_FUNCDECL_SYS (rpmatch, int, (const char *response) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (rpmatch, int, (const char *response)); -_GL_CXXALIASWARN (rpmatch); -#elif defined GNULIB_POSIXCHECK -# undef rpmatch -# if HAVE_RAW_DECL_RPMATCH -_GL_WARN_ON_USE (rpmatch, "rpmatch is unportable - " - "use gnulib module rpmatch for portability"); -# endif -#endif - -#if @GNULIB_SETENV@ -/* Set NAME to VALUE in the environment. - If REPLACE is nonzero, overwrite an existing value. */ -# if @REPLACE_SETENV@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef setenv -# define setenv rpl_setenv -# endif -_GL_FUNCDECL_RPL (setenv, int, - (const char *name, const char *value, int replace) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (setenv, int, - (const char *name, const char *value, int replace)); -# else -# if !@HAVE_SETENV@ -_GL_FUNCDECL_SYS (setenv, int, - (const char *name, const char *value, int replace) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (setenv, int, - (const char *name, const char *value, int replace)); -# endif -_GL_CXXALIASWARN (setenv); -#elif defined GNULIB_POSIXCHECK -# undef setenv -# if HAVE_RAW_DECL_SETENV -_GL_WARN_ON_USE (setenv, "setenv is unportable - " - "use gnulib module setenv for portability"); -# endif -#endif - -#if @GNULIB_STRTOD@ - /* Parse a double from STRING, updating ENDP if appropriate. */ -# if @REPLACE_STRTOD@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define strtod rpl_strtod -# endif -_GL_FUNCDECL_RPL (strtod, double, (const char *str, char **endp) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (strtod, double, (const char *str, char **endp)); -# else -# if !@HAVE_STRTOD@ -_GL_FUNCDECL_SYS (strtod, double, (const char *str, char **endp) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (strtod, double, (const char *str, char **endp)); -# endif -_GL_CXXALIASWARN (strtod); -#elif defined GNULIB_POSIXCHECK -# undef strtod -# if HAVE_RAW_DECL_STRTOD -_GL_WARN_ON_USE (strtod, "strtod is unportable - " - "use gnulib module strtod for portability"); -# endif -#endif - -#if @GNULIB_STRTOLL@ -/* Parse a signed integer whose textual representation starts at STRING. - The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0, - it may be decimal or octal (with prefix "0") or hexadecimal (with prefix - "0x"). - If ENDPTR is not NULL, the address of the first byte after the integer is - stored in *ENDPTR. - Upon overflow, the return value is LLONG_MAX or LLONG_MIN, and errno is set - to ERANGE. */ -# if !@HAVE_STRTOLL@ -_GL_FUNCDECL_SYS (strtoll, long long, - (const char *string, char **endptr, int base) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (strtoll, long long, - (const char *string, char **endptr, int base)); -_GL_CXXALIASWARN (strtoll); -#elif defined GNULIB_POSIXCHECK -# undef strtoll -# if HAVE_RAW_DECL_STRTOLL -_GL_WARN_ON_USE (strtoll, "strtoll is unportable - " - "use gnulib module strtoll for portability"); -# endif -#endif - -#if @GNULIB_STRTOULL@ -/* Parse an unsigned integer whose textual representation starts at STRING. - The integer is expected to be in base BASE (2 <= BASE <= 36); if BASE == 0, - it may be decimal or octal (with prefix "0") or hexadecimal (with prefix - "0x"). - If ENDPTR is not NULL, the address of the first byte after the integer is - stored in *ENDPTR. - Upon overflow, the return value is ULLONG_MAX, and errno is set to - ERANGE. */ -# if !@HAVE_STRTOULL@ -_GL_FUNCDECL_SYS (strtoull, unsigned long long, - (const char *string, char **endptr, int base) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (strtoull, unsigned long long, - (const char *string, char **endptr, int base)); -_GL_CXXALIASWARN (strtoull); -#elif defined GNULIB_POSIXCHECK -# undef strtoull -# if HAVE_RAW_DECL_STRTOULL -_GL_WARN_ON_USE (strtoull, "strtoull is unportable - " - "use gnulib module strtoull for portability"); -# endif -#endif - -#if @GNULIB_UNLOCKPT@ -/* Unlock the slave side of the pseudo-terminal whose master side is specified - by FD, so that it can be opened. */ -# if !@HAVE_UNLOCKPT@ -_GL_FUNCDECL_SYS (unlockpt, int, (int fd)); -# endif -_GL_CXXALIAS_SYS (unlockpt, int, (int fd)); -_GL_CXXALIASWARN (unlockpt); -#elif defined GNULIB_POSIXCHECK -# undef unlockpt -# if HAVE_RAW_DECL_UNLOCKPT -_GL_WARN_ON_USE (unlockpt, "unlockpt is not portable - " - "use gnulib module unlockpt for portability"); -# endif -#endif - -#if @GNULIB_UNSETENV@ -/* Remove the variable NAME from the environment. */ -# if @REPLACE_UNSETENV@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef unsetenv -# define unsetenv rpl_unsetenv -# endif -_GL_FUNCDECL_RPL (unsetenv, int, (const char *name) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (unsetenv, int, (const char *name)); -# else -# if !@HAVE_UNSETENV@ -_GL_FUNCDECL_SYS (unsetenv, int, (const char *name) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (unsetenv, int, (const char *name)); -# endif -_GL_CXXALIASWARN (unsetenv); -#elif defined GNULIB_POSIXCHECK -# undef unsetenv -# if HAVE_RAW_DECL_UNSETENV -_GL_WARN_ON_USE (unsetenv, "unsetenv is unportable - " - "use gnulib module unsetenv for portability"); -# endif -#endif - - -#endif /* _GL_STDLIB_H */ -#endif /* _GL_STDLIB_H */ -#endif diff --git a/grub-core/gnulib/strcasecmp.c b/grub-core/gnulib/strcasecmp.c deleted file mode 100644 index 612c80fdc..000000000 --- a/grub-core/gnulib/strcasecmp.c +++ /dev/null @@ -1,63 +0,0 @@ -/* Case-insensitive string comparison function. - Copyright (C) 1998-1999, 2005-2007, 2009-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include - -#include -#include - -#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) - -/* Compare strings S1 and S2, ignoring case, returning less than, equal to or - greater than zero if S1 is lexicographically less than, equal to or greater - than S2. - Note: This function does not work with multibyte strings! */ - -int -strcasecmp (const char *s1, const char *s2) -{ - const unsigned char *p1 = (const unsigned char *) s1; - const unsigned char *p2 = (const unsigned char *) s2; - unsigned char c1, c2; - - if (p1 == p2) - return 0; - - do - { - c1 = TOLOWER (*p1); - c2 = TOLOWER (*p2); - - if (c1 == '\0') - break; - - ++p1; - ++p2; - } - while (c1 == c2); - - if (UCHAR_MAX <= INT_MAX) - return c1 - c2; - else - /* On machines where 'char' and 'int' are types of the same size, the - difference of two 'unsigned char' values - including the sign bit - - doesn't fit in an 'int'. */ - return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); -} diff --git a/grub-core/gnulib/strchrnul.c b/grub-core/gnulib/strchrnul.c deleted file mode 100644 index f834d3434..000000000 --- a/grub-core/gnulib/strchrnul.c +++ /dev/null @@ -1,142 +0,0 @@ -/* Searching in a string. - Copyright (C) 2003, 2007, 2008, 2009, 2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -/* Find the first occurrence of C in S or the final NUL byte. */ -char * -strchrnul (const char *s, int c_in) -{ - /* On 32-bit hardware, choosing longword to be a 32-bit unsigned - long instead of a 64-bit uintmax_t tends to give better - performance. On 64-bit hardware, unsigned long is generally 64 - bits already. Change this typedef to experiment with - performance. */ - typedef unsigned long int longword; - - const unsigned char *char_ptr; - const longword *longword_ptr; - longword repeated_one; - longword repeated_c; - unsigned char c; - - c = (unsigned char) c_in; - if (!c) - return rawmemchr (s, 0); - - /* Handle the first few bytes by reading one byte at a time. - Do this until CHAR_PTR is aligned on a longword boundary. */ - for (char_ptr = (const unsigned char *) s; - (size_t) char_ptr % sizeof (longword) != 0; - ++char_ptr) - if (!*char_ptr || *char_ptr == c) - return (char *) char_ptr; - - longword_ptr = (const longword *) char_ptr; - - /* All these elucidatory comments refer to 4-byte longwords, - but the theory applies equally well to any size longwords. */ - - /* Compute auxiliary longword values: - repeated_one is a value which has a 1 in every byte. - repeated_c has c in every byte. */ - repeated_one = 0x01010101; - repeated_c = c | (c << 8); - repeated_c |= repeated_c << 16; - if (0xffffffffU < (longword) -1) - { - repeated_one |= repeated_one << 31 << 1; - repeated_c |= repeated_c << 31 << 1; - if (8 < sizeof (longword)) - { - size_t i; - - for (i = 64; i < sizeof (longword) * 8; i *= 2) - { - repeated_one |= repeated_one << i; - repeated_c |= repeated_c << i; - } - } - } - - /* Instead of the traditional loop which tests each byte, we will - test a longword at a time. The tricky part is testing if *any of - the four* bytes in the longword in question are equal to NUL or - c. We first use an xor with repeated_c. This reduces the task - to testing whether *any of the four* bytes in longword1 or - longword2 is zero. - - Let's consider longword1. We compute tmp = - ((longword1 - repeated_one) & ~longword1) & (repeated_one << 7). - That is, we perform the following operations: - 1. Subtract repeated_one. - 2. & ~longword1. - 3. & a mask consisting of 0x80 in every byte. - Consider what happens in each byte: - - If a byte of longword1 is zero, step 1 and 2 transform it into 0xff, - and step 3 transforms it into 0x80. A carry can also be propagated - to more significant bytes. - - If a byte of longword1 is nonzero, let its lowest 1 bit be at - position k (0 <= k <= 7); so the lowest k bits are 0. After step 1, - the byte ends in a single bit of value 0 and k bits of value 1. - After step 2, the result is just k bits of value 1: 2^k - 1. After - step 3, the result is 0. And no carry is produced. - So, if longword1 has only non-zero bytes, tmp is zero. - Whereas if longword1 has a zero byte, call j the position of the least - significant zero byte. Then the result has a zero at positions 0, ..., - j-1 and a 0x80 at position j. We cannot predict the result at the more - significant bytes (positions j+1..3), but it does not matter since we - already have a non-zero bit at position 8*j+7. - - The test whether any byte in longword1 or longword2 is zero is equivalent - to testing whether tmp1 is nonzero or tmp2 is nonzero. We can combine - this into a single test, whether (tmp1 | tmp2) is nonzero. - - This test can read more than one byte beyond the end of a string, - depending on where the terminating NUL is encountered. However, - this is considered safe since the initialization phase ensured - that the read will be aligned, therefore, the read will not cross - page boundaries and will not cause a fault. */ - - while (1) - { - longword longword1 = *longword_ptr ^ repeated_c; - longword longword2 = *longword_ptr; - - if (((((longword1 - repeated_one) & ~longword1) - | ((longword2 - repeated_one) & ~longword2)) - & (repeated_one << 7)) != 0) - break; - longword_ptr++; - } - - char_ptr = (const unsigned char *) longword_ptr; - - /* At this point, we know that one of the sizeof (longword) bytes - starting at char_ptr is == 0 or == c. On little-endian machines, - we could determine the first such byte without any further memory - accesses, just by looking at the tmp result from the last loop - iteration. But this does not work on big-endian machines. - Choose code that works in both cases. */ - - char_ptr = (unsigned char *) longword_ptr; - while (*char_ptr && (*char_ptr != c)) - char_ptr++; - return (char *) char_ptr; -} diff --git a/grub-core/gnulib/strchrnul.valgrind b/grub-core/gnulib/strchrnul.valgrind deleted file mode 100644 index b14fa1304..000000000 --- a/grub-core/gnulib/strchrnul.valgrind +++ /dev/null @@ -1,12 +0,0 @@ -# Suppress a valgrind message about use of uninitialized memory in strchrnul(). -# This use is OK because it provides only a speedup. -{ - strchrnul-value4 - Memcheck:Value4 - fun:strchrnul -} -{ - strchrnul-value8 - Memcheck:Value8 - fun:strchrnul -} diff --git a/grub-core/gnulib/streq.h b/grub-core/gnulib/streq.h deleted file mode 100644 index aa65bb8e1..000000000 --- a/grub-core/gnulib/streq.h +++ /dev/null @@ -1,176 +0,0 @@ -/* Optimized string comparison. - Copyright (C) 2001-2002, 2007, 2009-2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* Written by Bruno Haible . */ - -#ifndef _GL_STREQ_H -#define _GL_STREQ_H - -#include - -/* STREQ allows to optimize string comparison with a small literal string. - STREQ (s, "EUC-KR", 'E', 'U', 'C', '-', 'K', 'R', 0, 0, 0) - is semantically equivalent to - strcmp (s, "EUC-KR") == 0 - just faster. */ - -/* Help GCC to generate good code for string comparisons with - immediate strings. */ -#if defined (__GNUC__) && defined (__OPTIMIZE__) - -static inline int -streq9 (const char *s1, const char *s2) -{ - return strcmp (s1 + 9, s2 + 9) == 0; -} - -static inline int -streq8 (const char *s1, const char *s2, char s28) -{ - if (s1[8] == s28) - { - if (s28 == 0) - return 1; - else - return streq9 (s1, s2); - } - else - return 0; -} - -static inline int -streq7 (const char *s1, const char *s2, char s27, char s28) -{ - if (s1[7] == s27) - { - if (s27 == 0) - return 1; - else - return streq8 (s1, s2, s28); - } - else - return 0; -} - -static inline int -streq6 (const char *s1, const char *s2, char s26, char s27, char s28) -{ - if (s1[6] == s26) - { - if (s26 == 0) - return 1; - else - return streq7 (s1, s2, s27, s28); - } - else - return 0; -} - -static inline int -streq5 (const char *s1, const char *s2, char s25, char s26, char s27, char s28) -{ - if (s1[5] == s25) - { - if (s25 == 0) - return 1; - else - return streq6 (s1, s2, s26, s27, s28); - } - else - return 0; -} - -static inline int -streq4 (const char *s1, const char *s2, char s24, char s25, char s26, char s27, char s28) -{ - if (s1[4] == s24) - { - if (s24 == 0) - return 1; - else - return streq5 (s1, s2, s25, s26, s27, s28); - } - else - return 0; -} - -static inline int -streq3 (const char *s1, const char *s2, char s23, char s24, char s25, char s26, char s27, char s28) -{ - if (s1[3] == s23) - { - if (s23 == 0) - return 1; - else - return streq4 (s1, s2, s24, s25, s26, s27, s28); - } - else - return 0; -} - -static inline int -streq2 (const char *s1, const char *s2, char s22, char s23, char s24, char s25, char s26, char s27, char s28) -{ - if (s1[2] == s22) - { - if (s22 == 0) - return 1; - else - return streq3 (s1, s2, s23, s24, s25, s26, s27, s28); - } - else - return 0; -} - -static inline int -streq1 (const char *s1, const char *s2, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28) -{ - if (s1[1] == s21) - { - if (s21 == 0) - return 1; - else - return streq2 (s1, s2, s22, s23, s24, s25, s26, s27, s28); - } - else - return 0; -} - -static inline int -streq0 (const char *s1, const char *s2, char s20, char s21, char s22, char s23, char s24, char s25, char s26, char s27, char s28) -{ - if (s1[0] == s20) - { - if (s20 == 0) - return 1; - else - return streq1 (s1, s2, s21, s22, s23, s24, s25, s26, s27, s28); - } - else - return 0; -} - -#define STREQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ - streq0 (s1, s2, s20, s21, s22, s23, s24, s25, s26, s27, s28) - -#else - -#define STREQ(s1,s2,s20,s21,s22,s23,s24,s25,s26,s27,s28) \ - (strcmp (s1, s2) == 0) - -#endif - -#endif /* _GL_STREQ_H */ diff --git a/grub-core/gnulib/strerror.c b/grub-core/gnulib/strerror.c deleted file mode 100644 index 46153abf5..000000000 --- a/grub-core/gnulib/strerror.c +++ /dev/null @@ -1,350 +0,0 @@ -/* strerror.c --- POSIX compatible system error routine - - Copyright (C) 2007-2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -#include - -#if REPLACE_STRERROR - -# include -# include - -# if GNULIB_defined_ESOCK /* native Windows platforms */ -# if HAVE_WINSOCK2_H -# include -# endif -# endif - -# include "intprops.h" - -/* Use the system functions, not the gnulib overrides in this file. */ -# undef sprintf - -# undef strerror -# if ! HAVE_DECL_STRERROR -# define strerror(n) NULL -# endif - -char * -rpl_strerror (int n) -{ - char const *msg = NULL; - /* These error messages are taken from glibc/sysdeps/gnu/errlist.c. */ - switch (n) - { -# if GNULIB_defined_ETXTBSY - case ETXTBSY: - msg = "Text file busy"; - break; -# endif - -# if GNULIB_defined_ESOCK /* native Windows platforms */ - /* EWOULDBLOCK is the same as EAGAIN. */ - case EINPROGRESS: - msg = "Operation now in progress"; - break; - case EALREADY: - msg = "Operation already in progress"; - break; - case ENOTSOCK: - msg = "Socket operation on non-socket"; - break; - case EDESTADDRREQ: - msg = "Destination address required"; - break; - case EMSGSIZE: - msg = "Message too long"; - break; - case EPROTOTYPE: - msg = "Protocol wrong type for socket"; - break; - case ENOPROTOOPT: - msg = "Protocol not available"; - break; - case EPROTONOSUPPORT: - msg = "Protocol not supported"; - break; - case ESOCKTNOSUPPORT: - msg = "Socket type not supported"; - break; - case EOPNOTSUPP: - msg = "Operation not supported"; - break; - case EPFNOSUPPORT: - msg = "Protocol family not supported"; - break; - case EAFNOSUPPORT: - msg = "Address family not supported by protocol"; - break; - case EADDRINUSE: - msg = "Address already in use"; - break; - case EADDRNOTAVAIL: - msg = "Cannot assign requested address"; - break; - case ENETDOWN: - msg = "Network is down"; - break; - case ENETUNREACH: - msg = "Network is unreachable"; - break; - case ENETRESET: - msg = "Network dropped connection on reset"; - break; - case ECONNABORTED: - msg = "Software caused connection abort"; - break; - case ECONNRESET: - msg = "Connection reset by peer"; - break; - case ENOBUFS: - msg = "No buffer space available"; - break; - case EISCONN: - msg = "Transport endpoint is already connected"; - break; - case ENOTCONN: - msg = "Transport endpoint is not connected"; - break; - case ESHUTDOWN: - msg = "Cannot send after transport endpoint shutdown"; - break; - case ETOOMANYREFS: - msg = "Too many references: cannot splice"; - break; - case ETIMEDOUT: - msg = "Connection timed out"; - break; - case ECONNREFUSED: - msg = "Connection refused"; - break; - case ELOOP: - msg = "Too many levels of symbolic links"; - break; - case EHOSTDOWN: - msg = "Host is down"; - break; - case EHOSTUNREACH: - msg = "No route to host"; - break; - case EPROCLIM: - msg = "Too many processes"; - break; - case EUSERS: - msg = "Too many users"; - break; - case EDQUOT: - msg = "Disk quota exceeded"; - break; - case ESTALE: - msg = "Stale NFS file handle"; - break; - case EREMOTE: - msg = "Object is remote"; - break; -# if HAVE_WINSOCK2_H - /* WSA_INVALID_HANDLE maps to EBADF */ - /* WSA_NOT_ENOUGH_MEMORY maps to ENOMEM */ - /* WSA_INVALID_PARAMETER maps to EINVAL */ - case WSA_OPERATION_ABORTED: - msg = "Overlapped operation aborted"; - break; - case WSA_IO_INCOMPLETE: - msg = "Overlapped I/O event object not in signaled state"; - break; - case WSA_IO_PENDING: - msg = "Overlapped operations will complete later"; - break; - /* WSAEINTR maps to EINTR */ - /* WSAEBADF maps to EBADF */ - /* WSAEACCES maps to EACCES */ - /* WSAEFAULT maps to EFAULT */ - /* WSAEINVAL maps to EINVAL */ - /* WSAEMFILE maps to EMFILE */ - /* WSAEWOULDBLOCK maps to EWOULDBLOCK */ - /* WSAEINPROGRESS is EINPROGRESS */ - /* WSAEALREADY is EALREADY */ - /* WSAENOTSOCK is ENOTSOCK */ - /* WSAEDESTADDRREQ is EDESTADDRREQ */ - /* WSAEMSGSIZE is EMSGSIZE */ - /* WSAEPROTOTYPE is EPROTOTYPE */ - /* WSAENOPROTOOPT is ENOPROTOOPT */ - /* WSAEPROTONOSUPPORT is EPROTONOSUPPORT */ - /* WSAESOCKTNOSUPPORT is ESOCKTNOSUPPORT */ - /* WSAEOPNOTSUPP is EOPNOTSUPP */ - /* WSAEPFNOSUPPORT is EPFNOSUPPORT */ - /* WSAEAFNOSUPPORT is EAFNOSUPPORT */ - /* WSAEADDRINUSE is EADDRINUSE */ - /* WSAEADDRNOTAVAIL is EADDRNOTAVAIL */ - /* WSAENETDOWN is ENETDOWN */ - /* WSAENETUNREACH is ENETUNREACH */ - /* WSAENETRESET is ENETRESET */ - /* WSAECONNABORTED is ECONNABORTED */ - /* WSAECONNRESET is ECONNRESET */ - /* WSAENOBUFS is ENOBUFS */ - /* WSAEISCONN is EISCONN */ - /* WSAENOTCONN is ENOTCONN */ - /* WSAESHUTDOWN is ESHUTDOWN */ - /* WSAETOOMANYREFS is ETOOMANYREFS */ - /* WSAETIMEDOUT is ETIMEDOUT */ - /* WSAECONNREFUSED is ECONNREFUSED */ - /* WSAELOOP is ELOOP */ - /* WSAENAMETOOLONG maps to ENAMETOOLONG */ - /* WSAEHOSTDOWN is EHOSTDOWN */ - /* WSAEHOSTUNREACH is EHOSTUNREACH */ - /* WSAENOTEMPTY maps to ENOTEMPTY */ - /* WSAEPROCLIM is EPROCLIM */ - /* WSAEUSERS is EUSERS */ - /* WSAEDQUOT is EDQUOT */ - /* WSAESTALE is ESTALE */ - /* WSAEREMOTE is EREMOTE */ - case WSASYSNOTREADY: - msg = "Network subsystem is unavailable"; - break; - case WSAVERNOTSUPPORTED: - msg = "Winsock.dll version out of range"; - break; - case WSANOTINITIALISED: - msg = "Successful WSAStartup not yet performed"; - break; - case WSAEDISCON: - msg = "Graceful shutdown in progress"; - break; - case WSAENOMORE: case WSA_E_NO_MORE: - msg = "No more results"; - break; - case WSAECANCELLED: case WSA_E_CANCELLED: - msg = "Call was canceled"; - break; - case WSAEINVALIDPROCTABLE: - msg = "Procedure call table is invalid"; - break; - case WSAEINVALIDPROVIDER: - msg = "Service provider is invalid"; - break; - case WSAEPROVIDERFAILEDINIT: - msg = "Service provider failed to initialize"; - break; - case WSASYSCALLFAILURE: - msg = "System call failure"; - break; - case WSASERVICE_NOT_FOUND: - msg = "Service not found"; - break; - case WSATYPE_NOT_FOUND: - msg = "Class type not found"; - break; - case WSAEREFUSED: - msg = "Database query was refused"; - break; - case WSAHOST_NOT_FOUND: - msg = "Host not found"; - break; - case WSATRY_AGAIN: - msg = "Nonauthoritative host not found"; - break; - case WSANO_RECOVERY: - msg = "Nonrecoverable error"; - break; - case WSANO_DATA: - msg = "Valid name, no data record of requested type"; - break; - /* WSA_QOS_* omitted */ -# endif -# endif - -# if GNULIB_defined_ENOMSG - case ENOMSG: - msg = "No message of desired type"; - break; -# endif - -# if GNULIB_defined_EIDRM - case EIDRM: - msg = "Identifier removed"; - break; -# endif - -# if GNULIB_defined_ENOLINK - case ENOLINK: - msg = "Link has been severed"; - break; -# endif - -# if GNULIB_defined_EPROTO - case EPROTO: - msg = "Protocol error"; - break; -# endif - -# if GNULIB_defined_EMULTIHOP - case EMULTIHOP: - msg = "Multihop attempted"; - break; -# endif - -# if GNULIB_defined_EBADMSG - case EBADMSG: - msg = "Bad message"; - break; -# endif - -# if GNULIB_defined_EOVERFLOW - case EOVERFLOW: - msg = "Value too large for defined data type"; - break; -# endif - -# if GNULIB_defined_ENOTSUP - case ENOTSUP: - msg = "Not supported"; - break; -# endif - -# if GNULIB_defined_ESTALE - case ESTALE: - msg = "Stale NFS file handle"; - break; -# endif - -# if GNULIB_defined_ECANCELED - case ECANCELED: - msg = "Operation canceled"; - break; -# endif - } - - if (msg) - return (char *) msg; - - { - char *result = strerror (n); - - if (result == NULL || result[0] == '\0') - { - static char const fmt[] = "Unknown error (%d)"; - static char msg_buf[sizeof fmt + INT_STRLEN_BOUND (n)]; - sprintf (msg_buf, fmt, n); - return msg_buf; - } - - return result; - } -} - -#endif diff --git a/grub-core/gnulib/string.in.h b/grub-core/gnulib/string.in.h deleted file mode 100644 index 49c711d8f..000000000 --- a/grub-core/gnulib/string.in.h +++ /dev/null @@ -1,945 +0,0 @@ -/* A GNU-like . - - Copyright (C) 1995-1996, 2001-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GL_STRING_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -/* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_STRING_H@ - -#ifndef _GL_STRING_H -#define _GL_STRING_H - -/* NetBSD 5.0 mis-defines NULL. */ -#include - -/* MirBSD defines mbslen as a macro. */ -#if @GNULIB_MBSLEN@ && defined __MirBSD__ -# include -#endif - -#ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) -# define __attribute__(Spec) /* empty */ -# endif -#endif -/* The attribute __pure__ was added in gcc 2.96. */ -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) -# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__)) -#else -# define _GL_ATTRIBUTE_PURE /* empty */ -#endif - -/* NetBSD 5.0 declares strsignal in , not in . */ -/* But avoid namespace pollution on glibc systems. */ -#if (@GNULIB_STRSIGNAL@ || defined GNULIB_POSIXCHECK) \ - && ! defined __GLIBC__ -# include -#endif - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - - -/* Return the first instance of C within N bytes of S, or NULL. */ -#if @GNULIB_MEMCHR@ -# if @REPLACE_MEMCHR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define memchr rpl_memchr -# endif -_GL_FUNCDECL_RPL (memchr, void *, (void const *__s, int __c, size_t __n) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (memchr, void *, (void const *__s, int __c, size_t __n)); -# else -# if ! @HAVE_MEMCHR@ -_GL_FUNCDECL_SYS (memchr, void *, (void const *__s, int __c, size_t __n) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -# endif - /* On some systems, this function is defined as an overloaded function: - extern "C" { const void * std::memchr (const void *, int, size_t); } - extern "C++" { void * std::memchr (void *, int, size_t); } */ -_GL_CXXALIAS_SYS_CAST2 (memchr, - void *, (void const *__s, int __c, size_t __n), - void const *, (void const *__s, int __c, size_t __n)); -# endif -# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 10 \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (memchr, void *, (void *__s, int __c, size_t __n)); -_GL_CXXALIASWARN1 (memchr, void const *, - (void const *__s, int __c, size_t __n)); -# else -_GL_CXXALIASWARN (memchr); -# endif -#elif defined GNULIB_POSIXCHECK -# undef memchr -/* Assume memchr is always declared. */ -_GL_WARN_ON_USE (memchr, "memchr has platform-specific bugs - " - "use gnulib module memchr for portability" ); -#endif - -/* Return the first occurrence of NEEDLE in HAYSTACK. */ -#if @GNULIB_MEMMEM@ -# if @REPLACE_MEMMEM@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define memmem rpl_memmem -# endif -_GL_FUNCDECL_RPL (memmem, void *, - (void const *__haystack, size_t __haystack_len, - void const *__needle, size_t __needle_len) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 3))); -_GL_CXXALIAS_RPL (memmem, void *, - (void const *__haystack, size_t __haystack_len, - void const *__needle, size_t __needle_len)); -# else -# if ! @HAVE_DECL_MEMMEM@ -_GL_FUNCDECL_SYS (memmem, void *, - (void const *__haystack, size_t __haystack_len, - void const *__needle, size_t __needle_len) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 3))); -# endif -_GL_CXXALIAS_SYS (memmem, void *, - (void const *__haystack, size_t __haystack_len, - void const *__needle, size_t __needle_len)); -# endif -_GL_CXXALIASWARN (memmem); -#elif defined GNULIB_POSIXCHECK -# undef memmem -# if HAVE_RAW_DECL_MEMMEM -_GL_WARN_ON_USE (memmem, "memmem is unportable and often quadratic - " - "use gnulib module memmem-simple for portability, " - "and module memmem for speed" ); -# endif -#endif - -/* Copy N bytes of SRC to DEST, return pointer to bytes after the - last written byte. */ -#if @GNULIB_MEMPCPY@ -# if ! @HAVE_MEMPCPY@ -_GL_FUNCDECL_SYS (mempcpy, void *, - (void *restrict __dest, void const *restrict __src, - size_t __n) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (mempcpy, void *, - (void *restrict __dest, void const *restrict __src, - size_t __n)); -_GL_CXXALIASWARN (mempcpy); -#elif defined GNULIB_POSIXCHECK -# undef mempcpy -# if HAVE_RAW_DECL_MEMPCPY -_GL_WARN_ON_USE (mempcpy, "mempcpy is unportable - " - "use gnulib module mempcpy for portability"); -# endif -#endif - -/* Search backwards through a block for a byte (specified as an int). */ -#if @GNULIB_MEMRCHR@ -# if ! @HAVE_DECL_MEMRCHR@ -_GL_FUNCDECL_SYS (memrchr, void *, (void const *, int, size_t) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -# endif - /* On some systems, this function is defined as an overloaded function: - extern "C++" { const void * std::memrchr (const void *, int, size_t); } - extern "C++" { void * std::memrchr (void *, int, size_t); } */ -_GL_CXXALIAS_SYS_CAST2 (memrchr, - void *, (void const *, int, size_t), - void const *, (void const *, int, size_t)); -# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 10 \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (memrchr, void *, (void *, int, size_t)); -_GL_CXXALIASWARN1 (memrchr, void const *, (void const *, int, size_t)); -# else -_GL_CXXALIASWARN (memrchr); -# endif -#elif defined GNULIB_POSIXCHECK -# undef memrchr -# if HAVE_RAW_DECL_MEMRCHR -_GL_WARN_ON_USE (memrchr, "memrchr is unportable - " - "use gnulib module memrchr for portability"); -# endif -#endif - -/* Find the first occurrence of C in S. More efficient than - memchr(S,C,N), at the expense of undefined behavior if C does not - occur within N bytes. */ -#if @GNULIB_RAWMEMCHR@ -# if ! @HAVE_RAWMEMCHR@ -_GL_FUNCDECL_SYS (rawmemchr, void *, (void const *__s, int __c_in) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -# endif - /* On some systems, this function is defined as an overloaded function: - extern "C++" { const void * std::rawmemchr (const void *, int); } - extern "C++" { void * std::rawmemchr (void *, int); } */ -_GL_CXXALIAS_SYS_CAST2 (rawmemchr, - void *, (void const *__s, int __c_in), - void const *, (void const *__s, int __c_in)); -# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 10 \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (rawmemchr, void *, (void *__s, int __c_in)); -_GL_CXXALIASWARN1 (rawmemchr, void const *, (void const *__s, int __c_in)); -# else -_GL_CXXALIASWARN (rawmemchr); -# endif -#elif defined GNULIB_POSIXCHECK -# undef rawmemchr -# if HAVE_RAW_DECL_RAWMEMCHR -_GL_WARN_ON_USE (rawmemchr, "rawmemchr is unportable - " - "use gnulib module rawmemchr for portability"); -# endif -#endif - -/* Copy SRC to DST, returning the address of the terminating '\0' in DST. */ -#if @GNULIB_STPCPY@ -# if ! @HAVE_STPCPY@ -_GL_FUNCDECL_SYS (stpcpy, char *, - (char *restrict __dst, char const *restrict __src) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (stpcpy, char *, - (char *restrict __dst, char const *restrict __src)); -_GL_CXXALIASWARN (stpcpy); -#elif defined GNULIB_POSIXCHECK -# undef stpcpy -# if HAVE_RAW_DECL_STPCPY -_GL_WARN_ON_USE (stpcpy, "stpcpy is unportable - " - "use gnulib module stpcpy for portability"); -# endif -#endif - -/* Copy no more than N bytes of SRC to DST, returning a pointer past the - last non-NUL byte written into DST. */ -#if @GNULIB_STPNCPY@ -# if @REPLACE_STPNCPY@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef stpncpy -# define stpncpy rpl_stpncpy -# endif -_GL_FUNCDECL_RPL (stpncpy, char *, - (char *restrict __dst, char const *restrict __src, - size_t __n) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (stpncpy, char *, - (char *restrict __dst, char const *restrict __src, - size_t __n)); -# else -# if ! @HAVE_STPNCPY@ -_GL_FUNCDECL_SYS (stpncpy, char *, - (char *restrict __dst, char const *restrict __src, - size_t __n) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (stpncpy, char *, - (char *restrict __dst, char const *restrict __src, - size_t __n)); -# endif -_GL_CXXALIASWARN (stpncpy); -#elif defined GNULIB_POSIXCHECK -# undef stpncpy -# if HAVE_RAW_DECL_STPNCPY -_GL_WARN_ON_USE (stpncpy, "stpncpy is unportable - " - "use gnulib module stpncpy for portability"); -# endif -#endif - -#if defined GNULIB_POSIXCHECK -/* strchr() does not work with multibyte strings if the locale encoding is - GB18030 and the character to be searched is a digit. */ -# undef strchr -/* Assume strchr is always declared. */ -_GL_WARN_ON_USE (strchr, "strchr cannot work correctly on character strings " - "in some multibyte locales - " - "use mbschr if you care about internationalization"); -#endif - -/* Find the first occurrence of C in S or the final NUL byte. */ -#if @GNULIB_STRCHRNUL@ -# if ! @HAVE_STRCHRNUL@ -_GL_FUNCDECL_SYS (strchrnul, char *, (char const *__s, int __c_in) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -# endif - /* On some systems, this function is defined as an overloaded function: - extern "C++" { const char * std::strchrnul (const char *, int); } - extern "C++" { char * std::strchrnul (char *, int); } */ -_GL_CXXALIAS_SYS_CAST2 (strchrnul, - char *, (char const *__s, int __c_in), - char const *, (char const *__s, int __c_in)); -# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 10 \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (strchrnul, char *, (char *__s, int __c_in)); -_GL_CXXALIASWARN1 (strchrnul, char const *, (char const *__s, int __c_in)); -# else -_GL_CXXALIASWARN (strchrnul); -# endif -#elif defined GNULIB_POSIXCHECK -# undef strchrnul -# if HAVE_RAW_DECL_STRCHRNUL -_GL_WARN_ON_USE (strchrnul, "strchrnul is unportable - " - "use gnulib module strchrnul for portability"); -# endif -#endif - -/* Duplicate S, returning an identical malloc'd string. */ -#if @GNULIB_STRDUP@ -# if @REPLACE_STRDUP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strdup -# define strdup rpl_strdup -# endif -_GL_FUNCDECL_RPL (strdup, char *, (char const *__s) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (strdup, char *, (char const *__s)); -# else -# if defined __cplusplus && defined GNULIB_NAMESPACE && defined strdup - /* strdup exists as a function and as a macro. Get rid of the macro. */ -# undef strdup -# endif -# if !(@HAVE_DECL_STRDUP@ || defined strdup) -_GL_FUNCDECL_SYS (strdup, char *, (char const *__s) _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (strdup, char *, (char const *__s)); -# endif -_GL_CXXALIASWARN (strdup); -#elif defined GNULIB_POSIXCHECK -# undef strdup -# if HAVE_RAW_DECL_STRDUP -_GL_WARN_ON_USE (strdup, "strdup is unportable - " - "use gnulib module strdup for portability"); -# endif -#endif - -/* Append no more than N characters from SRC onto DEST. */ -#if @GNULIB_STRNCAT@ -# if @REPLACE_STRNCAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strncat -# define strncat rpl_strncat -# endif -_GL_FUNCDECL_RPL (strncat, char *, (char *dest, const char *src, size_t n) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (strncat, char *, (char *dest, const char *src, size_t n)); -# else -_GL_CXXALIAS_SYS (strncat, char *, (char *dest, const char *src, size_t n)); -# endif -_GL_CXXALIASWARN (strncat); -#elif defined GNULIB_POSIXCHECK -# undef strncat -# if HAVE_RAW_DECL_STRNCAT -_GL_WARN_ON_USE (strncat, "strncat is unportable - " - "use gnulib module strncat for portability"); -# endif -#endif - -/* Return a newly allocated copy of at most N bytes of STRING. */ -#if @GNULIB_STRNDUP@ -# if @REPLACE_STRNDUP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strndup -# define strndup rpl_strndup -# endif -_GL_FUNCDECL_RPL (strndup, char *, (char const *__string, size_t __n) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (strndup, char *, (char const *__string, size_t __n)); -# else -# if ! @HAVE_DECL_STRNDUP@ -_GL_FUNCDECL_SYS (strndup, char *, (char const *__string, size_t __n) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (strndup, char *, (char const *__string, size_t __n)); -# endif -_GL_CXXALIASWARN (strndup); -#elif defined GNULIB_POSIXCHECK -# undef strndup -# if HAVE_RAW_DECL_STRNDUP -_GL_WARN_ON_USE (strndup, "strndup is unportable - " - "use gnulib module strndup for portability"); -# endif -#endif - -/* Find the length (number of bytes) of STRING, but scan at most - MAXLEN bytes. If no '\0' terminator is found in that many bytes, - return MAXLEN. */ -#if @GNULIB_STRNLEN@ -# if @REPLACE_STRNLEN@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strnlen -# define strnlen rpl_strnlen -# endif -_GL_FUNCDECL_RPL (strnlen, size_t, (char const *__string, size_t __maxlen) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (strnlen, size_t, (char const *__string, size_t __maxlen)); -# else -# if ! @HAVE_DECL_STRNLEN@ -_GL_FUNCDECL_SYS (strnlen, size_t, (char const *__string, size_t __maxlen) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (strnlen, size_t, (char const *__string, size_t __maxlen)); -# endif -_GL_CXXALIASWARN (strnlen); -#elif defined GNULIB_POSIXCHECK -# undef strnlen -# if HAVE_RAW_DECL_STRNLEN -_GL_WARN_ON_USE (strnlen, "strnlen is unportable - " - "use gnulib module strnlen for portability"); -# endif -#endif - -#if defined GNULIB_POSIXCHECK -/* strcspn() assumes the second argument is a list of single-byte characters. - Even in this simple case, it does not work with multibyte strings if the - locale encoding is GB18030 and one of the characters to be searched is a - digit. */ -# undef strcspn -/* Assume strcspn is always declared. */ -_GL_WARN_ON_USE (strcspn, "strcspn cannot work correctly on character strings " - "in multibyte locales - " - "use mbscspn if you care about internationalization"); -#endif - -/* Find the first occurrence in S of any character in ACCEPT. */ -#if @GNULIB_STRPBRK@ -# if ! @HAVE_STRPBRK@ -_GL_FUNCDECL_SYS (strpbrk, char *, (char const *__s, char const *__accept) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -# endif - /* On some systems, this function is defined as an overloaded function: - extern "C" { const char * strpbrk (const char *, const char *); } - extern "C++" { char * strpbrk (char *, const char *); } */ -_GL_CXXALIAS_SYS_CAST2 (strpbrk, - char *, (char const *__s, char const *__accept), - const char *, (char const *__s, char const *__accept)); -# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 10 \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (strpbrk, char *, (char *__s, char const *__accept)); -_GL_CXXALIASWARN1 (strpbrk, char const *, - (char const *__s, char const *__accept)); -# else -_GL_CXXALIASWARN (strpbrk); -# endif -# if defined GNULIB_POSIXCHECK -/* strpbrk() assumes the second argument is a list of single-byte characters. - Even in this simple case, it does not work with multibyte strings if the - locale encoding is GB18030 and one of the characters to be searched is a - digit. */ -# undef strpbrk -_GL_WARN_ON_USE (strpbrk, "strpbrk cannot work correctly on character strings " - "in multibyte locales - " - "use mbspbrk if you care about internationalization"); -# endif -#elif defined GNULIB_POSIXCHECK -# undef strpbrk -# if HAVE_RAW_DECL_STRPBRK -_GL_WARN_ON_USE (strpbrk, "strpbrk is unportable - " - "use gnulib module strpbrk for portability"); -# endif -#endif - -#if defined GNULIB_POSIXCHECK -/* strspn() assumes the second argument is a list of single-byte characters. - Even in this simple case, it cannot work with multibyte strings. */ -# undef strspn -/* Assume strspn is always declared. */ -_GL_WARN_ON_USE (strspn, "strspn cannot work correctly on character strings " - "in multibyte locales - " - "use mbsspn if you care about internationalization"); -#endif - -#if defined GNULIB_POSIXCHECK -/* strrchr() does not work with multibyte strings if the locale encoding is - GB18030 and the character to be searched is a digit. */ -# undef strrchr -/* Assume strrchr is always declared. */ -_GL_WARN_ON_USE (strrchr, "strrchr cannot work correctly on character strings " - "in some multibyte locales - " - "use mbsrchr if you care about internationalization"); -#endif - -/* Search the next delimiter (char listed in DELIM) starting at *STRINGP. - If one is found, overwrite it with a NUL, and advance *STRINGP - to point to the next char after it. Otherwise, set *STRINGP to NULL. - If *STRINGP was already NULL, nothing happens. - Return the old value of *STRINGP. - - This is a variant of strtok() that is multithread-safe and supports - empty fields. - - Caveat: It modifies the original string. - Caveat: These functions cannot be used on constant strings. - Caveat: The identity of the delimiting character is lost. - Caveat: It doesn't work with multibyte strings unless all of the delimiter - characters are ASCII characters < 0x30. - - See also strtok_r(). */ -#if @GNULIB_STRSEP@ -# if ! @HAVE_STRSEP@ -_GL_FUNCDECL_SYS (strsep, char *, - (char **restrict __stringp, char const *restrict __delim) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (strsep, char *, - (char **restrict __stringp, char const *restrict __delim)); -_GL_CXXALIASWARN (strsep); -# if defined GNULIB_POSIXCHECK -# undef strsep -_GL_WARN_ON_USE (strsep, "strsep cannot work correctly on character strings " - "in multibyte locales - " - "use mbssep if you care about internationalization"); -# endif -#elif defined GNULIB_POSIXCHECK -# undef strsep -# if HAVE_RAW_DECL_STRSEP -_GL_WARN_ON_USE (strsep, "strsep is unportable - " - "use gnulib module strsep for portability"); -# endif -#endif - -#if @GNULIB_STRSTR@ -# if @REPLACE_STRSTR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define strstr rpl_strstr -# endif -_GL_FUNCDECL_RPL (strstr, char *, (const char *haystack, const char *needle) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (strstr, char *, (const char *haystack, const char *needle)); -# else - /* On some systems, this function is defined as an overloaded function: - extern "C++" { const char * strstr (const char *, const char *); } - extern "C++" { char * strstr (char *, const char *); } */ -_GL_CXXALIAS_SYS_CAST2 (strstr, - char *, (const char *haystack, const char *needle), - const char *, (const char *haystack, const char *needle)); -# endif -# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 10 \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (strstr, char *, (char *haystack, const char *needle)); -_GL_CXXALIASWARN1 (strstr, const char *, - (const char *haystack, const char *needle)); -# else -_GL_CXXALIASWARN (strstr); -# endif -#elif defined GNULIB_POSIXCHECK -/* strstr() does not work with multibyte strings if the locale encoding is - different from UTF-8: - POSIX says that it operates on "strings", and "string" in POSIX is defined - as a sequence of bytes, not of characters. */ -# undef strstr -/* Assume strstr is always declared. */ -_GL_WARN_ON_USE (strstr, "strstr is quadratic on many systems, and cannot " - "work correctly on character strings in most " - "multibyte locales - " - "use mbsstr if you care about internationalization, " - "or use strstr if you care about speed"); -#endif - -/* Find the first occurrence of NEEDLE in HAYSTACK, using case-insensitive - comparison. */ -#if @GNULIB_STRCASESTR@ -# if @REPLACE_STRCASESTR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define strcasestr rpl_strcasestr -# endif -_GL_FUNCDECL_RPL (strcasestr, char *, - (const char *haystack, const char *needle) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (strcasestr, char *, - (const char *haystack, const char *needle)); -# else -# if ! @HAVE_STRCASESTR@ -_GL_FUNCDECL_SYS (strcasestr, char *, - (const char *haystack, const char *needle) - _GL_ATTRIBUTE_PURE - _GL_ARG_NONNULL ((1, 2))); -# endif - /* On some systems, this function is defined as an overloaded function: - extern "C++" { const char * strcasestr (const char *, const char *); } - extern "C++" { char * strcasestr (char *, const char *); } */ -_GL_CXXALIAS_SYS_CAST2 (strcasestr, - char *, (const char *haystack, const char *needle), - const char *, (const char *haystack, const char *needle)); -# endif -# if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 10 \ - && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) -_GL_CXXALIASWARN1 (strcasestr, char *, (char *haystack, const char *needle)); -_GL_CXXALIASWARN1 (strcasestr, const char *, - (const char *haystack, const char *needle)); -# else -_GL_CXXALIASWARN (strcasestr); -# endif -#elif defined GNULIB_POSIXCHECK -/* strcasestr() does not work with multibyte strings: - It is a glibc extension, and glibc implements it only for unibyte - locales. */ -# undef strcasestr -# if HAVE_RAW_DECL_STRCASESTR -_GL_WARN_ON_USE (strcasestr, "strcasestr does work correctly on character " - "strings in multibyte locales - " - "use mbscasestr if you care about " - "internationalization, or use c-strcasestr if you want " - "a locale independent function"); -# endif -#endif - -/* Parse S into tokens separated by characters in DELIM. - If S is NULL, the saved pointer in SAVE_PTR is used as - the next starting point. For example: - char s[] = "-abc-=-def"; - char *sp; - x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def" - x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL - x = strtok_r(NULL, "=", &sp); // x = NULL - // s = "abc\0-def\0" - - This is a variant of strtok() that is multithread-safe. - - For the POSIX documentation for this function, see: - http://www.opengroup.org/susv3xsh/strtok.html - - Caveat: It modifies the original string. - Caveat: These functions cannot be used on constant strings. - Caveat: The identity of the delimiting character is lost. - Caveat: It doesn't work with multibyte strings unless all of the delimiter - characters are ASCII characters < 0x30. - - See also strsep(). */ -#if @GNULIB_STRTOK_R@ -# if @REPLACE_STRTOK_R@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strtok_r -# define strtok_r rpl_strtok_r -# endif -_GL_FUNCDECL_RPL (strtok_r, char *, - (char *restrict s, char const *restrict delim, - char **restrict save_ptr) - _GL_ARG_NONNULL ((2, 3))); -_GL_CXXALIAS_RPL (strtok_r, char *, - (char *restrict s, char const *restrict delim, - char **restrict save_ptr)); -# else -# if @UNDEFINE_STRTOK_R@ || defined GNULIB_POSIXCHECK -# undef strtok_r -# endif -# if ! @HAVE_DECL_STRTOK_R@ -_GL_FUNCDECL_SYS (strtok_r, char *, - (char *restrict s, char const *restrict delim, - char **restrict save_ptr) - _GL_ARG_NONNULL ((2, 3))); -# endif -_GL_CXXALIAS_SYS (strtok_r, char *, - (char *restrict s, char const *restrict delim, - char **restrict save_ptr)); -# endif -_GL_CXXALIASWARN (strtok_r); -# if defined GNULIB_POSIXCHECK -_GL_WARN_ON_USE (strtok_r, "strtok_r cannot work correctly on character " - "strings in multibyte locales - " - "use mbstok_r if you care about internationalization"); -# endif -#elif defined GNULIB_POSIXCHECK -# undef strtok_r -# if HAVE_RAW_DECL_STRTOK_R -_GL_WARN_ON_USE (strtok_r, "strtok_r is unportable - " - "use gnulib module strtok_r for portability"); -# endif -#endif - - -/* The following functions are not specified by POSIX. They are gnulib - extensions. */ - -#if @GNULIB_MBSLEN@ -/* Return the number of multibyte characters in the character string STRING. - This considers multibyte characters, unlike strlen, which counts bytes. */ -# ifdef __MirBSD__ /* MirBSD defines mbslen as a macro. Override it. */ -# undef mbslen -# endif -# if @HAVE_MBSLEN@ /* AIX, OSF/1, MirBSD define mbslen already in libc. */ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define mbslen rpl_mbslen -# endif -_GL_FUNCDECL_RPL (mbslen, size_t, (const char *string) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (mbslen, size_t, (const char *string)); -# else -_GL_FUNCDECL_SYS (mbslen, size_t, (const char *string) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_SYS (mbslen, size_t, (const char *string)); -# endif -_GL_CXXALIASWARN (mbslen); -#endif - -#if @GNULIB_MBSNLEN@ -/* Return the number of multibyte characters in the character string starting - at STRING and ending at STRING + LEN. */ -_GL_EXTERN_C size_t mbsnlen (const char *string, size_t len) - _GL_ARG_NONNULL ((1)); -#endif - -#if @GNULIB_MBSCHR@ -/* Locate the first single-byte character C in the character string STRING, - and return a pointer to it. Return NULL if C is not found in STRING. - Unlike strchr(), this function works correctly in multibyte locales with - encodings such as GB18030. */ -# if defined __hpux -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define mbschr rpl_mbschr /* avoid collision with HP-UX function */ -# endif -_GL_FUNCDECL_RPL (mbschr, char *, (const char *string, int c) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (mbschr, char *, (const char *string, int c)); -# else -_GL_FUNCDECL_SYS (mbschr, char *, (const char *string, int c) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_SYS (mbschr, char *, (const char *string, int c)); -# endif -_GL_CXXALIASWARN (mbschr); -#endif - -#if @GNULIB_MBSRCHR@ -/* Locate the last single-byte character C in the character string STRING, - and return a pointer to it. Return NULL if C is not found in STRING. - Unlike strrchr(), this function works correctly in multibyte locales with - encodings such as GB18030. */ -# if defined __hpux -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define mbsrchr rpl_mbsrchr /* avoid collision with HP-UX function */ -# endif -_GL_FUNCDECL_RPL (mbsrchr, char *, (const char *string, int c) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (mbsrchr, char *, (const char *string, int c)); -# else -_GL_FUNCDECL_SYS (mbsrchr, char *, (const char *string, int c) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_SYS (mbsrchr, char *, (const char *string, int c)); -# endif -_GL_CXXALIASWARN (mbsrchr); -#endif - -#if @GNULIB_MBSSTR@ -/* Find the first occurrence of the character string NEEDLE in the character - string HAYSTACK. Return NULL if NEEDLE is not found in HAYSTACK. - Unlike strstr(), this function works correctly in multibyte locales with - encodings different from UTF-8. */ -_GL_EXTERN_C char * mbsstr (const char *haystack, const char *needle) - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSCASECMP@ -/* Compare the character strings S1 and S2, ignoring case, returning less than, - equal to or greater than zero if S1 is lexicographically less than, equal to - or greater than S2. - Note: This function may, in multibyte locales, return 0 for strings of - different lengths! - Unlike strcasecmp(), this function works correctly in multibyte locales. */ -_GL_EXTERN_C int mbscasecmp (const char *s1, const char *s2) - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSNCASECMP@ -/* Compare the initial segment of the character string S1 consisting of at most - N characters with the initial segment of the character string S2 consisting - of at most N characters, ignoring case, returning less than, equal to or - greater than zero if the initial segment of S1 is lexicographically less - than, equal to or greater than the initial segment of S2. - Note: This function may, in multibyte locales, return 0 for initial segments - of different lengths! - Unlike strncasecmp(), this function works correctly in multibyte locales. - But beware that N is not a byte count but a character count! */ -_GL_EXTERN_C int mbsncasecmp (const char *s1, const char *s2, size_t n) - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSPCASECMP@ -/* Compare the initial segment of the character string STRING consisting of - at most mbslen (PREFIX) characters with the character string PREFIX, - ignoring case. If the two match, return a pointer to the first byte - after this prefix in STRING. Otherwise, return NULL. - Note: This function may, in multibyte locales, return non-NULL if STRING - is of smaller length than PREFIX! - Unlike strncasecmp(), this function works correctly in multibyte - locales. */ -_GL_EXTERN_C char * mbspcasecmp (const char *string, const char *prefix) - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSCASESTR@ -/* Find the first occurrence of the character string NEEDLE in the character - string HAYSTACK, using case-insensitive comparison. - Note: This function may, in multibyte locales, return success even if - strlen (haystack) < strlen (needle) ! - Unlike strcasestr(), this function works correctly in multibyte locales. */ -_GL_EXTERN_C char * mbscasestr (const char *haystack, const char *needle) - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSCSPN@ -/* Find the first occurrence in the character string STRING of any character - in the character string ACCEPT. Return the number of bytes from the - beginning of the string to this occurrence, or to the end of the string - if none exists. - Unlike strcspn(), this function works correctly in multibyte locales. */ -_GL_EXTERN_C size_t mbscspn (const char *string, const char *accept) - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSPBRK@ -/* Find the first occurrence in the character string STRING of any character - in the character string ACCEPT. Return the pointer to it, or NULL if none - exists. - Unlike strpbrk(), this function works correctly in multibyte locales. */ -# if defined __hpux -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define mbspbrk rpl_mbspbrk /* avoid collision with HP-UX function */ -# endif -_GL_FUNCDECL_RPL (mbspbrk, char *, (const char *string, const char *accept) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (mbspbrk, char *, (const char *string, const char *accept)); -# else -_GL_FUNCDECL_SYS (mbspbrk, char *, (const char *string, const char *accept) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_SYS (mbspbrk, char *, (const char *string, const char *accept)); -# endif -_GL_CXXALIASWARN (mbspbrk); -#endif - -#if @GNULIB_MBSSPN@ -/* Find the first occurrence in the character string STRING of any character - not in the character string REJECT. Return the number of bytes from the - beginning of the string to this occurrence, or to the end of the string - if none exists. - Unlike strspn(), this function works correctly in multibyte locales. */ -_GL_EXTERN_C size_t mbsspn (const char *string, const char *reject) - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSSEP@ -/* Search the next delimiter (multibyte character listed in the character - string DELIM) starting at the character string *STRINGP. - If one is found, overwrite it with a NUL, and advance *STRINGP to point - to the next multibyte character after it. Otherwise, set *STRINGP to NULL. - If *STRINGP was already NULL, nothing happens. - Return the old value of *STRINGP. - - This is a variant of mbstok_r() that supports empty fields. - - Caveat: It modifies the original string. - Caveat: These functions cannot be used on constant strings. - Caveat: The identity of the delimiting character is lost. - - See also mbstok_r(). */ -_GL_EXTERN_C char * mbssep (char **stringp, const char *delim) - _GL_ARG_NONNULL ((1, 2)); -#endif - -#if @GNULIB_MBSTOK_R@ -/* Parse the character string STRING into tokens separated by characters in - the character string DELIM. - If STRING is NULL, the saved pointer in SAVE_PTR is used as - the next starting point. For example: - char s[] = "-abc-=-def"; - char *sp; - x = mbstok_r(s, "-", &sp); // x = "abc", sp = "=-def" - x = mbstok_r(NULL, "-=", &sp); // x = "def", sp = NULL - x = mbstok_r(NULL, "=", &sp); // x = NULL - // s = "abc\0-def\0" - - Caveat: It modifies the original string. - Caveat: These functions cannot be used on constant strings. - Caveat: The identity of the delimiting character is lost. - - See also mbssep(). */ -_GL_EXTERN_C char * mbstok_r (char *string, const char *delim, char **save_ptr) - _GL_ARG_NONNULL ((2, 3)); -#endif - -/* Map any int, typically from errno, into an error message. */ -#if @GNULIB_STRERROR@ -# if @REPLACE_STRERROR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef strerror -# define strerror rpl_strerror -# endif -_GL_FUNCDECL_RPL (strerror, char *, (int)); -_GL_CXXALIAS_RPL (strerror, char *, (int)); -# else -_GL_CXXALIAS_SYS (strerror, char *, (int)); -# endif -_GL_CXXALIASWARN (strerror); -#elif defined GNULIB_POSIXCHECK -# undef strerror -/* Assume strerror is always declared. */ -_GL_WARN_ON_USE (strerror, "strerror is unportable - " - "use gnulib module strerror to guarantee non-NULL result"); -#endif - -#if @GNULIB_STRSIGNAL@ -# if @REPLACE_STRSIGNAL@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define strsignal rpl_strsignal -# endif -_GL_FUNCDECL_RPL (strsignal, char *, (int __sig)); -_GL_CXXALIAS_RPL (strsignal, char *, (int __sig)); -# else -# if ! @HAVE_DECL_STRSIGNAL@ -_GL_FUNCDECL_SYS (strsignal, char *, (int __sig)); -# endif -/* Need to cast, because on Cygwin 1.5.x systems, the return type is - 'const char *'. */ -_GL_CXXALIAS_SYS_CAST (strsignal, char *, (int __sig)); -# endif -_GL_CXXALIASWARN (strsignal); -#elif defined GNULIB_POSIXCHECK -# undef strsignal -# if HAVE_RAW_DECL_STRSIGNAL -_GL_WARN_ON_USE (strsignal, "strsignal is unportable - " - "use gnulib module strsignal for portability"); -# endif -#endif - -#if @GNULIB_STRVERSCMP@ -# if !@HAVE_STRVERSCMP@ -_GL_FUNCDECL_SYS (strverscmp, int, (const char *, const char *) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (strverscmp, int, (const char *, const char *)); -_GL_CXXALIASWARN (strverscmp); -#elif defined GNULIB_POSIXCHECK -# undef strverscmp -# if HAVE_RAW_DECL_STRVERSCMP -_GL_WARN_ON_USE (strverscmp, "strverscmp is unportable - " - "use gnulib module strverscmp for portability"); -# endif -#endif - - -#endif /* _GL_STRING_H */ -#endif /* _GL_STRING_H */ diff --git a/grub-core/gnulib/strings.in.h b/grub-core/gnulib/strings.in.h deleted file mode 100644 index c726a1623..000000000 --- a/grub-core/gnulib/strings.in.h +++ /dev/null @@ -1,93 +0,0 @@ -/* A substitute . - - Copyright (C) 2007-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GL_STRINGS_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -/* The include_next requires a split double-inclusion guard. */ -#@INCLUDE_NEXT@ @NEXT_STRINGS_H@ - -#ifndef _GL_STRINGS_H -#define _GL_STRINGS_H - - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Compare strings S1 and S2, ignoring case, returning less than, equal to or - greater than zero if S1 is lexicographically less than, equal to or greater - than S2. - Note: This function does not work in multibyte locales. */ -#if ! @HAVE_STRCASECMP@ -extern int strcasecmp (char const *s1, char const *s2) - _GL_ARG_NONNULL ((1, 2)); -#endif -#if defined GNULIB_POSIXCHECK -/* strcasecmp() does not work with multibyte strings: - POSIX says that it operates on "strings", and "string" in POSIX is defined - as a sequence of bytes, not of characters. */ -# undef strcasecmp -# if HAVE_RAW_DECL_STRCASECMP -_GL_WARN_ON_USE (strcasecmp, "strcasecmp cannot work correctly on character " - "strings in multibyte locales - " - "use mbscasecmp if you care about " - "internationalization, or use c_strcasecmp , " - "gnulib module c-strcase) if you want a locale " - "independent function"); -# endif -#endif - -/* Compare no more than N bytes of strings S1 and S2, ignoring case, - returning less than, equal to or greater than zero if S1 is - lexicographically less than, equal to or greater than S2. - Note: This function cannot work correctly in multibyte locales. */ -#if ! @HAVE_DECL_STRNCASECMP@ -extern int strncasecmp (char const *s1, char const *s2, size_t n) - _GL_ARG_NONNULL ((1, 2)); -#endif -#if defined GNULIB_POSIXCHECK -/* strncasecmp() does not work with multibyte strings: - POSIX says that it operates on "strings", and "string" in POSIX is defined - as a sequence of bytes, not of characters. */ -# undef strncasecmp -# if HAVE_RAW_DECL_STRNCASECMP -_GL_WARN_ON_USE (strncasecmp, "strncasecmp cannot work correctly on character " - "strings in multibyte locales - " - "use mbsncasecmp or mbspcasecmp if you care about " - "internationalization, or use c_strncasecmp , " - "gnulib module c-strcase) if you want a locale " - "independent function"); -# endif -#endif - - -#ifdef __cplusplus -} -#endif - -#endif /* _GL_STRING_H */ -#endif /* _GL_STRING_H */ diff --git a/grub-core/gnulib/stripslash.c b/grub-core/gnulib/stripslash.c deleted file mode 100644 index 3a5996fd9..000000000 --- a/grub-core/gnulib/stripslash.c +++ /dev/null @@ -1,45 +0,0 @@ -/* stripslash.c -- remove redundant trailing slashes from a file name - - Copyright (C) 1990, 2001, 2003-2006, 2009-2010 Free Software Foundation, - 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -#include "dirname.h" - -/* Remove trailing slashes from FILE. Return true if a trailing slash - was removed. This is useful when using file name completion from a - shell that adds a "/" after directory names (such as tcsh and - bash), because on symlinks to directories, several system calls - have different semantics according to whether a trailing slash is - present. */ - -bool -strip_trailing_slashes (char *file) -{ - char *base = last_component (file); - char *base_lim; - bool had_slash; - - /* last_component returns "" for file system roots, but we need to turn - `///' into `/'. */ - if (! *base) - base = file; - base_lim = base + base_len (base); - had_slash = (*base_lim != '\0'); - *base_lim = '\0'; - return had_slash; -} diff --git a/grub-core/gnulib/strncasecmp.c b/grub-core/gnulib/strncasecmp.c deleted file mode 100644 index 8c806a6b0..000000000 --- a/grub-core/gnulib/strncasecmp.c +++ /dev/null @@ -1,63 +0,0 @@ -/* strncasecmp.c -- case insensitive string comparator - Copyright (C) 1998-1999, 2005-2007, 2009-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include - -#include -#include - -#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) - -/* Compare no more than N bytes of strings S1 and S2, ignoring case, - returning less than, equal to or greater than zero if S1 is - lexicographically less than, equal to or greater than S2. - Note: This function cannot work correctly in multibyte locales. */ - -int -strncasecmp (const char *s1, const char *s2, size_t n) -{ - register const unsigned char *p1 = (const unsigned char *) s1; - register const unsigned char *p2 = (const unsigned char *) s2; - unsigned char c1, c2; - - if (p1 == p2 || n == 0) - return 0; - - do - { - c1 = TOLOWER (*p1); - c2 = TOLOWER (*p2); - - if (--n == 0 || c1 == '\0') - break; - - ++p1; - ++p2; - } - while (c1 == c2); - - if (UCHAR_MAX <= INT_MAX) - return c1 - c2; - else - /* On machines where 'char' and 'int' are types of the same size, the - difference of two 'unsigned char' values - including the sign bit - - doesn't fit in an 'int'. */ - return (c1 > c2 ? 1 : c1 < c2 ? -1 : 0); -} diff --git a/grub-core/gnulib/strndup.c b/grub-core/gnulib/strndup.c deleted file mode 100644 index 3de3dbc5a..000000000 --- a/grub-core/gnulib/strndup.c +++ /dev/null @@ -1,37 +0,0 @@ -/* A replacement function, for systems that lack strndup. - - Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2005, 2006, 2007, 2009, - 2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include - -#include - -char * -strndup (char const *s, size_t n) -{ - size_t len = strnlen (s, n); - char *new = malloc (len + 1); - - if (new == NULL) - return NULL; - - new[len] = '\0'; - return memcpy (new, s, len); -} diff --git a/grub-core/gnulib/strnlen.c b/grub-core/gnulib/strnlen.c deleted file mode 100644 index f1ec356dc..000000000 --- a/grub-core/gnulib/strnlen.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Find the length of STRING, but scan at most MAXLEN characters. - Copyright (C) 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc. - Written by Simon Josefsson. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include - -/* Find the length of STRING, but scan at most MAXLEN characters. - If no '\0' terminator is found in that many characters, return MAXLEN. */ - -size_t -strnlen (const char *string, size_t maxlen) -{ - const char *end = memchr (string, '\0', maxlen); - return end ? (size_t) (end - string) : maxlen; -} diff --git a/grub-core/gnulib/strnlen1.c b/grub-core/gnulib/strnlen1.c deleted file mode 100644 index b8cd2bff0..000000000 --- a/grub-core/gnulib/strnlen1.c +++ /dev/null @@ -1,35 +0,0 @@ -/* Find the length of STRING + 1, but scan at most MAXLEN bytes. - Copyright (C) 2005-2006, 2009-2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include "strnlen1.h" - -#include - -/* Find the length of STRING + 1, but scan at most MAXLEN bytes. - If no '\0' terminator is found in that many characters, return MAXLEN. */ -/* This is the same as strnlen (string, maxlen - 1) + 1. */ -size_t -strnlen1 (const char *string, size_t maxlen) -{ - const char *end = (const char *) memchr (string, '\0', maxlen); - if (end != NULL) - return end - string + 1; - else - return maxlen; -} diff --git a/grub-core/gnulib/strnlen1.h b/grub-core/gnulib/strnlen1.h deleted file mode 100644 index dfaf62dcb..000000000 --- a/grub-core/gnulib/strnlen1.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Find the length of STRING + 1, but scan at most MAXLEN bytes. - Copyright (C) 2005, 2009, 2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#ifndef _STRNLEN1_H -#define _STRNLEN1_H - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Find the length of STRING + 1, but scan at most MAXLEN bytes. - If no '\0' terminator is found in that many characters, return MAXLEN. */ -/* This is the same as strnlen (string, maxlen - 1) + 1. */ -extern size_t strnlen1 (const char *string, size_t maxlen); - - -#ifdef __cplusplus -} -#endif - - -#endif /* _STRNLEN1_H */ diff --git a/grub-core/gnulib/sys_wait.in.h b/grub-core/gnulib/sys_wait.in.h deleted file mode 100644 index 009fa219b..000000000 --- a/grub-core/gnulib/sys_wait.in.h +++ /dev/null @@ -1,106 +0,0 @@ -/* A POSIX-like . - Copyright (C) 2001-2003, 2005-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - - -#ifndef _GL_SYS_WAIT_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -/* The include_next requires a split double-inclusion guard. */ -#if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) -# @INCLUDE_NEXT@ @NEXT_SYS_WAIT_H@ -#endif - -#ifndef _GL_SYS_WAIT_H -#define _GL_SYS_WAIT_H - -#if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) -/* Unix API. */ - -/* The following macros apply to an argument x, that is a status of a process, - as returned by waitpid(). - On nearly all systems, including Linux/x86, WEXITSTATUS are bits 15..8 and - WTERMSIG are bits 7..0, while BeOS uses the opposite. Therefore programs - have to use the abstract macros. */ - -/* For valid x, exactly one of WIFSIGNALED(x), WIFEXITED(x), WIFSTOPPED(x) - is true. */ -# ifndef WIFSIGNALED -# define WIFSIGNALED(x) (WTERMSIG (x) != 0 && WTERMSIG(x) != 0x7f) -# endif -# ifndef WIFEXITED -# define WIFEXITED(x) (WTERMSIG (x) == 0) -# endif -# ifndef WIFSTOPPED -# define WIFSTOPPED(x) (WTERMSIG (x) == 0x7f) -# endif - -/* The termination signal. Only to be accessed if WIFSIGNALED(x) is true. */ -# ifndef WTERMSIG -# define WTERMSIG(x) ((x) & 0x7f) -# endif - -/* The exit status. Only to be accessed if WIFEXITED(x) is true. */ -# ifndef WEXITSTATUS -# define WEXITSTATUS(x) (((x) >> 8) & 0xff) -# endif - -/* True if the process dumped core. Not standardized by POSIX. */ -# ifndef WCOREDUMP -# define WCOREDUMP(x) ((x) & 0x80) -# endif - -# ifdef __cplusplus -extern "C" { -# endif - -/* Declarations of functions. */ - -# ifdef __cplusplus -} -# endif - -#else -/* Native Windows API. */ - -# include - -# define waitpid(pid,statusp,options) _cwait (statusp, pid, WAIT_CHILD) - -/* The following macros apply to an argument x, that is a status of a process, - as returned by waitpid() or, equivalently, _cwait() or GetExitCodeProcess(). - This value is simply an 'int', not composed of bit fields. */ - -/* When an unhandled fatal signal terminates a process, the exit code is 3. */ -# define WIFSIGNALED(x) ((x) == 3) -# define WIFEXITED(x) ((x) != 3) -# define WIFSTOPPED(x) 0 - -/* The signal that terminated a process is not known posthum. */ -# define WTERMSIG(x) SIGTERM - -# define WEXITSTATUS(x) (x) - -/* There are no core dumps. */ -# define WCOREDUMP(x) 0 - -#endif - -#endif /* _GL_SYS_WAIT_H */ -#endif /* _GL_SYS_WAIT_H */ diff --git a/grub-core/gnulib/sysexits.in.h b/grub-core/gnulib/sysexits.in.h deleted file mode 100644 index 45255dfa5..000000000 --- a/grub-core/gnulib/sysexits.in.h +++ /dev/null @@ -1,71 +0,0 @@ -/* exit() exit codes for some BSD system programs. - Copyright (C) 2003, 2006-2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* Written by Simon Josefsson based on sysexits(3) man page */ - -#ifndef _GL_SYSEXITS_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -#if @HAVE_SYSEXITS_H@ - -/* IRIX 6.5 has an that defines a macro EX_OK with a nonzero - value. Override it. See - */ -# ifdef __sgi -# include -# undef EX_OK -# endif - -/* The include_next requires a split double-inclusion guard. */ -# @INCLUDE_NEXT@ @NEXT_SYSEXITS_H@ - -/* HP-UX 11 ends at EX_NOPERM. */ -# ifndef EX_CONFIG -# define EX_CONFIG 78 -# endif - -#endif - -#ifndef _GL_SYSEXITS_H -#define _GL_SYSEXITS_H - -#if !@HAVE_SYSEXITS_H@ - -# define EX_OK 0 /* same value as EXIT_SUCCESS */ - -# define EX_USAGE 64 -# define EX_DATAERR 65 -# define EX_NOINPUT 66 -# define EX_NOUSER 67 -# define EX_NOHOST 68 -# define EX_UNAVAILABLE 69 -# define EX_SOFTWARE 70 -# define EX_OSERR 71 -# define EX_OSFILE 72 -# define EX_CANTCREAT 73 -# define EX_IOERR 74 -# define EX_TEMPFAIL 75 -# define EX_PROTOCOL 76 -# define EX_NOPERM 77 -# define EX_CONFIG 78 - -#endif - -#endif /* _GL_SYSEXITS_H */ -#endif /* _GL_SYSEXITS_H */ diff --git a/grub-core/gnulib/unistd.in.h b/grub-core/gnulib/unistd.in.h deleted file mode 100644 index 26a4cbd6a..000000000 --- a/grub-core/gnulib/unistd.in.h +++ /dev/null @@ -1,1326 +0,0 @@ -/* Substitute for and wrapper around . - Copyright (C) 2003-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -/* Special invocation convention: - - On mingw, several headers, including , include , - but we need to ensure that both the system and - are completely included before we replace gethostname. */ -#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ \ - && !defined _GL_WINSOCK2_H_WITNESS && defined _WINSOCK2_H -/* is being indirectly included for the first time from - ; avoid declaring any overrides. */ -# if @HAVE_UNISTD_H@ -# @INCLUDE_NEXT@ @NEXT_UNISTD_H@ -# else -# error unexpected; report this to bug-gnulib@gnu.org -# endif -# define _GL_WINSOCK2_H_WITNESS - -/* Normal invocation. */ -#elif !defined _GL_UNISTD_H - -/* The include_next requires a split double-inclusion guard. */ -#if @HAVE_UNISTD_H@ -# @INCLUDE_NEXT@ @NEXT_UNISTD_H@ -#endif - -/* Get all possible declarations of gethostname(). */ -#if @GNULIB_GETHOSTNAME@ && @UNISTD_H_HAVE_WINSOCK2_H@ \ - && !defined _GL_INCLUDING_WINSOCK2_H -# define _GL_INCLUDING_WINSOCK2_H -# include -# undef _GL_INCLUDING_WINSOCK2_H -#endif - -#if !defined _GL_UNISTD_H && !defined _GL_INCLUDING_WINSOCK2_H -#define _GL_UNISTD_H - -/* NetBSD 5.0 mis-defines NULL. Also get size_t. */ -#include - -/* mingw doesn't define the SEEK_* or *_FILENO macros in . */ -/* Cygwin 1.7.1 declares symlinkat in , not in . */ -/* But avoid namespace pollution on glibc systems. */ -#if (!(defined SEEK_CUR && defined SEEK_END && defined SEEK_SET) \ - || (@GNULIB_SYMLINKAT@ || defined GNULIB_POSIXCHECK)) \ - && ! defined __GLIBC__ -# include -#endif - -/* Cygwin 1.7.1 declares unlinkat in , not in . */ -/* But avoid namespace pollution on glibc systems. */ -#if (@GNULIB_UNLINKAT@ || defined GNULIB_POSIXCHECK) && ! defined __GLIBC__ -# include -#endif - -/* mingw fails to declare _exit in . */ -/* mingw, BeOS, Haiku declare environ in , not in . */ -/* Solaris declares getcwd not only in but also in . */ -/* But avoid namespace pollution on glibc systems. */ -#ifndef __GLIBC__ -# include -#endif - -/* mingw declares getcwd in , not in . */ -#if ((@GNULIB_GETCWD@ || defined GNULIB_POSIXCHECK) \ - && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)) -# include -#endif - -#if (@GNULIB_WRITE@ || @GNULIB_READLINK@ || @GNULIB_READLINKAT@ \ - || @GNULIB_PREAD@ || @GNULIB_PWRITE@ || defined GNULIB_POSIXCHECK) -/* Get ssize_t. */ -# include -#endif - -/* Get getopt(), optarg, optind, opterr, optopt. - But avoid namespace pollution on glibc systems. */ -#if @GNULIB_UNISTD_H_GETOPT@ && !defined __GLIBC__ && !defined _GL_SYSTEM_GETOPT -# include -#endif - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - - -#if @GNULIB_GETHOSTNAME@ -/* Get all possible declarations of gethostname(). */ -# if @UNISTD_H_HAVE_WINSOCK2_H@ -# if !defined _GL_SYS_SOCKET_H -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef socket -# define socket socket_used_without_including_sys_socket_h -# undef connect -# define connect connect_used_without_including_sys_socket_h -# undef accept -# define accept accept_used_without_including_sys_socket_h -# undef bind -# define bind bind_used_without_including_sys_socket_h -# undef getpeername -# define getpeername getpeername_used_without_including_sys_socket_h -# undef getsockname -# define getsockname getsockname_used_without_including_sys_socket_h -# undef getsockopt -# define getsockopt getsockopt_used_without_including_sys_socket_h -# undef listen -# define listen listen_used_without_including_sys_socket_h -# undef recv -# define recv recv_used_without_including_sys_socket_h -# undef send -# define send send_used_without_including_sys_socket_h -# undef recvfrom -# define recvfrom recvfrom_used_without_including_sys_socket_h -# undef sendto -# define sendto sendto_used_without_including_sys_socket_h -# undef setsockopt -# define setsockopt setsockopt_used_without_including_sys_socket_h -# undef shutdown -# define shutdown shutdown_used_without_including_sys_socket_h -# else - _GL_WARN_ON_USE (socket, - "socket() used without including "); - _GL_WARN_ON_USE (connect, - "connect() used without including "); - _GL_WARN_ON_USE (accept, - "accept() used without including "); - _GL_WARN_ON_USE (bind, - "bind() used without including "); - _GL_WARN_ON_USE (getpeername, - "getpeername() used without including "); - _GL_WARN_ON_USE (getsockname, - "getsockname() used without including "); - _GL_WARN_ON_USE (getsockopt, - "getsockopt() used without including "); - _GL_WARN_ON_USE (listen, - "listen() used without including "); - _GL_WARN_ON_USE (recv, - "recv() used without including "); - _GL_WARN_ON_USE (send, - "send() used without including "); - _GL_WARN_ON_USE (recvfrom, - "recvfrom() used without including "); - _GL_WARN_ON_USE (sendto, - "sendto() used without including "); - _GL_WARN_ON_USE (setsockopt, - "setsockopt() used without including "); - _GL_WARN_ON_USE (shutdown, - "shutdown() used without including "); -# endif -# endif -# if !defined _GL_SYS_SELECT_H -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef select -# define select select_used_without_including_sys_select_h -# else - _GL_WARN_ON_USE (select, - "select() used without including "); -# endif -# endif -# endif -#endif - - -/* OS/2 EMX lacks these macros. */ -#ifndef STDIN_FILENO -# define STDIN_FILENO 0 -#endif -#ifndef STDOUT_FILENO -# define STDOUT_FILENO 1 -#endif -#ifndef STDERR_FILENO -# define STDERR_FILENO 2 -#endif - -/* Ensure *_OK macros exist. */ -#ifndef F_OK -# define F_OK 0 -# define X_OK 1 -# define W_OK 2 -# define R_OK 4 -#endif - - -/* Declare overridden functions. */ - - -#if defined GNULIB_POSIXCHECK -/* The access() function is a security risk. */ -_GL_WARN_ON_USE (access, "the access function is a security risk - " - "use the gnulib module faccessat instead"); -#endif - - -#if @GNULIB_CHOWN@ -/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE - to GID (if GID is not -1). Follow symbolic links. - Return 0 if successful, otherwise -1 and errno set. - See the POSIX:2001 specification - . */ -# if @REPLACE_CHOWN@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef chown -# define chown rpl_chown -# endif -_GL_FUNCDECL_RPL (chown, int, (const char *file, uid_t uid, gid_t gid) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (chown, int, (const char *file, uid_t uid, gid_t gid)); -# else -# if !@HAVE_CHOWN@ -_GL_FUNCDECL_SYS (chown, int, (const char *file, uid_t uid, gid_t gid) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (chown, int, (const char *file, uid_t uid, gid_t gid)); -# endif -_GL_CXXALIASWARN (chown); -#elif defined GNULIB_POSIXCHECK -# undef chown -# if HAVE_RAW_DECL_CHOWN -_GL_WARN_ON_USE (chown, "chown fails to follow symlinks on some systems and " - "doesn't treat a uid or gid of -1 on some systems - " - "use gnulib module chown for portability"); -# endif -#endif - - -#if @GNULIB_CLOSE@ -# if @REPLACE_CLOSE@ -/* Automatically included by modules that need a replacement for close. */ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef close -# define close rpl_close -# endif -_GL_FUNCDECL_RPL (close, int, (int fd)); -_GL_CXXALIAS_RPL (close, int, (int fd)); -# else -_GL_CXXALIAS_SYS (close, int, (int fd)); -# endif -_GL_CXXALIASWARN (close); -#elif @UNISTD_H_HAVE_WINSOCK2_H_AND_USE_SOCKETS@ -# undef close -# define close close_used_without_requesting_gnulib_module_close -#elif defined GNULIB_POSIXCHECK -# undef close -/* Assume close is always declared. */ -_GL_WARN_ON_USE (close, "close does not portably work on sockets - " - "use gnulib module close for portability"); -#endif - - -#if @REPLACE_DUP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define dup rpl_dup -# endif -_GL_FUNCDECL_RPL (dup, int, (int oldfd)); -_GL_CXXALIAS_RPL (dup, int, (int oldfd)); -#else -_GL_CXXALIAS_SYS (dup, int, (int oldfd)); -#endif -_GL_CXXALIASWARN (dup); - - -#if @GNULIB_DUP2@ -/* Copy the file descriptor OLDFD into file descriptor NEWFD. Do nothing if - NEWFD = OLDFD, otherwise close NEWFD first if it is open. - Return newfd if successful, otherwise -1 and errno set. - See the POSIX:2001 specification - . */ -# if @REPLACE_DUP2@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define dup2 rpl_dup2 -# endif -_GL_FUNCDECL_RPL (dup2, int, (int oldfd, int newfd)); -_GL_CXXALIAS_RPL (dup2, int, (int oldfd, int newfd)); -# else -# if !@HAVE_DUP2@ -_GL_FUNCDECL_SYS (dup2, int, (int oldfd, int newfd)); -# endif -_GL_CXXALIAS_SYS (dup2, int, (int oldfd, int newfd)); -# endif -_GL_CXXALIASWARN (dup2); -#elif defined GNULIB_POSIXCHECK -# undef dup2 -# if HAVE_RAW_DECL_DUP2 -_GL_WARN_ON_USE (dup2, "dup2 is unportable - " - "use gnulib module dup2 for portability"); -# endif -#endif - - -#if @GNULIB_DUP3@ -/* Copy the file descriptor OLDFD into file descriptor NEWFD, with the - specified flags. - The flags are a bitmask, possibly including O_CLOEXEC (defined in ) - and O_TEXT, O_BINARY (defined in "binary-io.h"). - Close NEWFD first if it is open. - Return newfd if successful, otherwise -1 and errno set. - See the Linux man page at - . */ -# if @HAVE_DUP3@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define dup3 rpl_dup3 -# endif -_GL_FUNCDECL_RPL (dup3, int, (int oldfd, int newfd, int flags)); -_GL_CXXALIAS_RPL (dup3, int, (int oldfd, int newfd, int flags)); -# else -_GL_FUNCDECL_SYS (dup3, int, (int oldfd, int newfd, int flags)); -_GL_CXXALIAS_SYS (dup3, int, (int oldfd, int newfd, int flags)); -# endif -_GL_CXXALIASWARN (dup3); -#elif defined GNULIB_POSIXCHECK -# undef dup3 -# if HAVE_RAW_DECL_DUP3 -_GL_WARN_ON_USE (dup3, "dup3 is unportable - " - "use gnulib module dup3 for portability"); -# endif -#endif - - -#if @GNULIB_ENVIRON@ -# if !@HAVE_DECL_ENVIRON@ -/* Set of environment variables and values. An array of strings of the form - "VARIABLE=VALUE", terminated with a NULL. */ -# if defined __APPLE__ && defined __MACH__ -# include -# define environ (*_NSGetEnviron ()) -# else -# ifdef __cplusplus -extern "C" { -# endif -extern char **environ; -# ifdef __cplusplus -} -# endif -# endif -# endif -#elif defined GNULIB_POSIXCHECK -# if HAVE_RAW_DECL_ENVIRON -static inline char *** -rpl_environ (void) -{ - return &environ; -} -_GL_WARN_ON_USE (rpl_environ, "environ is unportable - " - "use gnulib module environ for portability"); -# undef environ -# define environ (*rpl_environ ()) -# endif -#endif - - -#if @GNULIB_EUIDACCESS@ -/* Like access(), except that it uses the effective user id and group id of - the current process. */ -# if !@HAVE_EUIDACCESS@ -_GL_FUNCDECL_SYS (euidaccess, int, (const char *filename, int mode) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (euidaccess, int, (const char *filename, int mode)); -_GL_CXXALIASWARN (euidaccess); -# if defined GNULIB_POSIXCHECK -/* Like access(), this function is a security risk. */ -_GL_WARN_ON_USE (euidaccess, "the euidaccess function is a security risk - " - "use the gnulib module faccessat instead"); -# endif -#elif defined GNULIB_POSIXCHECK -# undef euidaccess -# if HAVE_RAW_DECL_EUIDACCESS -_GL_WARN_ON_USE (euidaccess, "euidaccess is unportable - " - "use gnulib module euidaccess for portability"); -# endif -#endif - - -#if @GNULIB_FACCESSAT@ -# if !@HAVE_FACCESSAT@ -_GL_FUNCDECL_SYS (faccessat, int, - (int fd, char const *file, int mode, int flag) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (faccessat, int, - (int fd, char const *file, int mode, int flag)); -_GL_CXXALIASWARN (faccessat); -#elif defined GNULIB_POSIXCHECK -# undef faccessat -# if HAVE_RAW_DECL_FACCESSAT -_GL_WARN_ON_USE (faccessat, "faccessat is not portable - " - "use gnulib module faccessat for portability"); -# endif -#endif - - -#if @GNULIB_FCHDIR@ -/* Change the process' current working directory to the directory on which - the given file descriptor is open. - Return 0 if successful, otherwise -1 and errno set. - See the POSIX:2001 specification - . */ -# if ! @HAVE_FCHDIR@ -_GL_FUNCDECL_SYS (fchdir, int, (int /*fd*/)); - -/* Gnulib internal hooks needed to maintain the fchdir metadata. */ -_GL_EXTERN_C int _gl_register_fd (int fd, const char *filename) - _GL_ARG_NONNULL ((2)); -_GL_EXTERN_C void _gl_unregister_fd (int fd); -_GL_EXTERN_C int _gl_register_dup (int oldfd, int newfd); -_GL_EXTERN_C const char *_gl_directory_name (int fd); - -# endif -_GL_CXXALIAS_SYS (fchdir, int, (int /*fd*/)); -_GL_CXXALIASWARN (fchdir); -#elif defined GNULIB_POSIXCHECK -# undef fchdir -# if HAVE_RAW_DECL_FCHDIR -_GL_WARN_ON_USE (fchdir, "fchdir is unportable - " - "use gnulib module fchdir for portability"); -# endif -#endif - - -#if @GNULIB_FCHOWNAT@ -# if @REPLACE_FCHOWNAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef fchownat -# define fchownat rpl_fchownat -# endif -_GL_FUNCDECL_RPL (fchownat, int, (int fd, char const *file, - uid_t owner, gid_t group, int flag) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (fchownat, int, (int fd, char const *file, - uid_t owner, gid_t group, int flag)); -# else -# if !@HAVE_FCHOWNAT@ -_GL_FUNCDECL_SYS (fchownat, int, (int fd, char const *file, - uid_t owner, gid_t group, int flag) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (fchownat, int, (int fd, char const *file, - uid_t owner, gid_t group, int flag)); -# endif -_GL_CXXALIASWARN (fchownat); -#elif defined GNULIB_POSIXCHECK -# undef fchownat -# if HAVE_RAW_DECL_FCHOWNAT -_GL_WARN_ON_USE (fchownat, "fchownat is not portable - " - "use gnulib module openat for portability"); -# endif -#endif - - -#if @GNULIB_FSYNC@ -/* Synchronize changes to a file. - Return 0 if successful, otherwise -1 and errno set. - See POSIX:2001 specification - . */ -# if !@HAVE_FSYNC@ -_GL_FUNCDECL_SYS (fsync, int, (int fd)); -# endif -_GL_CXXALIAS_SYS (fsync, int, (int fd)); -_GL_CXXALIASWARN (fsync); -#elif defined GNULIB_POSIXCHECK -# undef fsync -# if HAVE_RAW_DECL_FSYNC -_GL_WARN_ON_USE (fsync, "fsync is unportable - " - "use gnulib module fsync for portability"); -# endif -#endif - - -#if @GNULIB_FTRUNCATE@ -/* Change the size of the file to which FD is opened to become equal to LENGTH. - Return 0 if successful, otherwise -1 and errno set. - See the POSIX:2001 specification - . */ -# if !@HAVE_FTRUNCATE@ -_GL_FUNCDECL_SYS (ftruncate, int, (int fd, off_t length)); -# endif -_GL_CXXALIAS_SYS (ftruncate, int, (int fd, off_t length)); -_GL_CXXALIASWARN (ftruncate); -#elif defined GNULIB_POSIXCHECK -# undef ftruncate -# if HAVE_RAW_DECL_FTRUNCATE -_GL_WARN_ON_USE (ftruncate, "ftruncate is unportable - " - "use gnulib module ftruncate for portability"); -# endif -#endif - - -#if @GNULIB_GETCWD@ -/* Get the name of the current working directory, and put it in SIZE bytes - of BUF. - Return BUF if successful, or NULL if the directory couldn't be determined - or SIZE was too small. - See the POSIX:2001 specification - . - Additionally, the gnulib module 'getcwd' guarantees the following GNU - extension: If BUF is NULL, an array is allocated with 'malloc'; the array - is SIZE bytes long, unless SIZE == 0, in which case it is as big as - necessary. */ -# if @REPLACE_GETCWD@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define getcwd rpl_getcwd -# endif -_GL_FUNCDECL_RPL (getcwd, char *, (char *buf, size_t size)); -_GL_CXXALIAS_RPL (getcwd, char *, (char *buf, size_t size)); -# else -/* Need to cast, because on mingw, the second parameter is - int size. */ -_GL_CXXALIAS_SYS_CAST (getcwd, char *, (char *buf, size_t size)); -# endif -_GL_CXXALIASWARN (getcwd); -#elif defined GNULIB_POSIXCHECK -# undef getcwd -# if HAVE_RAW_DECL_GETCWD -_GL_WARN_ON_USE (getcwd, "getcwd is unportable - " - "use gnulib module getcwd for portability"); -# endif -#endif - - -#if @GNULIB_GETDOMAINNAME@ -/* Return the NIS domain name of the machine. - WARNING! The NIS domain name is unrelated to the fully qualified host name - of the machine. It is also unrelated to email addresses. - WARNING! The NIS domain name is usually the empty string or "(none)" when - not using NIS. - - Put up to LEN bytes of the NIS domain name into NAME. - Null terminate it if the name is shorter than LEN. - If the NIS domain name is longer than LEN, set errno = EINVAL and return -1. - Return 0 if successful, otherwise set errno and return -1. */ -# if !@HAVE_GETDOMAINNAME@ -_GL_FUNCDECL_SYS (getdomainname, int, (char *name, size_t len) - _GL_ARG_NONNULL ((1))); -# endif -/* Need to cast, because on MacOS X 10.5 systems, the second parameter is - int len. */ -_GL_CXXALIAS_SYS_CAST (getdomainname, int, (char *name, size_t len)); -_GL_CXXALIASWARN (getdomainname); -#elif defined GNULIB_POSIXCHECK -# undef getdomainname -# if HAVE_RAW_DECL_GETDOMAINNAME -_GL_WARN_ON_USE (getdomainname, "getdomainname is unportable - " - "use gnulib module getdomainname for portability"); -# endif -#endif - - -#if @GNULIB_GETDTABLESIZE@ -/* Return the maximum number of file descriptors in the current process. - In POSIX, this is same as sysconf (_SC_OPEN_MAX). */ -# if !@HAVE_GETDTABLESIZE@ -_GL_FUNCDECL_SYS (getdtablesize, int, (void)); -# endif -_GL_CXXALIAS_SYS (getdtablesize, int, (void)); -_GL_CXXALIASWARN (getdtablesize); -#elif defined GNULIB_POSIXCHECK -# undef getdtablesize -# if HAVE_RAW_DECL_GETDTABLESIZE -_GL_WARN_ON_USE (getdtablesize, "getdtablesize is unportable - " - "use gnulib module getdtablesize for portability"); -# endif -#endif - - -#if @GNULIB_GETGROUPS@ -/* Return the supplemental groups that the current process belongs to. - It is unspecified whether the effective group id is in the list. - If N is 0, return the group count; otherwise, N describes how many - entries are available in GROUPS. Return -1 and set errno if N is - not 0 and not large enough. Fails with ENOSYS on some systems. */ -# if @REPLACE_GETGROUPS@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef getgroups -# define getgroups rpl_getgroups -# endif -_GL_FUNCDECL_RPL (getgroups, int, (int n, gid_t *groups)); -_GL_CXXALIAS_RPL (getgroups, int, (int n, gid_t *groups)); -# else -# if !@HAVE_GETGROUPS@ -_GL_FUNCDECL_SYS (getgroups, int, (int n, gid_t *groups)); -# endif -_GL_CXXALIAS_SYS (getgroups, int, (int n, gid_t *groups)); -# endif -_GL_CXXALIASWARN (getgroups); -#elif defined GNULIB_POSIXCHECK -# undef getgroups -# if HAVE_RAW_DECL_GETGROUPS -_GL_WARN_ON_USE (getgroups, "getgroups is unportable - " - "use gnulib module getgroups for portability"); -# endif -#endif - - -#if @GNULIB_GETHOSTNAME@ -/* Return the standard host name of the machine. - WARNING! The host name may or may not be fully qualified. - - Put up to LEN bytes of the host name into NAME. - Null terminate it if the name is shorter than LEN. - If the host name is longer than LEN, set errno = EINVAL and return -1. - Return 0 if successful, otherwise set errno and return -1. */ -# if @UNISTD_H_HAVE_WINSOCK2_H@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef gethostname -# define gethostname rpl_gethostname -# endif -_GL_FUNCDECL_RPL (gethostname, int, (char *name, size_t len) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (gethostname, int, (char *name, size_t len)); -# else -# if !@HAVE_GETHOSTNAME@ -_GL_FUNCDECL_SYS (gethostname, int, (char *name, size_t len) - _GL_ARG_NONNULL ((1))); -# endif -/* Need to cast, because on Solaris 10 systems, the second parameter is - int len. */ -_GL_CXXALIAS_SYS_CAST (gethostname, int, (char *name, size_t len)); -# endif -_GL_CXXALIASWARN (gethostname); -#elif @UNISTD_H_HAVE_WINSOCK2_H@ -# undef gethostname -# define gethostname gethostname_used_without_requesting_gnulib_module_gethostname -#elif defined GNULIB_POSIXCHECK -# undef gethostname -# if HAVE_RAW_DECL_GETHOSTNAME -_GL_WARN_ON_USE (gethostname, "gethostname is unportable - " - "use gnulib module gethostname for portability"); -# endif -#endif - - -#if @GNULIB_GETLOGIN@ -/* Returns the user's login name, or NULL if it cannot be found. Upon error, - returns NULL with errno set. - - See . - - Most programs don't need to use this function, because the information is - available through environment variables: - ${LOGNAME-$USER} on Unix platforms, - $USERNAME on native Windows platforms. - */ -# if !@HAVE_GETLOGIN@ -_GL_FUNCDECL_SYS (getlogin, char *, (void)); -# endif -_GL_CXXALIAS_SYS (getlogin, char *, (void)); -_GL_CXXALIASWARN (getlogin); -#elif defined GNULIB_POSIXCHECK -# undef getlogin -# if HAVE_RAW_DECL_GETLOGIN -_GL_WARN_ON_USE (getlogin, "getlogin is unportable - " - "use gnulib module getlogin for portability"); -# endif -#endif - - -#if @GNULIB_GETLOGIN_R@ -/* Copies the user's login name to NAME. - The array pointed to by NAME has room for SIZE bytes. - - Returns 0 if successful. Upon error, an error number is returned, or -1 in - the case that the login name cannot be found but no specific error is - provided (this case is hopefully rare but is left open by the POSIX spec). - - See . - - Most programs don't need to use this function, because the information is - available through environment variables: - ${LOGNAME-$USER} on Unix platforms, - $USERNAME on native Windows platforms. - */ -# if !@HAVE_DECL_GETLOGIN_R@ -_GL_FUNCDECL_SYS (getlogin_r, int, (char *name, size_t size) - _GL_ARG_NONNULL ((1))); -# endif -/* Need to cast, because on Solaris 10 systems, the second argument is - int size. */ -_GL_CXXALIAS_SYS_CAST (getlogin_r, int, (char *name, size_t size)); -_GL_CXXALIASWARN (getlogin_r); -#elif defined GNULIB_POSIXCHECK -# undef getlogin_r -# if HAVE_RAW_DECL_GETLOGIN_R -_GL_WARN_ON_USE (getlogin_r, "getlogin_r is unportable - " - "use gnulib module getlogin_r for portability"); -# endif -#endif - - -#if @GNULIB_GETPAGESIZE@ -# if @REPLACE_GETPAGESIZE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define getpagesize rpl_getpagesize -# endif -_GL_FUNCDECL_RPL (getpagesize, int, (void)); -_GL_CXXALIAS_RPL (getpagesize, int, (void)); -# else -# if !@HAVE_GETPAGESIZE@ -# if !defined getpagesize -/* This is for POSIX systems. */ -# if !defined _gl_getpagesize && defined _SC_PAGESIZE -# if ! (defined __VMS && __VMS_VER < 70000000) -# define _gl_getpagesize() sysconf (_SC_PAGESIZE) -# endif -# endif -/* This is for older VMS. */ -# if !defined _gl_getpagesize && defined __VMS -# ifdef __ALPHA -# define _gl_getpagesize() 8192 -# else -# define _gl_getpagesize() 512 -# endif -# endif -/* This is for BeOS. */ -# if !defined _gl_getpagesize && @HAVE_OS_H@ -# include -# if defined B_PAGE_SIZE -# define _gl_getpagesize() B_PAGE_SIZE -# endif -# endif -/* This is for AmigaOS4.0. */ -# if !defined _gl_getpagesize && defined __amigaos4__ -# define _gl_getpagesize() 2048 -# endif -/* This is for older Unix systems. */ -# if !defined _gl_getpagesize && @HAVE_SYS_PARAM_H@ -# include -# ifdef EXEC_PAGESIZE -# define _gl_getpagesize() EXEC_PAGESIZE -# else -# ifdef NBPG -# ifndef CLSIZE -# define CLSIZE 1 -# endif -# define _gl_getpagesize() (NBPG * CLSIZE) -# else -# ifdef NBPC -# define _gl_getpagesize() NBPC -# endif -# endif -# endif -# endif -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define getpagesize() _gl_getpagesize () -# else -static inline int -getpagesize () -{ - return _gl_getpagesize (); -} -# endif -# endif -# endif -/* Need to cast, because on Cygwin 1.5.x systems, the return type is size_t. */ -_GL_CXXALIAS_SYS_CAST (getpagesize, int, (void)); -# endif -# if @HAVE_DECL_GETPAGESIZE@ -_GL_CXXALIASWARN (getpagesize); -# endif -#elif defined GNULIB_POSIXCHECK -# undef getpagesize -# if HAVE_RAW_DECL_GETPAGESIZE -_GL_WARN_ON_USE (getpagesize, "getpagesize is unportable - " - "use gnulib module getpagesize for portability"); -# endif -#endif - - -#if @GNULIB_GETUSERSHELL@ -/* Return the next valid login shell on the system, or NULL when the end of - the list has been reached. */ -# if !@HAVE_DECL_GETUSERSHELL@ -_GL_FUNCDECL_SYS (getusershell, char *, (void)); -# endif -_GL_CXXALIAS_SYS (getusershell, char *, (void)); -_GL_CXXALIASWARN (getusershell); -#elif defined GNULIB_POSIXCHECK -# undef getusershell -# if HAVE_RAW_DECL_GETUSERSHELL -_GL_WARN_ON_USE (getusershell, "getusershell is unportable - " - "use gnulib module getusershell for portability"); -# endif -#endif - -#if @GNULIB_GETUSERSHELL@ -/* Rewind to pointer that is advanced at each getusershell() call. */ -# if !@HAVE_DECL_GETUSERSHELL@ -_GL_FUNCDECL_SYS (setusershell, void, (void)); -# endif -_GL_CXXALIAS_SYS (setusershell, void, (void)); -_GL_CXXALIASWARN (setusershell); -#elif defined GNULIB_POSIXCHECK -# undef setusershell -# if HAVE_RAW_DECL_SETUSERSHELL -_GL_WARN_ON_USE (setusershell, "setusershell is unportable - " - "use gnulib module getusershell for portability"); -# endif -#endif - -#if @GNULIB_GETUSERSHELL@ -/* Free the pointer that is advanced at each getusershell() call and - associated resources. */ -# if !@HAVE_DECL_GETUSERSHELL@ -_GL_FUNCDECL_SYS (endusershell, void, (void)); -# endif -_GL_CXXALIAS_SYS (endusershell, void, (void)); -_GL_CXXALIASWARN (endusershell); -#elif defined GNULIB_POSIXCHECK -# undef endusershell -# if HAVE_RAW_DECL_ENDUSERSHELL -_GL_WARN_ON_USE (endusershell, "endusershell is unportable - " - "use gnulib module getusershell for portability"); -# endif -#endif - - -#if @GNULIB_LCHOWN@ -/* Change the owner of FILE to UID (if UID is not -1) and the group of FILE - to GID (if GID is not -1). Do not follow symbolic links. - Return 0 if successful, otherwise -1 and errno set. - See the POSIX:2001 specification - . */ -# if @REPLACE_LCHOWN@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef lchown -# define lchown rpl_lchown -# endif -_GL_FUNCDECL_RPL (lchown, int, (char const *file, uid_t owner, gid_t group) - _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (lchown, int, (char const *file, uid_t owner, gid_t group)); -# else -# if !@HAVE_LCHOWN@ -_GL_FUNCDECL_SYS (lchown, int, (char const *file, uid_t owner, gid_t group) - _GL_ARG_NONNULL ((1))); -# endif -_GL_CXXALIAS_SYS (lchown, int, (char const *file, uid_t owner, gid_t group)); -# endif -_GL_CXXALIASWARN (lchown); -#elif defined GNULIB_POSIXCHECK -# undef lchown -# if HAVE_RAW_DECL_LCHOWN -_GL_WARN_ON_USE (lchown, "lchown is unportable to pre-POSIX.1-2001 systems - " - "use gnulib module lchown for portability"); -# endif -#endif - - -#if @GNULIB_LINK@ -/* Create a new hard link for an existing file. - Return 0 if successful, otherwise -1 and errno set. - See POSIX:2001 specification - . */ -# if @REPLACE_LINK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define link rpl_link -# endif -_GL_FUNCDECL_RPL (link, int, (const char *path1, const char *path2) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (link, int, (const char *path1, const char *path2)); -# else -# if !@HAVE_LINK@ -_GL_FUNCDECL_SYS (link, int, (const char *path1, const char *path2) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (link, int, (const char *path1, const char *path2)); -# endif -_GL_CXXALIASWARN (link); -#elif defined GNULIB_POSIXCHECK -# undef link -# if HAVE_RAW_DECL_LINK -_GL_WARN_ON_USE (link, "link is unportable - " - "use gnulib module link for portability"); -# endif -#endif - - -#if @GNULIB_LINKAT@ -/* Create a new hard link for an existing file, relative to two - directories. FLAG controls whether symlinks are followed. - Return 0 if successful, otherwise -1 and errno set. */ -# if @REPLACE_LINKAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef linkat -# define linkat rpl_linkat -# endif -_GL_FUNCDECL_RPL (linkat, int, - (int fd1, const char *path1, int fd2, const char *path2, - int flag) - _GL_ARG_NONNULL ((2, 4))); -_GL_CXXALIAS_RPL (linkat, int, - (int fd1, const char *path1, int fd2, const char *path2, - int flag)); -# else -# if !@HAVE_LINKAT@ -_GL_FUNCDECL_SYS (linkat, int, - (int fd1, const char *path1, int fd2, const char *path2, - int flag) - _GL_ARG_NONNULL ((2, 4))); -# endif -_GL_CXXALIAS_SYS (linkat, int, - (int fd1, const char *path1, int fd2, const char *path2, - int flag)); -# endif -_GL_CXXALIASWARN (linkat); -#elif defined GNULIB_POSIXCHECK -# undef linkat -# if HAVE_RAW_DECL_LINKAT -_GL_WARN_ON_USE (linkat, "linkat is unportable - " - "use gnulib module linkat for portability"); -# endif -#endif - - -#if @GNULIB_LSEEK@ -/* Set the offset of FD relative to SEEK_SET, SEEK_CUR, or SEEK_END. - Return the new offset if successful, otherwise -1 and errno set. - See the POSIX:2001 specification - . */ -# if @REPLACE_LSEEK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define lseek rpl_lseek -# endif -_GL_FUNCDECL_RPL (lseek, off_t, (int fd, off_t offset, int whence)); -_GL_CXXALIAS_RPL (lseek, off_t, (int fd, off_t offset, int whence)); -# else -_GL_CXXALIAS_SYS (lseek, off_t, (int fd, off_t offset, int whence)); -# endif -_GL_CXXALIASWARN (lseek); -#elif defined GNULIB_POSIXCHECK -# undef lseek -# if HAVE_RAW_DECL_LSEEK -_GL_WARN_ON_USE (lseek, "lseek does not fail with ESPIPE on pipes on some " - "systems - use gnulib module lseek for portability"); -# endif -#endif - - -#if @GNULIB_PIPE2@ -/* Create a pipe, applying the given flags when opening the read-end of the - pipe and the write-end of the pipe. - The flags are a bitmask, possibly including O_CLOEXEC (defined in ) - and O_TEXT, O_BINARY (defined in "binary-io.h"). - Store the read-end as fd[0] and the write-end as fd[1]. - Return 0 upon success, or -1 with errno set upon failure. - See also the Linux man page at - . */ -# if @HAVE_PIPE2@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define pipe2 rpl_pipe2 -# endif -_GL_FUNCDECL_RPL (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (pipe2, int, (int fd[2], int flags)); -# else -_GL_FUNCDECL_SYS (pipe2, int, (int fd[2], int flags) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_SYS (pipe2, int, (int fd[2], int flags)); -# endif -_GL_CXXALIASWARN (pipe2); -#elif defined GNULIB_POSIXCHECK -# undef pipe2 -# if HAVE_RAW_DECL_PIPE2 -_GL_WARN_ON_USE (pipe2, "pipe2 is unportable - " - "use gnulib module pipe2 for portability"); -# endif -#endif - - -#if @GNULIB_PREAD@ -/* Read at most BUFSIZE bytes from FD into BUF, starting at OFFSET. - Return the number of bytes placed into BUF if successful, otherwise - set errno and return -1. 0 indicates EOF. See the POSIX:2001 - specification . */ -# if @REPLACE_PREAD@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define pread rpl_pread -# endif -_GL_FUNCDECL_RPL (pread, ssize_t, - (int fd, void *buf, size_t bufsize, off_t offset) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (pread, ssize_t, - (int fd, void *buf, size_t bufsize, off_t offset)); -# else -# if !@HAVE_PREAD@ -_GL_FUNCDECL_SYS (pread, ssize_t, - (int fd, void *buf, size_t bufsize, off_t offset) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (pread, ssize_t, - (int fd, void *buf, size_t bufsize, off_t offset)); -# endif -_GL_CXXALIASWARN (pread); -#elif defined GNULIB_POSIXCHECK -# undef pread -# if HAVE_RAW_DECL_PREAD -_GL_WARN_ON_USE (pread, "pread is unportable - " - "use gnulib module pread for portability"); -# endif -#endif - - -#if @GNULIB_PWRITE@ -/* Write at most BUFSIZE bytes from BUF into FD, starting at OFFSET. - Return the number of bytes written if successful, otherwise - set errno and return -1. 0 indicates nothing written. See the - POSIX:2001 specification - . */ -# if @REPLACE_PWRITE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define pwrite rpl_pwrite -# endif -_GL_FUNCDECL_RPL (pwrite, ssize_t, - (int fd, const void *buf, size_t bufsize, off_t offset) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (pwrite, ssize_t, - (int fd, const void *buf, size_t bufsize, off_t offset)); -# else -# if !@HAVE_PWRITE@ -_GL_FUNCDECL_SYS (pwrite, ssize_t, - (int fd, const void *buf, size_t bufsize, off_t offset) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (pwrite, ssize_t, - (int fd, const void *buf, size_t bufsize, off_t offset)); -# endif -_GL_CXXALIASWARN (pwrite); -#elif defined GNULIB_POSIXCHECK -# undef pwrite -# if HAVE_RAW_DECL_PWRITE -_GL_WARN_ON_USE (pwrite, "pwrite is unportable - " - "use gnulib module pwrite for portability"); -# endif -#endif - - -#if @GNULIB_READLINK@ -/* Read the contents of the symbolic link FILE and place the first BUFSIZE - bytes of it into BUF. Return the number of bytes placed into BUF if - successful, otherwise -1 and errno set. - See the POSIX:2001 specification - . */ -# if @REPLACE_READLINK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define readlink rpl_readlink -# endif -_GL_FUNCDECL_RPL (readlink, ssize_t, - (const char *file, char *buf, size_t bufsize) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (readlink, ssize_t, - (const char *file, char *buf, size_t bufsize)); -# else -# if !@HAVE_READLINK@ -_GL_FUNCDECL_SYS (readlink, ssize_t, - (const char *file, char *buf, size_t bufsize) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (readlink, ssize_t, - (const char *file, char *buf, size_t bufsize)); -# endif -_GL_CXXALIASWARN (readlink); -#elif defined GNULIB_POSIXCHECK -# undef readlink -# if HAVE_RAW_DECL_READLINK -_GL_WARN_ON_USE (readlink, "readlink is unportable - " - "use gnulib module readlink for portability"); -# endif -#endif - - -#if @GNULIB_READLINKAT@ -# if !@HAVE_READLINKAT@ -_GL_FUNCDECL_SYS (readlinkat, ssize_t, - (int fd, char const *file, char *buf, size_t len) - _GL_ARG_NONNULL ((2, 3))); -# endif -_GL_CXXALIAS_SYS (readlinkat, ssize_t, - (int fd, char const *file, char *buf, size_t len)); -_GL_CXXALIASWARN (readlinkat); -#elif defined GNULIB_POSIXCHECK -# undef readlinkat -# if HAVE_RAW_DECL_READLINKAT -_GL_WARN_ON_USE (readlinkat, "readlinkat is not portable - " - "use gnulib module readlinkat for portability"); -# endif -#endif - - -#if @GNULIB_RMDIR@ -/* Remove the directory DIR. */ -# if @REPLACE_RMDIR@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define rmdir rpl_rmdir -# endif -_GL_FUNCDECL_RPL (rmdir, int, (char const *name) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (rmdir, int, (char const *name)); -# else -_GL_CXXALIAS_SYS (rmdir, int, (char const *name)); -# endif -_GL_CXXALIASWARN (rmdir); -#elif defined GNULIB_POSIXCHECK -# undef rmdir -# if HAVE_RAW_DECL_RMDIR -_GL_WARN_ON_USE (rmdir, "rmdir is unportable - " - "use gnulib module rmdir for portability"); -# endif -#endif - - -#if @GNULIB_SLEEP@ -/* Pause the execution of the current thread for N seconds. - Returns the number of seconds left to sleep. - See the POSIX:2001 specification - . */ -# if @REPLACE_SLEEP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef sleep -# define sleep rpl_sleep -# endif -_GL_FUNCDECL_RPL (sleep, unsigned int, (unsigned int n)); -_GL_CXXALIAS_RPL (sleep, unsigned int, (unsigned int n)); -# else -# if !@HAVE_SLEEP@ -_GL_FUNCDECL_SYS (sleep, unsigned int, (unsigned int n)); -# endif -_GL_CXXALIAS_SYS (sleep, unsigned int, (unsigned int n)); -# endif -_GL_CXXALIASWARN (sleep); -#elif defined GNULIB_POSIXCHECK -# undef sleep -# if HAVE_RAW_DECL_SLEEP -_GL_WARN_ON_USE (sleep, "sleep is unportable - " - "use gnulib module sleep for portability"); -# endif -#endif - - -#if @GNULIB_SYMLINK@ -# if @REPLACE_SYMLINK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef symlink -# define symlink rpl_symlink -# endif -_GL_FUNCDECL_RPL (symlink, int, (char const *contents, char const *file) - _GL_ARG_NONNULL ((1, 2))); -_GL_CXXALIAS_RPL (symlink, int, (char const *contents, char const *file)); -# else -# if !@HAVE_SYMLINK@ -_GL_FUNCDECL_SYS (symlink, int, (char const *contents, char const *file) - _GL_ARG_NONNULL ((1, 2))); -# endif -_GL_CXXALIAS_SYS (symlink, int, (char const *contents, char const *file)); -# endif -_GL_CXXALIASWARN (symlink); -#elif defined GNULIB_POSIXCHECK -# undef symlink -# if HAVE_RAW_DECL_SYMLINK -_GL_WARN_ON_USE (symlink, "symlink is not portable - " - "use gnulib module symlink for portability"); -# endif -#endif - - -#if @GNULIB_SYMLINKAT@ -# if !@HAVE_SYMLINKAT@ -_GL_FUNCDECL_SYS (symlinkat, int, - (char const *contents, int fd, char const *file) - _GL_ARG_NONNULL ((1, 3))); -# endif -_GL_CXXALIAS_SYS (symlinkat, int, - (char const *contents, int fd, char const *file)); -_GL_CXXALIASWARN (symlinkat); -#elif defined GNULIB_POSIXCHECK -# undef symlinkat -# if HAVE_RAW_DECL_SYMLINKAT -_GL_WARN_ON_USE (symlinkat, "symlinkat is not portable - " - "use gnulib module symlinkat for portability"); -# endif -#endif - - -#if @GNULIB_TTYNAME_R@ -/* Store at most BUFLEN characters of the pathname of the terminal FD is - open on in BUF. Return 0 on success, otherwise an error number. */ -# if @REPLACE_TTYNAME_R@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef ttyname_r -# define ttyname_r rpl_ttyname_r -# endif -_GL_FUNCDECL_RPL (ttyname_r, int, - (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (ttyname_r, int, - (int fd, char *buf, size_t buflen)); -# else -# if !@HAVE_TTYNAME_R@ -_GL_FUNCDECL_SYS (ttyname_r, int, - (int fd, char *buf, size_t buflen) _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (ttyname_r, int, - (int fd, char *buf, size_t buflen)); -# endif -_GL_CXXALIASWARN (ttyname_r); -#elif defined GNULIB_POSIXCHECK -# undef ttyname_r -# if HAVE_RAW_DECL_TTYNAME_R -_GL_WARN_ON_USE (ttyname_r, "ttyname_r is not portable - " - "use gnulib module ttyname_r for portability"); -# endif -#endif - - -#if @GNULIB_UNLINK@ -# if @REPLACE_UNLINK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef unlink -# define unlink rpl_unlink -# endif -_GL_FUNCDECL_RPL (unlink, int, (char const *file) _GL_ARG_NONNULL ((1))); -_GL_CXXALIAS_RPL (unlink, int, (char const *file)); -# else -_GL_CXXALIAS_SYS (unlink, int, (char const *file)); -# endif -_GL_CXXALIASWARN (unlink); -#elif defined GNULIB_POSIXCHECK -# undef unlink -# if HAVE_RAW_DECL_UNLINK -_GL_WARN_ON_USE (unlink, "unlink is not portable - " - "use gnulib module unlink for portability"); -# endif -#endif - - -#if @GNULIB_UNLINKAT@ -# if @REPLACE_UNLINKAT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef unlinkat -# define unlinkat rpl_unlinkat -# endif -_GL_FUNCDECL_RPL (unlinkat, int, (int fd, char const *file, int flag) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (unlinkat, int, (int fd, char const *file, int flag)); -# else -# if !@HAVE_UNLINKAT@ -_GL_FUNCDECL_SYS (unlinkat, int, (int fd, char const *file, int flag) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (unlinkat, int, (int fd, char const *file, int flag)); -# endif -_GL_CXXALIASWARN (unlinkat); -#elif defined GNULIB_POSIXCHECK -# undef unlinkat -# if HAVE_RAW_DECL_UNLINKAT -_GL_WARN_ON_USE (unlinkat, "unlinkat is not portable - " - "use gnulib module openat for portability"); -# endif -#endif - - -#if @GNULIB_USLEEP@ -/* Pause the execution of the current thread for N microseconds. - Returns 0 on completion, or -1 on range error. - See the POSIX:2001 specification - . */ -# if @REPLACE_USLEEP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef usleep -# define usleep rpl_usleep -# endif -_GL_FUNCDECL_RPL (usleep, int, (useconds_t n)); -_GL_CXXALIAS_RPL (usleep, int, (useconds_t n)); -# else -# if !@HAVE_USLEEP@ -_GL_FUNCDECL_SYS (usleep, int, (useconds_t n)); -# endif -_GL_CXXALIAS_SYS (usleep, int, (useconds_t n)); -# endif -_GL_CXXALIASWARN (usleep); -#elif defined GNULIB_POSIXCHECK -# undef usleep -# if HAVE_RAW_DECL_USLEEP -_GL_WARN_ON_USE (usleep, "usleep is unportable - " - "use gnulib module usleep for portability"); -# endif -#endif - - -#if @GNULIB_WRITE@ -/* Write up to COUNT bytes starting at BUF to file descriptor FD. - See the POSIX:2001 specification - . */ -# if @REPLACE_WRITE@ && @GNULIB_UNISTD_H_SIGPIPE@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef write -# define write rpl_write -# endif -_GL_FUNCDECL_RPL (write, ssize_t, (int fd, const void *buf, size_t count) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (write, ssize_t, (int fd, const void *buf, size_t count)); -# else -/* Need to cast, because on mingw, the third parameter is - unsigned int count - and the return type is 'int'. */ -_GL_CXXALIAS_SYS_CAST (write, ssize_t, (int fd, const void *buf, size_t count)); -# endif -_GL_CXXALIASWARN (write); -#endif - - -#endif /* _GL_UNISTD_H */ -#endif /* _GL_UNISTD_H */ diff --git a/grub-core/gnulib/vasnprintf.c b/grub-core/gnulib/vasnprintf.c deleted file mode 100644 index e618901ba..000000000 --- a/grub-core/gnulib/vasnprintf.c +++ /dev/null @@ -1,5567 +0,0 @@ -/* vsprintf with automatic memory allocation. - Copyright (C) 1999, 2002-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* This file can be parametrized with the following macros: - VASNPRINTF The name of the function being defined. - FCHAR_T The element type of the format string. - DCHAR_T The element type of the destination (result) string. - FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters - in the format string are ASCII. MUST be set if - FCHAR_T and DCHAR_T are not the same type. - DIRECTIVE Structure denoting a format directive. - Depends on FCHAR_T. - DIRECTIVES Structure denoting the set of format directives of a - format string. Depends on FCHAR_T. - PRINTF_PARSE Function that parses a format string. - Depends on FCHAR_T. - DCHAR_CPY memcpy like function for DCHAR_T[] arrays. - DCHAR_SET memset like function for DCHAR_T[] arrays. - DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays. - SNPRINTF The system's snprintf (or similar) function. - This may be either snprintf or swprintf. - TCHAR_T The element type of the argument and result string - of the said SNPRINTF function. This may be either - char or wchar_t. The code exploits that - sizeof (TCHAR_T) | sizeof (DCHAR_T) and - alignof (TCHAR_T) <= alignof (DCHAR_T). - DCHAR_IS_TCHAR Set to 1 if DCHAR_T and TCHAR_T are the same type. - DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[]. - DCHAR_IS_UINT8_T Set to 1 if DCHAR_T is uint8_t. - DCHAR_IS_UINT16_T Set to 1 if DCHAR_T is uint16_t. - DCHAR_IS_UINT32_T Set to 1 if DCHAR_T is uint32_t. */ - -/* Tell glibc's to provide a prototype for snprintf(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifndef VASNPRINTF -# include -#endif -#ifndef IN_LIBINTL -# include -#endif - -/* Specification. */ -#ifndef VASNPRINTF -# if WIDE_CHAR_VERSION -# include "vasnwprintf.h" -# else -# include "vasnprintf.h" -# endif -#endif - -#include /* localeconv() */ -#include /* snprintf(), sprintf() */ -#include /* abort(), malloc(), realloc(), free() */ -#include /* memcpy(), strlen() */ -#include /* errno */ -#include /* CHAR_BIT */ -#include /* DBL_MAX_EXP, LDBL_MAX_EXP */ -#if HAVE_NL_LANGINFO -# include -#endif -#ifndef VASNPRINTF -# if WIDE_CHAR_VERSION -# include "wprintf-parse.h" -# else -# include "printf-parse.h" -# endif -#endif - -/* Checked size_t computations. */ -#include "xsize.h" - -#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL -# include -# include "float+.h" -#endif - -#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL -# include -# include "isnand-nolibm.h" -#endif - -#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL -# include -# include "isnanl-nolibm.h" -# include "fpucw.h" -#endif - -#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL -# include -# include "isnand-nolibm.h" -# include "printf-frexp.h" -#endif - -#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL -# include -# include "isnanl-nolibm.h" -# include "printf-frexpl.h" -# include "fpucw.h" -#endif - -/* Default parameters. */ -#ifndef VASNPRINTF -# if WIDE_CHAR_VERSION -# define VASNPRINTF vasnwprintf -# define FCHAR_T wchar_t -# define DCHAR_T wchar_t -# define TCHAR_T wchar_t -# define DCHAR_IS_TCHAR 1 -# define DIRECTIVE wchar_t_directive -# define DIRECTIVES wchar_t_directives -# define PRINTF_PARSE wprintf_parse -# define DCHAR_CPY wmemcpy -# define DCHAR_SET wmemset -# else -# define VASNPRINTF vasnprintf -# define FCHAR_T char -# define DCHAR_T char -# define TCHAR_T char -# define DCHAR_IS_TCHAR 1 -# define DIRECTIVE char_directive -# define DIRECTIVES char_directives -# define PRINTF_PARSE printf_parse -# define DCHAR_CPY memcpy -# define DCHAR_SET memset -# endif -#endif -#if WIDE_CHAR_VERSION - /* TCHAR_T is wchar_t. */ -# define USE_SNPRINTF 1 -# if HAVE_DECL__SNWPRINTF - /* On Windows, the function swprintf() has a different signature than - on Unix; we use the function _snwprintf() or - on mingw - snwprintf() - instead. The mingw function snwprintf() has fewer bugs than the - MSVCRT function _snwprintf(), so prefer that. */ -# if defined __MINGW32__ -# define SNPRINTF snwprintf -# else -# define SNPRINTF _snwprintf -# endif -# else - /* Unix. */ -# define SNPRINTF swprintf -# endif -#else - /* TCHAR_T is char. */ - /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'. - But don't use it on BeOS, since BeOS snprintf produces no output if the - size argument is >= 0x3000000. - Also don't use it on Linux libc5, since there snprintf with size = 1 - writes any output without bounds, like sprintf. */ -# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1) -# define USE_SNPRINTF 1 -# else -# define USE_SNPRINTF 0 -# endif -# if HAVE_DECL__SNPRINTF - /* Windows. The mingw function snprintf() has fewer bugs than the MSVCRT - function _snprintf(), so prefer that. */ -# if defined __MINGW32__ -# define SNPRINTF snprintf - /* Here we need to call the native snprintf, not rpl_snprintf. */ -# undef snprintf -# else -# define SNPRINTF _snprintf -# endif -# else - /* Unix. */ -# define SNPRINTF snprintf - /* Here we need to call the native snprintf, not rpl_snprintf. */ -# undef snprintf -# endif -#endif -/* Here we need to call the native sprintf, not rpl_sprintf. */ -#undef sprintf - -/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized" - warnings in this file. Use -Dlint to suppress them. */ -#ifdef lint -# define IF_LINT(Code) Code -#else -# define IF_LINT(Code) /* empty */ -#endif - -/* Avoid some warnings from "gcc -Wshadow". - This file doesn't use the exp() and remainder() functions. */ -#undef exp -#define exp expo -#undef remainder -#define remainder rem - -#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION -# if (HAVE_STRNLEN && !defined _AIX) -# define local_strnlen strnlen -# else -# ifndef local_strnlen_defined -# define local_strnlen_defined 1 -static size_t -local_strnlen (const char *string, size_t maxlen) -{ - const char *end = memchr (string, '\0', maxlen); - return end ? (size_t) (end - string) : maxlen; -} -# endif -# endif -#endif - -#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T -# if HAVE_WCSLEN -# define local_wcslen wcslen -# else - /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid - a dependency towards this library, here is a local substitute. - Define this substitute only once, even if this file is included - twice in the same compilation unit. */ -# ifndef local_wcslen_defined -# define local_wcslen_defined 1 -static size_t -local_wcslen (const wchar_t *s) -{ - const wchar_t *ptr; - - for (ptr = s; *ptr != (wchar_t) 0; ptr++) - ; - return ptr - s; -} -# endif -# endif -#endif - -#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION -# if HAVE_WCSNLEN -# define local_wcsnlen wcsnlen -# else -# ifndef local_wcsnlen_defined -# define local_wcsnlen_defined 1 -static size_t -local_wcsnlen (const wchar_t *s, size_t maxlen) -{ - const wchar_t *ptr; - - for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--) - ; - return ptr - s; -} -# endif -# endif -#endif - -#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL -/* Determine the decimal-point character according to the current locale. */ -# ifndef decimal_point_char_defined -# define decimal_point_char_defined 1 -static char -decimal_point_char (void) -{ - const char *point; - /* Determine it in a multithread-safe way. We know nl_langinfo is - multithread-safe on glibc systems and MacOS X systems, but is not required - to be multithread-safe by POSIX. sprintf(), however, is multithread-safe. - localeconv() is rarely multithread-safe. */ -# if HAVE_NL_LANGINFO && (__GLIBC__ || (defined __APPLE__ && defined __MACH__)) - point = nl_langinfo (RADIXCHAR); -# elif 1 - char pointbuf[5]; - sprintf (pointbuf, "%#.0f", 1.0); - point = &pointbuf[1]; -# else - point = localeconv () -> decimal_point; -# endif - /* The decimal point is always a single byte: either '.' or ','. */ - return (point[0] != '\0' ? point[0] : '.'); -} -# endif -#endif - -#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL - -/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */ -static int -is_infinite_or_zero (double x) -{ - return isnand (x) || x + x == x; -} - -#endif - -#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL - -/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */ -static int -is_infinite_or_zerol (long double x) -{ - return isnanl (x) || x + x == x; -} - -#endif - -#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL - -/* Converting 'long double' to decimal without rare rounding bugs requires - real bignums. We use the naming conventions of GNU gmp, but vastly simpler - (and slower) algorithms. */ - -typedef unsigned int mp_limb_t; -# define GMP_LIMB_BITS 32 -typedef int mp_limb_verify[2 * (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS) - 1]; - -typedef unsigned long long mp_twolimb_t; -# define GMP_TWOLIMB_BITS 64 -typedef int mp_twolimb_verify[2 * (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS) - 1]; - -/* Representation of a bignum >= 0. */ -typedef struct -{ - size_t nlimbs; - mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc(). */ -} mpn_t; - -/* Compute the product of two bignums >= 0. - Return the allocated memory in case of success, NULL in case of memory - allocation failure. */ -static void * -multiply (mpn_t src1, mpn_t src2, mpn_t *dest) -{ - const mp_limb_t *p1; - const mp_limb_t *p2; - size_t len1; - size_t len2; - - if (src1.nlimbs <= src2.nlimbs) - { - len1 = src1.nlimbs; - p1 = src1.limbs; - len2 = src2.nlimbs; - p2 = src2.limbs; - } - else - { - len1 = src2.nlimbs; - p1 = src2.limbs; - len2 = src1.nlimbs; - p2 = src1.limbs; - } - /* Now 0 <= len1 <= len2. */ - if (len1 == 0) - { - /* src1 or src2 is zero. */ - dest->nlimbs = 0; - dest->limbs = (mp_limb_t *) malloc (1); - } - else - { - /* Here 1 <= len1 <= len2. */ - size_t dlen; - mp_limb_t *dp; - size_t k, i, j; - - dlen = len1 + len2; - dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t)); - if (dp == NULL) - return NULL; - for (k = len2; k > 0; ) - dp[--k] = 0; - for (i = 0; i < len1; i++) - { - mp_limb_t digit1 = p1[i]; - mp_twolimb_t carry = 0; - for (j = 0; j < len2; j++) - { - mp_limb_t digit2 = p2[j]; - carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2; - carry += dp[i + j]; - dp[i + j] = (mp_limb_t) carry; - carry = carry >> GMP_LIMB_BITS; - } - dp[i + len2] = (mp_limb_t) carry; - } - /* Normalise. */ - while (dlen > 0 && dp[dlen - 1] == 0) - dlen--; - dest->nlimbs = dlen; - dest->limbs = dp; - } - return dest->limbs; -} - -/* Compute the quotient of a bignum a >= 0 and a bignum b > 0. - a is written as a = q * b + r with 0 <= r < b. q is the quotient, r - the remainder. - Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd, - q is incremented. - Return the allocated memory in case of success, NULL in case of memory - allocation failure. */ -static void * -divide (mpn_t a, mpn_t b, mpn_t *q) -{ - /* Algorithm: - First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]] - with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS). - If m=n=1, perform a single-precision division: - r:=0, j:=m, - while j>0 do - {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j = - = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r=n>1, perform a multiple-precision division: - We have a/b < beta^(m-n+1). - s:=intDsize-1-(highest bit in b[n-1]), 0<=s=beta/2. - For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).} - Compute q* : - q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]). - In case of overflow (q* >= beta) set q* := beta-1. - Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2] - and c3 := b[n-2] * q*. - {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow - occurred. Furthermore 0 <= c3 < beta^2. - If there was overflow and - r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2, - the next test can be skipped.} - While c3 > c2, {Here 0 <= c2 < c3 < beta^2} - Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2]. - If q* > 0: - Put r := r - b * q* * beta^j. In detail: - [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]]. - hence: u:=0, for i:=0 to n-1 do - u := u + q* * b[i], - r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry), - u:=u div beta (+ 1, if carry in subtraction) - r[n+j]:=r[n+j]-u. - {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1 - < q* + 1 <= beta, - the carry u does not overflow.} - If a negative carry occurs, put q* := q* - 1 - and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]]. - Set q[j] := q*. - Normalise [q[m-n],..,q[0]]; this yields the quotient q. - Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the - rest r. - The room for q[j] can be allocated at the memory location of r[n+j]. - Finally, round-to-even: - Shift r left by 1 bit. - If r > b or if r = b and q[0] is odd, q := q+1. - */ - const mp_limb_t *a_ptr = a.limbs; - size_t a_len = a.nlimbs; - const mp_limb_t *b_ptr = b.limbs; - size_t b_len = b.nlimbs; - mp_limb_t *roomptr; - mp_limb_t *tmp_roomptr = NULL; - mp_limb_t *q_ptr; - size_t q_len; - mp_limb_t *r_ptr; - size_t r_len; - - /* Allocate room for a_len+2 digits. - (Need a_len+1 digits for the real division and 1 more digit for the - final rounding of q.) */ - roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t)); - if (roomptr == NULL) - return NULL; - - /* Normalise a. */ - while (a_len > 0 && a_ptr[a_len - 1] == 0) - a_len--; - - /* Normalise b. */ - for (;;) - { - if (b_len == 0) - /* Division by zero. */ - abort (); - if (b_ptr[b_len - 1] == 0) - b_len--; - else - break; - } - - /* Here m = a_len >= 0 and n = b_len > 0. */ - - if (a_len < b_len) - { - /* m beta^(m-2) <= a/b < beta^m */ - r_ptr = roomptr; - q_ptr = roomptr + 1; - { - mp_limb_t den = b_ptr[0]; - mp_limb_t remainder = 0; - const mp_limb_t *sourceptr = a_ptr + a_len; - mp_limb_t *destptr = q_ptr + a_len; - size_t count; - for (count = a_len; count > 0; count--) - { - mp_twolimb_t num = - ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr; - *--destptr = num / den; - remainder = num % den; - } - /* Normalise and store r. */ - if (remainder > 0) - { - r_ptr[0] = remainder; - r_len = 1; - } - else - r_len = 0; - /* Normalise q. */ - q_len = a_len; - if (q_ptr[q_len - 1] == 0) - q_len--; - } - } - else - { - /* n>1: multiple precision division. - beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==> - beta^(m-n-1) <= a/b < beta^(m-n+1). */ - /* Determine s. */ - size_t s; - { - mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */ - s = 31; - if (msd >= 0x10000) - { - msd = msd >> 16; - s -= 16; - } - if (msd >= 0x100) - { - msd = msd >> 8; - s -= 8; - } - if (msd >= 0x10) - { - msd = msd >> 4; - s -= 4; - } - if (msd >= 0x4) - { - msd = msd >> 2; - s -= 2; - } - if (msd >= 0x2) - { - msd = msd >> 1; - s -= 1; - } - } - /* 0 <= s < GMP_LIMB_BITS. - Copy b, shifting it left by s bits. */ - if (s > 0) - { - tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t)); - if (tmp_roomptr == NULL) - { - free (roomptr); - return NULL; - } - { - const mp_limb_t *sourceptr = b_ptr; - mp_limb_t *destptr = tmp_roomptr; - mp_twolimb_t accu = 0; - size_t count; - for (count = b_len; count > 0; count--) - { - accu += (mp_twolimb_t) *sourceptr++ << s; - *destptr++ = (mp_limb_t) accu; - accu = accu >> GMP_LIMB_BITS; - } - /* accu must be zero, since that was how s was determined. */ - if (accu != 0) - abort (); - } - b_ptr = tmp_roomptr; - } - /* Copy a, shifting it left by s bits, yields r. - Memory layout: - At the beginning: r = roomptr[0..a_len], - at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len] */ - r_ptr = roomptr; - if (s == 0) - { - memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t)); - r_ptr[a_len] = 0; - } - else - { - const mp_limb_t *sourceptr = a_ptr; - mp_limb_t *destptr = r_ptr; - mp_twolimb_t accu = 0; - size_t count; - for (count = a_len; count > 0; count--) - { - accu += (mp_twolimb_t) *sourceptr++ << s; - *destptr++ = (mp_limb_t) accu; - accu = accu >> GMP_LIMB_BITS; - } - *destptr++ = (mp_limb_t) accu; - } - q_ptr = roomptr + b_len; - q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */ - { - size_t j = a_len - b_len; /* m-n */ - mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */ - mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */ - mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */ - ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd; - /* Division loop, traversed m-n+1 times. - j counts down, b is unchanged, beta/2 <= b[n-1] < beta. */ - for (;;) - { - mp_limb_t q_star; - mp_limb_t c1; - if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */ - { - /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow. */ - mp_twolimb_t num = - ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS) - | r_ptr[j + b_len - 1]; - q_star = num / b_msd; - c1 = num % b_msd; - } - else - { - /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1]. */ - q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */ - /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta - <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta - <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) - {<= beta !}. - If yes, jump directly to the subtraction loop. - (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta - <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */ - if (r_ptr[j + b_len] > b_msd - || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd) - /* r[j+n] >= b[n-1]+1 or - r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a - carry. */ - goto subtract; - } - /* q_star = q*, - c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, 0, decrease it by - b[n-1]*beta+b[n-2]. Because of b[n-1]*beta+b[n-2] >= beta^2/2 - this can happen only twice. */ - if (c3 > c2) - { - q_star = q_star - 1; /* q* := q* - 1 */ - if (c3 - c2 > b_msdd) - q_star = q_star - 1; /* q* := q* - 1 */ - } - } - if (q_star > 0) - subtract: - { - /* Subtract r := r - b * q* * beta^j. */ - mp_limb_t cr; - { - const mp_limb_t *sourceptr = b_ptr; - mp_limb_t *destptr = r_ptr + j; - mp_twolimb_t carry = 0; - size_t count; - for (count = b_len; count > 0; count--) - { - /* Here 0 <= carry <= q*. */ - carry = - carry - + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++ - + (mp_limb_t) ~(*destptr); - /* Here 0 <= carry <= beta*q* + beta-1. */ - *destptr++ = ~(mp_limb_t) carry; - carry = carry >> GMP_LIMB_BITS; /* <= q* */ - } - cr = (mp_limb_t) carry; - } - /* Subtract cr from r_ptr[j + b_len], then forget about - r_ptr[j + b_len]. */ - if (cr > r_ptr[j + b_len]) - { - /* Subtraction gave a carry. */ - q_star = q_star - 1; /* q* := q* - 1 */ - /* Add b back. */ - { - const mp_limb_t *sourceptr = b_ptr; - mp_limb_t *destptr = r_ptr + j; - mp_limb_t carry = 0; - size_t count; - for (count = b_len; count > 0; count--) - { - mp_limb_t source1 = *sourceptr++; - mp_limb_t source2 = *destptr; - *destptr++ = source1 + source2 + carry; - carry = - (carry - ? source1 >= (mp_limb_t) ~source2 - : source1 > (mp_limb_t) ~source2); - } - } - /* Forget about the carry and about r[j+n]. */ - } - } - /* q* is determined. Store it as q[j]. */ - q_ptr[j] = q_star; - if (j == 0) - break; - j--; - } - } - r_len = b_len; - /* Normalise q. */ - if (q_ptr[q_len - 1] == 0) - q_len--; -# if 0 /* Not needed here, since we need r only to compare it with b/2, and - b is shifted left by s bits. */ - /* Shift r right by s bits. */ - if (s > 0) - { - mp_limb_t ptr = r_ptr + r_len; - mp_twolimb_t accu = 0; - size_t count; - for (count = r_len; count > 0; count--) - { - accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS; - accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s); - *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS); - } - } -# endif - /* Normalise r. */ - while (r_len > 0 && r_ptr[r_len - 1] == 0) - r_len--; - } - /* Compare r << 1 with b. */ - if (r_len > b_len) - goto increment_q; - { - size_t i; - for (i = b_len;;) - { - mp_limb_t r_i = - (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0) - | (i < r_len ? r_ptr[i] << 1 : 0); - mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0); - if (r_i > b_i) - goto increment_q; - if (r_i < b_i) - goto keep_q; - if (i == 0) - break; - i--; - } - } - if (q_len > 0 && ((q_ptr[0] & 1) != 0)) - /* q is odd. */ - increment_q: - { - size_t i; - for (i = 0; i < q_len; i++) - if (++(q_ptr[i]) != 0) - goto keep_q; - q_ptr[q_len++] = 1; - } - keep_q: - if (tmp_roomptr != NULL) - free (tmp_roomptr); - q->limbs = q_ptr; - q->nlimbs = q_len; - return roomptr; -} - -/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal - representation. - Destroys the contents of a. - Return the allocated memory - containing the decimal digits in low-to-high - order, terminated with a NUL character - in case of success, NULL in case - of memory allocation failure. */ -static char * -convert_to_decimal (mpn_t a, size_t extra_zeroes) -{ - mp_limb_t *a_ptr = a.limbs; - size_t a_len = a.nlimbs; - /* 0.03345 is slightly larger than log(2)/(9*log(10)). */ - size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1); - char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes)); - if (c_ptr != NULL) - { - char *d_ptr = c_ptr; - for (; extra_zeroes > 0; extra_zeroes--) - *d_ptr++ = '0'; - while (a_len > 0) - { - /* Divide a by 10^9, in-place. */ - mp_limb_t remainder = 0; - mp_limb_t *ptr = a_ptr + a_len; - size_t count; - for (count = a_len; count > 0; count--) - { - mp_twolimb_t num = - ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr; - *ptr = num / 1000000000; - remainder = num % 1000000000; - } - /* Store the remainder as 9 decimal digits. */ - for (count = 9; count > 0; count--) - { - *d_ptr++ = '0' + (remainder % 10); - remainder = remainder / 10; - } - /* Normalize a. */ - if (a_ptr[a_len - 1] == 0) - a_len--; - } - /* Remove leading zeroes. */ - while (d_ptr > c_ptr && d_ptr[-1] == '0') - d_ptr--; - /* But keep at least one zero. */ - if (d_ptr == c_ptr) - *d_ptr++ = '0'; - /* Terminate the string. */ - *d_ptr = '\0'; - } - return c_ptr; -} - -# if NEED_PRINTF_LONG_DOUBLE - -/* Assuming x is finite and >= 0: - write x as x = 2^e * m, where m is a bignum. - Return the allocated memory in case of success, NULL in case of memory - allocation failure. */ -static void * -decode_long_double (long double x, int *ep, mpn_t *mp) -{ - mpn_t m; - int exp; - long double y; - size_t i; - - /* Allocate memory for result. */ - m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; - m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t)); - if (m.limbs == NULL) - return NULL; - /* Split into exponential part and mantissa. */ - y = frexpl (x, &exp); - if (!(y >= 0.0L && y < 1.0L)) - abort (); - /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * LDBL_MANT_BIT), and the - latter is an integer. */ - /* Convert the mantissa (y * LDBL_MANT_BIT) to a sequence of limbs. - I'm not sure whether it's safe to cast a 'long double' value between - 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only - 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int', - doesn't matter). */ -# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0 -# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2 - { - mp_limb_t hi, lo; - y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2)); - hi = (int) y; - y -= hi; - if (!(y >= 0.0L && y < 1.0L)) - abort (); - y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); - lo = (int) y; - y -= lo; - if (!(y >= 0.0L && y < 1.0L)) - abort (); - m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo; - } -# else - { - mp_limb_t d; - y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS); - d = (int) y; - y -= d; - if (!(y >= 0.0L && y < 1.0L)) - abort (); - m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d; - } -# endif -# endif - for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; ) - { - mp_limb_t hi, lo; - y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); - hi = (int) y; - y -= hi; - if (!(y >= 0.0L && y < 1.0L)) - abort (); - y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); - lo = (int) y; - y -= lo; - if (!(y >= 0.0L && y < 1.0L)) - abort (); - m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo; - } -#if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess - precision. */ - if (!(y == 0.0L)) - abort (); -#endif - /* Normalise. */ - while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0) - m.nlimbs--; - *mp = m; - *ep = exp - LDBL_MANT_BIT; - return m.limbs; -} - -# endif - -# if NEED_PRINTF_DOUBLE - -/* Assuming x is finite and >= 0: - write x as x = 2^e * m, where m is a bignum. - Return the allocated memory in case of success, NULL in case of memory - allocation failure. */ -static void * -decode_double (double x, int *ep, mpn_t *mp) -{ - mpn_t m; - int exp; - double y; - size_t i; - - /* Allocate memory for result. */ - m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS; - m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t)); - if (m.limbs == NULL) - return NULL; - /* Split into exponential part and mantissa. */ - y = frexp (x, &exp); - if (!(y >= 0.0 && y < 1.0)) - abort (); - /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * DBL_MANT_BIT), and the - latter is an integer. */ - /* Convert the mantissa (y * DBL_MANT_BIT) to a sequence of limbs. - I'm not sure whether it's safe to cast a 'double' value between - 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only - 'double' values between 0 and 2^16 (to 'unsigned int' or 'int', - doesn't matter). */ -# if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0 -# if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2 - { - mp_limb_t hi, lo; - y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2)); - hi = (int) y; - y -= hi; - if (!(y >= 0.0 && y < 1.0)) - abort (); - y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); - lo = (int) y; - y -= lo; - if (!(y >= 0.0 && y < 1.0)) - abort (); - m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo; - } -# else - { - mp_limb_t d; - y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS); - d = (int) y; - y -= d; - if (!(y >= 0.0 && y < 1.0)) - abort (); - m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d; - } -# endif -# endif - for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; ) - { - mp_limb_t hi, lo; - y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); - hi = (int) y; - y -= hi; - if (!(y >= 0.0 && y < 1.0)) - abort (); - y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2); - lo = (int) y; - y -= lo; - if (!(y >= 0.0 && y < 1.0)) - abort (); - m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo; - } - if (!(y == 0.0)) - abort (); - /* Normalise. */ - while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0) - m.nlimbs--; - *mp = m; - *ep = exp - DBL_MANT_BIT; - return m.limbs; -} - -# endif - -/* Assuming x = 2^e * m is finite and >= 0, and n is an integer: - Returns the decimal representation of round (x * 10^n). - Return the allocated memory - containing the decimal digits in low-to-high - order, terminated with a NUL character - in case of success, NULL in case - of memory allocation failure. */ -static char * -scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n) -{ - int s; - size_t extra_zeroes; - unsigned int abs_n; - unsigned int abs_s; - mp_limb_t *pow5_ptr; - size_t pow5_len; - unsigned int s_limbs; - unsigned int s_bits; - mpn_t pow5; - mpn_t z; - void *z_memory; - char *digits; - - if (memory == NULL) - return NULL; - /* x = 2^e * m, hence - y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m) - = round (2^s * 5^n * m). */ - s = e + n; - extra_zeroes = 0; - /* Factor out a common power of 10 if possible. */ - if (s > 0 && n > 0) - { - extra_zeroes = (s < n ? s : n); - s -= extra_zeroes; - n -= extra_zeroes; - } - /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes. - Before converting to decimal, we need to compute - z = round (2^s * 5^n * m). */ - /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same - sign. 2.322 is slightly larger than log(5)/log(2). */ - abs_n = (n >= 0 ? n : -n); - abs_s = (s >= 0 ? s : -s); - pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1 - + abs_s / GMP_LIMB_BITS + 1) - * sizeof (mp_limb_t)); - if (pow5_ptr == NULL) - { - free (memory); - return NULL; - } - /* Initialize with 1. */ - pow5_ptr[0] = 1; - pow5_len = 1; - /* Multiply with 5^|n|. */ - if (abs_n > 0) - { - static mp_limb_t const small_pow5[13 + 1] = - { - 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625, - 48828125, 244140625, 1220703125 - }; - unsigned int n13; - for (n13 = 0; n13 <= abs_n; n13 += 13) - { - mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13]; - size_t j; - mp_twolimb_t carry = 0; - for (j = 0; j < pow5_len; j++) - { - mp_limb_t digit2 = pow5_ptr[j]; - carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2; - pow5_ptr[j] = (mp_limb_t) carry; - carry = carry >> GMP_LIMB_BITS; - } - if (carry > 0) - pow5_ptr[pow5_len++] = (mp_limb_t) carry; - } - } - s_limbs = abs_s / GMP_LIMB_BITS; - s_bits = abs_s % GMP_LIMB_BITS; - if (n >= 0 ? s >= 0 : s <= 0) - { - /* Multiply with 2^|s|. */ - if (s_bits > 0) - { - mp_limb_t *ptr = pow5_ptr; - mp_twolimb_t accu = 0; - size_t count; - for (count = pow5_len; count > 0; count--) - { - accu += (mp_twolimb_t) *ptr << s_bits; - *ptr++ = (mp_limb_t) accu; - accu = accu >> GMP_LIMB_BITS; - } - if (accu > 0) - { - *ptr = (mp_limb_t) accu; - pow5_len++; - } - } - if (s_limbs > 0) - { - size_t count; - for (count = pow5_len; count > 0;) - { - count--; - pow5_ptr[s_limbs + count] = pow5_ptr[count]; - } - for (count = s_limbs; count > 0;) - { - count--; - pow5_ptr[count] = 0; - } - pow5_len += s_limbs; - } - pow5.limbs = pow5_ptr; - pow5.nlimbs = pow5_len; - if (n >= 0) - { - /* Multiply m with pow5. No division needed. */ - z_memory = multiply (m, pow5, &z); - } - else - { - /* Divide m by pow5 and round. */ - z_memory = divide (m, pow5, &z); - } - } - else - { - pow5.limbs = pow5_ptr; - pow5.nlimbs = pow5_len; - if (n >= 0) - { - /* n >= 0, s < 0. - Multiply m with pow5, then divide by 2^|s|. */ - mpn_t numerator; - mpn_t denominator; - void *tmp_memory; - tmp_memory = multiply (m, pow5, &numerator); - if (tmp_memory == NULL) - { - free (pow5_ptr); - free (memory); - return NULL; - } - /* Construct 2^|s|. */ - { - mp_limb_t *ptr = pow5_ptr + pow5_len; - size_t i; - for (i = 0; i < s_limbs; i++) - ptr[i] = 0; - ptr[s_limbs] = (mp_limb_t) 1 << s_bits; - denominator.limbs = ptr; - denominator.nlimbs = s_limbs + 1; - } - z_memory = divide (numerator, denominator, &z); - free (tmp_memory); - } - else - { - /* n < 0, s > 0. - Multiply m with 2^s, then divide by pow5. */ - mpn_t numerator; - mp_limb_t *num_ptr; - num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1) - * sizeof (mp_limb_t)); - if (num_ptr == NULL) - { - free (pow5_ptr); - free (memory); - return NULL; - } - { - mp_limb_t *destptr = num_ptr; - { - size_t i; - for (i = 0; i < s_limbs; i++) - *destptr++ = 0; - } - if (s_bits > 0) - { - const mp_limb_t *sourceptr = m.limbs; - mp_twolimb_t accu = 0; - size_t count; - for (count = m.nlimbs; count > 0; count--) - { - accu += (mp_twolimb_t) *sourceptr++ << s_bits; - *destptr++ = (mp_limb_t) accu; - accu = accu >> GMP_LIMB_BITS; - } - if (accu > 0) - *destptr++ = (mp_limb_t) accu; - } - else - { - const mp_limb_t *sourceptr = m.limbs; - size_t count; - for (count = m.nlimbs; count > 0; count--) - *destptr++ = *sourceptr++; - } - numerator.limbs = num_ptr; - numerator.nlimbs = destptr - num_ptr; - } - z_memory = divide (numerator, pow5, &z); - free (num_ptr); - } - } - free (pow5_ptr); - free (memory); - - /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */ - - if (z_memory == NULL) - return NULL; - digits = convert_to_decimal (z, extra_zeroes); - free (z_memory); - return digits; -} - -# if NEED_PRINTF_LONG_DOUBLE - -/* Assuming x is finite and >= 0, and n is an integer: - Returns the decimal representation of round (x * 10^n). - Return the allocated memory - containing the decimal digits in low-to-high - order, terminated with a NUL character - in case of success, NULL in case - of memory allocation failure. */ -static char * -scale10_round_decimal_long_double (long double x, int n) -{ - int e IF_LINT(= 0); - mpn_t m; - void *memory = decode_long_double (x, &e, &m); - return scale10_round_decimal_decoded (e, m, memory, n); -} - -# endif - -# if NEED_PRINTF_DOUBLE - -/* Assuming x is finite and >= 0, and n is an integer: - Returns the decimal representation of round (x * 10^n). - Return the allocated memory - containing the decimal digits in low-to-high - order, terminated with a NUL character - in case of success, NULL in case - of memory allocation failure. */ -static char * -scale10_round_decimal_double (double x, int n) -{ - int e IF_LINT(= 0); - mpn_t m; - void *memory = decode_double (x, &e, &m); - return scale10_round_decimal_decoded (e, m, memory, n); -} - -# endif - -# if NEED_PRINTF_LONG_DOUBLE - -/* Assuming x is finite and > 0: - Return an approximation for n with 10^n <= x < 10^(n+1). - The approximation is usually the right n, but may be off by 1 sometimes. */ -static int -floorlog10l (long double x) -{ - int exp; - long double y; - double z; - double l; - - /* Split into exponential part and mantissa. */ - y = frexpl (x, &exp); - if (!(y >= 0.0L && y < 1.0L)) - abort (); - if (y == 0.0L) - return INT_MIN; - if (y < 0.5L) - { - while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2)))) - { - y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2)); - exp -= GMP_LIMB_BITS; - } - if (y < (1.0L / (1 << 16))) - { - y *= 1.0L * (1 << 16); - exp -= 16; - } - if (y < (1.0L / (1 << 8))) - { - y *= 1.0L * (1 << 8); - exp -= 8; - } - if (y < (1.0L / (1 << 4))) - { - y *= 1.0L * (1 << 4); - exp -= 4; - } - if (y < (1.0L / (1 << 2))) - { - y *= 1.0L * (1 << 2); - exp -= 2; - } - if (y < (1.0L / (1 << 1))) - { - y *= 1.0L * (1 << 1); - exp -= 1; - } - } - if (!(y >= 0.5L && y < 1.0L)) - abort (); - /* Compute an approximation for l = log2(x) = exp + log2(y). */ - l = exp; - z = y; - if (z < 0.70710678118654752444) - { - z *= 1.4142135623730950488; - l -= 0.5; - } - if (z < 0.8408964152537145431) - { - z *= 1.1892071150027210667; - l -= 0.25; - } - if (z < 0.91700404320467123175) - { - z *= 1.0905077326652576592; - l -= 0.125; - } - if (z < 0.9576032806985736469) - { - z *= 1.0442737824274138403; - l -= 0.0625; - } - /* Now 0.95 <= z <= 1.01. */ - z = 1 - z; - /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...) - Four terms are enough to get an approximation with error < 10^-7. */ - l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25))); - /* Finally multiply with log(2)/log(10), yields an approximation for - log10(x). */ - l *= 0.30102999566398119523; - /* Round down to the next integer. */ - return (int) l + (l < 0 ? -1 : 0); -} - -# endif - -# if NEED_PRINTF_DOUBLE - -/* Assuming x is finite and > 0: - Return an approximation for n with 10^n <= x < 10^(n+1). - The approximation is usually the right n, but may be off by 1 sometimes. */ -static int -floorlog10 (double x) -{ - int exp; - double y; - double z; - double l; - - /* Split into exponential part and mantissa. */ - y = frexp (x, &exp); - if (!(y >= 0.0 && y < 1.0)) - abort (); - if (y == 0.0) - return INT_MIN; - if (y < 0.5) - { - while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2)))) - { - y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2)); - exp -= GMP_LIMB_BITS; - } - if (y < (1.0 / (1 << 16))) - { - y *= 1.0 * (1 << 16); - exp -= 16; - } - if (y < (1.0 / (1 << 8))) - { - y *= 1.0 * (1 << 8); - exp -= 8; - } - if (y < (1.0 / (1 << 4))) - { - y *= 1.0 * (1 << 4); - exp -= 4; - } - if (y < (1.0 / (1 << 2))) - { - y *= 1.0 * (1 << 2); - exp -= 2; - } - if (y < (1.0 / (1 << 1))) - { - y *= 1.0 * (1 << 1); - exp -= 1; - } - } - if (!(y >= 0.5 && y < 1.0)) - abort (); - /* Compute an approximation for l = log2(x) = exp + log2(y). */ - l = exp; - z = y; - if (z < 0.70710678118654752444) - { - z *= 1.4142135623730950488; - l -= 0.5; - } - if (z < 0.8408964152537145431) - { - z *= 1.1892071150027210667; - l -= 0.25; - } - if (z < 0.91700404320467123175) - { - z *= 1.0905077326652576592; - l -= 0.125; - } - if (z < 0.9576032806985736469) - { - z *= 1.0442737824274138403; - l -= 0.0625; - } - /* Now 0.95 <= z <= 1.01. */ - z = 1 - z; - /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...) - Four terms are enough to get an approximation with error < 10^-7. */ - l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25))); - /* Finally multiply with log(2)/log(10), yields an approximation for - log10(x). */ - l *= 0.30102999566398119523; - /* Round down to the next integer. */ - return (int) l + (l < 0 ? -1 : 0); -} - -# endif - -/* Tests whether a string of digits consists of exactly PRECISION zeroes and - a single '1' digit. */ -static int -is_borderline (const char *digits, size_t precision) -{ - for (; precision > 0; precision--, digits++) - if (*digits != '0') - return 0; - if (*digits != '1') - return 0; - digits++; - return *digits == '\0'; -} - -#endif - -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 - -/* Use a different function name, to make it possible that the 'wchar_t' - parametrization and the 'char' parametrization get compiled in the same - translation unit. */ -# if WIDE_CHAR_VERSION -# define MAX_ROOM_NEEDED wmax_room_needed -# else -# define MAX_ROOM_NEEDED max_room_needed -# endif - -/* Returns the number of TCHAR_T units needed as temporary space for the result - of sprintf or SNPRINTF of a single conversion directive. */ -static inline size_t -MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion, - arg_type type, int flags, size_t width, int has_precision, - size_t precision, int pad_ourselves) -{ - size_t tmp_length; - - switch (conversion) - { - case 'd': case 'i': case 'u': -# if HAVE_LONG_LONG_INT - if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long long) * CHAR_BIT - * 0.30103 /* binary -> decimal */ - ) - + 1; /* turn floor into ceil */ - else -# endif - if (type == TYPE_LONGINT || type == TYPE_ULONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long) * CHAR_BIT - * 0.30103 /* binary -> decimal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) (sizeof (unsigned int) * CHAR_BIT - * 0.30103 /* binary -> decimal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Multiply by 2, as an estimate for FLAG_GROUP. */ - tmp_length = xsum (tmp_length, tmp_length); - /* Add 1, to account for a leading sign. */ - tmp_length = xsum (tmp_length, 1); - break; - - case 'o': -# if HAVE_LONG_LONG_INT - if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long long) * CHAR_BIT - * 0.333334 /* binary -> octal */ - ) - + 1; /* turn floor into ceil */ - else -# endif - if (type == TYPE_LONGINT || type == TYPE_ULONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long) * CHAR_BIT - * 0.333334 /* binary -> octal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) (sizeof (unsigned int) * CHAR_BIT - * 0.333334 /* binary -> octal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Add 1, to account for a leading sign. */ - tmp_length = xsum (tmp_length, 1); - break; - - case 'x': case 'X': -# if HAVE_LONG_LONG_INT - if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long long) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - else -# endif - if (type == TYPE_LONGINT || type == TYPE_ULONGINT) - tmp_length = - (unsigned int) (sizeof (unsigned long) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) (sizeof (unsigned int) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Add 2, to account for a leading sign or alternate form. */ - tmp_length = xsum (tmp_length, 2); - break; - - case 'f': case 'F': - if (type == TYPE_LONGDOUBLE) - tmp_length = - (unsigned int) (LDBL_MAX_EXP - * 0.30103 /* binary -> decimal */ - * 2 /* estimate for FLAG_GROUP */ - ) - + 1 /* turn floor into ceil */ - + 10; /* sign, decimal point etc. */ - else - tmp_length = - (unsigned int) (DBL_MAX_EXP - * 0.30103 /* binary -> decimal */ - * 2 /* estimate for FLAG_GROUP */ - ) - + 1 /* turn floor into ceil */ - + 10; /* sign, decimal point etc. */ - tmp_length = xsum (tmp_length, precision); - break; - - case 'e': case 'E': case 'g': case 'G': - tmp_length = - 12; /* sign, decimal point, exponent etc. */ - tmp_length = xsum (tmp_length, precision); - break; - - case 'a': case 'A': - if (type == TYPE_LONGDOUBLE) - tmp_length = - (unsigned int) (LDBL_DIG - * 0.831 /* decimal -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) (DBL_DIG - * 0.831 /* decimal -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Account for sign, decimal point etc. */ - tmp_length = xsum (tmp_length, 12); - break; - - case 'c': -# if HAVE_WINT_T && !WIDE_CHAR_VERSION - if (type == TYPE_WIDE_CHAR) - tmp_length = MB_CUR_MAX; - else -# endif - tmp_length = 1; - break; - - case 's': -# if HAVE_WCHAR_T - if (type == TYPE_WIDE_STRING) - { -# if WIDE_CHAR_VERSION - /* ISO C says about %ls in fwprintf: - "If the precision is not specified or is greater than the size - of the array, the array shall contain a null wide character." - So if there is a precision, we must not use wcslen. */ - const wchar_t *arg = ap->arg[arg_index].a.a_wide_string; - - if (has_precision) - tmp_length = local_wcsnlen (arg, precision); - else - tmp_length = local_wcslen (arg); -# else - /* ISO C says about %ls in fprintf: - "If a precision is specified, no more than that many bytes are - written (including shift sequences, if any), and the array - shall contain a null wide character if, to equal the multibyte - character sequence length given by the precision, the function - would need to access a wide character one past the end of the - array." - So if there is a precision, we must not use wcslen. */ - /* This case has already been handled separately in VASNPRINTF. */ - abort (); -# endif - } - else -# endif - { -# if WIDE_CHAR_VERSION - /* ISO C says about %s in fwprintf: - "If the precision is not specified or is greater than the size - of the converted array, the converted array shall contain a - null wide character." - So if there is a precision, we must not use strlen. */ - /* This case has already been handled separately in VASNPRINTF. */ - abort (); -# else - /* ISO C says about %s in fprintf: - "If the precision is not specified or greater than the size of - the array, the array shall contain a null character." - So if there is a precision, we must not use strlen. */ - const char *arg = ap->arg[arg_index].a.a_string; - - if (has_precision) - tmp_length = local_strnlen (arg, precision); - else - tmp_length = strlen (arg); -# endif - } - break; - - case 'p': - tmp_length = - (unsigned int) (sizeof (void *) * CHAR_BIT - * 0.25 /* binary -> hexadecimal */ - ) - + 1 /* turn floor into ceil */ - + 2; /* account for leading 0x */ - break; - - default: - abort (); - } - - if (!pad_ourselves) - { -# if ENABLE_UNISTDIO - /* Padding considers the number of characters, therefore the number of - elements after padding may be - > max (tmp_length, width) - but is certainly - <= tmp_length + width. */ - tmp_length = xsum (tmp_length, width); -# else - /* Padding considers the number of elements, says POSIX. */ - if (tmp_length < width) - tmp_length = width; -# endif - } - - tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ - - return tmp_length; -} - -#endif - -DCHAR_T * -VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, - const FCHAR_T *format, va_list args) -{ - DIRECTIVES d; - arguments a; - - if (PRINTF_PARSE (format, &d, &a) < 0) - /* errno is already set. */ - return NULL; - -#define CLEANUP() \ - free (d.dir); \ - if (a.arg) \ - free (a.arg); - - if (PRINTF_FETCHARGS (args, &a) < 0) - { - CLEANUP (); - errno = EINVAL; - return NULL; - } - - { - size_t buf_neededlength; - TCHAR_T *buf; - TCHAR_T *buf_malloced; - const FCHAR_T *cp; - size_t i; - DIRECTIVE *dp; - /* Output string accumulator. */ - DCHAR_T *result; - size_t allocated; - size_t length; - - /* Allocate a small buffer that will hold a directive passed to - sprintf or snprintf. */ - buf_neededlength = - xsum4 (7, d.max_width_length, d.max_precision_length, 6); -#if HAVE_ALLOCA - if (buf_neededlength < 4000 / sizeof (TCHAR_T)) - { - buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T)); - buf_malloced = NULL; - } - else -#endif - { - size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T)); - if (size_overflow_p (buf_memsize)) - goto out_of_memory_1; - buf = (TCHAR_T *) malloc (buf_memsize); - if (buf == NULL) - goto out_of_memory_1; - buf_malloced = buf; - } - - if (resultbuf != NULL) - { - result = resultbuf; - allocated = *lengthp; - } - else - { - result = NULL; - allocated = 0; - } - length = 0; - /* Invariants: - result is either == resultbuf or == NULL or malloc-allocated. - If length > 0, then result != NULL. */ - - /* Ensures that allocated >= needed. Aborts through a jump to - out_of_memory if needed is SIZE_MAX or otherwise too big. */ -#define ENSURE_ALLOCATION(needed) \ - if ((needed) > allocated) \ - { \ - size_t memory_size; \ - DCHAR_T *memory; \ - \ - allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \ - if ((needed) > allocated) \ - allocated = (needed); \ - memory_size = xtimes (allocated, sizeof (DCHAR_T)); \ - if (size_overflow_p (memory_size)) \ - goto out_of_memory; \ - if (result == resultbuf || result == NULL) \ - memory = (DCHAR_T *) malloc (memory_size); \ - else \ - memory = (DCHAR_T *) realloc (result, memory_size); \ - if (memory == NULL) \ - goto out_of_memory; \ - if (result == resultbuf && length > 0) \ - DCHAR_CPY (memory, result, length); \ - result = memory; \ - } - - for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++) - { - if (cp != dp->dir_start) - { - size_t n = dp->dir_start - cp; - size_t augmented_length = xsum (length, n); - - ENSURE_ALLOCATION (augmented_length); - /* This copies a piece of FCHAR_T[] into a DCHAR_T[]. Here we - need that the format string contains only ASCII characters - if FCHAR_T and DCHAR_T are not the same type. */ - if (sizeof (FCHAR_T) == sizeof (DCHAR_T)) - { - DCHAR_CPY (result + length, (const DCHAR_T *) cp, n); - length = augmented_length; - } - else - { - do - result[length++] = (unsigned char) *cp++; - while (--n > 0); - } - } - if (i == d.count) - break; - - /* Execute a single directive. */ - if (dp->conversion == '%') - { - size_t augmented_length; - - if (!(dp->arg_index == ARG_NONE)) - abort (); - augmented_length = xsum (length, 1); - ENSURE_ALLOCATION (augmented_length); - result[length] = '%'; - length = augmented_length; - } - else - { - if (!(dp->arg_index != ARG_NONE)) - abort (); - - if (dp->conversion == 'n') - { - switch (a.arg[dp->arg_index].type) - { - case TYPE_COUNT_SCHAR_POINTER: - *a.arg[dp->arg_index].a.a_count_schar_pointer = length; - break; - case TYPE_COUNT_SHORT_POINTER: - *a.arg[dp->arg_index].a.a_count_short_pointer = length; - break; - case TYPE_COUNT_INT_POINTER: - *a.arg[dp->arg_index].a.a_count_int_pointer = length; - break; - case TYPE_COUNT_LONGINT_POINTER: - *a.arg[dp->arg_index].a.a_count_longint_pointer = length; - break; -#if HAVE_LONG_LONG_INT - case TYPE_COUNT_LONGLONGINT_POINTER: - *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length; - break; -#endif - default: - abort (); - } - } -#if ENABLE_UNISTDIO - /* The unistdio extensions. */ - else if (dp->conversion == 'U') - { - arg_type type = a.arg[dp->arg_index].type; - int flags = dp->flags; - int has_width; - size_t width; - int has_precision; - size_t precision; - - has_width = 0; - width = 0; - if (dp->width_start != dp->width_end) - { - if (dp->width_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->width_arg_index].a.a_int; - if (arg < 0) - { - /* "A negative field width is taken as a '-' flag - followed by a positive field width." */ - flags |= FLAG_LEFT; - width = (unsigned int) (-arg); - } - else - width = arg; - } - else - { - const FCHAR_T *digitp = dp->width_start; - - do - width = xsum (xtimes (width, 10), *digitp++ - '0'); - while (digitp != dp->width_end); - } - has_width = 1; - } - - has_precision = 0; - precision = 0; - if (dp->precision_start != dp->precision_end) - { - if (dp->precision_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->precision_arg_index].a.a_int; - /* "A negative precision is taken as if the precision - were omitted." */ - if (arg >= 0) - { - precision = arg; - has_precision = 1; - } - } - else - { - const FCHAR_T *digitp = dp->precision_start + 1; - - precision = 0; - while (digitp != dp->precision_end) - precision = xsum (xtimes (precision, 10), *digitp++ - '0'); - has_precision = 1; - } - } - - switch (type) - { - case TYPE_U8_STRING: - { - const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string; - const uint8_t *arg_end; - size_t characters; - - if (has_precision) - { - /* Use only PRECISION characters, from the left. */ - arg_end = arg; - characters = 0; - for (; precision > 0; precision--) - { - int count = u8_strmblen (arg_end); - if (count == 0) - break; - if (count < 0) - { - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EILSEQ; - return NULL; - } - arg_end += count; - characters++; - } - } - else if (has_width) - { - /* Use the entire string, and count the number of - characters. */ - arg_end = arg; - characters = 0; - for (;;) - { - int count = u8_strmblen (arg_end); - if (count == 0) - break; - if (count < 0) - { - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EILSEQ; - return NULL; - } - arg_end += count; - characters++; - } - } - else - { - /* Use the entire string. */ - arg_end = arg + u8_strlen (arg); - /* The number of characters doesn't matter. */ - characters = 0; - } - - if (has_width && width > characters - && !(dp->flags & FLAG_LEFT)) - { - size_t n = width - characters; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_SET (result + length, ' ', n); - length += n; - } - -# if DCHAR_IS_UINT8_T - { - size_t n = arg_end - arg; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_CPY (result + length, arg, n); - length += n; - } -# else - { /* Convert. */ - DCHAR_T *converted = result + length; - size_t converted_len = allocated - length; -# if DCHAR_IS_TCHAR - /* Convert from UTF-8 to locale encoding. */ - converted = - u8_conv_to_encoding (locale_charset (), - iconveh_question_mark, - arg, arg_end - arg, NULL, - converted, &converted_len); -# else - /* Convert from UTF-8 to UTF-16/UTF-32. */ - converted = - U8_TO_DCHAR (arg, arg_end - arg, - converted, &converted_len); -# endif - if (converted == NULL) - { - int saved_errno = errno; - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = saved_errno; - return NULL; - } - if (converted != result + length) - { - ENSURE_ALLOCATION (xsum (length, converted_len)); - DCHAR_CPY (result + length, converted, converted_len); - free (converted); - } - length += converted_len; - } -# endif - - if (has_width && width > characters - && (dp->flags & FLAG_LEFT)) - { - size_t n = width - characters; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_SET (result + length, ' ', n); - length += n; - } - } - break; - - case TYPE_U16_STRING: - { - const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string; - const uint16_t *arg_end; - size_t characters; - - if (has_precision) - { - /* Use only PRECISION characters, from the left. */ - arg_end = arg; - characters = 0; - for (; precision > 0; precision--) - { - int count = u16_strmblen (arg_end); - if (count == 0) - break; - if (count < 0) - { - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EILSEQ; - return NULL; - } - arg_end += count; - characters++; - } - } - else if (has_width) - { - /* Use the entire string, and count the number of - characters. */ - arg_end = arg; - characters = 0; - for (;;) - { - int count = u16_strmblen (arg_end); - if (count == 0) - break; - if (count < 0) - { - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EILSEQ; - return NULL; - } - arg_end += count; - characters++; - } - } - else - { - /* Use the entire string. */ - arg_end = arg + u16_strlen (arg); - /* The number of characters doesn't matter. */ - characters = 0; - } - - if (has_width && width > characters - && !(dp->flags & FLAG_LEFT)) - { - size_t n = width - characters; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_SET (result + length, ' ', n); - length += n; - } - -# if DCHAR_IS_UINT16_T - { - size_t n = arg_end - arg; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_CPY (result + length, arg, n); - length += n; - } -# else - { /* Convert. */ - DCHAR_T *converted = result + length; - size_t converted_len = allocated - length; -# if DCHAR_IS_TCHAR - /* Convert from UTF-16 to locale encoding. */ - converted = - u16_conv_to_encoding (locale_charset (), - iconveh_question_mark, - arg, arg_end - arg, NULL, - converted, &converted_len); -# else - /* Convert from UTF-16 to UTF-8/UTF-32. */ - converted = - U16_TO_DCHAR (arg, arg_end - arg, - converted, &converted_len); -# endif - if (converted == NULL) - { - int saved_errno = errno; - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = saved_errno; - return NULL; - } - if (converted != result + length) - { - ENSURE_ALLOCATION (xsum (length, converted_len)); - DCHAR_CPY (result + length, converted, converted_len); - free (converted); - } - length += converted_len; - } -# endif - - if (has_width && width > characters - && (dp->flags & FLAG_LEFT)) - { - size_t n = width - characters; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_SET (result + length, ' ', n); - length += n; - } - } - break; - - case TYPE_U32_STRING: - { - const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string; - const uint32_t *arg_end; - size_t characters; - - if (has_precision) - { - /* Use only PRECISION characters, from the left. */ - arg_end = arg; - characters = 0; - for (; precision > 0; precision--) - { - int count = u32_strmblen (arg_end); - if (count == 0) - break; - if (count < 0) - { - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EILSEQ; - return NULL; - } - arg_end += count; - characters++; - } - } - else if (has_width) - { - /* Use the entire string, and count the number of - characters. */ - arg_end = arg; - characters = 0; - for (;;) - { - int count = u32_strmblen (arg_end); - if (count == 0) - break; - if (count < 0) - { - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EILSEQ; - return NULL; - } - arg_end += count; - characters++; - } - } - else - { - /* Use the entire string. */ - arg_end = arg + u32_strlen (arg); - /* The number of characters doesn't matter. */ - characters = 0; - } - - if (has_width && width > characters - && !(dp->flags & FLAG_LEFT)) - { - size_t n = width - characters; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_SET (result + length, ' ', n); - length += n; - } - -# if DCHAR_IS_UINT32_T - { - size_t n = arg_end - arg; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_CPY (result + length, arg, n); - length += n; - } -# else - { /* Convert. */ - DCHAR_T *converted = result + length; - size_t converted_len = allocated - length; -# if DCHAR_IS_TCHAR - /* Convert from UTF-32 to locale encoding. */ - converted = - u32_conv_to_encoding (locale_charset (), - iconveh_question_mark, - arg, arg_end - arg, NULL, - converted, &converted_len); -# else - /* Convert from UTF-32 to UTF-8/UTF-16. */ - converted = - U32_TO_DCHAR (arg, arg_end - arg, - converted, &converted_len); -# endif - if (converted == NULL) - { - int saved_errno = errno; - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = saved_errno; - return NULL; - } - if (converted != result + length) - { - ENSURE_ALLOCATION (xsum (length, converted_len)); - DCHAR_CPY (result + length, converted, converted_len); - free (converted); - } - length += converted_len; - } -# endif - - if (has_width && width > characters - && (dp->flags & FLAG_LEFT)) - { - size_t n = width - characters; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_SET (result + length, ' ', n); - length += n; - } - } - break; - - default: - abort (); - } - } -#endif -#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T - else if (dp->conversion == 's' -# if WIDE_CHAR_VERSION - && a.arg[dp->arg_index].type != TYPE_WIDE_STRING -# else - && a.arg[dp->arg_index].type == TYPE_WIDE_STRING -# endif - ) - { - /* The normal handling of the 's' directive below requires - allocating a temporary buffer. The determination of its - length (tmp_length), in the case when a precision is - specified, below requires a conversion between a char[] - string and a wchar_t[] wide string. It could be done, but - we have no guarantee that the implementation of sprintf will - use the exactly same algorithm. Without this guarantee, it - is possible to have buffer overrun bugs. In order to avoid - such bugs, we implement the entire processing of the 's' - directive ourselves. */ - int flags = dp->flags; - int has_width; - size_t width; - int has_precision; - size_t precision; - - has_width = 0; - width = 0; - if (dp->width_start != dp->width_end) - { - if (dp->width_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->width_arg_index].a.a_int; - if (arg < 0) - { - /* "A negative field width is taken as a '-' flag - followed by a positive field width." */ - flags |= FLAG_LEFT; - width = (unsigned int) (-arg); - } - else - width = arg; - } - else - { - const FCHAR_T *digitp = dp->width_start; - - do - width = xsum (xtimes (width, 10), *digitp++ - '0'); - while (digitp != dp->width_end); - } - has_width = 1; - } - - has_precision = 0; - precision = 6; - if (dp->precision_start != dp->precision_end) - { - if (dp->precision_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->precision_arg_index].a.a_int; - /* "A negative precision is taken as if the precision - were omitted." */ - if (arg >= 0) - { - precision = arg; - has_precision = 1; - } - } - else - { - const FCHAR_T *digitp = dp->precision_start + 1; - - precision = 0; - while (digitp != dp->precision_end) - precision = xsum (xtimes (precision, 10), *digitp++ - '0'); - has_precision = 1; - } - } - -# if WIDE_CHAR_VERSION - /* %s in vasnwprintf. See the specification of fwprintf. */ - { - const char *arg = a.arg[dp->arg_index].a.a_string; - const char *arg_end; - size_t characters; - - if (has_precision) - { - /* Use only as many bytes as needed to produce PRECISION - wide characters, from the left. */ -# if HAVE_MBRTOWC - mbstate_t state; - memset (&state, '\0', sizeof (mbstate_t)); -# endif - arg_end = arg; - characters = 0; - for (; precision > 0; precision--) - { - int count; -# if HAVE_MBRTOWC - count = mbrlen (arg_end, MB_CUR_MAX, &state); -# else - count = mblen (arg_end, MB_CUR_MAX); -# endif - if (count == 0) - /* Found the terminating NUL. */ - break; - if (count < 0) - { - /* Invalid or incomplete multibyte character. */ - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EILSEQ; - return NULL; - } - arg_end += count; - characters++; - } - } - else if (has_width) - { - /* Use the entire string, and count the number of wide - characters. */ -# if HAVE_MBRTOWC - mbstate_t state; - memset (&state, '\0', sizeof (mbstate_t)); -# endif - arg_end = arg; - characters = 0; - for (;;) - { - int count; -# if HAVE_MBRTOWC - count = mbrlen (arg_end, MB_CUR_MAX, &state); -# else - count = mblen (arg_end, MB_CUR_MAX); -# endif - if (count == 0) - /* Found the terminating NUL. */ - break; - if (count < 0) - { - /* Invalid or incomplete multibyte character. */ - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EILSEQ; - return NULL; - } - arg_end += count; - characters++; - } - } - else - { - /* Use the entire string. */ - arg_end = arg + strlen (arg); - /* The number of characters doesn't matter. */ - characters = 0; - } - - if (has_width && width > characters - && !(dp->flags & FLAG_LEFT)) - { - size_t n = width - characters; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_SET (result + length, ' ', n); - length += n; - } - - if (has_precision || has_width) - { - /* We know the number of wide characters in advance. */ - size_t remaining; -# if HAVE_MBRTOWC - mbstate_t state; - memset (&state, '\0', sizeof (mbstate_t)); -# endif - ENSURE_ALLOCATION (xsum (length, characters)); - for (remaining = characters; remaining > 0; remaining--) - { - wchar_t wc; - int count; -# if HAVE_MBRTOWC - count = mbrtowc (&wc, arg, arg_end - arg, &state); -# else - count = mbtowc (&wc, arg, arg_end - arg); -# endif - if (count <= 0) - /* mbrtowc not consistent with mbrlen, or mbtowc - not consistent with mblen. */ - abort (); - result[length++] = wc; - arg += count; - } - if (!(arg == arg_end)) - abort (); - } - else - { -# if HAVE_MBRTOWC - mbstate_t state; - memset (&state, '\0', sizeof (mbstate_t)); -# endif - while (arg < arg_end) - { - wchar_t wc; - int count; -# if HAVE_MBRTOWC - count = mbrtowc (&wc, arg, arg_end - arg, &state); -# else - count = mbtowc (&wc, arg, arg_end - arg); -# endif - if (count <= 0) - /* mbrtowc not consistent with mbrlen, or mbtowc - not consistent with mblen. */ - abort (); - ENSURE_ALLOCATION (xsum (length, 1)); - result[length++] = wc; - arg += count; - } - } - - if (has_width && width > characters - && (dp->flags & FLAG_LEFT)) - { - size_t n = width - characters; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_SET (result + length, ' ', n); - length += n; - } - } -# else - /* %ls in vasnprintf. See the specification of fprintf. */ - { - const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; - const wchar_t *arg_end; - size_t characters; -# if !DCHAR_IS_TCHAR - /* This code assumes that TCHAR_T is 'char'. */ - typedef int TCHAR_T_verify[2 * (sizeof (TCHAR_T) == 1) - 1]; - TCHAR_T *tmpsrc; - DCHAR_T *tmpdst; - size_t tmpdst_len; -# endif - size_t w; - - if (has_precision) - { - /* Use only as many wide characters as needed to produce - at most PRECISION bytes, from the left. */ -# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - mbstate_t state; - memset (&state, '\0', sizeof (mbstate_t)); -# endif - arg_end = arg; - characters = 0; - while (precision > 0) - { - char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ - int count; - - if (*arg_end == 0) - /* Found the terminating null wide character. */ - break; -# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - count = wcrtomb (cbuf, *arg_end, &state); -# else - count = wctomb (cbuf, *arg_end); -# endif - if (count < 0) - { - /* Cannot convert. */ - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EILSEQ; - return NULL; - } - if (precision < count) - break; - arg_end++; - characters += count; - precision -= count; - } - } -# if DCHAR_IS_TCHAR - else if (has_width) -# else - else -# endif - { - /* Use the entire string, and count the number of - bytes. */ -# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - mbstate_t state; - memset (&state, '\0', sizeof (mbstate_t)); -# endif - arg_end = arg; - characters = 0; - for (;;) - { - char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ - int count; - - if (*arg_end == 0) - /* Found the terminating null wide character. */ - break; -# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - count = wcrtomb (cbuf, *arg_end, &state); -# else - count = wctomb (cbuf, *arg_end); -# endif - if (count < 0) - { - /* Cannot convert. */ - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EILSEQ; - return NULL; - } - arg_end++; - characters += count; - } - } -# if DCHAR_IS_TCHAR - else - { - /* Use the entire string. */ - arg_end = arg + local_wcslen (arg); - /* The number of bytes doesn't matter. */ - characters = 0; - } -# endif - -# if !DCHAR_IS_TCHAR - /* Convert the string into a piece of temporary memory. */ - tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T)); - if (tmpsrc == NULL) - goto out_of_memory; - { - TCHAR_T *tmpptr = tmpsrc; - size_t remaining; -# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - mbstate_t state; - memset (&state, '\0', sizeof (mbstate_t)); -# endif - for (remaining = characters; remaining > 0; ) - { - char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ - int count; - - if (*arg == 0) - abort (); -# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - count = wcrtomb (cbuf, *arg, &state); -# else - count = wctomb (cbuf, *arg); -# endif - if (count <= 0) - /* Inconsistency. */ - abort (); - memcpy (tmpptr, cbuf, count); - tmpptr += count; - arg++; - remaining -= count; - } - if (!(arg == arg_end)) - abort (); - } - - /* Convert from TCHAR_T[] to DCHAR_T[]. */ - tmpdst = - DCHAR_CONV_FROM_ENCODING (locale_charset (), - iconveh_question_mark, - tmpsrc, characters, - NULL, - NULL, &tmpdst_len); - if (tmpdst == NULL) - { - int saved_errno = errno; - free (tmpsrc); - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = saved_errno; - return NULL; - } - free (tmpsrc); -# endif - - if (has_width) - { -# if ENABLE_UNISTDIO - /* Outside POSIX, it's preferrable to compare the width - against the number of _characters_ of the converted - value. */ - w = DCHAR_MBSNLEN (result + length, characters); -# else - /* The width is compared against the number of _bytes_ - of the converted value, says POSIX. */ - w = characters; -# endif - } - else - /* w doesn't matter. */ - w = 0; - - if (has_width && width > w - && !(dp->flags & FLAG_LEFT)) - { - size_t n = width - w; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_SET (result + length, ' ', n); - length += n; - } - -# if DCHAR_IS_TCHAR - if (has_precision || has_width) - { - /* We know the number of bytes in advance. */ - size_t remaining; -# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - mbstate_t state; - memset (&state, '\0', sizeof (mbstate_t)); -# endif - ENSURE_ALLOCATION (xsum (length, characters)); - for (remaining = characters; remaining > 0; ) - { - char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ - int count; - - if (*arg == 0) - abort (); -# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - count = wcrtomb (cbuf, *arg, &state); -# else - count = wctomb (cbuf, *arg); -# endif - if (count <= 0) - /* Inconsistency. */ - abort (); - memcpy (result + length, cbuf, count); - length += count; - arg++; - remaining -= count; - } - if (!(arg == arg_end)) - abort (); - } - else - { -# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - mbstate_t state; - memset (&state, '\0', sizeof (mbstate_t)); -# endif - while (arg < arg_end) - { - char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */ - int count; - - if (*arg == 0) - abort (); -# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t - count = wcrtomb (cbuf, *arg, &state); -# else - count = wctomb (cbuf, *arg); -# endif - if (count <= 0) - { - /* Cannot convert. */ - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EILSEQ; - return NULL; - } - ENSURE_ALLOCATION (xsum (length, count)); - memcpy (result + length, cbuf, count); - length += count; - arg++; - } - } -# else - ENSURE_ALLOCATION (xsum (length, tmpdst_len)); - DCHAR_CPY (result + length, tmpdst, tmpdst_len); - free (tmpdst); - length += tmpdst_len; -# endif - - if (has_width && width > w - && (dp->flags & FLAG_LEFT)) - { - size_t n = width - w; - ENSURE_ALLOCATION (xsum (length, n)); - DCHAR_SET (result + length, ' ', n); - length += n; - } - } -# endif - } -#endif -#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL - else if ((dp->conversion == 'a' || dp->conversion == 'A') -# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE)) - && (0 -# if NEED_PRINTF_DOUBLE - || a.arg[dp->arg_index].type == TYPE_DOUBLE -# endif -# if NEED_PRINTF_LONG_DOUBLE - || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE -# endif - ) -# endif - ) - { - arg_type type = a.arg[dp->arg_index].type; - int flags = dp->flags; - int has_width; - size_t width; - int has_precision; - size_t precision; - size_t tmp_length; - DCHAR_T tmpbuf[700]; - DCHAR_T *tmp; - DCHAR_T *pad_ptr; - DCHAR_T *p; - - has_width = 0; - width = 0; - if (dp->width_start != dp->width_end) - { - if (dp->width_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->width_arg_index].a.a_int; - if (arg < 0) - { - /* "A negative field width is taken as a '-' flag - followed by a positive field width." */ - flags |= FLAG_LEFT; - width = (unsigned int) (-arg); - } - else - width = arg; - } - else - { - const FCHAR_T *digitp = dp->width_start; - - do - width = xsum (xtimes (width, 10), *digitp++ - '0'); - while (digitp != dp->width_end); - } - has_width = 1; - } - - has_precision = 0; - precision = 0; - if (dp->precision_start != dp->precision_end) - { - if (dp->precision_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->precision_arg_index].a.a_int; - /* "A negative precision is taken as if the precision - were omitted." */ - if (arg >= 0) - { - precision = arg; - has_precision = 1; - } - } - else - { - const FCHAR_T *digitp = dp->precision_start + 1; - - precision = 0; - while (digitp != dp->precision_end) - precision = xsum (xtimes (precision, 10), *digitp++ - '0'); - has_precision = 1; - } - } - - /* Allocate a temporary buffer of sufficient size. */ - if (type == TYPE_LONGDOUBLE) - tmp_length = - (unsigned int) ((LDBL_DIG + 1) - * 0.831 /* decimal -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - else - tmp_length = - (unsigned int) ((DBL_DIG + 1) - * 0.831 /* decimal -> hexadecimal */ - ) - + 1; /* turn floor into ceil */ - if (tmp_length < precision) - tmp_length = precision; - /* Account for sign, decimal point etc. */ - tmp_length = xsum (tmp_length, 12); - - if (tmp_length < width) - tmp_length = width; - - tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ - - if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T)) - tmp = tmpbuf; - else - { - size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T)); - - if (size_overflow_p (tmp_memsize)) - /* Overflow, would lead to out of memory. */ - goto out_of_memory; - tmp = (DCHAR_T *) malloc (tmp_memsize); - if (tmp == NULL) - /* Out of memory. */ - goto out_of_memory; - } - - pad_ptr = NULL; - p = tmp; - if (type == TYPE_LONGDOUBLE) - { -# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE - long double arg = a.arg[dp->arg_index].a.a_longdouble; - - if (isnanl (arg)) - { - if (dp->conversion == 'A') - { - *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; - } - else - { - *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; - } - } - else - { - int sign = 0; - DECL_LONG_DOUBLE_ROUNDING - - BEGIN_LONG_DOUBLE_ROUNDING (); - - if (signbit (arg)) /* arg < 0.0L or negative zero */ - { - sign = -1; - arg = -arg; - } - - if (sign < 0) - *p++ = '-'; - else if (flags & FLAG_SHOWSIGN) - *p++ = '+'; - else if (flags & FLAG_SPACE) - *p++ = ' '; - - if (arg > 0.0L && arg + arg == arg) - { - if (dp->conversion == 'A') - { - *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; - } - else - { - *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; - } - } - else - { - int exponent; - long double mantissa; - - if (arg > 0.0L) - mantissa = printf_frexpl (arg, &exponent); - else - { - exponent = 0; - mantissa = 0.0L; - } - - if (has_precision - && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1) - { - /* Round the mantissa. */ - long double tail = mantissa; - size_t q; - - for (q = precision; ; q--) - { - int digit = (int) tail; - tail -= digit; - if (q == 0) - { - if (digit & 1 ? tail >= 0.5L : tail > 0.5L) - tail = 1 - tail; - else - tail = - tail; - break; - } - tail *= 16.0L; - } - if (tail != 0.0L) - for (q = precision; q > 0; q--) - tail *= 0.0625L; - mantissa += tail; - } - - *p++ = '0'; - *p++ = dp->conversion - 'A' + 'X'; - pad_ptr = p; - { - int digit; - - digit = (int) mantissa; - mantissa -= digit; - *p++ = '0' + digit; - if ((flags & FLAG_ALT) - || mantissa > 0.0L || precision > 0) - { - *p++ = decimal_point_char (); - /* This loop terminates because we assume - that FLT_RADIX is a power of 2. */ - while (mantissa > 0.0L) - { - mantissa *= 16.0L; - digit = (int) mantissa; - mantissa -= digit; - *p++ = digit - + (digit < 10 - ? '0' - : dp->conversion - 10); - if (precision > 0) - precision--; - } - while (precision > 0) - { - *p++ = '0'; - precision--; - } - } - } - *p++ = dp->conversion - 'A' + 'P'; -# if WIDE_CHAR_VERSION - { - static const wchar_t decimal_format[] = - { '%', '+', 'd', '\0' }; - SNPRINTF (p, 6 + 1, decimal_format, exponent); - } - while (*p != '\0') - p++; -# else - if (sizeof (DCHAR_T) == 1) - { - sprintf ((char *) p, "%+d", exponent); - while (*p != '\0') - p++; - } - else - { - char expbuf[6 + 1]; - const char *ep; - sprintf (expbuf, "%+d", exponent); - for (ep = expbuf; (*p = *ep) != '\0'; ep++) - p++; - } -# endif - } - - END_LONG_DOUBLE_ROUNDING (); - } -# else - abort (); -# endif - } - else - { -# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE - double arg = a.arg[dp->arg_index].a.a_double; - - if (isnand (arg)) - { - if (dp->conversion == 'A') - { - *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; - } - else - { - *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; - } - } - else - { - int sign = 0; - - if (signbit (arg)) /* arg < 0.0 or negative zero */ - { - sign = -1; - arg = -arg; - } - - if (sign < 0) - *p++ = '-'; - else if (flags & FLAG_SHOWSIGN) - *p++ = '+'; - else if (flags & FLAG_SPACE) - *p++ = ' '; - - if (arg > 0.0 && arg + arg == arg) - { - if (dp->conversion == 'A') - { - *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; - } - else - { - *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; - } - } - else - { - int exponent; - double mantissa; - - if (arg > 0.0) - mantissa = printf_frexp (arg, &exponent); - else - { - exponent = 0; - mantissa = 0.0; - } - - if (has_precision - && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1) - { - /* Round the mantissa. */ - double tail = mantissa; - size_t q; - - for (q = precision; ; q--) - { - int digit = (int) tail; - tail -= digit; - if (q == 0) - { - if (digit & 1 ? tail >= 0.5 : tail > 0.5) - tail = 1 - tail; - else - tail = - tail; - break; - } - tail *= 16.0; - } - if (tail != 0.0) - for (q = precision; q > 0; q--) - tail *= 0.0625; - mantissa += tail; - } - - *p++ = '0'; - *p++ = dp->conversion - 'A' + 'X'; - pad_ptr = p; - { - int digit; - - digit = (int) mantissa; - mantissa -= digit; - *p++ = '0' + digit; - if ((flags & FLAG_ALT) - || mantissa > 0.0 || precision > 0) - { - *p++ = decimal_point_char (); - /* This loop terminates because we assume - that FLT_RADIX is a power of 2. */ - while (mantissa > 0.0) - { - mantissa *= 16.0; - digit = (int) mantissa; - mantissa -= digit; - *p++ = digit - + (digit < 10 - ? '0' - : dp->conversion - 10); - if (precision > 0) - precision--; - } - while (precision > 0) - { - *p++ = '0'; - precision--; - } - } - } - *p++ = dp->conversion - 'A' + 'P'; -# if WIDE_CHAR_VERSION - { - static const wchar_t decimal_format[] = - { '%', '+', 'd', '\0' }; - SNPRINTF (p, 6 + 1, decimal_format, exponent); - } - while (*p != '\0') - p++; -# else - if (sizeof (DCHAR_T) == 1) - { - sprintf ((char *) p, "%+d", exponent); - while (*p != '\0') - p++; - } - else - { - char expbuf[6 + 1]; - const char *ep; - sprintf (expbuf, "%+d", exponent); - for (ep = expbuf; (*p = *ep) != '\0'; ep++) - p++; - } -# endif - } - } -# else - abort (); -# endif - } - /* The generated string now extends from tmp to p, with the - zero padding insertion point being at pad_ptr. */ - if (has_width && p - tmp < width) - { - size_t pad = width - (p - tmp); - DCHAR_T *end = p + pad; - - if (flags & FLAG_LEFT) - { - /* Pad with spaces on the right. */ - for (; pad > 0; pad--) - *p++ = ' '; - } - else if ((flags & FLAG_ZERO) && pad_ptr != NULL) - { - /* Pad with zeroes. */ - DCHAR_T *q = end; - - while (p > pad_ptr) - *--q = *--p; - for (; pad > 0; pad--) - *p++ = '0'; - } - else - { - /* Pad with spaces on the left. */ - DCHAR_T *q = end; - - while (p > tmp) - *--q = *--p; - for (; pad > 0; pad--) - *p++ = ' '; - } - - p = end; - } - - { - size_t count = p - tmp; - - if (count >= tmp_length) - /* tmp_length was incorrectly calculated - fix the - code above! */ - abort (); - - /* Make room for the result. */ - if (count >= allocated - length) - { - size_t n = xsum (length, count); - - ENSURE_ALLOCATION (n); - } - - /* Append the result. */ - memcpy (result + length, tmp, count * sizeof (DCHAR_T)); - if (tmp != tmpbuf) - free (tmp); - length += count; - } - } -#endif -#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL - else if ((dp->conversion == 'f' || dp->conversion == 'F' - || dp->conversion == 'e' || dp->conversion == 'E' - || dp->conversion == 'g' || dp->conversion == 'G' - || dp->conversion == 'a' || dp->conversion == 'A') - && (0 -# if NEED_PRINTF_DOUBLE - || a.arg[dp->arg_index].type == TYPE_DOUBLE -# elif NEED_PRINTF_INFINITE_DOUBLE - || (a.arg[dp->arg_index].type == TYPE_DOUBLE - /* The systems (mingw) which produce wrong output - for Inf, -Inf, and NaN also do so for -0.0. - Therefore we treat this case here as well. */ - && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double)) -# endif -# if NEED_PRINTF_LONG_DOUBLE - || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE -# elif NEED_PRINTF_INFINITE_LONG_DOUBLE - || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE - /* Some systems produce wrong output for Inf, - -Inf, and NaN. Some systems in this category - (IRIX 5.3) also do so for -0.0. Therefore we - treat this case here as well. */ - && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble)) -# endif - )) - { -# if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) - arg_type type = a.arg[dp->arg_index].type; -# endif - int flags = dp->flags; - int has_width; - size_t width; - int has_precision; - size_t precision; - size_t tmp_length; - DCHAR_T tmpbuf[700]; - DCHAR_T *tmp; - DCHAR_T *pad_ptr; - DCHAR_T *p; - - has_width = 0; - width = 0; - if (dp->width_start != dp->width_end) - { - if (dp->width_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->width_arg_index].a.a_int; - if (arg < 0) - { - /* "A negative field width is taken as a '-' flag - followed by a positive field width." */ - flags |= FLAG_LEFT; - width = (unsigned int) (-arg); - } - else - width = arg; - } - else - { - const FCHAR_T *digitp = dp->width_start; - - do - width = xsum (xtimes (width, 10), *digitp++ - '0'); - while (digitp != dp->width_end); - } - has_width = 1; - } - - has_precision = 0; - precision = 0; - if (dp->precision_start != dp->precision_end) - { - if (dp->precision_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->precision_arg_index].a.a_int; - /* "A negative precision is taken as if the precision - were omitted." */ - if (arg >= 0) - { - precision = arg; - has_precision = 1; - } - } - else - { - const FCHAR_T *digitp = dp->precision_start + 1; - - precision = 0; - while (digitp != dp->precision_end) - precision = xsum (xtimes (precision, 10), *digitp++ - '0'); - has_precision = 1; - } - } - - /* POSIX specifies the default precision to be 6 for %f, %F, - %e, %E, but not for %g, %G. Implementations appear to use - the same default precision also for %g, %G. But for %a, %A, - the default precision is 0. */ - if (!has_precision) - if (!(dp->conversion == 'a' || dp->conversion == 'A')) - precision = 6; - - /* Allocate a temporary buffer of sufficient size. */ -# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE - tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1); -# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE - tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0); -# elif NEED_PRINTF_LONG_DOUBLE - tmp_length = LDBL_DIG + 1; -# elif NEED_PRINTF_DOUBLE - tmp_length = DBL_DIG + 1; -# else - tmp_length = 0; -# endif - if (tmp_length < precision) - tmp_length = precision; -# if NEED_PRINTF_LONG_DOUBLE -# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE - if (type == TYPE_LONGDOUBLE) -# endif - if (dp->conversion == 'f' || dp->conversion == 'F') - { - long double arg = a.arg[dp->arg_index].a.a_longdouble; - if (!(isnanl (arg) || arg + arg == arg)) - { - /* arg is finite and nonzero. */ - int exponent = floorlog10l (arg < 0 ? -arg : arg); - if (exponent >= 0 && tmp_length < exponent + precision) - tmp_length = exponent + precision; - } - } -# endif -# if NEED_PRINTF_DOUBLE -# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE - if (type == TYPE_DOUBLE) -# endif - if (dp->conversion == 'f' || dp->conversion == 'F') - { - double arg = a.arg[dp->arg_index].a.a_double; - if (!(isnand (arg) || arg + arg == arg)) - { - /* arg is finite and nonzero. */ - int exponent = floorlog10 (arg < 0 ? -arg : arg); - if (exponent >= 0 && tmp_length < exponent + precision) - tmp_length = exponent + precision; - } - } -# endif - /* Account for sign, decimal point etc. */ - tmp_length = xsum (tmp_length, 12); - - if (tmp_length < width) - tmp_length = width; - - tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */ - - if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T)) - tmp = tmpbuf; - else - { - size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T)); - - if (size_overflow_p (tmp_memsize)) - /* Overflow, would lead to out of memory. */ - goto out_of_memory; - tmp = (DCHAR_T *) malloc (tmp_memsize); - if (tmp == NULL) - /* Out of memory. */ - goto out_of_memory; - } - - pad_ptr = NULL; - p = tmp; - -# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE -# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE - if (type == TYPE_LONGDOUBLE) -# endif - { - long double arg = a.arg[dp->arg_index].a.a_longdouble; - - if (isnanl (arg)) - { - if (dp->conversion >= 'A' && dp->conversion <= 'Z') - { - *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; - } - else - { - *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; - } - } - else - { - int sign = 0; - DECL_LONG_DOUBLE_ROUNDING - - BEGIN_LONG_DOUBLE_ROUNDING (); - - if (signbit (arg)) /* arg < 0.0L or negative zero */ - { - sign = -1; - arg = -arg; - } - - if (sign < 0) - *p++ = '-'; - else if (flags & FLAG_SHOWSIGN) - *p++ = '+'; - else if (flags & FLAG_SPACE) - *p++ = ' '; - - if (arg > 0.0L && arg + arg == arg) - { - if (dp->conversion >= 'A' && dp->conversion <= 'Z') - { - *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; - } - else - { - *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; - } - } - else - { -# if NEED_PRINTF_LONG_DOUBLE - pad_ptr = p; - - if (dp->conversion == 'f' || dp->conversion == 'F') - { - char *digits; - size_t ndigits; - - digits = - scale10_round_decimal_long_double (arg, precision); - if (digits == NULL) - { - END_LONG_DOUBLE_ROUNDING (); - goto out_of_memory; - } - ndigits = strlen (digits); - - if (ndigits > precision) - do - { - --ndigits; - *p++ = digits[ndigits]; - } - while (ndigits > precision); - else - *p++ = '0'; - /* Here ndigits <= precision. */ - if ((flags & FLAG_ALT) || precision > 0) - { - *p++ = decimal_point_char (); - for (; precision > ndigits; precision--) - *p++ = '0'; - while (ndigits > 0) - { - --ndigits; - *p++ = digits[ndigits]; - } - } - - free (digits); - } - else if (dp->conversion == 'e' || dp->conversion == 'E') - { - int exponent; - - if (arg == 0.0L) - { - exponent = 0; - *p++ = '0'; - if ((flags & FLAG_ALT) || precision > 0) - { - *p++ = decimal_point_char (); - for (; precision > 0; precision--) - *p++ = '0'; - } - } - else - { - /* arg > 0.0L. */ - int adjusted; - char *digits; - size_t ndigits; - - exponent = floorlog10l (arg); - adjusted = 0; - for (;;) - { - digits = - scale10_round_decimal_long_double (arg, - (int)precision - exponent); - if (digits == NULL) - { - END_LONG_DOUBLE_ROUNDING (); - goto out_of_memory; - } - ndigits = strlen (digits); - - if (ndigits == precision + 1) - break; - if (ndigits < precision - || ndigits > precision + 2) - /* The exponent was not guessed - precisely enough. */ - abort (); - if (adjusted) - /* None of two values of exponent is - the right one. Prevent an endless - loop. */ - abort (); - free (digits); - if (ndigits == precision) - exponent -= 1; - else - exponent += 1; - adjusted = 1; - } - /* Here ndigits = precision+1. */ - if (is_borderline (digits, precision)) - { - /* Maybe the exponent guess was too high - and a smaller exponent can be reached - by turning a 10...0 into 9...9x. */ - char *digits2 = - scale10_round_decimal_long_double (arg, - (int)precision - exponent + 1); - if (digits2 == NULL) - { - free (digits); - END_LONG_DOUBLE_ROUNDING (); - goto out_of_memory; - } - if (strlen (digits2) == precision + 1) - { - free (digits); - digits = digits2; - exponent -= 1; - } - else - free (digits2); - } - /* Here ndigits = precision+1. */ - - *p++ = digits[--ndigits]; - if ((flags & FLAG_ALT) || precision > 0) - { - *p++ = decimal_point_char (); - while (ndigits > 0) - { - --ndigits; - *p++ = digits[ndigits]; - } - } - - free (digits); - } - - *p++ = dp->conversion; /* 'e' or 'E' */ -# if WIDE_CHAR_VERSION - { - static const wchar_t decimal_format[] = - { '%', '+', '.', '2', 'd', '\0' }; - SNPRINTF (p, 6 + 1, decimal_format, exponent); - } - while (*p != '\0') - p++; -# else - if (sizeof (DCHAR_T) == 1) - { - sprintf ((char *) p, "%+.2d", exponent); - while (*p != '\0') - p++; - } - else - { - char expbuf[6 + 1]; - const char *ep; - sprintf (expbuf, "%+.2d", exponent); - for (ep = expbuf; (*p = *ep) != '\0'; ep++) - p++; - } -# endif - } - else if (dp->conversion == 'g' || dp->conversion == 'G') - { - if (precision == 0) - precision = 1; - /* precision >= 1. */ - - if (arg == 0.0L) - /* The exponent is 0, >= -4, < precision. - Use fixed-point notation. */ - { - size_t ndigits = precision; - /* Number of trailing zeroes that have to be - dropped. */ - size_t nzeroes = - (flags & FLAG_ALT ? 0 : precision - 1); - - --ndigits; - *p++ = '0'; - if ((flags & FLAG_ALT) || ndigits > nzeroes) - { - *p++ = decimal_point_char (); - while (ndigits > nzeroes) - { - --ndigits; - *p++ = '0'; - } - } - } - else - { - /* arg > 0.0L. */ - int exponent; - int adjusted; - char *digits; - size_t ndigits; - size_t nzeroes; - - exponent = floorlog10l (arg); - adjusted = 0; - for (;;) - { - digits = - scale10_round_decimal_long_double (arg, - (int)(precision - 1) - exponent); - if (digits == NULL) - { - END_LONG_DOUBLE_ROUNDING (); - goto out_of_memory; - } - ndigits = strlen (digits); - - if (ndigits == precision) - break; - if (ndigits < precision - 1 - || ndigits > precision + 1) - /* The exponent was not guessed - precisely enough. */ - abort (); - if (adjusted) - /* None of two values of exponent is - the right one. Prevent an endless - loop. */ - abort (); - free (digits); - if (ndigits < precision) - exponent -= 1; - else - exponent += 1; - adjusted = 1; - } - /* Here ndigits = precision. */ - if (is_borderline (digits, precision - 1)) - { - /* Maybe the exponent guess was too high - and a smaller exponent can be reached - by turning a 10...0 into 9...9x. */ - char *digits2 = - scale10_round_decimal_long_double (arg, - (int)(precision - 1) - exponent + 1); - if (digits2 == NULL) - { - free (digits); - END_LONG_DOUBLE_ROUNDING (); - goto out_of_memory; - } - if (strlen (digits2) == precision) - { - free (digits); - digits = digits2; - exponent -= 1; - } - else - free (digits2); - } - /* Here ndigits = precision. */ - - /* Determine the number of trailing zeroes - that have to be dropped. */ - nzeroes = 0; - if ((flags & FLAG_ALT) == 0) - while (nzeroes < ndigits - && digits[nzeroes] == '0') - nzeroes++; - - /* The exponent is now determined. */ - if (exponent >= -4 - && exponent < (long)precision) - { - /* Fixed-point notation: - max(exponent,0)+1 digits, then the - decimal point, then the remaining - digits without trailing zeroes. */ - if (exponent >= 0) - { - size_t count = exponent + 1; - /* Note: count <= precision = ndigits. */ - for (; count > 0; count--) - *p++ = digits[--ndigits]; - if ((flags & FLAG_ALT) || ndigits > nzeroes) - { - *p++ = decimal_point_char (); - while (ndigits > nzeroes) - { - --ndigits; - *p++ = digits[ndigits]; - } - } - } - else - { - size_t count = -exponent - 1; - *p++ = '0'; - *p++ = decimal_point_char (); - for (; count > 0; count--) - *p++ = '0'; - while (ndigits > nzeroes) - { - --ndigits; - *p++ = digits[ndigits]; - } - } - } - else - { - /* Exponential notation. */ - *p++ = digits[--ndigits]; - if ((flags & FLAG_ALT) || ndigits > nzeroes) - { - *p++ = decimal_point_char (); - while (ndigits > nzeroes) - { - --ndigits; - *p++ = digits[ndigits]; - } - } - *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */ -# if WIDE_CHAR_VERSION - { - static const wchar_t decimal_format[] = - { '%', '+', '.', '2', 'd', '\0' }; - SNPRINTF (p, 6 + 1, decimal_format, exponent); - } - while (*p != '\0') - p++; -# else - if (sizeof (DCHAR_T) == 1) - { - sprintf ((char *) p, "%+.2d", exponent); - while (*p != '\0') - p++; - } - else - { - char expbuf[6 + 1]; - const char *ep; - sprintf (expbuf, "%+.2d", exponent); - for (ep = expbuf; (*p = *ep) != '\0'; ep++) - p++; - } -# endif - } - - free (digits); - } - } - else - abort (); -# else - /* arg is finite. */ - if (!(arg == 0.0L)) - abort (); - - pad_ptr = p; - - if (dp->conversion == 'f' || dp->conversion == 'F') - { - *p++ = '0'; - if ((flags & FLAG_ALT) || precision > 0) - { - *p++ = decimal_point_char (); - for (; precision > 0; precision--) - *p++ = '0'; - } - } - else if (dp->conversion == 'e' || dp->conversion == 'E') - { - *p++ = '0'; - if ((flags & FLAG_ALT) || precision > 0) - { - *p++ = decimal_point_char (); - for (; precision > 0; precision--) - *p++ = '0'; - } - *p++ = dp->conversion; /* 'e' or 'E' */ - *p++ = '+'; - *p++ = '0'; - *p++ = '0'; - } - else if (dp->conversion == 'g' || dp->conversion == 'G') - { - *p++ = '0'; - if (flags & FLAG_ALT) - { - size_t ndigits = - (precision > 0 ? precision - 1 : 0); - *p++ = decimal_point_char (); - for (; ndigits > 0; --ndigits) - *p++ = '0'; - } - } - else if (dp->conversion == 'a' || dp->conversion == 'A') - { - *p++ = '0'; - *p++ = dp->conversion - 'A' + 'X'; - pad_ptr = p; - *p++ = '0'; - if ((flags & FLAG_ALT) || precision > 0) - { - *p++ = decimal_point_char (); - for (; precision > 0; precision--) - *p++ = '0'; - } - *p++ = dp->conversion - 'A' + 'P'; - *p++ = '+'; - *p++ = '0'; - } - else - abort (); -# endif - } - - END_LONG_DOUBLE_ROUNDING (); - } - } -# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE - else -# endif -# endif -# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE - { - double arg = a.arg[dp->arg_index].a.a_double; - - if (isnand (arg)) - { - if (dp->conversion >= 'A' && dp->conversion <= 'Z') - { - *p++ = 'N'; *p++ = 'A'; *p++ = 'N'; - } - else - { - *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; - } - } - else - { - int sign = 0; - - if (signbit (arg)) /* arg < 0.0 or negative zero */ - { - sign = -1; - arg = -arg; - } - - if (sign < 0) - *p++ = '-'; - else if (flags & FLAG_SHOWSIGN) - *p++ = '+'; - else if (flags & FLAG_SPACE) - *p++ = ' '; - - if (arg > 0.0 && arg + arg == arg) - { - if (dp->conversion >= 'A' && dp->conversion <= 'Z') - { - *p++ = 'I'; *p++ = 'N'; *p++ = 'F'; - } - else - { - *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; - } - } - else - { -# if NEED_PRINTF_DOUBLE - pad_ptr = p; - - if (dp->conversion == 'f' || dp->conversion == 'F') - { - char *digits; - size_t ndigits; - - digits = - scale10_round_decimal_double (arg, precision); - if (digits == NULL) - goto out_of_memory; - ndigits = strlen (digits); - - if (ndigits > precision) - do - { - --ndigits; - *p++ = digits[ndigits]; - } - while (ndigits > precision); - else - *p++ = '0'; - /* Here ndigits <= precision. */ - if ((flags & FLAG_ALT) || precision > 0) - { - *p++ = decimal_point_char (); - for (; precision > ndigits; precision--) - *p++ = '0'; - while (ndigits > 0) - { - --ndigits; - *p++ = digits[ndigits]; - } - } - - free (digits); - } - else if (dp->conversion == 'e' || dp->conversion == 'E') - { - int exponent; - - if (arg == 0.0) - { - exponent = 0; - *p++ = '0'; - if ((flags & FLAG_ALT) || precision > 0) - { - *p++ = decimal_point_char (); - for (; precision > 0; precision--) - *p++ = '0'; - } - } - else - { - /* arg > 0.0. */ - int adjusted; - char *digits; - size_t ndigits; - - exponent = floorlog10 (arg); - adjusted = 0; - for (;;) - { - digits = - scale10_round_decimal_double (arg, - (int)precision - exponent); - if (digits == NULL) - goto out_of_memory; - ndigits = strlen (digits); - - if (ndigits == precision + 1) - break; - if (ndigits < precision - || ndigits > precision + 2) - /* The exponent was not guessed - precisely enough. */ - abort (); - if (adjusted) - /* None of two values of exponent is - the right one. Prevent an endless - loop. */ - abort (); - free (digits); - if (ndigits == precision) - exponent -= 1; - else - exponent += 1; - adjusted = 1; - } - /* Here ndigits = precision+1. */ - if (is_borderline (digits, precision)) - { - /* Maybe the exponent guess was too high - and a smaller exponent can be reached - by turning a 10...0 into 9...9x. */ - char *digits2 = - scale10_round_decimal_double (arg, - (int)precision - exponent + 1); - if (digits2 == NULL) - { - free (digits); - goto out_of_memory; - } - if (strlen (digits2) == precision + 1) - { - free (digits); - digits = digits2; - exponent -= 1; - } - else - free (digits2); - } - /* Here ndigits = precision+1. */ - - *p++ = digits[--ndigits]; - if ((flags & FLAG_ALT) || precision > 0) - { - *p++ = decimal_point_char (); - while (ndigits > 0) - { - --ndigits; - *p++ = digits[ndigits]; - } - } - - free (digits); - } - - *p++ = dp->conversion; /* 'e' or 'E' */ -# if WIDE_CHAR_VERSION - { - static const wchar_t decimal_format[] = - /* Produce the same number of exponent digits - as the native printf implementation. */ -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - { '%', '+', '.', '3', 'd', '\0' }; -# else - { '%', '+', '.', '2', 'd', '\0' }; -# endif - SNPRINTF (p, 6 + 1, decimal_format, exponent); - } - while (*p != '\0') - p++; -# else - { - static const char decimal_format[] = - /* Produce the same number of exponent digits - as the native printf implementation. */ -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - "%+.3d"; -# else - "%+.2d"; -# endif - if (sizeof (DCHAR_T) == 1) - { - sprintf ((char *) p, decimal_format, exponent); - while (*p != '\0') - p++; - } - else - { - char expbuf[6 + 1]; - const char *ep; - sprintf (expbuf, decimal_format, exponent); - for (ep = expbuf; (*p = *ep) != '\0'; ep++) - p++; - } - } -# endif - } - else if (dp->conversion == 'g' || dp->conversion == 'G') - { - if (precision == 0) - precision = 1; - /* precision >= 1. */ - - if (arg == 0.0) - /* The exponent is 0, >= -4, < precision. - Use fixed-point notation. */ - { - size_t ndigits = precision; - /* Number of trailing zeroes that have to be - dropped. */ - size_t nzeroes = - (flags & FLAG_ALT ? 0 : precision - 1); - - --ndigits; - *p++ = '0'; - if ((flags & FLAG_ALT) || ndigits > nzeroes) - { - *p++ = decimal_point_char (); - while (ndigits > nzeroes) - { - --ndigits; - *p++ = '0'; - } - } - } - else - { - /* arg > 0.0. */ - int exponent; - int adjusted; - char *digits; - size_t ndigits; - size_t nzeroes; - - exponent = floorlog10 (arg); - adjusted = 0; - for (;;) - { - digits = - scale10_round_decimal_double (arg, - (int)(precision - 1) - exponent); - if (digits == NULL) - goto out_of_memory; - ndigits = strlen (digits); - - if (ndigits == precision) - break; - if (ndigits < precision - 1 - || ndigits > precision + 1) - /* The exponent was not guessed - precisely enough. */ - abort (); - if (adjusted) - /* None of two values of exponent is - the right one. Prevent an endless - loop. */ - abort (); - free (digits); - if (ndigits < precision) - exponent -= 1; - else - exponent += 1; - adjusted = 1; - } - /* Here ndigits = precision. */ - if (is_borderline (digits, precision - 1)) - { - /* Maybe the exponent guess was too high - and a smaller exponent can be reached - by turning a 10...0 into 9...9x. */ - char *digits2 = - scale10_round_decimal_double (arg, - (int)(precision - 1) - exponent + 1); - if (digits2 == NULL) - { - free (digits); - goto out_of_memory; - } - if (strlen (digits2) == precision) - { - free (digits); - digits = digits2; - exponent -= 1; - } - else - free (digits2); - } - /* Here ndigits = precision. */ - - /* Determine the number of trailing zeroes - that have to be dropped. */ - nzeroes = 0; - if ((flags & FLAG_ALT) == 0) - while (nzeroes < ndigits - && digits[nzeroes] == '0') - nzeroes++; - - /* The exponent is now determined. */ - if (exponent >= -4 - && exponent < (long)precision) - { - /* Fixed-point notation: - max(exponent,0)+1 digits, then the - decimal point, then the remaining - digits without trailing zeroes. */ - if (exponent >= 0) - { - size_t count = exponent + 1; - /* Note: count <= precision = ndigits. */ - for (; count > 0; count--) - *p++ = digits[--ndigits]; - if ((flags & FLAG_ALT) || ndigits > nzeroes) - { - *p++ = decimal_point_char (); - while (ndigits > nzeroes) - { - --ndigits; - *p++ = digits[ndigits]; - } - } - } - else - { - size_t count = -exponent - 1; - *p++ = '0'; - *p++ = decimal_point_char (); - for (; count > 0; count--) - *p++ = '0'; - while (ndigits > nzeroes) - { - --ndigits; - *p++ = digits[ndigits]; - } - } - } - else - { - /* Exponential notation. */ - *p++ = digits[--ndigits]; - if ((flags & FLAG_ALT) || ndigits > nzeroes) - { - *p++ = decimal_point_char (); - while (ndigits > nzeroes) - { - --ndigits; - *p++ = digits[ndigits]; - } - } - *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */ -# if WIDE_CHAR_VERSION - { - static const wchar_t decimal_format[] = - /* Produce the same number of exponent digits - as the native printf implementation. */ -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - { '%', '+', '.', '3', 'd', '\0' }; -# else - { '%', '+', '.', '2', 'd', '\0' }; -# endif - SNPRINTF (p, 6 + 1, decimal_format, exponent); - } - while (*p != '\0') - p++; -# else - { - static const char decimal_format[] = - /* Produce the same number of exponent digits - as the native printf implementation. */ -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - "%+.3d"; -# else - "%+.2d"; -# endif - if (sizeof (DCHAR_T) == 1) - { - sprintf ((char *) p, decimal_format, exponent); - while (*p != '\0') - p++; - } - else - { - char expbuf[6 + 1]; - const char *ep; - sprintf (expbuf, decimal_format, exponent); - for (ep = expbuf; (*p = *ep) != '\0'; ep++) - p++; - } - } -# endif - } - - free (digits); - } - } - else - abort (); -# else - /* arg is finite. */ - if (!(arg == 0.0)) - abort (); - - pad_ptr = p; - - if (dp->conversion == 'f' || dp->conversion == 'F') - { - *p++ = '0'; - if ((flags & FLAG_ALT) || precision > 0) - { - *p++ = decimal_point_char (); - for (; precision > 0; precision--) - *p++ = '0'; - } - } - else if (dp->conversion == 'e' || dp->conversion == 'E') - { - *p++ = '0'; - if ((flags & FLAG_ALT) || precision > 0) - { - *p++ = decimal_point_char (); - for (; precision > 0; precision--) - *p++ = '0'; - } - *p++ = dp->conversion; /* 'e' or 'E' */ - *p++ = '+'; - /* Produce the same number of exponent digits as - the native printf implementation. */ -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - *p++ = '0'; -# endif - *p++ = '0'; - *p++ = '0'; - } - else if (dp->conversion == 'g' || dp->conversion == 'G') - { - *p++ = '0'; - if (flags & FLAG_ALT) - { - size_t ndigits = - (precision > 0 ? precision - 1 : 0); - *p++ = decimal_point_char (); - for (; ndigits > 0; --ndigits) - *p++ = '0'; - } - } - else - abort (); -# endif - } - } - } -# endif - - /* The generated string now extends from tmp to p, with the - zero padding insertion point being at pad_ptr. */ - if (has_width && p - tmp < width) - { - size_t pad = width - (p - tmp); - DCHAR_T *end = p + pad; - - if (flags & FLAG_LEFT) - { - /* Pad with spaces on the right. */ - for (; pad > 0; pad--) - *p++ = ' '; - } - else if ((flags & FLAG_ZERO) && pad_ptr != NULL) - { - /* Pad with zeroes. */ - DCHAR_T *q = end; - - while (p > pad_ptr) - *--q = *--p; - for (; pad > 0; pad--) - *p++ = '0'; - } - else - { - /* Pad with spaces on the left. */ - DCHAR_T *q = end; - - while (p > tmp) - *--q = *--p; - for (; pad > 0; pad--) - *p++ = ' '; - } - - p = end; - } - - { - size_t count = p - tmp; - - if (count >= tmp_length) - /* tmp_length was incorrectly calculated - fix the - code above! */ - abort (); - - /* Make room for the result. */ - if (count >= allocated - length) - { - size_t n = xsum (length, count); - - ENSURE_ALLOCATION (n); - } - - /* Append the result. */ - memcpy (result + length, tmp, count * sizeof (DCHAR_T)); - if (tmp != tmpbuf) - free (tmp); - length += count; - } - } -#endif - else - { - arg_type type = a.arg[dp->arg_index].type; - int flags = dp->flags; -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION - int has_width; - size_t width; -#endif -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION - int has_precision; - size_t precision; -#endif -#if NEED_PRINTF_UNBOUNDED_PRECISION - int prec_ourselves; -#else -# define prec_ourselves 0 -#endif -#if NEED_PRINTF_FLAG_LEFTADJUST -# define pad_ourselves 1 -#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION - int pad_ourselves; -#else -# define pad_ourselves 0 -#endif - TCHAR_T *fbp; - unsigned int prefix_count; - int prefixes[2] IF_LINT (= { 0 }); -#if !USE_SNPRINTF - size_t tmp_length; - TCHAR_T tmpbuf[700]; - TCHAR_T *tmp; -#endif - -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION - has_width = 0; - width = 0; - if (dp->width_start != dp->width_end) - { - if (dp->width_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->width_arg_index].a.a_int; - if (arg < 0) - { - /* "A negative field width is taken as a '-' flag - followed by a positive field width." */ - flags |= FLAG_LEFT; - width = (unsigned int) (-arg); - } - else - width = arg; - } - else - { - const FCHAR_T *digitp = dp->width_start; - - do - width = xsum (xtimes (width, 10), *digitp++ - '0'); - while (digitp != dp->width_end); - } - has_width = 1; - } -#endif - -#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION - has_precision = 0; - precision = 6; - if (dp->precision_start != dp->precision_end) - { - if (dp->precision_arg_index != ARG_NONE) - { - int arg; - - if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) - abort (); - arg = a.arg[dp->precision_arg_index].a.a_int; - /* "A negative precision is taken as if the precision - were omitted." */ - if (arg >= 0) - { - precision = arg; - has_precision = 1; - } - } - else - { - const FCHAR_T *digitp = dp->precision_start + 1; - - precision = 0; - while (digitp != dp->precision_end) - precision = xsum (xtimes (precision, 10), *digitp++ - '0'); - has_precision = 1; - } - } -#endif - - /* Decide whether to handle the precision ourselves. */ -#if NEED_PRINTF_UNBOUNDED_PRECISION - switch (dp->conversion) - { - case 'd': case 'i': case 'u': - case 'o': - case 'x': case 'X': case 'p': - prec_ourselves = has_precision && (precision > 0); - break; - default: - prec_ourselves = 0; - break; - } -#endif - - /* Decide whether to perform the padding ourselves. */ -#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION) - switch (dp->conversion) - { -# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO - /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need - to perform the padding after this conversion. Functions - with unistdio extensions perform the padding based on - character count rather than element count. */ - case 'c': case 's': -# endif -# if NEED_PRINTF_FLAG_ZERO - case 'f': case 'F': case 'e': case 'E': case 'g': case 'G': - case 'a': case 'A': -# endif - pad_ourselves = 1; - break; - default: - pad_ourselves = prec_ourselves; - break; - } -#endif - -#if !USE_SNPRINTF - /* Allocate a temporary buffer of sufficient size for calling - sprintf. */ - tmp_length = - MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type, - flags, width, has_precision, precision, - pad_ourselves); - - if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T)) - tmp = tmpbuf; - else - { - size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T)); - - if (size_overflow_p (tmp_memsize)) - /* Overflow, would lead to out of memory. */ - goto out_of_memory; - tmp = (TCHAR_T *) malloc (tmp_memsize); - if (tmp == NULL) - /* Out of memory. */ - goto out_of_memory; - } -#endif - - /* Construct the format string for calling snprintf or - sprintf. */ - fbp = buf; - *fbp++ = '%'; -#if NEED_PRINTF_FLAG_GROUPING - /* The underlying implementation doesn't support the ' flag. - Produce no grouping characters in this case; this is - acceptable because the grouping is locale dependent. */ -#else - if (flags & FLAG_GROUP) - *fbp++ = '\''; -#endif - if (flags & FLAG_LEFT) - *fbp++ = '-'; - if (flags & FLAG_SHOWSIGN) - *fbp++ = '+'; - if (flags & FLAG_SPACE) - *fbp++ = ' '; - if (flags & FLAG_ALT) - *fbp++ = '#'; - if (!pad_ourselves) - { - if (flags & FLAG_ZERO) - *fbp++ = '0'; - if (dp->width_start != dp->width_end) - { - size_t n = dp->width_end - dp->width_start; - /* The width specification is known to consist only - of standard ASCII characters. */ - if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) - { - memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T)); - fbp += n; - } - else - { - const FCHAR_T *mp = dp->width_start; - do - *fbp++ = (unsigned char) *mp++; - while (--n > 0); - } - } - } - if (!prec_ourselves) - { - if (dp->precision_start != dp->precision_end) - { - size_t n = dp->precision_end - dp->precision_start; - /* The precision specification is known to consist only - of standard ASCII characters. */ - if (sizeof (FCHAR_T) == sizeof (TCHAR_T)) - { - memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T)); - fbp += n; - } - else - { - const FCHAR_T *mp = dp->precision_start; - do - *fbp++ = (unsigned char) *mp++; - while (--n > 0); - } - } - } - - switch (type) - { -#if HAVE_LONG_LONG_INT - case TYPE_LONGLONGINT: - case TYPE_ULONGLONGINT: -# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ - *fbp++ = 'I'; - *fbp++ = '6'; - *fbp++ = '4'; - break; -# else - *fbp++ = 'l'; - /*FALLTHROUGH*/ -# endif -#endif - case TYPE_LONGINT: - case TYPE_ULONGINT: -#if HAVE_WINT_T - case TYPE_WIDE_CHAR: -#endif -#if HAVE_WCHAR_T - case TYPE_WIDE_STRING: -#endif - *fbp++ = 'l'; - break; - case TYPE_LONGDOUBLE: - *fbp++ = 'L'; - break; - default: - break; - } -#if NEED_PRINTF_DIRECTIVE_F - if (dp->conversion == 'F') - *fbp = 'f'; - else -#endif - *fbp = dp->conversion; -#if USE_SNPRINTF -# if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)) - fbp[1] = '%'; - fbp[2] = 'n'; - fbp[3] = '\0'; -# else - /* On glibc2 systems from glibc >= 2.3 - probably also older - ones - we know that snprintf's returns value conforms to - ISO C 99: the gl_SNPRINTF_DIRECTIVE_N test passes. - Therefore we can avoid using %n in this situation. - On glibc2 systems from 2004-10-18 or newer, the use of %n - in format strings in writable memory may crash the program - (if compiled with _FORTIFY_SOURCE=2), so we should avoid it - in this situation. */ - /* On native Win32 systems (such as mingw), we can avoid using - %n because: - - Although the gl_SNPRINTF_TRUNCATION_C99 test fails, - snprintf does not write more than the specified number - of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes - '4', '5', '6' into buf, not '4', '5', '\0'.) - - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf - allows us to recognize the case of an insufficient - buffer size: it returns -1 in this case. - On native Win32 systems (such as mingw) where the OS is - Windows Vista, the use of %n in format strings by default - crashes the program. See - and - - So we should avoid %n in this situation. */ - fbp[1] = '\0'; -# endif -#else - fbp[1] = '\0'; -#endif - - /* Construct the arguments for calling snprintf or sprintf. */ - prefix_count = 0; - if (!pad_ourselves && dp->width_arg_index != ARG_NONE) - { - if (!(a.arg[dp->width_arg_index].type == TYPE_INT)) - abort (); - prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int; - } - if (!prec_ourselves && dp->precision_arg_index != ARG_NONE) - { - if (!(a.arg[dp->precision_arg_index].type == TYPE_INT)) - abort (); - prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int; - } - -#if USE_SNPRINTF - /* The SNPRINTF result is appended after result[0..length]. - The latter is an array of DCHAR_T; SNPRINTF appends an - array of TCHAR_T to it. This is possible because - sizeof (TCHAR_T) divides sizeof (DCHAR_T) and - alignof (TCHAR_T) <= alignof (DCHAR_T). */ -# define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T)) - /* Ensure that maxlen below will be >= 2. Needed on BeOS, - where an snprintf() with maxlen==1 acts like sprintf(). */ - ENSURE_ALLOCATION (xsum (length, - (2 + TCHARS_PER_DCHAR - 1) - / TCHARS_PER_DCHAR)); - /* Prepare checking whether snprintf returns the count - via %n. */ - *(TCHAR_T *) (result + length) = '\0'; -#endif - - for (;;) - { - int count = -1; - -#if USE_SNPRINTF - int retcount = 0; - size_t maxlen = allocated - length; - /* SNPRINTF can fail if its second argument is - > INT_MAX. */ - if (maxlen > INT_MAX / TCHARS_PER_DCHAR) - maxlen = INT_MAX / TCHARS_PER_DCHAR; - maxlen = maxlen * TCHARS_PER_DCHAR; -# define SNPRINTF_BUF(arg) \ - switch (prefix_count) \ - { \ - case 0: \ - retcount = SNPRINTF ((TCHAR_T *) (result + length), \ - maxlen, buf, \ - arg, &count); \ - break; \ - case 1: \ - retcount = SNPRINTF ((TCHAR_T *) (result + length), \ - maxlen, buf, \ - prefixes[0], arg, &count); \ - break; \ - case 2: \ - retcount = SNPRINTF ((TCHAR_T *) (result + length), \ - maxlen, buf, \ - prefixes[0], prefixes[1], arg, \ - &count); \ - break; \ - default: \ - abort (); \ - } -#else -# define SNPRINTF_BUF(arg) \ - switch (prefix_count) \ - { \ - case 0: \ - count = sprintf (tmp, buf, arg); \ - break; \ - case 1: \ - count = sprintf (tmp, buf, prefixes[0], arg); \ - break; \ - case 2: \ - count = sprintf (tmp, buf, prefixes[0], prefixes[1],\ - arg); \ - break; \ - default: \ - abort (); \ - } -#endif - - errno = 0; - switch (type) - { - case TYPE_SCHAR: - { - int arg = a.arg[dp->arg_index].a.a_schar; - SNPRINTF_BUF (arg); - } - break; - case TYPE_UCHAR: - { - unsigned int arg = a.arg[dp->arg_index].a.a_uchar; - SNPRINTF_BUF (arg); - } - break; - case TYPE_SHORT: - { - int arg = a.arg[dp->arg_index].a.a_short; - SNPRINTF_BUF (arg); - } - break; - case TYPE_USHORT: - { - unsigned int arg = a.arg[dp->arg_index].a.a_ushort; - SNPRINTF_BUF (arg); - } - break; - case TYPE_INT: - { - int arg = a.arg[dp->arg_index].a.a_int; - SNPRINTF_BUF (arg); - } - break; - case TYPE_UINT: - { - unsigned int arg = a.arg[dp->arg_index].a.a_uint; - SNPRINTF_BUF (arg); - } - break; - case TYPE_LONGINT: - { - long int arg = a.arg[dp->arg_index].a.a_longint; - SNPRINTF_BUF (arg); - } - break; - case TYPE_ULONGINT: - { - unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint; - SNPRINTF_BUF (arg); - } - break; -#if HAVE_LONG_LONG_INT - case TYPE_LONGLONGINT: - { - long long int arg = a.arg[dp->arg_index].a.a_longlongint; - SNPRINTF_BUF (arg); - } - break; - case TYPE_ULONGLONGINT: - { - unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint; - SNPRINTF_BUF (arg); - } - break; -#endif - case TYPE_DOUBLE: - { - double arg = a.arg[dp->arg_index].a.a_double; - SNPRINTF_BUF (arg); - } - break; - case TYPE_LONGDOUBLE: - { - long double arg = a.arg[dp->arg_index].a.a_longdouble; - SNPRINTF_BUF (arg); - } - break; - case TYPE_CHAR: - { - int arg = a.arg[dp->arg_index].a.a_char; - SNPRINTF_BUF (arg); - } - break; -#if HAVE_WINT_T - case TYPE_WIDE_CHAR: - { - wint_t arg = a.arg[dp->arg_index].a.a_wide_char; - SNPRINTF_BUF (arg); - } - break; -#endif - case TYPE_STRING: - { - const char *arg = a.arg[dp->arg_index].a.a_string; - SNPRINTF_BUF (arg); - } - break; -#if HAVE_WCHAR_T - case TYPE_WIDE_STRING: - { - const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string; - SNPRINTF_BUF (arg); - } - break; -#endif - case TYPE_POINTER: - { - void *arg = a.arg[dp->arg_index].a.a_pointer; - SNPRINTF_BUF (arg); - } - break; - default: - abort (); - } - -#if USE_SNPRINTF - /* Portability: Not all implementations of snprintf() - are ISO C 99 compliant. Determine the number of - bytes that snprintf() has produced or would have - produced. */ - if (count >= 0) - { - /* Verify that snprintf() has NUL-terminated its - result. */ - if (count < maxlen - && ((TCHAR_T *) (result + length)) [count] != '\0') - abort (); - /* Portability hack. */ - if (retcount > count) - count = retcount; - } - else - { - /* snprintf() doesn't understand the '%n' - directive. */ - if (fbp[1] != '\0') - { - /* Don't use the '%n' directive; instead, look - at the snprintf() return value. */ - fbp[1] = '\0'; - continue; - } - else - { - /* Look at the snprintf() return value. */ - if (retcount < 0) - { -# if !HAVE_SNPRINTF_RETVAL_C99 - /* HP-UX 10.20 snprintf() is doubly deficient: - It doesn't understand the '%n' directive, - *and* it returns -1 (rather than the length - that would have been required) when the - buffer is too small. - But a failure at this point can also come - from other reasons than a too small buffer, - such as an invalid wide string argument to - the %ls directive, or possibly an invalid - floating-point argument. */ - size_t tmp_length = - MAX_ROOM_NEEDED (&a, dp->arg_index, - dp->conversion, type, flags, - width, has_precision, - precision, pad_ourselves); - - if (maxlen < tmp_length) - { - /* Make more room. But try to do through - this reallocation only once. */ - size_t bigger_need = - xsum (length, - xsum (tmp_length, - TCHARS_PER_DCHAR - 1) - / TCHARS_PER_DCHAR); - /* And always grow proportionally. - (There may be several arguments, each - needing a little more room than the - previous one.) */ - size_t bigger_need2 = - xsum (xtimes (allocated, 2), 12); - if (bigger_need < bigger_need2) - bigger_need = bigger_need2; - ENSURE_ALLOCATION (bigger_need); - continue; - } -# endif - } - else - count = retcount; - } - } -#endif - - /* Attempt to handle failure. */ - if (count < 0) - { - /* SNPRINTF or sprintf failed. Save and use the errno - that it has set, if any. */ - int saved_errno = errno; - - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = - (saved_errno != 0 - ? saved_errno - : (dp->conversion == 'c' || dp->conversion == 's' - ? EILSEQ - : EINVAL)); - return NULL; - } - -#if USE_SNPRINTF - /* Handle overflow of the allocated buffer. - If such an overflow occurs, a C99 compliant snprintf() - returns a count >= maxlen. However, a non-compliant - snprintf() function returns only count = maxlen - 1. To - cover both cases, test whether count >= maxlen - 1. */ - if ((unsigned int) count + 1 >= maxlen) - { - /* If maxlen already has attained its allowed maximum, - allocating more memory will not increase maxlen. - Instead of looping, bail out. */ - if (maxlen == INT_MAX / TCHARS_PER_DCHAR) - goto overflow; - else - { - /* Need at least (count + 1) * sizeof (TCHAR_T) - bytes. (The +1 is for the trailing NUL.) - But ask for (count + 2) * sizeof (TCHAR_T) - bytes, so that in the next round, we likely get - maxlen > (unsigned int) count + 1 - and so we don't get here again. - And allocate proportionally, to avoid looping - eternally if snprintf() reports a too small - count. */ - size_t n = - xmax (xsum (length, - ((unsigned int) count + 2 - + TCHARS_PER_DCHAR - 1) - / TCHARS_PER_DCHAR), - xtimes (allocated, 2)); - - ENSURE_ALLOCATION (n); - continue; - } - } -#endif - -#if NEED_PRINTF_UNBOUNDED_PRECISION - if (prec_ourselves) - { - /* Handle the precision. */ - TCHAR_T *prec_ptr = -# if USE_SNPRINTF - (TCHAR_T *) (result + length); -# else - tmp; -# endif - size_t prefix_count; - size_t move; - - prefix_count = 0; - /* Put the additional zeroes after the sign. */ - if (count >= 1 - && (*prec_ptr == '-' || *prec_ptr == '+' - || *prec_ptr == ' ')) - prefix_count = 1; - /* Put the additional zeroes after the 0x prefix if - (flags & FLAG_ALT) || (dp->conversion == 'p'). */ - else if (count >= 2 - && prec_ptr[0] == '0' - && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X')) - prefix_count = 2; - - move = count - prefix_count; - if (precision > move) - { - /* Insert zeroes. */ - size_t insert = precision - move; - TCHAR_T *prec_end; - -# if USE_SNPRINTF - size_t n = - xsum (length, - (count + insert + TCHARS_PER_DCHAR - 1) - / TCHARS_PER_DCHAR); - length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR; - ENSURE_ALLOCATION (n); - length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR; - prec_ptr = (TCHAR_T *) (result + length); -# endif - - prec_end = prec_ptr + count; - prec_ptr += prefix_count; - - while (prec_end > prec_ptr) - { - prec_end--; - prec_end[insert] = prec_end[0]; - } - - prec_end += insert; - do - *--prec_end = '0'; - while (prec_end > prec_ptr); - - count += insert; - } - } -#endif - -#if !USE_SNPRINTF - if (count >= tmp_length) - /* tmp_length was incorrectly calculated - fix the - code above! */ - abort (); -#endif - -#if !DCHAR_IS_TCHAR - /* Convert from TCHAR_T[] to DCHAR_T[]. */ - if (dp->conversion == 'c' || dp->conversion == 's') - { - /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING - TYPE_WIDE_STRING. - The result string is not certainly ASCII. */ - const TCHAR_T *tmpsrc; - DCHAR_T *tmpdst; - size_t tmpdst_len; - /* This code assumes that TCHAR_T is 'char'. */ - typedef int TCHAR_T_verify - [2 * (sizeof (TCHAR_T) == 1) - 1]; -# if USE_SNPRINTF - tmpsrc = (TCHAR_T *) (result + length); -# else - tmpsrc = tmp; -# endif - tmpdst = - DCHAR_CONV_FROM_ENCODING (locale_charset (), - iconveh_question_mark, - tmpsrc, count, - NULL, - NULL, &tmpdst_len); - if (tmpdst == NULL) - { - int saved_errno = errno; - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = saved_errno; - return NULL; - } - ENSURE_ALLOCATION (xsum (length, tmpdst_len)); - DCHAR_CPY (result + length, tmpdst, tmpdst_len); - free (tmpdst); - count = tmpdst_len; - } - else - { - /* The result string is ASCII. - Simple 1:1 conversion. */ -# if USE_SNPRINTF - /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a - no-op conversion, in-place on the array starting - at (result + length). */ - if (sizeof (DCHAR_T) != sizeof (TCHAR_T)) -# endif - { - const TCHAR_T *tmpsrc; - DCHAR_T *tmpdst; - size_t n; - -# if USE_SNPRINTF - if (result == resultbuf) - { - tmpsrc = (TCHAR_T *) (result + length); - /* ENSURE_ALLOCATION will not move tmpsrc - (because it's part of resultbuf). */ - ENSURE_ALLOCATION (xsum (length, count)); - } - else - { - /* ENSURE_ALLOCATION will move the array - (because it uses realloc(). */ - ENSURE_ALLOCATION (xsum (length, count)); - tmpsrc = (TCHAR_T *) (result + length); - } -# else - tmpsrc = tmp; - ENSURE_ALLOCATION (xsum (length, count)); -# endif - tmpdst = result + length; - /* Copy backwards, because of overlapping. */ - tmpsrc += count; - tmpdst += count; - for (n = count; n > 0; n--) - *--tmpdst = (unsigned char) *--tmpsrc; - } - } -#endif - -#if DCHAR_IS_TCHAR && !USE_SNPRINTF - /* Make room for the result. */ - if (count > allocated - length) - { - /* Need at least count elements. But allocate - proportionally. */ - size_t n = - xmax (xsum (length, count), xtimes (allocated, 2)); - - ENSURE_ALLOCATION (n); - } -#endif - - /* Here count <= allocated - length. */ - - /* Perform padding. */ -#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION - if (pad_ourselves && has_width) - { - size_t w; -# if ENABLE_UNISTDIO - /* Outside POSIX, it's preferrable to compare the width - against the number of _characters_ of the converted - value. */ - w = DCHAR_MBSNLEN (result + length, count); -# else - /* The width is compared against the number of _bytes_ - of the converted value, says POSIX. */ - w = count; -# endif - if (w < width) - { - size_t pad = width - w; - - /* Make room for the result. */ - if (xsum (count, pad) > allocated - length) - { - /* Need at least count + pad elements. But - allocate proportionally. */ - size_t n = - xmax (xsum3 (length, count, pad), - xtimes (allocated, 2)); - -# if USE_SNPRINTF - length += count; - ENSURE_ALLOCATION (n); - length -= count; -# else - ENSURE_ALLOCATION (n); -# endif - } - /* Here count + pad <= allocated - length. */ - - { -# if !DCHAR_IS_TCHAR || USE_SNPRINTF - DCHAR_T * const rp = result + length; -# else - DCHAR_T * const rp = tmp; -# endif - DCHAR_T *p = rp + count; - DCHAR_T *end = p + pad; - DCHAR_T *pad_ptr; -# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO - if (dp->conversion == 'c' - || dp->conversion == 's') - /* No zero-padding for string directives. */ - pad_ptr = NULL; - else -# endif - { - pad_ptr = (*rp == '-' ? rp + 1 : rp); - /* No zero-padding of "inf" and "nan". */ - if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z') - || (*pad_ptr >= 'a' && *pad_ptr <= 'z')) - pad_ptr = NULL; - } - /* The generated string now extends from rp to p, - with the zero padding insertion point being at - pad_ptr. */ - - count = count + pad; /* = end - rp */ - - if (flags & FLAG_LEFT) - { - /* Pad with spaces on the right. */ - for (; pad > 0; pad--) - *p++ = ' '; - } - else if ((flags & FLAG_ZERO) && pad_ptr != NULL) - { - /* Pad with zeroes. */ - DCHAR_T *q = end; - - while (p > pad_ptr) - *--q = *--p; - for (; pad > 0; pad--) - *p++ = '0'; - } - else - { - /* Pad with spaces on the left. */ - DCHAR_T *q = end; - - while (p > rp) - *--q = *--p; - for (; pad > 0; pad--) - *p++ = ' '; - } - } - } - } -#endif - - /* Here still count <= allocated - length. */ - -#if !DCHAR_IS_TCHAR || USE_SNPRINTF - /* The snprintf() result did fit. */ -#else - /* Append the sprintf() result. */ - memcpy (result + length, tmp, count * sizeof (DCHAR_T)); -#endif -#if !USE_SNPRINTF - if (tmp != tmpbuf) - free (tmp); -#endif - -#if NEED_PRINTF_DIRECTIVE_F - if (dp->conversion == 'F') - { - /* Convert the %f result to upper case for %F. */ - DCHAR_T *rp = result + length; - size_t rc; - for (rc = count; rc > 0; rc--, rp++) - if (*rp >= 'a' && *rp <= 'z') - *rp = *rp - 'a' + 'A'; - } -#endif - - length += count; - break; - } -#undef pad_ourselves -#undef prec_ourselves - } - } - } - - /* Add the final NUL. */ - ENSURE_ALLOCATION (xsum (length, 1)); - result[length] = '\0'; - - if (result != resultbuf && length + 1 < allocated) - { - /* Shrink the allocated memory if possible. */ - DCHAR_T *memory; - - memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T)); - if (memory != NULL) - result = memory; - } - - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - *lengthp = length; - /* Note that we can produce a big string of a length > INT_MAX. POSIX - says that snprintf() fails with errno = EOVERFLOW in this case, but - that's only because snprintf() returns an 'int'. This function does - not have this limitation. */ - return result; - -#if USE_SNPRINTF - overflow: - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - CLEANUP (); - errno = EOVERFLOW; - return NULL; -#endif - - out_of_memory: - if (!(result == resultbuf || result == NULL)) - free (result); - if (buf_malloced != NULL) - free (buf_malloced); - out_of_memory_1: - CLEANUP (); - errno = ENOMEM; - return NULL; - } -} - -#undef MAX_ROOM_NEEDED -#undef TCHARS_PER_DCHAR -#undef SNPRINTF -#undef USE_SNPRINTF -#undef DCHAR_SET -#undef DCHAR_CPY -#undef PRINTF_PARSE -#undef DIRECTIVES -#undef DIRECTIVE -#undef DCHAR_IS_TCHAR -#undef TCHAR_T -#undef DCHAR_T -#undef FCHAR_T -#undef VASNPRINTF diff --git a/grub-core/gnulib/vasnprintf.h b/grub-core/gnulib/vasnprintf.h deleted file mode 100644 index a689bad25..000000000 --- a/grub-core/gnulib/vasnprintf.h +++ /dev/null @@ -1,80 +0,0 @@ -/* vsprintf with automatic memory allocation. - Copyright (C) 2002-2004, 2007-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _VASNPRINTF_H -#define _VASNPRINTF_H - -/* Get va_list. */ -#include - -/* Get size_t. */ -#include - -#ifndef __attribute__ -/* The __attribute__ feature is available in gcc versions 2.5 and later. - The __-protected variants of the attributes 'format' and 'printf' are - accepted by gcc versions 2.6.4 (effectively 2.7) and later. - We enable __attribute__ only if these are supported too, because - gnulib and libintl do '#define printf __printf__' when they override - the 'printf' function. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __attribute__(Spec) /* empty */ -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Write formatted output to a string dynamically allocated with malloc(). - You can pass a preallocated buffer for the result in RESULTBUF and its - size in *LENGTHP; otherwise you pass RESULTBUF = NULL. - If successful, return the address of the string (this may be = RESULTBUF - if no dynamic memory allocation was necessary) and set *LENGTHP to the - number of resulting bytes, excluding the trailing NUL. Upon error, set - errno and return NULL. - - When dynamic memory allocation occurs, the preallocated buffer is left - alone (with possibly modified contents). This makes it possible to use - a statically allocated or stack-allocated buffer, like this: - - char buf[100]; - size_t len = sizeof (buf); - char *output = vasnprintf (buf, &len, format, args); - if (output == NULL) - ... error handling ...; - else - { - ... use the output string ...; - if (output != buf) - free (output); - } - */ -#if REPLACE_VASNPRINTF -# define asnprintf rpl_asnprintf -# define vasnprintf rpl_vasnprintf -#endif -extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); -extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args) - __attribute__ ((__format__ (__printf__, 3, 0))); - -#ifdef __cplusplus -} -#endif - -#endif /* _VASNPRINTF_H */ diff --git a/grub-core/gnulib/verify.h b/grub-core/gnulib/verify.h deleted file mode 100644 index 4ad780c8f..000000000 --- a/grub-core/gnulib/verify.h +++ /dev/null @@ -1,163 +0,0 @@ -/* Compile-time assert-like macros. - - Copyright (C) 2005-2006, 2009-2010 Free Software Foundation, 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -/* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ - -#ifndef VERIFY_H -# define VERIFY_H 1 - -/* Each of these macros verifies that its argument R is nonzero. To - be portable, R should be an integer constant expression. Unlike - assert (R), there is no run-time overhead. - - There are two macros, since no single macro can be used in all - contexts in C. verify_true (R) is for scalar contexts, including - integer constant expression contexts. verify (R) is for declaration - contexts, e.g., the top level. - - Symbols ending in "__" are private to this header. - - The code below uses several ideas. - - * The first step is ((R) ? 1 : -1). Given an expression R, of - integral or boolean or floating-point type, this yields an - expression of integral type, whose value is later verified to be - constant and nonnegative. - - * Next this expression W is wrapped in a type - struct verify_type__ { unsigned int verify_error_if_negative_size__: W; }. - If W is negative, this yields a compile-time error. No compiler can - deal with a bit-field of negative size. - - One might think that an array size check would have the same - effect, that is, that the type struct { unsigned int dummy[W]; } - would work as well. However, inside a function, some compilers - (such as C++ compilers and GNU C) allow local parameters and - variables inside array size expressions. With these compilers, - an array size check would not properly diagnose this misuse of - the verify macro: - - void function (int n) { verify (n < 0); } - - * For the verify macro, the struct verify_type__ will need to - somehow be embedded into a declaration. To be portable, this - declaration must declare an object, a constant, a function, or a - typedef name. If the declared entity uses the type directly, - such as in - - struct dummy {...}; - typedef struct {...} dummy; - extern struct {...} *dummy; - extern void dummy (struct {...} *); - extern struct {...} *dummy (void); - - two uses of the verify macro would yield colliding declarations - if the entity names are not disambiguated. A workaround is to - attach the current line number to the entity name: - - #define _GL_CONCAT0(x, y) x##y - #define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) - extern struct {...} * _GL_CONCAT (dummy, __LINE__); - - But this has the problem that two invocations of verify from - within the same macro would collide, since the __LINE__ value - would be the same for both invocations. (The GCC __COUNTER__ - macro solves this problem, but is not portable.) - - A solution is to use the sizeof operator. It yields a number, - getting rid of the identity of the type. Declarations like - - extern int dummy [sizeof (struct {...})]; - extern void dummy (int [sizeof (struct {...})]); - extern int (*dummy (void)) [sizeof (struct {...})]; - - can be repeated. - - * Should the implementation use a named struct or an unnamed struct? - Which of the following alternatives can be used? - - extern int dummy [sizeof (struct {...})]; - extern int dummy [sizeof (struct verify_type__ {...})]; - extern void dummy (int [sizeof (struct {...})]); - extern void dummy (int [sizeof (struct verify_type__ {...})]); - extern int (*dummy (void)) [sizeof (struct {...})]; - extern int (*dummy (void)) [sizeof (struct verify_type__ {...})]; - - In the second and sixth case, the struct type is exported to the - outer scope; two such declarations therefore collide. GCC warns - about the first, third, and fourth cases. So the only remaining - possibility is the fifth case: - - extern int (*dummy (void)) [sizeof (struct {...})]; - - * GCC warns about duplicate declarations of the dummy function if - -Wredundant_decls is used. GCC 4.3 and later have a builtin - __COUNTER__ macro that can let us generate unique identifiers for - each dummy function, to suppress this warning. - - * This implementation exploits the fact that GCC does not warn about - the last declaration mentioned above. If a future version of GCC - introduces a warning for this, the problem could be worked around - by using code specialized to GCC, just as __COUNTER__ is already - being used if available. - - #if 4 <= __GNUC__ - # define verify(R) [another version to keep GCC happy] - #endif - - * In C++, any struct definition inside sizeof is invalid. - Use a template type to work around the problem. */ - -/* Concatenate two preprocessor tokens. */ -# define _GL_CONCAT(x, y) _GL_CONCAT0 (x, y) -# define _GL_CONCAT0(x, y) x##y - -/* _GL_COUNTER is an integer, preferably one that changes each time we - use it. Use __COUNTER__ if it works, falling back on __LINE__ - otherwise. __LINE__ isn't perfect, but it's better than a - constant. */ -# if defined __COUNTER__ && __COUNTER__ != __COUNTER__ -# define _GL_COUNTER __COUNTER__ -# else -# define _GL_COUNTER __LINE__ -# endif - -/* Generate a symbol with the given prefix, making it unique if - possible. */ -# define _GL_GENSYM(prefix) _GL_CONCAT (prefix, _GL_COUNTER) - -/* Verify requirement R at compile-time, as an integer constant expression. - Return 1. */ - -# ifdef __cplusplus -template - struct verify_type__ { unsigned int verify_error_if_negative_size__: w; }; -# define verify_true(R) \ - (!!sizeof (verify_type__<(R) ? 1 : -1>)) -# else -# define verify_true(R) \ - (!!sizeof \ - (struct { unsigned int verify_error_if_negative_size__: (R) ? 1 : -1; })) -# endif - -/* Verify requirement R at compile-time, as a declaration without a - trailing ';'. */ - -# define verify(R) \ - extern int (* _GL_GENSYM (verify_function) (void)) [verify_true (R)] - -#endif diff --git a/grub-core/gnulib/vsnprintf.c b/grub-core/gnulib/vsnprintf.c deleted file mode 100644 index d447cc2d5..000000000 --- a/grub-core/gnulib/vsnprintf.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Formatted output to strings. - Copyright (C) 2004, 2006-2010 Free Software Foundation, Inc. - Written by Simon Josefsson and Yoann Vandoorselaere . - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -/* Specification. */ -#include - -#include -#include -#include -#include -#include - -#include "vasnprintf.h" - -/* Print formatted output to string STR. Similar to vsprintf, but - additional length SIZE limit how much is written into STR. Returns - string length of formatted string (which may be larger than SIZE). - STR may be NULL, in which case nothing will be written. On error, - return a negative value. */ -int -vsnprintf (char *str, size_t size, const char *format, va_list args) -{ - char *output; - size_t len; - size_t lenbuf = size; - - output = vasnprintf (str, &lenbuf, format, args); - len = lenbuf; - - if (!output) - return -1; - - if (output != str) - { - if (size) - { - size_t pruned_len = (len < size ? len : size - 1); - memcpy (str, output, pruned_len); - str[pruned_len] = '\0'; - } - - free (output); - } - - if (len > INT_MAX) - { - errno = EOVERFLOW; - return -1; - } - - return len; -} diff --git a/grub-core/gnulib/wchar.in.h b/grub-core/gnulib/wchar.in.h deleted file mode 100644 index 88d47dbc0..000000000 --- a/grub-core/gnulib/wchar.in.h +++ /dev/null @@ -1,428 +0,0 @@ -/* A substitute for ISO C99 , for platforms that have issues. - - Copyright (C) 2007-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Eric Blake. */ - -/* - * ISO C 99 for platforms that have issues. - * - * - * For now, this just ensures proper prerequisite inclusion order and - * the declaration of wcwidth(). - */ - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -#if defined __need_mbstate_t || defined __need_wint_t || (defined __hpux && ((defined _INTTYPES_INCLUDED && !defined strtoimax) || defined _GL_JUST_INCLUDE_SYSTEM_WCHAR_H)) || defined _GL_ALREADY_INCLUDING_WCHAR_H -/* Special invocation convention: - - Inside glibc and uClibc header files. - - On HP-UX 11.00 we have a sequence of nested includes - -> -> , and the latter includes , - once indirectly -> -> -> - and once directly. In both situations 'wint_t' is not yet defined, - therefore we cannot provide the function overrides; instead include only - the system's . - - On IRIX 6.5, similarly, we have an include -> , and - the latter includes . But here, we have no way to detect whether - is completely included or is still being included. */ - -#@INCLUDE_NEXT@ @NEXT_WCHAR_H@ - -#else -/* Normal invocation convention. */ - -#ifndef _GL_WCHAR_H - -#define _GL_ALREADY_INCLUDING_WCHAR_H - -/* Tru64 with Desktop Toolkit C has a bug: must be included before - . - BSD/OS 4.0.1 has a bug: , and must be - included before . - But avoid namespace pollution on glibc systems. */ -#ifndef __GLIBC__ -# include -# include -# include -#endif - -/* Include the original if it exists. - Some builds of uClibc lack it. */ -/* The include_next requires a split double-inclusion guard. */ -#if @HAVE_WCHAR_H@ -# @INCLUDE_NEXT@ @NEXT_WCHAR_H@ -#endif - -#undef _GL_ALREADY_INCLUDING_WCHAR_H - -#ifndef _GL_WCHAR_H -#define _GL_WCHAR_H - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_ARG_NONNULL is copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - - -/* Define wint_t and WEOF. (Also done in wctype.in.h.) */ -#if !@HAVE_WINT_T@ && !defined wint_t -# define wint_t int -# ifndef WEOF -# define WEOF -1 -# endif -#else -# ifndef WEOF -# define WEOF ((wint_t) -1) -# endif -#endif - - -/* Override mbstate_t if it is too small. - On IRIX 6.5, sizeof (mbstate_t) == 1, which is not sufficient for - implementing mbrtowc for encodings like UTF-8. */ -#if !(@HAVE_MBSINIT@ && @HAVE_MBRTOWC@) || @REPLACE_MBSTATE_T@ -typedef int rpl_mbstate_t; -# undef mbstate_t -# define mbstate_t rpl_mbstate_t -# define GNULIB_defined_mbstate_t 1 -#endif - - -/* Convert a single-byte character to a wide character. */ -#if @GNULIB_BTOWC@ -# if @REPLACE_BTOWC@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef btowc -# define btowc rpl_btowc -# endif -_GL_FUNCDECL_RPL (btowc, wint_t, (int c)); -_GL_CXXALIAS_RPL (btowc, wint_t, (int c)); -# else -# if !@HAVE_BTOWC@ -_GL_FUNCDECL_SYS (btowc, wint_t, (int c)); -# endif -_GL_CXXALIAS_SYS (btowc, wint_t, (int c)); -# endif -_GL_CXXALIASWARN (btowc); -#elif defined GNULIB_POSIXCHECK -# undef btowc -# if HAVE_RAW_DECL_BTOWC -_GL_WARN_ON_USE (btowc, "btowc is unportable - " - "use gnulib module btowc for portability"); -# endif -#endif - - -/* Convert a wide character to a single-byte character. */ -#if @GNULIB_WCTOB@ -# if @REPLACE_WCTOB@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef wctob -# define wctob rpl_wctob -# endif -_GL_FUNCDECL_RPL (wctob, int, (wint_t wc)); -_GL_CXXALIAS_RPL (wctob, int, (wint_t wc)); -# else -# if !defined wctob && !@HAVE_DECL_WCTOB@ -/* wctob is provided by gnulib, or wctob exists but is not declared. */ -_GL_FUNCDECL_SYS (wctob, int, (wint_t wc)); -# endif -_GL_CXXALIAS_SYS (wctob, int, (wint_t wc)); -# endif -_GL_CXXALIASWARN (wctob); -#elif defined GNULIB_POSIXCHECK -# undef wctob -# if HAVE_RAW_DECL_WCTOB -_GL_WARN_ON_USE (wctob, "wctob is unportable - " - "use gnulib module wctob for portability"); -# endif -#endif - - -/* Test whether *PS is in the initial state. */ -#if @GNULIB_MBSINIT@ -# if @REPLACE_MBSINIT@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mbsinit -# define mbsinit rpl_mbsinit -# endif -_GL_FUNCDECL_RPL (mbsinit, int, (const mbstate_t *ps)); -_GL_CXXALIAS_RPL (mbsinit, int, (const mbstate_t *ps)); -# else -# if !@HAVE_MBSINIT@ -_GL_FUNCDECL_SYS (mbsinit, int, (const mbstate_t *ps)); -# endif -_GL_CXXALIAS_SYS (mbsinit, int, (const mbstate_t *ps)); -# endif -_GL_CXXALIASWARN (mbsinit); -#elif defined GNULIB_POSIXCHECK -# undef mbsinit -# if HAVE_RAW_DECL_MBSINIT -_GL_WARN_ON_USE (mbsinit, "mbsinit is unportable - " - "use gnulib module mbsinit for portability"); -# endif -#endif - - -/* Convert a multibyte character to a wide character. */ -#if @GNULIB_MBRTOWC@ -# if @REPLACE_MBRTOWC@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mbrtowc -# define mbrtowc rpl_mbrtowc -# endif -_GL_FUNCDECL_RPL (mbrtowc, size_t, - (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); -_GL_CXXALIAS_RPL (mbrtowc, size_t, - (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); -# else -# if !@HAVE_MBRTOWC@ -_GL_FUNCDECL_SYS (mbrtowc, size_t, - (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); -# endif -_GL_CXXALIAS_SYS (mbrtowc, size_t, - (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)); -# endif -_GL_CXXALIASWARN (mbrtowc); -#elif defined GNULIB_POSIXCHECK -# undef mbrtowc -# if HAVE_RAW_DECL_MBRTOWC -_GL_WARN_ON_USE (mbrtowc, "mbrtowc is unportable - " - "use gnulib module mbrtowc for portability"); -# endif -#endif - - -/* Recognize a multibyte character. */ -#if @GNULIB_MBRLEN@ -# if @REPLACE_MBRLEN@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mbrlen -# define mbrlen rpl_mbrlen -# endif -_GL_FUNCDECL_RPL (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); -_GL_CXXALIAS_RPL (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); -# else -# if !@HAVE_MBRLEN@ -_GL_FUNCDECL_SYS (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); -# endif -_GL_CXXALIAS_SYS (mbrlen, size_t, (const char *s, size_t n, mbstate_t *ps)); -# endif -_GL_CXXALIASWARN (mbrlen); -#elif defined GNULIB_POSIXCHECK -# undef mbrlen -# if HAVE_RAW_DECL_MBRLEN -_GL_WARN_ON_USE (mbrlen, "mbrlen is unportable - " - "use gnulib module mbrlen for portability"); -# endif -#endif - - -/* Convert a string to a wide string. */ -#if @GNULIB_MBSRTOWCS@ -# if @REPLACE_MBSRTOWCS@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mbsrtowcs -# define mbsrtowcs rpl_mbsrtowcs -# endif -_GL_FUNCDECL_RPL (mbsrtowcs, size_t, - (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (mbsrtowcs, size_t, - (wchar_t *dest, const char **srcp, size_t len, - mbstate_t *ps)); -# else -# if !@HAVE_MBSRTOWCS@ -_GL_FUNCDECL_SYS (mbsrtowcs, size_t, - (wchar_t *dest, const char **srcp, size_t len, mbstate_t *ps) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (mbsrtowcs, size_t, - (wchar_t *dest, const char **srcp, size_t len, - mbstate_t *ps)); -# endif -_GL_CXXALIASWARN (mbsrtowcs); -#elif defined GNULIB_POSIXCHECK -# undef mbsrtowcs -# if HAVE_RAW_DECL_MBSRTOWCS -_GL_WARN_ON_USE (mbsrtowcs, "mbsrtowcs is unportable - " - "use gnulib module mbsrtowcs for portability"); -# endif -#endif - - -/* Convert a string to a wide string. */ -#if @GNULIB_MBSNRTOWCS@ -# if @REPLACE_MBSNRTOWCS@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef mbsnrtowcs -# define mbsnrtowcs rpl_mbsnrtowcs -# endif -_GL_FUNCDECL_RPL (mbsnrtowcs, size_t, - (wchar_t *dest, const char **srcp, size_t srclen, size_t len, - mbstate_t *ps) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (mbsnrtowcs, size_t, - (wchar_t *dest, const char **srcp, size_t srclen, size_t len, - mbstate_t *ps)); -# else -# if !@HAVE_MBSNRTOWCS@ -_GL_FUNCDECL_SYS (mbsnrtowcs, size_t, - (wchar_t *dest, const char **srcp, size_t srclen, size_t len, - mbstate_t *ps) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (mbsnrtowcs, size_t, - (wchar_t *dest, const char **srcp, size_t srclen, size_t len, - mbstate_t *ps)); -# endif -_GL_CXXALIASWARN (mbsnrtowcs); -#elif defined GNULIB_POSIXCHECK -# undef mbsnrtowcs -# if HAVE_RAW_DECL_MBSNRTOWCS -_GL_WARN_ON_USE (mbsnrtowcs, "mbsnrtowcs is unportable - " - "use gnulib module mbsnrtowcs for portability"); -# endif -#endif - - -/* Convert a wide character to a multibyte character. */ -#if @GNULIB_WCRTOMB@ -# if @REPLACE_WCRTOMB@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef wcrtomb -# define wcrtomb rpl_wcrtomb -# endif -_GL_FUNCDECL_RPL (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); -_GL_CXXALIAS_RPL (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); -# else -# if !@HAVE_WCRTOMB@ -_GL_FUNCDECL_SYS (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); -# endif -_GL_CXXALIAS_SYS (wcrtomb, size_t, (char *s, wchar_t wc, mbstate_t *ps)); -# endif -_GL_CXXALIASWARN (wcrtomb); -#elif defined GNULIB_POSIXCHECK -# undef wcrtomb -# if HAVE_RAW_DECL_WCRTOMB -_GL_WARN_ON_USE (wcrtomb, "wcrtomb is unportable - " - "use gnulib module wcrtomb for portability"); -# endif -#endif - - -/* Convert a wide string to a string. */ -#if @GNULIB_WCSRTOMBS@ -# if @REPLACE_WCSRTOMBS@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef wcsrtombs -# define wcsrtombs rpl_wcsrtombs -# endif -_GL_FUNCDECL_RPL (wcsrtombs, size_t, - (char *dest, const wchar_t **srcp, size_t len, mbstate_t *ps) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (wcsrtombs, size_t, - (char *dest, const wchar_t **srcp, size_t len, - mbstate_t *ps)); -# else -# if !@HAVE_WCSRTOMBS@ -_GL_FUNCDECL_SYS (wcsrtombs, size_t, - (char *dest, const wchar_t **srcp, size_t len, mbstate_t *ps) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (wcsrtombs, size_t, - (char *dest, const wchar_t **srcp, size_t len, - mbstate_t *ps)); -# endif -_GL_CXXALIASWARN (wcsrtombs); -#elif defined GNULIB_POSIXCHECK -# undef wcsrtombs -# if HAVE_RAW_DECL_WCSRTOMBS -_GL_WARN_ON_USE (wcsrtombs, "wcsrtombs is unportable - " - "use gnulib module wcsrtombs for portability"); -# endif -#endif - - -/* Convert a wide string to a string. */ -#if @GNULIB_WCSNRTOMBS@ -# if @REPLACE_WCSNRTOMBS@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef wcsnrtombs -# define wcsnrtombs rpl_wcsnrtombs -# endif -_GL_FUNCDECL_RPL (wcsnrtombs, size_t, - (char *dest, const wchar_t **srcp, size_t srclen, size_t len, - mbstate_t *ps) - _GL_ARG_NONNULL ((2))); -_GL_CXXALIAS_RPL (wcsnrtombs, size_t, - (char *dest, const wchar_t **srcp, size_t srclen, size_t len, - mbstate_t *ps)); -# else -# if !@HAVE_WCSNRTOMBS@ -_GL_FUNCDECL_SYS (wcsnrtombs, size_t, - (char *dest, const wchar_t **srcp, size_t srclen, size_t len, - mbstate_t *ps) - _GL_ARG_NONNULL ((2))); -# endif -_GL_CXXALIAS_SYS (wcsnrtombs, size_t, - (char *dest, const wchar_t **srcp, size_t srclen, size_t len, - mbstate_t *ps)); -# endif -_GL_CXXALIASWARN (wcsnrtombs); -#elif defined GNULIB_POSIXCHECK -# undef wcsnrtombs -# if HAVE_RAW_DECL_WCSNRTOMBS -_GL_WARN_ON_USE (wcsnrtombs, "wcsnrtombs is unportable - " - "use gnulib module wcsnrtombs for portability"); -# endif -#endif - - -/* Return the number of screen columns needed for WC. */ -#if @GNULIB_WCWIDTH@ -# if @REPLACE_WCWIDTH@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# undef wcwidth -# define wcwidth rpl_wcwidth -# endif -_GL_FUNCDECL_RPL (wcwidth, int, (wchar_t)); -_GL_CXXALIAS_RPL (wcwidth, int, (wchar_t)); -# else -# if !@HAVE_DECL_WCWIDTH@ -/* wcwidth exists but is not declared. */ -_GL_FUNCDECL_SYS (wcwidth, int, (wchar_t)); -# endif -_GL_CXXALIAS_SYS (wcwidth, int, (wchar_t)); -# endif -_GL_CXXALIASWARN (wcwidth); -#elif defined GNULIB_POSIXCHECK -# undef wcwidth -# if HAVE_RAW_DECL_WCWIDTH -_GL_WARN_ON_USE (wcwidth, "wcwidth is unportable - " - "use gnulib module wcwidth for portability"); -# endif -#endif - - -#endif /* _GL_WCHAR_H */ -#endif /* _GL_WCHAR_H */ -#endif diff --git a/grub-core/gnulib/wcrtomb.c b/grub-core/gnulib/wcrtomb.c deleted file mode 100644 index e7345f698..000000000 --- a/grub-core/gnulib/wcrtomb.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Convert wide character to multibyte character. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. - Written by Bruno Haible , 2008. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -#include -#include - - -size_t -wcrtomb (char *s, wchar_t wc, mbstate_t *ps) -{ - /* This implementation of wcrtomb on top of wctomb() supports only - stateless encodings. ps must be in the initial state. */ - if (ps != NULL && !mbsinit (ps)) - { - errno = EINVAL; - return (size_t)(-1); - } - - if (s == NULL) - /* We know the NUL wide character corresponds to the NUL character. */ - return 1; - else - { - int ret = wctomb (s, wc); - - if (ret >= 0) - return ret; - else - { - errno = EILSEQ; - return (size_t)(-1); - } - } -} diff --git a/grub-core/gnulib/wctype.in.h b/grub-core/gnulib/wctype.in.h deleted file mode 100644 index 12c8975fe..000000000 --- a/grub-core/gnulib/wctype.in.h +++ /dev/null @@ -1,392 +0,0 @@ -/* A substitute for ISO C99 , for platforms that lack it. - - Copyright (C) 2006-2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Bruno Haible and Paul Eggert. */ - -/* - * ISO C 99 for platforms that lack it. - * - * - * iswctype, towctrans, towlower, towupper, wctrans, wctype, - * wctrans_t, and wctype_t are not yet implemented. - */ - -#ifndef _GL_WCTYPE_H - -#if __GNUC__ >= 3 -@PRAGMA_SYSTEM_HEADER@ -#endif - -#if @HAVE_WINT_T@ -/* Solaris 2.5 has a bug: must be included before . - Tru64 with Desktop Toolkit C has a bug: must be included before - . - BSD/OS 4.0.1 has a bug: , and must be - included before . */ -# include -# include -# include -# include -#endif - -/* Include the original if it exists. - BeOS 5 has the functions but no . */ -/* The include_next requires a split double-inclusion guard. */ -#if @HAVE_WCTYPE_H@ -# @INCLUDE_NEXT@ @NEXT_WCTYPE_H@ -#endif - -#ifndef _GL_WCTYPE_H -#define _GL_WCTYPE_H - -/* The definitions of _GL_FUNCDECL_RPL etc. are copied here. */ - -/* The definition of _GL_WARN_ON_USE is copied here. */ - -/* Define wint_t and WEOF. (Also done in wchar.in.h.) */ -#if !@HAVE_WINT_T@ && !defined wint_t -# define wint_t int -# ifndef WEOF -# define WEOF -1 -# endif -#else -# ifndef WEOF -# define WEOF ((wint_t) -1) -# endif -#endif - - -/* FreeBSD 4.4 to 4.11 has but lacks the functions. - Linux libc5 has and the functions but they are broken. - Assume all 11 functions (all isw* except iswblank) are implemented the - same way, or not at all. */ -#if ! @HAVE_ISWCNTRL@ || @REPLACE_ISWCNTRL@ - -/* IRIX 5.3 has macros but no functions, its isw* macros refer to an - undefined variable _ctmp_ and to macros like _P, and they - refer to system functions like _iswctype that are not in the - standard C library. Rather than try to get ancient buggy - implementations like this to work, just disable them. */ -# undef iswalnum -# undef iswalpha -# undef iswblank -# undef iswcntrl -# undef iswdigit -# undef iswgraph -# undef iswlower -# undef iswprint -# undef iswpunct -# undef iswspace -# undef iswupper -# undef iswxdigit -# undef towlower -# undef towupper - -/* Linux libc5 has and the functions but they are broken. */ -# if @REPLACE_ISWCNTRL@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define iswalnum rpl_iswalnum -# define iswalpha rpl_iswalpha -# define iswblank rpl_iswblank -# define iswcntrl rpl_iswcntrl -# define iswdigit rpl_iswdigit -# define iswgraph rpl_iswgraph -# define iswlower rpl_iswlower -# define iswprint rpl_iswprint -# define iswpunct rpl_iswpunct -# define iswspace rpl_iswspace -# define iswupper rpl_iswupper -# define iswxdigit rpl_iswxdigit -# define towlower rpl_towlower -# define towupper rpl_towupper -# endif -# endif - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswalnum -# else -iswalnum -# endif - (wint_t wc) -{ - return ((wc >= '0' && wc <= '9') - || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z')); -} - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswalpha -# else -iswalpha -# endif - (wint_t wc) -{ - return (wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z'; -} - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswblank -# else -iswblank -# endif - (wint_t wc) -{ - return wc == ' ' || wc == '\t'; -} - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswcntrl -# else -iswcntrl -# endif - (wint_t wc) -{ - return (wc & ~0x1f) == 0 || wc == 0x7f; -} - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswdigit -# else -iswdigit -# endif - (wint_t wc) -{ - return wc >= '0' && wc <= '9'; -} - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswgraph -# else -iswgraph -# endif - (wint_t wc) -{ - return wc >= '!' && wc <= '~'; -} - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswlower -# else -iswlower -# endif - (wint_t wc) -{ - return wc >= 'a' && wc <= 'z'; -} - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswprint -# else -iswprint -# endif - (wint_t wc) -{ - return wc >= ' ' && wc <= '~'; -} - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswpunct -# else -iswpunct -# endif - (wint_t wc) -{ - return (wc >= '!' && wc <= '~' - && !((wc >= '0' && wc <= '9') - || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'Z'))); -} - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswspace -# else -iswspace -# endif - (wint_t wc) -{ - return (wc == ' ' || wc == '\t' - || wc == '\n' || wc == '\v' || wc == '\f' || wc == '\r'); -} - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswupper -# else -iswupper -# endif - (wint_t wc) -{ - return wc >= 'A' && wc <= 'Z'; -} - -static inline int -# if @REPLACE_ISWCNTRL@ -rpl_iswxdigit -# else -iswxdigit -# endif - (wint_t wc) -{ - return ((wc >= '0' && wc <= '9') - || ((wc & ~0x20) >= 'A' && (wc & ~0x20) <= 'F')); -} - -static inline wint_t -# if @REPLACE_ISWCNTRL@ -rpl_towlower -# else -towlower -# endif - (wint_t wc) -{ - return (wc >= 'A' && wc <= 'Z' ? wc - 'A' + 'a' : wc); -} - -static inline wint_t -# if @REPLACE_ISWCNTRL@ -rpl_towupper -# else -towupper -# endif - (wint_t wc) -{ - return (wc >= 'a' && wc <= 'z' ? wc - 'a' + 'A' : wc); -} - -#elif ! @HAVE_ISWBLANK@ || @REPLACE_ISWBLANK@ -/* Only the iswblank function is missing. */ - -# if @REPLACE_ISWBLANK@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define iswblank rpl_iswblank -# endif -# endif - -static inline int -# if @REPLACE_ISWBLANK@ -rpl_iswblank -# else -iswblank -# endif - (wint_t wc) -{ - return wc == ' ' || wc == '\t'; -} - -#endif - -#if defined __MINGW32__ - -/* On native Windows, wchar_t is uint16_t, and wint_t is uint32_t. - The functions towlower and towupper are implemented in the MSVCRT library - to take a wchar_t argument and return a wchar_t result. mingw declares - these functions to take a wint_t argument and return a wint_t result. - This means that: - 1. When the user passes an argument outside the range 0x0000..0xFFFF, the - function will look only at the lower 16 bits. This is allowed according - to POSIX. - 2. The return value is returned in the lower 16 bits of the result register. - The upper 16 bits are random: whatever happened to be in that part of the - result register. We need to fix this by adding a zero-extend from - wchar_t to wint_t after the call. */ - -static inline wint_t -rpl_towlower (wint_t wc) -{ - return (wint_t) (wchar_t) towlower (wc); -} -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define towlower rpl_towlower -# endif - -static inline wint_t -rpl_towupper (wint_t wc) -{ - return (wint_t) (wchar_t) towupper (wc); -} -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define towupper rpl_towupper -# endif - -#endif /* __MINGW32__ */ - -#if @REPLACE_ISWCNTRL@ -_GL_CXXALIAS_RPL (iswalnum, int, (wint_t wc)); -_GL_CXXALIAS_RPL (iswalpha, int, (wint_t wc)); -_GL_CXXALIAS_RPL (iswblank, int, (wint_t wc)); -_GL_CXXALIAS_RPL (iswcntrl, int, (wint_t wc)); -_GL_CXXALIAS_RPL (iswdigit, int, (wint_t wc)); -_GL_CXXALIAS_RPL (iswgraph, int, (wint_t wc)); -_GL_CXXALIAS_RPL (iswlower, int, (wint_t wc)); -_GL_CXXALIAS_RPL (iswprint, int, (wint_t wc)); -_GL_CXXALIAS_RPL (iswpunct, int, (wint_t wc)); -_GL_CXXALIAS_RPL (iswspace, int, (wint_t wc)); -_GL_CXXALIAS_RPL (iswupper, int, (wint_t wc)); -_GL_CXXALIAS_RPL (iswxdigit, int, (wint_t wc)); -#else -_GL_CXXALIAS_SYS (iswalnum, int, (wint_t wc)); -_GL_CXXALIAS_SYS (iswalpha, int, (wint_t wc)); -# if @REPLACE_ISWBLANK@ -_GL_CXXALIAS_RPL (iswblank, int, (wint_t wc)); -# else -_GL_CXXALIAS_SYS (iswblank, int, (wint_t wc)); -# endif -_GL_CXXALIAS_SYS (iswcntrl, int, (wint_t wc)); -_GL_CXXALIAS_SYS (iswdigit, int, (wint_t wc)); -_GL_CXXALIAS_SYS (iswgraph, int, (wint_t wc)); -_GL_CXXALIAS_SYS (iswlower, int, (wint_t wc)); -_GL_CXXALIAS_SYS (iswprint, int, (wint_t wc)); -_GL_CXXALIAS_SYS (iswpunct, int, (wint_t wc)); -_GL_CXXALIAS_SYS (iswspace, int, (wint_t wc)); -_GL_CXXALIAS_SYS (iswupper, int, (wint_t wc)); -_GL_CXXALIAS_SYS (iswxdigit, int, (wint_t wc)); -#endif -_GL_CXXALIASWARN (iswalnum); -_GL_CXXALIASWARN (iswalpha); -_GL_CXXALIASWARN (iswblank); -_GL_CXXALIASWARN (iswcntrl); -_GL_CXXALIASWARN (iswdigit); -_GL_CXXALIASWARN (iswgraph); -_GL_CXXALIASWARN (iswlower); -_GL_CXXALIASWARN (iswprint); -_GL_CXXALIASWARN (iswpunct); -_GL_CXXALIASWARN (iswspace); -_GL_CXXALIASWARN (iswupper); -_GL_CXXALIASWARN (iswxdigit); - -#if @REPLACE_ISWCNTRL@ || defined __MINGW32__ -_GL_CXXALIAS_RPL (towlower, wint_t, (wint_t wc)); -_GL_CXXALIAS_RPL (towupper, wint_t, (wint_t wc)); -#else -_GL_CXXALIAS_SYS (towlower, wint_t, (wint_t wc)); -_GL_CXXALIAS_SYS (towupper, wint_t, (wint_t wc)); -#endif -_GL_CXXALIASWARN (towlower); -_GL_CXXALIASWARN (towupper); - - -#endif /* _GL_WCTYPE_H */ -#endif /* _GL_WCTYPE_H */ diff --git a/grub-core/gnulib/xsize.h b/grub-core/gnulib/xsize.h deleted file mode 100644 index fbd63290d..000000000 --- a/grub-core/gnulib/xsize.h +++ /dev/null @@ -1,108 +0,0 @@ -/* xsize.h -- Checked size_t computations. - - Copyright (C) 2003, 2008, 2009, 2010 Free Software Foundation, 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 3, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _XSIZE_H -#define _XSIZE_H - -/* Get size_t. */ -#include - -/* Get SIZE_MAX. */ -#include -#if HAVE_STDINT_H -# include -#endif - -/* The size of memory objects is often computed through expressions of - type size_t. Example: - void* p = malloc (header_size + n * element_size). - These computations can lead to overflow. When this happens, malloc() - returns a piece of memory that is way too small, and the program then - crashes while attempting to fill the memory. - To avoid this, the functions and macros in this file check for overflow. - The convention is that SIZE_MAX represents overflow. - malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc - implementation that uses mmap --, it's recommended to use size_overflow_p() - or size_in_bounds_p() before invoking malloc(). - The example thus becomes: - size_t size = xsum (header_size, xtimes (n, element_size)); - void *p = (size_in_bounds_p (size) ? malloc (size) : NULL); -*/ - -/* Convert an arbitrary value >= 0 to type size_t. */ -#define xcast_size_t(N) \ - ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX) - -/* Sum of two sizes, with overflow check. */ -static inline size_t -#if __GNUC__ >= 3 -__attribute__ ((__pure__)) -#endif -xsum (size_t size1, size_t size2) -{ - size_t sum = size1 + size2; - return (sum >= size1 ? sum : SIZE_MAX); -} - -/* Sum of three sizes, with overflow check. */ -static inline size_t -#if __GNUC__ >= 3 -__attribute__ ((__pure__)) -#endif -xsum3 (size_t size1, size_t size2, size_t size3) -{ - return xsum (xsum (size1, size2), size3); -} - -/* Sum of four sizes, with overflow check. */ -static inline size_t -#if __GNUC__ >= 3 -__attribute__ ((__pure__)) -#endif -xsum4 (size_t size1, size_t size2, size_t size3, size_t size4) -{ - return xsum (xsum (xsum (size1, size2), size3), size4); -} - -/* Maximum of two sizes, with overflow check. */ -static inline size_t -#if __GNUC__ >= 3 -__attribute__ ((__pure__)) -#endif -xmax (size_t size1, size_t size2) -{ - /* No explicit check is needed here, because for any n: - max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */ - return (size1 >= size2 ? size1 : size2); -} - -/* Multiplication of a count with an element size, with overflow check. - The count must be >= 0 and the element size must be > 0. - This is a macro, not an inline function, so that it works correctly even - when N is of a wider type and N > SIZE_MAX. */ -#define xtimes(N, ELSIZE) \ - ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX) - -/* Check for overflow. */ -#define size_overflow_p(SIZE) \ - ((SIZE) == SIZE_MAX) -/* Check against overflow. */ -#define size_in_bounds_p(SIZE) \ - ((SIZE) != SIZE_MAX) - -#endif /* _XSIZE_H */ diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c index 2a315e2d8..a458c3aca 100644 --- a/grub-core/io/bufio.c +++ b/grub-core/io/bufio.c @@ -43,12 +43,12 @@ typedef struct grub_bufio *grub_bufio_t; static struct grub_fs grub_bufio_fs; grub_file_t -grub_bufio_open (grub_file_t io, int size) +grub_bufio_open (grub_file_t io, grub_size_t size) { grub_file_t file; grub_bufio_t bufio = 0; - file = (grub_file_t) grub_malloc (sizeof (*file)); + file = (grub_file_t) grub_zalloc (sizeof (*file)); if (! file) return 0; @@ -57,11 +57,18 @@ grub_bufio_open (grub_file_t io, int size) else if (size > GRUB_BUFIO_MAX_SIZE) size = GRUB_BUFIO_MAX_SIZE; - if ((size < 0) || ((unsigned) size > io->size)) + if (size > io->size) size = ((io->size > GRUB_BUFIO_MAX_SIZE) ? GRUB_BUFIO_MAX_SIZE : io->size); - bufio = grub_malloc (sizeof (struct grub_bufio) + size); + /* + * Round up size to power of 2 which the binary math to + * calculate next_buf in grub_bufio_read() requires. + */ + while (size & (size - 1)) + size = (size | (size - 1)) + 1; + + bufio = grub_zalloc (sizeof (struct grub_bufio) + size); if (! bufio) { grub_free (file); @@ -70,14 +77,10 @@ grub_bufio_open (grub_file_t io, int size) bufio->file = io; bufio->block_size = size; - bufio->buffer_len = 0; - bufio->buffer_at = 0; file->device = io->device; - file->offset = 0; file->size = io->size; file->data = bufio; - file->read_hook = 0; file->fs = &grub_bufio_fs; file->not_easily_seekable = io->not_easily_seekable; @@ -85,11 +88,11 @@ grub_bufio_open (grub_file_t io, int size) } grub_file_t -grub_buffile_open (const char *name, int size) +grub_buffile_open (const char *name, enum grub_file_type type, grub_size_t size) { grub_file_t io, file; - io = grub_file_open (name); + io = grub_file_open (name, type); if (! io) return 0; @@ -202,10 +205,10 @@ grub_bufio_close (grub_file_t file) static struct grub_fs grub_bufio_fs = { .name = "bufio", - .dir = 0, - .open = 0, - .read = grub_bufio_read, - .close = grub_bufio_close, - .label = 0, + .fs_dir = 0, + .fs_open = 0, + .fs_read = grub_bufio_read, + .fs_close = grub_bufio_close, + .fs_label = 0, .next = 0 }; diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c index 83c0b64cb..cb7eb1fe3 100644 --- a/grub-core/io/gzio.c +++ b/grub-core/io/gzio.c @@ -43,6 +43,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -94,6 +95,14 @@ struct grub_gzio struct huft *tl; /* The distance code table. */ struct huft *td; + /* The checksum algorithm */ + const gcry_md_spec_t *hdesc; + /* The wanted checksum */ + grub_uint32_t orig_checksum; + /* The uncompressed length */ + grub_size_t orig_len; + /* Context for checksum calculation */ + grub_uint8_t *hcontext; /* The lookup bits for the literal/length code table. */ int bl; /* The lookup bits for the distance code table. */ @@ -140,24 +149,24 @@ eat_field (grub_file_t file, int len) #define OLD_GZIP_MAGIC grub_le_to_cpu16 (0x9E1F) /* Compression methods (see algorithm.doc) */ -#define STORED 0 -#define COMPRESSED 1 -#define PACKED 2 -#define LZHED 3 +#define GRUB_GZ_STORED 0 +#define GRUB_GZ_COMPRESSED 1 +#define GRUB_GZ_PACKED 2 +#define GRUB_GZ_LZHED 3 /* methods 4 to 7 reserved */ -#define DEFLATED 8 -#define MAX_METHODS 9 +#define GRUB_GZ_DEFLATED 8 +#define GRUB_GZ_MAX_METHODS 9 /* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ +#define GRUB_GZ_ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define GRUB_GZ_CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define GRUB_GZ_EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define GRUB_GZ_ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define GRUB_GZ_COMMENT 0x10 /* bit 4 set: file comment present */ +#define GRUB_GZ_ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define GRUB_GZ_RESERVED 0xC0 /* bit 6,7: reserved */ -#define UNSUPPORTED_FLAGS (CONTINUATION | ENCRYPTED | RESERVED) +#define GRUB_GZ_UNSUPPORTED_FLAGS (GRUB_GZ_CONTINUATION | GRUB_GZ_ENCRYPTED | GRUB_GZ_RESERVED) /* inflate block codes */ #define INFLATE_STORED 0 @@ -180,7 +189,7 @@ test_gzip_header (grub_file_t file) grub_uint8_t os_type; } hdr; grub_uint16_t extra_len; - grub_uint32_t orig_len; + grub_uint32_t crc32; grub_gzio_t gzio = file->data; if (grub_file_tell (gzio->file) != 0) @@ -201,26 +210,29 @@ test_gzip_header (grub_file_t file) * problem occurs from here on, then we have corrupt or otherwise * bad data, and the error should be reported to the user. */ - if (hdr.method != DEFLATED - || (hdr.flags & UNSUPPORTED_FLAGS) - || ((hdr.flags & EXTRA_FIELD) + if (hdr.method != GRUB_GZ_DEFLATED + || (hdr.flags & GRUB_GZ_UNSUPPORTED_FLAGS) + || ((hdr.flags & GRUB_GZ_EXTRA_FIELD) && (grub_file_read (gzio->file, &extra_len, 2) != 2 || eat_field (gzio->file, grub_le_to_cpu16 (extra_len)))) - || ((hdr.flags & ORIG_NAME) && eat_field (gzio->file, -1)) - || ((hdr.flags & COMMENT) && eat_field (gzio->file, -1))) + || ((hdr.flags & GRUB_GZ_ORIG_NAME) && eat_field (gzio->file, -1)) + || ((hdr.flags & GRUB_GZ_COMMENT) && eat_field (gzio->file, -1))) return 0; gzio->data_offset = grub_file_tell (gzio->file); /* FIXME: don't do this on not easily seekable files. */ { - grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4); - if (grub_file_read (gzio->file, &orig_len, 4) != 4) + grub_file_seek (gzio->file, grub_file_size (gzio->file) - 8); + if (grub_file_read (gzio->file, &crc32, 4) != 4) + return 0; + gzio->orig_checksum = grub_le_to_cpu32 (crc32); + if (grub_file_read (gzio->file, &gzio->orig_len, 4) != 4) return 0; /* FIXME: this does not handle files whose original size is over 4GB. But how can we know the real original size? */ - file->size = grub_le_to_cpu32 (orig_len); + file->size = grub_le_to_cpu32 (gzio->orig_len); } initialize_tables (gzio); @@ -354,6 +366,10 @@ static int dbits = 6; /* bits in base distance lookup table */ lookup of seven bits, the EOB code will be found in that first lookup, and so will not require that too many bits be pulled from the stream. + + Note that NEEDBITS() can fail if the file is corrupt/truncated. + The GOTOFAILIFERROR, RETURNIFERROR and RETURN1IFERROR macros can + help. */ static ush mask_bits[] = @@ -363,14 +379,16 @@ static ush mask_bits[] = 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; -#pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations" - #define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte(gzio))<>=(n);k-=(n);} while (0) +#define RETURNIFERROR if (grub_errno != GRUB_ERR_NONE) return +#define RETURN1IFERROR if (grub_errno != GRUB_ERR_NONE) return 1 +#define GOTOFAILIFERROR if (grub_errno != GRUB_ERR_NONE) goto fail static int get_byte (grub_gzio_t gzio) { + grub_ssize_t bytes_read; if (gzio->mem_input) { if (gzio->mem_input_off < gzio->mem_input_size) @@ -383,7 +401,16 @@ get_byte (grub_gzio_t gzio) || gzio->inbuf_d == INBUFSIZ)) { gzio->inbuf_d = 0; - grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ); + bytes_read = grub_file_read (gzio->file, gzio->inbuf, INBUFSIZ); + /* + * Only trigger if we get 0 bytes. If we get negative bytes there should + * be an existing GRUB error code that we don't want to overwrite. + */ + if (bytes_read == 0) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "File is too short"); + return 0; + } } return gzio->inbuf[gzio->inbuf_d++]; @@ -437,7 +464,7 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ int l; /* bits per table (returned in m) */ register unsigned *p; /* pointer into c[], b[], or v[] */ register struct huft *q; /* points to current table */ - struct huft r; /* table entry for structure assignment */ + struct huft r = {0}; /* table entry for structure assignment */ struct huft *u[BMAX]; /* table stack */ unsigned v[N_MAX]; /* values in order of bit length */ register int w; /* bits before this table == (l * h) */ @@ -497,6 +524,7 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ } /* Make a table of values in order of bit lengths */ + grub_memset (v, N_MAX, sizeof (v)); p = b; i = 0; do @@ -544,7 +572,7 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ z = 1 << j; /* table entries for j-bit table */ /* allocate and link in new table */ - q = (struct huft *) grub_malloc ((z + 1) * sizeof (struct huft)); + q = (struct huft *) grub_calloc (z + 1, sizeof (struct huft)); if (! q) { if (h) @@ -578,11 +606,18 @@ huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ r.v.n = (ush) (*p); /* simple code is just the value */ p++; /* one compiler does not like *p++ */ } - else + else if (*p < N_MAX) { r.e = (uch) e[*p - s]; /* non-simple--look up in lists */ r.v.n = d[*p++ - s]; } + else + { + /* Detected an uninitialised value, abort. */ + if (h) + huft_free (u[0]); + return 2; + } /* fill code-like entries with r */ f = 1 << (k - w); @@ -659,7 +694,14 @@ inflate_codes_in_window (grub_gzio_t gzio) { if (! gzio->code_state) { - NEEDBITS ((unsigned) gzio->bl); + + if (gzio->tl == NULL) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "NULL gzio->tl"); + return 1; + } + + NEEDBITS ((unsigned) gzio->bl); RETURN1IFERROR; if ((e = (t = gzio->tl + ((unsigned) b & ml))->e) > 16) do { @@ -671,7 +713,7 @@ inflate_codes_in_window (grub_gzio_t gzio) } DUMPBITS (t->b); e -= 16; - NEEDBITS (e); + NEEDBITS (e); RETURN1IFERROR; } while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); DUMPBITS (t->b); @@ -693,12 +735,18 @@ inflate_codes_in_window (grub_gzio_t gzio) } /* get length of block to copy */ - NEEDBITS (e); + NEEDBITS (e); RETURN1IFERROR; n = t->v.n + ((unsigned) b & mask_bits[e]); DUMPBITS (e); + if (gzio->td == NULL) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "NULL gzio->td"); + return 1; + } + /* decode distance of block to copy */ - NEEDBITS ((unsigned) gzio->bd); + NEEDBITS ((unsigned) gzio->bd); RETURN1IFERROR; if ((e = (t = gzio->td + ((unsigned) b & md))->e) > 16) do { @@ -710,12 +758,12 @@ inflate_codes_in_window (grub_gzio_t gzio) } DUMPBITS (t->b); e -= 16; - NEEDBITS (e); + NEEDBITS (e); RETURN1IFERROR; } while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); DUMPBITS (t->b); - NEEDBITS (e); + NEEDBITS (e); RETURN1IFERROR; d = w - t->v.n - ((unsigned) b & mask_bits[e]); DUMPBITS (e); gzio->code_state++; @@ -784,10 +832,10 @@ init_stored_block (grub_gzio_t gzio) DUMPBITS (k & 7); /* get the length and its complement */ - NEEDBITS (16); + NEEDBITS (16); RETURNIFERROR; gzio->block_len = ((unsigned) b & 0xffff); DUMPBITS (16); - NEEDBITS (16); + NEEDBITS (16); RETURNIFERROR; if (gzio->block_len != (int) ((~b) & 0xffff)) grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "the length of a stored block does not match"); @@ -869,13 +917,13 @@ init_dynamic_block (grub_gzio_t gzio) k = gzio->bk; /* read in table lengths */ - NEEDBITS (5); + NEEDBITS (5); RETURNIFERROR; nl = 257 + ((unsigned) b & 0x1f); /* number of literal/length codes */ DUMPBITS (5); - NEEDBITS (5); + NEEDBITS (5); RETURNIFERROR; nd = 1 + ((unsigned) b & 0x1f); /* number of distance codes */ DUMPBITS (5); - NEEDBITS (4); + NEEDBITS (4); RETURNIFERROR; nb = 4 + ((unsigned) b & 0xf); /* number of bit length codes */ DUMPBITS (4); if (nl > 286 || nd > 30) @@ -887,7 +935,7 @@ init_dynamic_block (grub_gzio_t gzio) /* read in bit-length-code lengths */ for (j = 0; j < nb; j++) { - NEEDBITS (3); + NEEDBITS (3); RETURNIFERROR; ll[bitorder[j]] = (unsigned) b & 7; DUMPBITS (3); } @@ -907,9 +955,16 @@ init_dynamic_block (grub_gzio_t gzio) n = nl + nd; m = mask_bits[gzio->bl]; i = l = 0; + + if (gzio->tl == NULL) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "NULL gzio->tl"); + return; + } + while ((unsigned) i < n) { - NEEDBITS ((unsigned) gzio->bl); + NEEDBITS ((unsigned) gzio->bl); GOTOFAILIFERROR; j = (gzio->td = gzio->tl + ((unsigned) b & m))->b; DUMPBITS (j); j = gzio->td->v.n; @@ -917,26 +972,26 @@ init_dynamic_block (grub_gzio_t gzio) ll[i++] = l = j; /* save last length in l */ else if (j == 16) /* repeat last length 3 to 6 times */ { - NEEDBITS (2); + NEEDBITS (2); GOTOFAILIFERROR; j = 3 + ((unsigned) b & 3); DUMPBITS (2); if ((unsigned) i + j > n) { grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found"); - return; + goto fail; } while (j--) ll[i++] = l; } else if (j == 17) /* 3 to 10 zero length codes */ { - NEEDBITS (3); + NEEDBITS (3); GOTOFAILIFERROR; j = 3 + ((unsigned) b & 7); DUMPBITS (3); if ((unsigned) i + j > n) { grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found"); - return; + goto fail; } while (j--) ll[i++] = 0; @@ -945,13 +1000,13 @@ init_dynamic_block (grub_gzio_t gzio) else /* j == 18: 11 to 138 zero length codes */ { - NEEDBITS (7); + NEEDBITS (7); GOTOFAILIFERROR; j = 11 + ((unsigned) b & 0x7f); DUMPBITS (7); if ((unsigned) i + j > n) { grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found"); - return; + goto fail; } while (j--) ll[i++] = 0; @@ -972,6 +1027,7 @@ init_dynamic_block (grub_gzio_t gzio) gzio->bl = lbits; if (huft_build (ll, nl, 257, cplens, cplext, &gzio->tl, &gzio->bl) != 0) { + gzio->tl = 0; grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "failed in building a Huffman code table"); return; @@ -981,6 +1037,7 @@ init_dynamic_block (grub_gzio_t gzio) { huft_free (gzio->tl); gzio->tl = 0; + gzio->td = 0; grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "failed in building a Huffman code table"); return; @@ -989,6 +1046,12 @@ init_dynamic_block (grub_gzio_t gzio) /* indicate we're now working on a block */ gzio->code_state = 0; gzio->block_len++; + return; + + fail: + huft_free (gzio->tl); + gzio->td = NULL; + gzio->tl = NULL; } @@ -1003,12 +1066,12 @@ get_new_block (grub_gzio_t gzio) k = gzio->bk; /* read in last block bit */ - NEEDBITS (1); + NEEDBITS (1); RETURNIFERROR; gzio->last_block = (int) b & 1; DUMPBITS (1); /* read in block type */ - NEEDBITS (2); + NEEDBITS (2); RETURNIFERROR; gzio->block_type = (unsigned) b & 3; DUMPBITS (2); @@ -1095,9 +1158,25 @@ inflate_window (grub_gzio_t gzio) } } - gzio->saved_offset += WSIZE; + gzio->saved_offset += gzio->wp; - /* XXX do CRC calculation here! */ + if (gzio->hcontext) + { + gzio->hdesc->write (gzio->hcontext, gzio->slide, gzio->wp); + + if (gzio->saved_offset == gzio->orig_len) + { + grub_uint32_t csum; + + gzio->hdesc->final (gzio->hcontext); + csum = grub_get_unaligned32 (gzio->hdesc->read (gzio->hcontext)); + csum = grub_be_to_cpu32 (csum); + if (csum != gzio->orig_checksum) + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, + "checksum mismatch %08x/%08x", + gzio->orig_checksum, csum); + } + } } @@ -1118,19 +1197,28 @@ initialize_tables (grub_gzio_t gzio) /* Reset memory allocation stuff. */ huft_free (gzio->tl); huft_free (gzio->td); + gzio->tl = NULL; + gzio->td = NULL; + + if (gzio->hcontext) + gzio->hdesc->init(gzio->hcontext); } -/* Open a new decompressing object on the top of IO. If TRANSPARENT is true, - even if IO does not contain data compressed by gzip, return a valid file - object. Note that this function won't close IO, even if an error occurs. */ +/* + * Open a new decompressing object on the top of IO. + * Note that this function won't close IO, even if an error occurs. + */ static grub_file_t -grub_gzio_open (grub_file_t io) +grub_gzio_open (grub_file_t io, enum grub_file_type type) { grub_file_t file; grub_gzio_t gzio = 0; - file = (grub_file_t) grub_malloc (sizeof (*file)); + if (type & GRUB_FILE_TYPE_NO_DECOMPRESS) + return io; + + file = (grub_file_t) grub_zalloc (sizeof (*file)); if (! file) return 0; @@ -1143,16 +1231,18 @@ grub_gzio_open (grub_file_t io) gzio->file = io; + gzio->hdesc = GRUB_MD_CRC32; + gzio->hcontext = grub_malloc(gzio->hdesc->contextsize); + file->device = io->device; - file->offset = 0; file->data = gzio; - file->read_hook = 0; file->fs = &grub_gzio_fs; file->not_easily_seekable = 1; if (! test_gzip_header (file)) { grub_errno = GRUB_ERR_NONE; + grub_free (gzio->hcontext); grub_free (gzio); grub_free (file); grub_file_seek (io, 0); @@ -1163,16 +1253,29 @@ grub_gzio_open (grub_file_t io) return file; } +static grub_uint8_t +mod_31 (grub_uint16_t v) +{ + /* At most 2 iterations for any number that + we can get here. + In any case faster than real division. */ + while (v > 0x1f) + v = (v & 0x1f) + (v >> 5); + if (v == 0x1f) + return 0; + return v; +} + static int test_zlib_header (grub_gzio_t gzio) { grub_uint8_t cmf, flg; - + cmf = get_byte (gzio); flg = get_byte (gzio); /* Check that compression method is DEFLATE. */ - if ((cmf & 0xf) != DEFLATED) + if ((cmf & 0xf) != GRUB_GZ_DEFLATED) { /* TRANSLATORS: It's about given file having some strange format, not complete lack of gzip support. */ @@ -1180,7 +1283,10 @@ test_zlib_header (grub_gzio_t gzio) return 0; } - if ((cmf * 256 + flg) % 31) + /* Usually it would be: (cmf * 256 + flg) % 31 != 0. */ + /* But 256 == 8 (31). */ + /* By multiplying by 4 and using 32 == 1 (31). We get our formula. */ + if (mod_31 (cmf + flg * 4) != 0) { grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, N_("unsupported gzip format")); return 0; @@ -1221,7 +1327,14 @@ grub_gzio_read_real (grub_gzio_t gzio, grub_off_t offset, register char *srcaddr; while (offset >= gzio->saved_offset) - inflate_window (gzio); + { + inflate_window (gzio); + if (gzio->wp == 0) + goto out; + } + + if (gzio->wp == 0) + goto out; srcaddr = (char *) ((offset & (WSIZE - 1)) + gzio->slide); size = gzio->saved_offset - offset; @@ -1236,6 +1349,7 @@ grub_gzio_read_real (grub_gzio_t gzio, grub_off_t offset, offset += size; } + out: if (grub_errno != GRUB_ERR_NONE) ret = -1; @@ -1245,7 +1359,15 @@ grub_gzio_read_real (grub_gzio_t gzio, grub_off_t offset, static grub_ssize_t grub_gzio_read (grub_file_t file, char *buf, grub_size_t len) { - return grub_gzio_read_real (file->data, file->offset, buf, len); + grub_ssize_t ret; + ret = grub_gzio_read_real (file->data, file->offset, buf, len); + + if (!grub_errno && ret != (grub_ssize_t) len) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "premature end of compressed"); + ret = -1; + } + return ret; } /* Release everything, including the underlying file object. */ @@ -1257,10 +1379,12 @@ grub_gzio_close (grub_file_t file) grub_file_close (gzio->file); huft_free (gzio->tl); huft_free (gzio->td); + grub_free (gzio->hcontext); grub_free (gzio); /* No need to close the same device twice. */ file->device = 0; + file->name = 0; return grub_errno; } @@ -1292,16 +1416,38 @@ grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off, return ret; } +grub_ssize_t +grub_deflate_decompress (char *inbuf, grub_size_t insize, grub_off_t off, + char *outbuf, grub_size_t outsize) +{ + grub_gzio_t gzio = 0; + grub_ssize_t ret; + + gzio = grub_zalloc (sizeof (*gzio)); + if (! gzio) + return -1; + gzio->mem_input = (grub_uint8_t *) inbuf; + gzio->mem_input_size = insize; + gzio->mem_input_off = 0; + + initialize_tables (gzio); + + ret = grub_gzio_read_real (gzio, off, outbuf, outsize); + grub_free (gzio); + + return ret; +} + static struct grub_fs grub_gzio_fs = { .name = "gzio", - .dir = 0, - .open = 0, - .read = grub_gzio_read, - .close = grub_gzio_close, - .label = 0, + .fs_dir = 0, + .fs_open = 0, + .fs_read = grub_gzio_read, + .fs_close = grub_gzio_close, + .fs_label = 0, .next = 0 }; diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c index 77291d001..a7d442543 100644 --- a/grub-core/io/lzopio.c +++ b/grub-core/io/lzopio.c @@ -125,8 +125,6 @@ read_block_header (struct grub_lzopio *lzopio) sizeof (lzopio->block.ucheck)) != sizeof (lzopio->block.ucheck)) return -1; - - lzopio->block.ucheck = lzopio->block.ucheck; } /* Read checksum of compressed data. */ @@ -143,8 +141,6 @@ read_block_header (struct grub_lzopio *lzopio) sizeof (lzopio->block.ccheck)) != sizeof (lzopio->block.ccheck)) return -1; - - lzopio->block.ccheck = lzopio->block.ccheck; } } @@ -166,15 +162,17 @@ read_block_data (struct grub_lzopio *lzopio) if (lzopio->ccheck_fun) { - grub_uint64_t context[(lzopio->ccheck_fun->contextsize + 7) / 8]; + grub_uint8_t computed_hash[GRUB_CRYPTO_MAX_MDLEN]; - lzopio->ccheck_fun->init (context); - lzopio->ccheck_fun->write (context, lzopio->block.cdata, - lzopio->block.csize); - lzopio->ccheck_fun->final (context); + if (lzopio->ccheck_fun->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return -1; + + grub_crypto_hash (lzopio->ccheck_fun, computed_hash, + lzopio->block.cdata, + lzopio->block.csize); if (grub_memcmp - (lzopio->ccheck_fun->read (context), &lzopio->block.ccheck, + (computed_hash, &lzopio->block.ccheck, sizeof (lzopio->block.ccheck)) != 0) return -1; } @@ -212,15 +210,17 @@ uncompress_block (struct grub_lzopio *lzopio) if (lzopio->ucheck_fun) { - grub_uint64_t context[(lzopio->ucheck_fun->contextsize + 7) / 8]; + grub_uint8_t computed_hash[GRUB_CRYPTO_MAX_MDLEN]; - lzopio->ucheck_fun->init (context); - lzopio->ucheck_fun->write (context, lzopio->block.udata, - lzopio->block.usize); - lzopio->ucheck_fun->final (context); + if (lzopio->ucheck_fun->mdlen > GRUB_CRYPTO_MAX_MDLEN) + return -1; + + grub_crypto_hash (lzopio->ucheck_fun, computed_hash, + lzopio->block.udata, + lzopio->block.usize); if (grub_memcmp - (lzopio->ucheck_fun->read (context), &lzopio->block.ucheck, + (computed_hash, &lzopio->block.ucheck, sizeof (lzopio->block.ucheck)) != 0) return -1; } @@ -286,7 +286,7 @@ struct lzop_header grub_uint32_t mtime_lo; grub_uint32_t mtime_hi; grub_uint8_t name_len; -} __attribute__ ((packed)); +} GRUB_PACKED; static int test_header (grub_file_t file) @@ -380,12 +380,8 @@ test_header (grub_file_t file) sizeof (checksum)) goto CORRUPTED; - if (hcheck) - { - checksum = checksum; - if (grub_memcmp (&checksum, hcheck->read(context), sizeof(checksum)) != 0) - goto CORRUPTED; - } + if (hcheck && grub_memcmp (&checksum, hcheck->read(context), sizeof(checksum)) != 0) + goto CORRUPTED; lzopio->start_block_off = grub_file_tell (lzopio->file); @@ -403,17 +399,18 @@ test_header (grub_file_t file) return 1; CORRUPTED: - grub_free(name); - return 0; } static grub_file_t -grub_lzopio_open (grub_file_t io) +grub_lzopio_open (grub_file_t io, enum grub_file_type type) { grub_file_t file; grub_lzopio_t lzopio; + if (type & GRUB_FILE_TYPE_NO_DECOMPRESS) + return io; + file = (grub_file_t) grub_zalloc (sizeof (*file)); if (!file) return 0; @@ -428,9 +425,7 @@ grub_lzopio_open (grub_file_t io) lzopio->file = io; file->device = io->device; - file->offset = 0; file->data = lzopio; - file->read_hook = 0; file->fs = &grub_lzopio_fs; file->size = GRUB_FILE_SIZE_UNKNOWN; file->not_easily_seekable = 1; @@ -526,16 +521,17 @@ grub_lzopio_close (grub_file_t file) /* Device must not be closed twice. */ file->device = 0; + file->name = 0; return grub_errno; } static struct grub_fs grub_lzopio_fs = { .name = "lzopio", - .dir = 0, - .open = 0, - .read = grub_lzopio_read, - .close = grub_lzopio_close, - .label = 0, + .fs_dir = 0, + .fs_open = 0, + .fs_read = grub_lzopio_read, + .fs_close = grub_lzopio_close, + .fs_label = 0, .next = 0 }; diff --git a/grub-core/io/offset.c b/grub-core/io/offset.c new file mode 100644 index 000000000..7e2db4a3a --- /dev/null +++ b/grub-core/io/offset.c @@ -0,0 +1,112 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_offset_file +{ + grub_file_t parent; + grub_off_t off; +}; + +static grub_ssize_t +grub_offset_read (grub_file_t file, char *buf, grub_size_t len) +{ + struct grub_offset_file *data = file->data; + if (grub_file_seek (data->parent, data->off + file->offset) == (grub_off_t) -1) + return -1; + return grub_file_read (data->parent, buf, len); +} + +static grub_err_t +grub_offset_close (grub_file_t file) +{ + struct grub_offset_file *data = file->data; + + if (data->parent) + grub_file_close (data->parent); + + /* No need to close the same device twice. */ + file->device = 0; + + return 0; +} + +static struct grub_fs grub_offset_fs = { + .name = "offset", + .fs_dir = 0, + .fs_open = 0, + .fs_read = grub_offset_read, + .fs_close = grub_offset_close, + .fs_label = 0, + .next = 0 +}; + +void +grub_file_offset_close (grub_file_t file) +{ + struct grub_offset_file *off_data = file->data; + off_data->parent = NULL; + grub_file_close (file); +} + +grub_file_t +grub_file_offset_open (grub_file_t parent, enum grub_file_type type, + grub_off_t start, grub_off_t size) +{ + struct grub_offset_file *off_data; + grub_file_t off_file, last_off_file; + grub_file_filter_id_t filter; + + off_file = grub_zalloc (sizeof (*off_file)); + off_data = grub_zalloc (sizeof (*off_data)); + if (!off_file || !off_data) + { + grub_free (off_file); + grub_free (off_data); + return 0; + } + + off_data->off = start; + off_data->parent = parent; + + off_file->device = parent->device; + off_file->data = off_data; + off_file->fs = &grub_offset_fs; + off_file->size = size; + + last_off_file = NULL; + for (filter = GRUB_FILE_FILTER_COMPRESSION_FIRST; + off_file && filter <= GRUB_FILE_FILTER_COMPRESSION_LAST; filter++) + if (grub_file_filters[filter]) + { + last_off_file = off_file; + off_file = grub_file_filters[filter] (off_file, type); + } + + if (!off_file) + { + off_data->parent = NULL; + grub_file_close (last_off_file); + return 0; + } + return off_file; +} diff --git a/grub-core/io/xzio.c b/grub-core/io/xzio.c index ae30e6f80..63d8cda6a 100644 --- a/grub-core/io/xzio.c +++ b/grub-core/io/xzio.c @@ -74,15 +74,15 @@ static grub_ssize_t read_vli (grub_file_t file, grub_uint64_t *num) { grub_uint8_t buf[VLI_MAX_DIGITS]; - grub_ssize_t read; + grub_ssize_t read_bytes; grub_size_t dec; - read = grub_file_read (file, buf, VLI_MAX_DIGITS); - if (read < 0) + read_bytes = grub_file_read (file, buf, VLI_MAX_DIGITS); + if (read_bytes < 0) return -1; - dec = decode_vli (buf, read, num); - grub_file_seek (file, file->offset - (read - dec)); + dec = decode_vli (buf, read_bytes, num); + grub_file_seek (file, file->offset - (read_bytes - dec)); return dec; } @@ -169,11 +169,14 @@ ERROR: } static grub_file_t -grub_xzio_open (grub_file_t io) +grub_xzio_open (grub_file_t io, enum grub_file_type type) { grub_file_t file; grub_xzio_t xzio; + if (type & GRUB_FILE_TYPE_NO_DECOMPRESS) + return io; + file = (grub_file_t) grub_zalloc (sizeof (*file)); if (!file) return 0; @@ -186,12 +189,9 @@ grub_xzio_open (grub_file_t io) } xzio->file = io; - xzio->saved_offset = 0; file->device = io->device; - file->offset = 0; file->data = xzio; - file->read_hook = 0; file->fs = &grub_xzio_fs; file->size = GRUB_FILE_SIZE_UNKNOWN; file->not_easily_seekable = 1; @@ -210,10 +210,7 @@ grub_xzio_open (grub_file_t io) } xzio->buf.in = xzio->inbuf; - xzio->buf.in_pos = 0; - xzio->buf.in_size = 0; xzio->buf.out = xzio->outbuf; - xzio->buf.out_pos = 0; xzio->buf.out_size = XZBUFSIZ; /* FIXME: don't test footer on not easily seekable files. */ @@ -286,7 +283,7 @@ grub_xzio_read (grub_file_t file, char *buf, grub_size_t len) { grub_off_t new_offset = current_offset + xzio->buf.out_pos; - + if (file->offset <= new_offset) /* Store first chunk of data in buffer. */ { @@ -324,16 +321,17 @@ grub_xzio_close (grub_file_t file) /* Device must not be closed twice. */ file->device = 0; + file->name = 0; return grub_errno; } static struct grub_fs grub_xzio_fs = { .name = "xzio", - .dir = 0, - .open = 0, - .read = grub_xzio_read, - .close = grub_xzio_close, - .label = 0, + .fs_dir = 0, + .fs_open = 0, + .fs_read = grub_xzio_read, + .fs_close = grub_xzio_close, + .fs_label = 0, .next = 0 }; diff --git a/grub-core/kern/acpi.c b/grub-core/kern/acpi.c new file mode 100644 index 000000000..8ff0835d5 --- /dev/null +++ b/grub-core/kern/acpi.c @@ -0,0 +1,135 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2012 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +/* Simple checksum by summing all bytes. Used by ACPI and SMBIOS. */ +grub_uint8_t +grub_byte_checksum (void *base, grub_size_t size) +{ + grub_uint8_t *ptr; + grub_uint8_t ret = 0; + for (ptr = (grub_uint8_t *) base; ptr < ((grub_uint8_t *) base) + size; + ptr++) + ret += *ptr; + return ret; +} + +static void * +grub_acpi_rsdt_find_table (struct grub_acpi_table_header *rsdt, const char *sig) +{ + grub_size_t s; + grub_unaligned_uint32_t *ptr; + + if (!rsdt) + return 0; + + if (grub_memcmp (rsdt->signature, "RSDT", 4) != 0) + return 0; + + ptr = (grub_unaligned_uint32_t *) (rsdt + 1); + s = (rsdt->length - sizeof (*rsdt)) / sizeof (grub_uint32_t); + for (; s; s--, ptr++) + { + struct grub_acpi_table_header *tbl; + + /* Skip NULL entries in RSDT/XSDT. */ + if (!ptr->val) + continue; + tbl = (struct grub_acpi_table_header *) (grub_addr_t) ptr->val; + if (grub_memcmp (tbl->signature, sig, 4) == 0) + return tbl; + } + return 0; +} + +static void * +grub_acpi_xsdt_find_table (struct grub_acpi_table_header *xsdt, const char *sig) +{ + grub_size_t s; + grub_unaligned_uint64_t *ptr; + + if (!xsdt) + return 0; + + if (grub_memcmp (xsdt->signature, "XSDT", 4) != 0) + return 0; + + ptr = (grub_unaligned_uint64_t *) (xsdt + 1); + s = (xsdt->length - sizeof (*xsdt)) / sizeof (grub_uint64_t); + for (; s; s--, ptr++) + { + struct grub_acpi_table_header *tbl; + + /* Skip NULL entries in RSDT/XSDT. */ + if (!ptr->val) + continue; +#if GRUB_CPU_SIZEOF_VOID_P != 8 + if (ptr->val >> 32) + continue; +#endif + tbl = (struct grub_acpi_table_header *) (grub_addr_t) ptr->val; + if (grub_memcmp (tbl->signature, sig, 4) == 0) + return tbl; + } + return 0; +} + +void * +grub_acpi_find_table (const char *sig) +{ + struct grub_acpi_fadt *r = NULL; + struct grub_acpi_rsdp_v10 *rsdpv1; + struct grub_acpi_rsdp_v20 *rsdpv2; + + rsdpv1 = grub_machine_acpi_get_rsdpv1 (); + if (rsdpv1) + r = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *) + (grub_addr_t) rsdpv1->rsdt_addr, + sig); + if (r) + return r; + rsdpv2 = grub_machine_acpi_get_rsdpv2 (); + if (rsdpv2 +#if GRUB_CPU_SIZEOF_VOID_P != 8 + && !(rsdpv2->xsdt_addr >> 32) +#endif + ) + r = grub_acpi_xsdt_find_table ((struct grub_acpi_table_header *) + (grub_addr_t) rsdpv2->xsdt_addr, + sig); + if (r) + return r; + if (rsdpv2) + r = grub_acpi_rsdt_find_table ((struct grub_acpi_table_header *) + (grub_addr_t) rsdpv2->rsdpv1.rsdt_addr, + sig); + if (r) + return r; + return 0; +} + +struct grub_acpi_fadt * +grub_acpi_find_fadt (void) +{ + return grub_acpi_find_table (GRUB_ACPI_FADT_SIGNATURE); +} diff --git a/grub-core/kern/arm/cache.S b/grub-core/kern/arm/cache.S new file mode 100644 index 000000000..354a069fe --- /dev/null +++ b/grub-core/kern/arm/cache.S @@ -0,0 +1,123 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include + + .file "cache.S" + .text + .syntax unified +#if !defined (__thumb2__) || !defined (ARMV7) + .arm +#else + .thumb +#endif + +#if !defined (ARMV6) && !defined (ARMV7) +# error Unsupported architecture version! +#endif + + .align 2 + +/* + * Simple cache maintenance functions + */ + +@ r0 - *beg (inclusive) +@ r1 - *end (exclusive) +@void grub_arm_clean_dcache_range (grub_addr_t start, grub_addr_t end, grub_addr_t dlinesz) +#ifdef ARMV6 +FUNCTION(grub_arm_clean_dcache_range_armv6) +#else +FUNCTION(grub_arm_clean_dcache_range_armv7) +#endif + DSB + @ Clean data cache for range to point-of-unification +1: cmp r0, r1 + bge 2f +#ifdef ARMV6 + mcr p15, 0, r0, c7, c10, 1 @ Clean data cache line by MVA +#else + mcr p15, 0, r0, c7, c11, 1 @ DCCMVAU +#endif + add r0, r0, r2 @ Next line + b 1b +2: DSB + bx lr + +@ r0 - *beg (inclusive) +@ r1 - *end (exclusive) +#ifdef ARMV6 +FUNCTION(grub_arm_invalidate_icache_range_armv6) +#else +FUNCTION(grub_arm_invalidate_icache_range_armv7) +#endif + @ Invalidate instruction cache for range to point-of-unification +1: cmp r0, r1 + bge 2f + mcr p15, 0, r0, c7, c5, 1 @ ICIMVAU + add r0, r0, r2 @ Next line + b 1b + @ Branch predictor invalidate all +2: mcr p15, 0, r0, c7, c5, 6 @ BPIALL + DSB + ISB + bx lr + +#ifdef ARMV6 +FUNCTION(grub_arm_disable_caches_mmu_armv6) +#else +FUNCTION(grub_arm_disable_caches_mmu_armv7) +#endif + + push {r4, lr} + + @ disable D-cache + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 2) + mcr p15, 0, r0, c1, c0, 0 + DSB + ISB + + @ clean/invalidate D-cache + bl clean_invalidate_dcache + + @ disable I-cache + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 12) + mcr p15, 0, r0, c1, c0, 0 + DSB + ISB + + @ invalidate I-cache (also invalidates branch predictors) + mcr p15, 0, r0, c7, c5, 0 + DSB + ISB + + @ clear SCTLR M bit + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 0) + mcr p15, 0, r0, c1, c0, 0 + + mcr p15, 0, r0, c8, c7, 0 @ invalidate TLB + mcr p15, 0, r0, c7, c5, 6 @ invalidate branch predictor + DSB + ISB + + pop {r4, lr} + bx lr + diff --git a/grub-core/kern/arm/cache.c b/grub-core/kern/arm/cache.c new file mode 100644 index 000000000..6c75193e4 --- /dev/null +++ b/grub-core/kern/arm/cache.c @@ -0,0 +1,311 @@ +#include +#include +#include +#ifdef GRUB_MACHINE_UBOOT +#include +#include +#include +#endif + +/* This is only about cache architecture. It doesn't imply + the CPU architecture. */ +static enum + { + ARCH_UNKNOWN, + ARCH_ARMV5_WRITE_THROUGH, + ARCH_ARMV6, + ARCH_ARMV6_UNIFIED, + ARCH_ARMV7 + } type = ARCH_UNKNOWN; + +static int is_v6_mmu; + +static grub_uint32_t grub_arch_cache_dlinesz; +static grub_uint32_t grub_arch_cache_ilinesz; +static grub_uint32_t grub_arch_cache_max_linesz; + +/* Prototypes for asm functions. */ +void grub_arm_clean_dcache_range_armv6 (grub_addr_t start, grub_addr_t end, + grub_addr_t dlinesz); +void grub_arm_clean_dcache_range_armv7 (grub_addr_t start, grub_addr_t end, + grub_addr_t dlinesz); +void grub_arm_clean_dcache_range_poc_armv7 (grub_addr_t start, grub_addr_t end, + grub_addr_t dlinesz); +void grub_arm_invalidate_icache_range_armv6 (grub_addr_t start, grub_addr_t end, + grub_addr_t dlinesz); +void grub_arm_invalidate_icache_range_armv7 (grub_addr_t start, grub_addr_t end, + grub_addr_t dlinesz); +void grub_arm_disable_caches_mmu_armv6 (void); +void grub_arm_disable_caches_mmu_armv7 (void); +grub_uint32_t grub_arm_main_id (void); +grub_uint32_t grub_arm_cache_type (void); + +static void +probe_caches (void) +{ + grub_uint32_t main_id, cache_type; + + /* Read main ID Register */ + main_id = grub_arm_main_id (); + + switch ((main_id >> 16) & 0xf) + { + case 0x3: + case 0x4: + case 0x5: + case 0x6: + is_v6_mmu = 0; + break; + case 0x7: + case 0xf: + is_v6_mmu = 1; + break; + default: + grub_fatal ("Unsupported ARM ID 0x%x", main_id); + } + + /* Read Cache Type Register */ + cache_type = grub_arm_cache_type (); + + switch (cache_type >> 24) + { + case 0x00: + case 0x01: + grub_arch_cache_dlinesz = 8 << ((cache_type >> 12) & 3); + grub_arch_cache_ilinesz = 8 << (cache_type & 3); + type = ARCH_ARMV5_WRITE_THROUGH; + break; + case 0x04: + case 0x0a: + case 0x0c: + case 0x0e: + case 0x1c: + grub_arch_cache_dlinesz = 8 << ((cache_type >> 12) & 3); + grub_arch_cache_ilinesz = 8 << (cache_type & 3); + type = ARCH_ARMV6_UNIFIED; + break; + case 0x05: + case 0x0b: + case 0x0d: + case 0x0f: + case 0x1d: + grub_arch_cache_dlinesz = 8 << ((cache_type >> 12) & 3); + grub_arch_cache_ilinesz = 8 << (cache_type & 3); + type = ARCH_ARMV6; + break; + default: + /* + * The CTR register is pretty much unchanged from v7 onwards, + * and is guaranteed to be backward compatible (the IDC/DIC bits + * allow certain CMOs to be elided, but performing them is never + * wrong), hence handling it like its AArch64 equivalent. + */ + grub_arch_cache_dlinesz = 4 << ((cache_type >> 16) & 0xf); + grub_arch_cache_ilinesz = 4 << (cache_type & 0xf); + type = ARCH_ARMV7; + } + if (grub_arch_cache_dlinesz > grub_arch_cache_ilinesz) + grub_arch_cache_max_linesz = grub_arch_cache_dlinesz; + else + grub_arch_cache_max_linesz = grub_arch_cache_ilinesz; +} + +#ifdef GRUB_MACHINE_UBOOT + +static void subdivide (grub_uint32_t *table, grub_uint32_t *subtable, + grub_uint32_t addr) +{ + grub_uint32_t j; + addr = addr >> 20 << 20; + table[addr >> 20] = (grub_addr_t) subtable | 1; + for (j = 0; j < 256; j++) + subtable[j] = addr | (j << 12) + | (3 << 4) | (3 << 6) | (3 << 8) | (3 << 10) + | (0 << 3) | (1 << 2) | 2; +} + +void +grub_arm_enable_caches_mmu (void) +{ + grub_uint32_t *table; + grub_uint32_t i; + grub_uint32_t border_crossing = 0; + grub_uint32_t *subtable; + struct sys_info *si = grub_uboot_get_sys_info (); + + if (!si || (si->mr_no == 0)) + { + grub_printf ("couldn't get memory map, not enabling caches"); + grub_errno = GRUB_ERR_NONE; + return; + } + + if (type == ARCH_UNKNOWN) + probe_caches (); + + for (i = 0; (signed) i < si->mr_no; i++) + { + if (si->mr[i].start & ((1 << 20) - 1)) + border_crossing++; + if ((si->mr[i].start + si->mr[i].size) & ((1 << 20) - 1)) + border_crossing++; + } + + grub_printf ("%d crossers\n", border_crossing); + + table = grub_memalign (1 << 14, (1 << 14) + (border_crossing << 10)); + if (!table) + { + grub_printf ("couldn't allocate place for MMU table, not enabling caches"); + grub_errno = GRUB_ERR_NONE; + return; + } + + subtable = table + (1 << 12); + /* Map all unknown as device. */ + for (i = 0; i < (1 << 12); i++) + table[i] = (i << 20) | (3 << 10) | (0 << 3) | (1 << 2) | 2; + /* + Device: TEX= 0, C=0, B=1 + normal: TEX= 0, C=1, B=1 + AP = 3 + IMP = 0 + Domain = 0 +*/ + + for (i = 0; (signed) i < si->mr_no; i++) + { + if (si->mr[i].start & ((1 << 20) - 1)) + { + subdivide (table, subtable, si->mr[i].start); + subtable += (1 << 8); + } + if ((si->mr[i].start + si->mr[i].size) & ((1 << 20) - 1)) + { + subdivide (table, subtable, si->mr[i].start + si->mr[i].size); + subtable += (1 << 8); + } + } + + for (i = 0; (signed) i < si->mr_no; i++) + if ((si->mr[i].flags & MR_ATTR_MASK) == MR_ATTR_DRAM + || (si->mr[i].flags & MR_ATTR_MASK) == MR_ATTR_SRAM + || (si->mr[i].flags & MR_ATTR_MASK) == MR_ATTR_FLASH) + { + grub_uint32_t cur, end; + cur = si->mr[i].start; + end = si->mr[i].start + si->mr[i].size; + while (cur < end) + { + grub_uint32_t *st; + if ((table[cur >> 20] & 3) == 2) + { + cur = cur >> 20 << 20; + table[cur >> 20] = cur | (3 << 10) | (1 << 3) | (1 << 2) | 2; + cur += (1 << 20); + continue; + } + cur = cur >> 12 << 12; + st = (grub_uint32_t *) (table[cur >> 20] & ~0x3ff); + st[(cur >> 12) & 0xff] = cur | (3 << 4) | (3 << 6) + | (3 << 8) | (3 << 10) + | (1 << 3) | (1 << 2) | 2; + cur += (1 << 12); + } + } + + grub_printf ("MMU tables generated\n"); + if (is_v6_mmu) + grub_arm_clear_mmu_v6 (); + + grub_printf ("enabling MMU\n"); + grub_arm_enable_mmu (table); + grub_printf ("MMU enabled\n"); +} + +#endif + +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ + grub_addr_t start = (grub_addr_t) address; + grub_addr_t end = start + len; + + if (type == ARCH_UNKNOWN) + probe_caches (); + start = ALIGN_DOWN (start, grub_arch_cache_max_linesz); + end = ALIGN_UP (end, grub_arch_cache_max_linesz); + switch (type) + { + case ARCH_ARMV6: + grub_arm_clean_dcache_range_armv6 (start, end, grub_arch_cache_dlinesz); + grub_arm_invalidate_icache_range_armv6 (start, end, + grub_arch_cache_ilinesz); + break; + case ARCH_ARMV7: + grub_arm_clean_dcache_range_armv7 (start, end, grub_arch_cache_dlinesz); + grub_arm_invalidate_icache_range_armv7 (start, end, + grub_arch_cache_ilinesz); + break; + /* Nothing to do. */ + case ARCH_ARMV5_WRITE_THROUGH: + case ARCH_ARMV6_UNIFIED: + break; + /* Pacify GCC. */ + case ARCH_UNKNOWN: + break; + } +} + +void +grub_arch_sync_dma_caches (volatile void *address, grub_size_t len) +{ + grub_addr_t start = (grub_addr_t) address; + grub_addr_t end = start + len; + + if (type == ARCH_UNKNOWN) + probe_caches (); + start = ALIGN_DOWN (start, grub_arch_cache_max_linesz); + end = ALIGN_UP (end, grub_arch_cache_max_linesz); + switch (type) + { + case ARCH_ARMV6: + grub_arm_clean_dcache_range_armv6 (start, end, grub_arch_cache_dlinesz); + grub_arm_invalidate_icache_range_armv6 (start, end, + grub_arch_cache_ilinesz); + break; + case ARCH_ARMV5_WRITE_THROUGH: + case ARCH_ARMV6_UNIFIED: + grub_arm_clean_dcache_range_armv6 (start, end, grub_arch_cache_dlinesz); + break; + case ARCH_ARMV7: + grub_arm_clean_dcache_range_poc_armv7 (start, end, grub_arch_cache_dlinesz); + grub_arm_invalidate_icache_range_armv7 (start, end, + grub_arch_cache_ilinesz); + break; + /* Pacify GCC. */ + case ARCH_UNKNOWN: + break; + } +} + +void +grub_arm_disable_caches_mmu (void) +{ + if (type == ARCH_UNKNOWN) + probe_caches (); + switch (type) + { + case ARCH_ARMV5_WRITE_THROUGH: + case ARCH_ARMV6_UNIFIED: + case ARCH_ARMV6: + grub_arm_disable_caches_mmu_armv6 (); + break; + case ARCH_ARMV7: + grub_arm_disable_caches_mmu_armv7 (); + break; + /* Pacify GCC. */ + case ARCH_UNKNOWN: + break; + } +} diff --git a/grub-core/kern/arm/cache_armv6.S b/grub-core/kern/arm/cache_armv6.S new file mode 100644 index 000000000..dfaded0eb --- /dev/null +++ b/grub-core/kern/arm/cache_armv6.S @@ -0,0 +1,72 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include + + .file "cache_armv6.S" + .text + .syntax unified + .arm + +# define DMB mcr p15, 0, r0, c7, c10, 5 +# define DSB mcr p15, 0, r0, c7, c10, 4 +# define ISB mcr p15, 0, r0, c7, c5, 4 +#define ARMV6 1 + +clean_invalidate_dcache: + mcr p15, 0, r0, c7, c14, 0 @ Clean/Invalidate D-cache + bx lr + +#include "cache.S" + +FUNCTION(grub_arm_main_id) + mrc p15, 0, r0, c0, c0, 0 + bx lr + +FUNCTION(grub_arm_cache_type) + mrc p15, 0, r0, c0, c0, 1 + bx lr + +FUNCTION(grub_arm_clear_mmu_v6) + mov r0, #0 + mcr p15, 0, r0, c2, c0, 2 + bx lr + +FUNCTION(grub_arm_enable_mmu) + mcr p15, 0, r0, c2, c0, 0 + + mvn r0, #0 + mcr p15, 0, r0, c3, c0, 0 + + mrc p15, 0, r0, c1, c0, 0 + bic r0, r0, #(1 << 23) + mcr p15, 0, r0, c1, c0, 0 + + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #(1 << 0) + mcr p15, 0, r0, c1, c0, 0 + + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #(1 << 2) + mcr p15, 0, r0, c1, c0, 0 + + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #(1 << 12) + mcr p15, 0, r0, c1, c0, 0 + + bx lr diff --git a/grub-core/kern/arm/cache_armv7.S b/grub-core/kern/arm/cache_armv7.S new file mode 100644 index 000000000..5ae76a3d8 --- /dev/null +++ b/grub-core/kern/arm/cache_armv7.S @@ -0,0 +1,138 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include + + .file "cache_armv7.S" + .text + .syntax unified +#if !defined (__thumb2__) + .arch armv7a + .arm +#else + .arch armv7 + .thumb +#endif +# define DMB dmb +# define DSB dsb +# define ISB isb +#define ARMV7 1 + +FUNCTION(grub_arm_clean_dcache_range_poc_armv7) + DSB + @ Clean data cache for range to point-of-coherence +1: cmp r0, r1 + bge 2f + mcr p15, 0, r0, c7, c14, 1 @ DCCMVAC + add r0, r0, r2 @ Next line + b 1b +2: DSB + bx lr + + + @ r0 - CLIDR + @ r1 - LoC + @ r2 - current level + @ r3 - num sets + @ r4 - num ways + @ r5 - current set + @ r6 - current way + @ r7 - line size + @ r8 - scratch + @ r9 - scratch + @ r10 - scratch + @ r11 - scratch +clean_invalidate_dcache: + push {r4-r12, lr} + mrc p15, 1, r0, c0, c0, 1 @ Read CLIDR + lsr r1, r0, #24 @ Extract LoC + and r1, r1, #0x7 + + mov r2, #0 @ First level, L1 +2: and r8, r0, #7 @ cache type at current level + cmp r8, #2 + blt 5f @ instruction only, or none, skip level + + @ set current cache level/type (for CCSIDR read) + lsl r8, r2, #1 + mcr p15, 2, r8, c0, c0, 0 @ Write CSSELR (level, type: data/uni) + + @ read current cache information + mrc p15, 1, r8, c0, c0, 0 @ Read CCSIDR + lsr r3, r8, #13 @ Number of sets -1 + + @ Keep only 14 bits of r3 + lsl r3, r3, #18 + lsr r3, r3, #18 + + lsr r4, r8, #3 @ Number of ways -1 + + @ Keep only 9 bits of r4 + lsl r4, r4, #23 + lsr r4, r4, #23 + + and r7, r8, #7 @ log2(line size in words) - 2 + add r7, r7, #2 @ adjust + mov r8, #1 + lsl r7, r8, r7 @ -> line size in words + lsl r7, r7, #2 @ -> bytes + + @ set loop + mov r5, #0 @ current set = 0 +3: lsl r8, r2, #1 @ insert level + clz r9, r7 @ calculate set field offset + mov r10, #31 + sub r9, r10, r9 + lsl r10, r5, r9 + orr r8, r8, r10 @ insert set field + + @ way loop + @ calculate way field offset + mov r6, #0 @ current way = 0 + add r10, r4, #1 + clz r9, r10 @ r9 = way field offset + add r9, r9, #1 +4: lsl r10, r6, r9 + orr r11, r8, r10 @ insert way field + + @ clean and invalidate line by set/way + mcr p15, 0, r11, c7, c14, 2 @ DCCISW + + @ next way + add r6, r6, #1 + cmp r6, r4 + ble 4b + + @ next set + add r5, r5, #1 + cmp r5, r3 + ble 3b + + @ next level +5: lsr r0, r0, #3 @ align next level CLIDR 'type' field + add r2, r2, #1 @ increment cache level counter + cmp r2, r1 + blt 2b @ outer loop + + @ return +6: DSB + ISB + pop {r4-r12, lr} + bx lr + +#include "cache.S" \ No newline at end of file diff --git a/grub-core/kern/arm/compiler-rt.S b/grub-core/kern/arm/compiler-rt.S new file mode 100644 index 000000000..645b42f50 --- /dev/null +++ b/grub-core/kern/arm/compiler-rt.S @@ -0,0 +1,86 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + + .file "misc.S" + .text + .syntax unified +#if !defined (__thumb2__) + .arm +#else + .thumb +#endif + + .align 2 + +FUNCTION(__muldi3) +FUNCTION(__aeabi_lmul) + stmfd sp!, {r4, fp} + add fp, sp, #4 + sub sp, sp, #16 + str r0, [fp, #-12] + str r1, [fp, #-8] + str r2, [fp, #-20] + str r3, [fp, #-16] + ldr r3, [fp, #-8] + ldr r2, [fp, #-20] + mul r2, r3, r2 + ldr r3, [fp, #-16] + ldr r1, [fp, #-12] + mul r3, r1, r3 + add r2, r2, r3 + ldr r0, [fp, #-12] + ldr r1, [fp, #-20] + umull r3, r4, r0, r1 + add r2, r2, r4 + mov r4, r2 + mov r0, r3 + mov r1, r4 + mov sp, fp + sub sp, sp, #4 + ldmfd sp!, {r4, fp} + bx lr + + .macro division32 parent + + sub sp, sp, #8 @ Allocate naturally aligned 64-bit space + stmfd sp!, {r3,lr} @ Dummy r3 to maintain stack alignment + add r2, sp, #8 @ Set r2 to address of 64-bit space + bl \parent + ldr r1, [sp, #8] @ Extract remainder + ldmfd sp!, {r3,lr} @ Pop into an unused arg/scratch register + add sp, sp, #8 + bx lr + .endm + +FUNCTION(__aeabi_uidivmod) + division32 grub_divmod32 +FUNCTION(__aeabi_idivmod) + division32 grub_divmod32s + +/* + * Null divide-by-zero handler + */ +FUNCTION(__aeabi_unwind_cpp_pr0) +FUNCTION(raise) + mov r0, #0 + bx lr + + END diff --git a/grub-core/kern/arm/coreboot/cbtable.c b/grub-core/kern/arm/coreboot/cbtable.c new file mode 100644 index 000000000..8a655bb5c --- /dev/null +++ b/grub-core/kern/arm/coreboot/cbtable.c @@ -0,0 +1,40 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#pragma GCC diagnostic ignored "-Wcast-align" + +grub_linuxbios_table_header_t +grub_linuxbios_get_tables (void) +{ + grub_linuxbios_table_header_t table_header + = (grub_linuxbios_table_header_t) grub_arm_saved_registers.r[0]; + + if (!grub_linuxbios_check_signature (table_header)) + return 0; + + return table_header; +} diff --git a/grub-core/kern/arm/coreboot/coreboot.S b/grub-core/kern/arm/coreboot/coreboot.S new file mode 100644 index 000000000..a1104526c --- /dev/null +++ b/grub-core/kern/arm/coreboot/coreboot.S @@ -0,0 +1,44 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2016 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include + + .file "coreboot.S" + .text + .syntax unified +#if !defined (__thumb2__) + .arch armv7a + .arm +#else + .arch armv7 + .thumb +#endif + +FUNCTION(grub_arm_pfr1) + mrc p15, 0, r0, c0, c1, 1 + bx lr + +FUNCTION(grub_armv7_get_timer_value) + isb + mrrc p15, 1, r0, r1, c14 + bx lr + +FUNCTION(grub_armv7_get_timer_frequency) + mrc p15, 0, r0, c14, c0, 0 + bx lr + diff --git a/grub-core/kern/arm/coreboot/dma.c b/grub-core/kern/arm/coreboot/dma.c new file mode 100644 index 000000000..2c2a62789 --- /dev/null +++ b/grub-core/kern/arm/coreboot/dma.c @@ -0,0 +1,59 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +struct grub_pci_dma_chunk * +grub_memalign_dma32 (grub_size_t align, grub_size_t size) +{ + void *ret; + if (align < 64) + align = 64; + size = ALIGN_UP (size, align); + ret = grub_memalign (align, size); + if (!ret) + return 0; + grub_arch_sync_dma_caches (ret, size); + return ret; +} + +void +grub_dma_free (struct grub_pci_dma_chunk *ch) +{ + grub_size_t size = (((struct grub_mm_header *) ch) - 1)->size * GRUB_MM_ALIGN; + grub_arch_sync_dma_caches (ch, size); + grub_free (ch); +} + +volatile void * +grub_dma_get_virt (struct grub_pci_dma_chunk *ch) +{ + return (void *) ch; +} + +grub_uint32_t +grub_dma_get_phys (struct grub_pci_dma_chunk *ch) +{ + return (grub_uint32_t) (grub_addr_t) ch; +} + diff --git a/grub-core/kern/arm/coreboot/init.c b/grub-core/kern/arm/coreboot/init.c new file mode 100644 index 000000000..8d8c5b829 --- /dev/null +++ b/grub-core/kern/arm/coreboot/init.c @@ -0,0 +1,151 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern grub_uint8_t _start[]; +extern grub_uint8_t _end[]; +extern grub_uint8_t _edata[]; +grub_addr_t start_of_ram = ~(grub_addr_t)0; + +void __attribute__ ((noreturn)) +grub_exit (void) +{ + /* We can't use grub_fatal() in this function. This would create an infinite + loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */ + while (1) + grub_cpu_idle (); +} + +static grub_uint64_t modend; +static int have_memory = 0; + +/* Helper for grub_machine_init. */ +static int +heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + void *data __attribute__ ((unused))) +{ + grub_uint64_t begin = addr, end = addr + size; + +#if GRUB_CPU_SIZEOF_VOID_P == 4 + /* Restrict ourselves to 32-bit memory space. */ + if (begin > GRUB_ULONG_MAX) + return 0; + if (end > GRUB_ULONG_MAX) + end = GRUB_ULONG_MAX; +#endif + + if (start_of_ram > begin) + start_of_ram = begin; + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + if (modend && begin < modend) + { + if (begin < (grub_addr_t)_start) + { + grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) ((grub_addr_t)_start - begin)); + have_memory = 1; + } + begin = modend; + } + + /* Avoid DMA problems. */ + if (end >= 0xfe000000) + end = 0xfe000000; + + if (end <= begin) + return 0; + + grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin)); + + have_memory = 1; + + return 0; +} + +void +grub_machine_init (void) +{ + struct grub_module_header *header; + void *dtb = 0; + grub_size_t dtb_size = 0; + + modend = grub_modules_get_end (); + + grub_video_coreboot_fb_early_init (); + + grub_machine_mmap_iterate (heap_init, NULL); + if (!have_memory) + grub_fatal ("No memory found"); + + grub_video_coreboot_fb_late_init (); + + grub_font_init (); + grub_gfxterm_init (); + + FOR_MODULES (header) + if (header->type == OBJ_TYPE_DTB) + { + char *dtb_orig_addr, *dtb_copy; + dtb_orig_addr = (char *) header + sizeof (struct grub_module_header); + + dtb_size = header->size - sizeof (struct grub_module_header); + dtb = dtb_copy = grub_malloc (dtb_size); + grub_memmove (dtb_copy, dtb_orig_addr, dtb_size); + break; + } + if (!dtb) + grub_fatal ("No DTB found"); + grub_fdtbus_init (dtb, dtb_size); + + grub_rk3288_spi_init (); + + grub_machine_timer_init (); + grub_cros_init (); + grub_pl050_init (); +} + +void +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) +{ +} + +void +grub_machine_fini (int flags __attribute__ ((unused))) +{ +} diff --git a/grub-core/kern/arm/coreboot/timer.c b/grub-core/kern/arm/coreboot/timer.c new file mode 100644 index 000000000..d97b844f8 --- /dev/null +++ b/grub-core/kern/arm/coreboot/timer.c @@ -0,0 +1,101 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2016 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +grub_uint64_t +grub_armv7_get_timer_value(void); + +grub_uint32_t +grub_armv7_get_timer_frequency(void); + +grub_uint32_t +grub_arm_pfr1(void); + +static int have_timer = 0; +static volatile grub_uint32_t *sp804_regs; + +static grub_uint64_t +sp804_get_time_ms (void) +{ + static grub_uint32_t high, last_low; + grub_uint32_t low = ~sp804_regs[1]; + if (last_low > low) + high++; + last_low = low; + return grub_divmod64 ((((grub_uint64_t) high) << 32) | low, + 1000, 0); +} + +static grub_err_t +sp804_attach(const struct grub_fdtbus_dev *dev) +{ + if (have_timer) + return GRUB_ERR_NONE; + sp804_regs = grub_fdtbus_map_reg (dev, 0, 0); + if (!grub_fdtbus_is_mapping_valid (sp804_regs)) + return grub_error (GRUB_ERR_IO, "could not map sp804: %p", sp804_regs); + grub_install_get_time_ms (sp804_get_time_ms); + have_timer = 1; + return GRUB_ERR_NONE; +} + +struct grub_fdtbus_driver sp804 = +{ + .compatible = "arm,sp804", + .attach = sp804_attach +}; + +static grub_uint32_t timer_frequency_in_khz; + +static grub_uint64_t +generic_get_time_ms (void) +{ + return grub_divmod64 (grub_armv7_get_timer_value(), timer_frequency_in_khz, 0); +} + +static int +try_generic_timer (void) +{ + if (((grub_arm_pfr1 () >> 16) & 0xf) != 1) + return 0; + grub_printf ("freq = %x\n", grub_armv7_get_timer_frequency()); + timer_frequency_in_khz = 0x016e3600 / 1000; //grub_armv7_get_timer_frequency() / 1000; + if (timer_frequency_in_khz == 0) + return 0; + grub_install_get_time_ms (generic_get_time_ms); + have_timer = 1; + return 1; +} + +void +grub_machine_timer_init (void) +{ + grub_fdtbus_register (&sp804); + + if (!have_timer) + try_generic_timer (); + if (!have_timer) + grub_fatal ("No timer found"); +} diff --git a/grub-core/kern/arm/dl.c b/grub-core/kern/arm/dl.c new file mode 100644 index 000000000..eab9d17ff --- /dev/null +++ b/grub-core/kern/arm/dl.c @@ -0,0 +1,280 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +struct trampoline_arm +{ +#define ARM_LOAD_IP 0xe59fc000 +#define ARM_BX 0xe12fff1c +#define ARM_MOV_PC 0xe1a0f00c + grub_uint32_t load_ip; /* ldr ip, [pc] */ + grub_uint32_t bx; /* bx ip or mov pc, ip*/ + grub_uint32_t addr; +}; + +static grub_uint16_t thumb_template[8] = + { + 0x468c, /* mov ip, r1 */ + 0x4903, /* ldr r1, [pc, #12] ; (10 <.text+0x10>) */ + /* Exchange R1 and IP in limited Thumb instruction set. + IP gets negated but we compensate it by C code. */ + /* R1 IP */ + /* -A R1 */ + 0x4461, /* add r1, ip */ /* R1-A R1 */ + 0x4249, /* negs r1, r1 */ /* A-R1 R1 */ + 0x448c, /* add ip, r1 */ /* A-R1 A */ + 0x4249, /* negs r1, r1 */ /* R1-A A */ + 0x4461, /* add r1, ip */ /* R1 A */ + 0x4760 /* bx ip */ + }; + +struct trampoline_thumb +{ + grub_uint16_t template[8]; + grub_uint32_t neg_addr; +}; + +#pragma GCC diagnostic ignored "-Wcast-align" + +grub_err_t +grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got) +{ + const Elf_Ehdr *e = ehdr; + const Elf_Shdr *s; + unsigned i; + + *tramp = 0; + *got = 0; + + for (i = 0, s = (const Elf_Shdr *) ((grub_addr_t) e + e->e_shoff); + i < e->e_shnum; + i++, s = (const Elf_Shdr *) ((grub_addr_t) s + e->e_shentsize)) + if (s->sh_type == SHT_REL) + { + const Elf_Rel *rel, *max; + + for (rel = (const Elf_Rel *) ((grub_addr_t) e + s->sh_offset), + max = (const Elf_Rel *) ((grub_addr_t) rel + s->sh_size); + rel + 1 <= max; + rel = (const Elf_Rel *) ((grub_addr_t) rel + s->sh_entsize)) + switch (ELF_R_TYPE (rel->r_info)) + { + case R_ARM_CALL: + case R_ARM_JUMP24: + { + *tramp += sizeof (struct trampoline_arm); + break; + } + case R_ARM_THM_CALL: + case R_ARM_THM_JUMP24: + case R_ARM_THM_JUMP19: + { + *tramp += sizeof (struct trampoline_thumb); + break; + } + } + } + + grub_dprintf ("dl", "trampoline size %x\n", *tramp); + + return GRUB_ERR_NONE; +} + +/************************************************* + * Runtime dynamic linker with helper functions. * + *************************************************/ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg) +{ + Elf_Rel *rel, *max; + + for (rel = (Elf_Rel *) ((char *) ehdr + s->sh_offset), + max = (Elf_Rel *) ((char *) rel + s->sh_size); + rel < max; + rel = (Elf_Rel *) ((char *) rel + s->sh_entsize)) + { + Elf_Addr *target, sym_addr; + grub_err_t retval; + Elf_Sym *sym; + + if (seg->size < rel->r_offset) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + target = (void *) ((char *) seg->addr + rel->r_offset); + sym = (Elf_Sym *) ((char *) mod->symtab + + mod->symsize * ELF_R_SYM (rel->r_info)); + + sym_addr = sym->st_value; + + switch (ELF_R_TYPE (rel->r_info)) + { + case R_ARM_ABS32: + { + /* Data will be naturally aligned */ + retval = grub_arm_reloc_abs32 (target, sym_addr); + if (retval != GRUB_ERR_NONE) + return retval; + } + break; + case R_ARM_CALL: + case R_ARM_JUMP24: + { + grub_int32_t offset; + + sym_addr += grub_arm_jump24_get_offset (target); + offset = sym_addr - (grub_uint32_t) target; + + if ((sym_addr & 1) || !grub_arm_jump24_check_offset (offset)) + { + struct trampoline_arm *tp = mod->trampptr; + mod->trampptr = tp + 1; + tp->load_ip = ARM_LOAD_IP; + tp->bx = (sym_addr & 1) ? ARM_BX : ARM_MOV_PC; + tp->addr = sym_addr + 8; + offset = (grub_uint8_t *) tp - (grub_uint8_t *) target - 8; + } + if (!grub_arm_jump24_check_offset (offset)) + return grub_error (GRUB_ERR_BAD_MODULE, + "trampoline out of range"); + grub_arm_jump24_set_offset (target, offset); + } + break; + case R_ARM_THM_CALL: + case R_ARM_THM_JUMP24: + { + /* Thumb instructions can be 16-bit aligned */ + grub_int32_t offset; + + sym_addr += grub_arm_thm_call_get_offset ((grub_uint16_t *) target); + + grub_dprintf ("dl", " sym_addr = 0x%08x\n", sym_addr); + if (ELF_ST_TYPE (sym->st_info) != STT_FUNC) + sym_addr |= 1; + + offset = sym_addr - (grub_uint32_t) target; + + grub_dprintf("dl", " BL*: target=%p, sym_addr=0x%08x, offset=%d\n", + target, sym_addr, offset); + + if (!(sym_addr & 1) || (offset < -0x200000 || offset >= 0x200000)) + { + struct trampoline_thumb *tp = mod->trampptr; + mod->trampptr = tp + 1; + grub_memcpy (tp->template, thumb_template, sizeof (tp->template)); + tp->neg_addr = -sym_addr - 4; + offset = ((grub_uint8_t *) tp - (grub_uint8_t *) target - 4) | 1; + } + + if (offset < -0x200000 || offset >= 0x200000) + return grub_error (GRUB_ERR_BAD_MODULE, + "trampoline out of range"); + + grub_dprintf ("dl", " relative destination = %p\n", + (char *) target + offset); + + retval = grub_arm_thm_call_set_offset ((grub_uint16_t *) target, offset); + if (retval != GRUB_ERR_NONE) + return retval; + } + break; + /* Happens when compiled with -march=armv4. Since currently we need + at least armv5, keep bx as-is. + */ + case R_ARM_V4BX: + break; + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: + { + grub_uint32_t offset; + offset = grub_arm_thm_movw_movt_get_value((grub_uint16_t *) target); + offset += sym_addr; + + if (ELF_R_TYPE (rel->r_info) == R_ARM_THM_MOVT_ABS) + offset >>= 16; + else + offset &= 0xffff; + + grub_arm_thm_movw_movt_set_value((grub_uint16_t *) target, offset); + } + break; + case R_ARM_THM_JUMP19: + { + /* Thumb instructions can be 16-bit aligned */ + grub_int32_t offset; + + sym_addr += grub_arm_thm_jump19_get_offset ((grub_uint16_t *) target); + + if (ELF_ST_TYPE (sym->st_info) != STT_FUNC) + sym_addr |= 1; + + offset = sym_addr - (grub_uint32_t) target; + + if (!grub_arm_thm_jump19_check_offset (offset) + || !(sym_addr & 1)) + { + struct trampoline_thumb *tp = mod->trampptr; + mod->trampptr = tp + 1; + grub_memcpy (tp->template, thumb_template, sizeof (tp->template)); + tp->neg_addr = -sym_addr - 4; + offset = ((grub_uint8_t *) tp - (grub_uint8_t *) target - 4) | 1; + } + + if (!grub_arm_thm_jump19_check_offset (offset)) + return grub_error (GRUB_ERR_BAD_MODULE, + "trampoline out of range"); + + grub_arm_thm_jump19_set_offset ((grub_uint16_t *) target, offset); + } + break; + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%x is not implemented yet"), + ELF_R_TYPE (rel->r_info)); + } + } + + return GRUB_ERR_NONE; +} + + +/* + * Check if EHDR is a valid ELF header. + */ +grub_err_t +grub_arch_dl_check_header (void *ehdr) +{ + Elf_Ehdr *e = ehdr; + + /* Check the magic numbers. */ + if (e->e_ident[EI_CLASS] != ELFCLASS32 + || e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_ARM) + return grub_error (GRUB_ERR_BAD_OS, + N_("invalid arch-dependent ELF magic")); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/arm/dl_helper.c b/grub-core/kern/arm/dl_helper.c new file mode 100644 index 000000000..21d77f763 --- /dev/null +++ b/grub-core/kern/arm/dl_helper.c @@ -0,0 +1,245 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +static inline grub_uint32_t +thumb_get_instruction_word (grub_uint16_t *target) +{ + /* Extract instruction word in alignment-safe manner */ + return grub_le_to_cpu16 ((*target)) << 16 | grub_le_to_cpu16 (*(target + 1)); +} + +static inline void +thumb_set_instruction_word (grub_uint16_t *target, grub_uint32_t insword) +{ + *target = grub_cpu_to_le16 (insword >> 16); + *(target + 1) = grub_cpu_to_le16 (insword & 0xffff); +} + +/* + * R_ARM_ABS32 + * + * Simple relocation of 32-bit value (in literal pool) + */ +grub_err_t +grub_arm_reloc_abs32 (Elf32_Word *target, Elf32_Addr sym_addr) +{ + Elf32_Addr tmp; + + tmp = grub_le_to_cpu32 (*target); + tmp += sym_addr; + *target = grub_cpu_to_le32 (tmp); + + return GRUB_ERR_NONE; +} + +/******************************************************************** + * Thumb (T32) relocations: * + * * + * 32-bit Thumb instructions can be 16-bit aligned, and are fetched * + * little-endian, requiring some additional fiddling. * + ********************************************************************/ + +grub_int32_t +grub_arm_thm_call_get_offset (grub_uint16_t *target) +{ + grub_uint32_t sign, j1, j2; + grub_uint32_t insword; + grub_int32_t offset; + + insword = thumb_get_instruction_word (target); + + /* Extract bitfields from instruction words */ + sign = (insword >> 26) & 1; + j1 = (insword >> 13) & 1; + j2 = (insword >> 11) & 1; + offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) | + ((~(j2 ^ sign) & 1) << 22) | + ((insword & 0x03ff0000) >> 4) | ((insword & 0x000007ff) << 1); + + /* Sign adjust and calculate offset */ + if (offset & (1 << 24)) + offset -= (1 << 25); + + return offset; +} + +grub_err_t +grub_arm_thm_call_set_offset (grub_uint16_t *target, grub_int32_t offset) +{ + grub_uint32_t sign, j1, j2; + const grub_uint32_t insmask = 0xf800d000; + grub_uint32_t insword; + int is_blx; + + insword = thumb_get_instruction_word (target); + + if (((insword >> 12) & 0xd) == 0xc) + is_blx = 1; + else + is_blx = 0; + + if (!is_blx && !(offset & 1)) + return grub_error (GRUB_ERR_BAD_MODULE, "bl/b.w targettting ARM"); + + /* Transform blx into bl if necessarry. */ + if (is_blx && (offset & 1)) + insword |= (1 << 12); + + /* Reassemble instruction word */ + sign = (offset >> 24) & 1; + j1 = sign ^ (~(offset >> 23) & 1); + j2 = sign ^ (~(offset >> 22) & 1); + insword = (insword & insmask) | + (sign << 26) | + (((offset >> 12) & 0x03ff) << 16) | + (j1 << 13) | (j2 << 11) | ((offset >> 1) & 0x07ff); + + thumb_set_instruction_word (target, insword); + + grub_dprintf ("dl", " *insword = 0x%08x", insword); + + return GRUB_ERR_NONE; +} + +grub_int32_t +grub_arm_thm_jump19_get_offset (grub_uint16_t *target) +{ + grub_int32_t offset; + grub_uint32_t insword; + + insword = thumb_get_instruction_word (target); + + /* Extract and sign extend offset */ + offset = ((insword >> 26) & 1) << 19 + | ((insword >> 11) & 1) << 18 + | ((insword >> 13) & 1) << 17 + | ((insword >> 16) & 0x3f) << 11 + | (insword & 0x7ff); + offset <<= 1; + if (offset & (1 << 20)) + offset -= (1 << 21); + + return offset; +} + +void +grub_arm_thm_jump19_set_offset (grub_uint16_t *target, grub_int32_t offset) +{ + grub_uint32_t insword; + const grub_uint32_t insmask = 0xfbc0d000; + + offset >>= 1; + offset &= 0xfffff; + + insword = thumb_get_instruction_word (target); + + /* Reassemble instruction word and write back */ + insword &= insmask; + insword |= ((offset >> 19) & 1) << 26 + | ((offset >> 18) & 1) << 11 + | ((offset >> 17) & 1) << 13 + | ((offset >> 11) & 0x3f) << 16 + | (offset & 0x7ff); + thumb_set_instruction_word (target, insword); +} + +int +grub_arm_thm_jump19_check_offset (grub_int32_t offset) +{ + if ((offset > 1048574) || (offset < -1048576)) + return 0; + return 1; +} + +grub_uint16_t +grub_arm_thm_movw_movt_get_value (grub_uint16_t *target) +{ + grub_uint32_t insword; + + insword = thumb_get_instruction_word (target); + + return ((insword & 0xf0000) >> 4) | ((insword & 0x04000000) >> 15) | \ + ((insword & 0x7000) >> 4) | (insword & 0xff); +} + +void +grub_arm_thm_movw_movt_set_value (grub_uint16_t *target, grub_uint16_t value) +{ + grub_uint32_t insword; + const grub_uint32_t insmask = 0xfbf08f00; + + insword = thumb_get_instruction_word (target); + insword &= insmask; + + insword |= ((value & 0xf000) << 4) | ((value & 0x0800) << 15) | \ + ((value & 0x0700) << 4) | (value & 0xff); + + thumb_set_instruction_word (target, insword); +} + + +/*********************************************************** + * ARM (A32) relocations: * + * * + * ARM instructions are 32-bit in size and 32-bit aligned. * + ***********************************************************/ + +grub_int32_t +grub_arm_jump24_get_offset (grub_uint32_t *target) +{ + grub_int32_t offset; + grub_uint32_t insword; + + insword = grub_le_to_cpu32 (*target); + + offset = (insword & 0x00ffffff) << 2; + if (offset & 0x02000000) + offset -= 0x04000000; + return offset; +} + +int +grub_arm_jump24_check_offset (grub_int32_t offset) +{ + if (offset >= 0x02000000 || offset < -0x02000000) + return 0; + return 1; +} + +void +grub_arm_jump24_set_offset (grub_uint32_t *target, + grub_int32_t offset) +{ + grub_uint32_t insword; + + insword = grub_le_to_cpu32 (*target); + + insword &= 0xff000000; + insword |= (offset >> 2) & 0x00ffffff; + + *target = grub_cpu_to_le32 (insword); +} diff --git a/grub-core/kern/arm/efi/init.c b/grub-core/kern/arm/efi/init.c new file mode 100644 index 000000000..809f69c8c --- /dev/null +++ b/grub-core/kern/arm/efi/init.c @@ -0,0 +1,77 @@ +/* init.c - initialize an arm-based EFI system */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +static grub_uint64_t tmr; +static grub_efi_event_t tmr_evt; + +static grub_uint64_t +grub_efi_get_time_ms (void) +{ + return tmr; +} + +static void __grub_efi_api +increment_timer (grub_efi_event_t event __attribute__ ((unused)), + void *context __attribute__ ((unused))) +{ + tmr += 10; +} + +void +grub_machine_init (void) +{ + grub_efi_boot_services_t *b; + + grub_efi_init (); + + b = grub_efi_system_table->boot_services; + + b->create_event (GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL, + GRUB_EFI_TPL_CALLBACK, increment_timer, NULL, &tmr_evt); + b->set_timer (tmr_evt, GRUB_EFI_TIMER_PERIODIC, 100000); + + grub_install_get_time_ms (grub_efi_get_time_ms); +} + +void +grub_machine_fini (int flags) +{ + grub_efi_boot_services_t *b; + + if (!(flags & GRUB_LOADER_FLAG_NORETURN)) + return; + + b = grub_efi_system_table->boot_services; + + b->set_timer (tmr_evt, GRUB_EFI_TIMER_CANCEL, 0); + b->close_event (tmr_evt); + + grub_efi_fini (); + + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY)) + grub_efi_memory_fini (); +} diff --git a/grub-core/kern/arm/efi/startup.S b/grub-core/kern/arm/efi/startup.S new file mode 100644 index 000000000..9f8265315 --- /dev/null +++ b/grub-core/kern/arm/efi/startup.S @@ -0,0 +1,36 @@ +/* + * (C) Copyright 2013 Free Software Foundation + * + * 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 + + .file "startup.S" + .text + .arm +FUNCTION(_start) + /* + * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in r1/r0. + */ + ldr ip, =EXT_C(grub_efi_image_handle) + str r0, [ip] + ldr ip, =EXT_C(grub_efi_system_table) + str r1, [ip] + ldr ip, =EXT_C(grub_main) + bx ip + END diff --git a/grub-core/kern/arm/startup.S b/grub-core/kern/arm/startup.S new file mode 100644 index 000000000..3946fe8e1 --- /dev/null +++ b/grub-core/kern/arm/startup.S @@ -0,0 +1,177 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include + +/* + * GRUB is called from U-Boot as a Linux Kernel type image, which + * means among other things that it always enters in ARM state. + * + * coreboot starts in ARM mode as well. + * + * Overview of GRUB image layout: + * + * _start: + * Entry point (1 ARM branch instruction, to "codestart") + * grub_total_module_size: + * Data field: Size of included module blob + * (when generated by grub-mkimage) + * codestart: + * Remainder of statically-linked executable code and data. + * __bss_start: + * Start of included module blob. + * Also where global/static variables are located. + * _end: + * End of bss region (but not necessarily module blob). + * : + * : + * Loadable modules, post relocation. + * : + */ + + .text + .arm +FUNCTION(_start) + b codestart + + @ Size of final image integrated module blob - set by grub-mkimage + .org _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE +VARIABLE(grub_total_module_size) + .long 0 + +VARIABLE(grub_modbase) + .long 0 +bss_start_ptr: + .long EXT_C(__bss_start) +end_ptr: + .long EXT_C(_end) + + @ Memory map at start: + @ * text+data + @ * list relocations + @ * modules + @ Before we enter C, we need to apply the relocations + @ and get following map: + @ * text+data + @ * BSS (cleared) + @ * stack + @ * modules + @ + @ To make things easier we ensure + @ that BSS+stack is larger than list of relocations + @ by increasing stack if necessarry. + @ This allows us to always unconditionally copy backwards + @ Currently list of relocations is ~5K and stack is set + @ to be at least 256K + +FUNCTION(codestart) + @ Store context: Machine ID, atags/dtb, ... + @ U-Boot API signature is stored on the U-Boot heap + @ Stack pointer used as start address for signature probing + mov r12, sp + adr sp, entry_state + push {r0-r12,lr} @ store U-Boot context (sp in r12) + + adr r1, _start + ldr r0, bss_start_ptr @ src + add r0, r0, r1 + + add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) + mvn r2, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) + and r0, r0, r2 +1: + ldr r3, [r0], #4 @load next offset + @ both -2 and -1 are treated the same as we have only one type of relocs + @ -2 means "end of this type of relocs" and -1 means "end of all relocs" + add r2, r3, #2 + cmp r2, #1 + bls reloc_done + @ Adjust next offset + ldr r2, [r3, r1] + add r2, r2, r1 + str r2, [r3, r1] + b 1b + +reloc_done: + + @ Modules have been stored as a blob + @ they need to be manually relocated to _end + add r0, r0, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) + mvn r1, #(GRUB_KERNEL_MACHINE_MOD_ALIGN - 1) + and r0, r0, r1 @ src = aligned end of relocations + + ldr r1, end_ptr @ dst = End of BSS + ldr r2, grub_total_module_size @ blob size + + add r1, r1, #GRUB_KERNEL_MACHINE_STACK_SIZE + and r1, r1, #~0x7 @ Ensure 8-byte alignment + + sub sp, r1, #8 + add r1, r1, #1024 + + str r1, EXT_C(grub_modbase) + + /* Coreboot already places modules at right place. */ +#ifndef GRUB_MACHINE_COREBOOT + add r1, r1, r2 + add r0, r0, r2 + sub r1, r1, #4 + sub r0, r0, #4 + +1: ldr r3, [r0], #-4 @ r3 = *src-- + str r3, [r1], #-4 @ *dst-- = r3 + subs r2, #4 @ remaining -= 4 + bne 1b @ while remaining != 0 +#endif + + @ Since we _are_ the C run-time, we need to manually zero the BSS + @ region before continuing + ldr r0, bss_start_ptr @ zero from here + @ If unaligned, bytewise zero until base address aligned. + mov r2, #0 +1: tst r0, #3 + beq 2f + strb r2, [r0], #1 + b 1b +2: ldr r1, end_ptr @ to here +1: str r2, [r0], #4 + cmp r0, r1 + bne 1b + + b EXT_C(grub_main) + + .align 3 +@ U-boot/coreboot context stack space +VARIABLE(grub_arm_saved_registers) + .long 0 @ r0 + .long 0 @ r1 + .long 0 @ r2 + .long 0 @ r3 + .long 0 @ r4 + .long 0 @ r5 + .long 0 @ r6 + .long 0 @ r7 + .long 0 @ r8 + .long 0 @ r9 + .long 0 @ r10 + .long 0 @ r11 + .long 0 @ sp + .long 0 @ lr +entry_state: diff --git a/grub-core/kern/arm/uboot/init.c b/grub-core/kern/arm/uboot/init.c new file mode 100644 index 000000000..2a6aa3fdd --- /dev/null +++ b/grub-core/kern/arm/uboot/init.c @@ -0,0 +1,70 @@ +/* init.c - generic U-Boot initialization and finalization */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2016 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include + +extern int (*grub_uboot_syscall_ptr) (int, int *, ...); + +grub_uint32_t +grub_uboot_get_machine_type (void) +{ + return grub_arm_saved_registers.r[1]; +} + +grub_addr_t +grub_uboot_get_boot_data (void) +{ + return grub_arm_saved_registers.r[2]; +} + +int +grub_uboot_api_init (void) +{ + struct api_signature *start, *end; + struct api_signature *p; + grub_addr_t grub_uboot_search_hint = grub_arm_saved_registers.sp; + if (grub_uboot_search_hint) + { + /* Extended search range to work around Trim Slice U-Boot issue */ + start = (struct api_signature *) ((grub_uboot_search_hint & ~0x000fffff) + - 0x00500000); + end = + (struct api_signature *) ((grub_addr_t) start + UBOOT_API_SEARCH_LEN - + API_SIG_MAGLEN + 0x00500000); + } + else + { + start = 0; + end = (struct api_signature *) (256 * 1024 * 1024); + } + + /* Structure alignment is (at least) 8 bytes */ + for (p = start; p < end; p = (void *) ((grub_addr_t) p + 8)) + { + if (grub_memcmp (&(p->magic), API_SIG_MAGIC, API_SIG_MAGLEN) == 0) + { + grub_uboot_syscall_ptr = p->syscall; + return p->version; + } + } + + return 0; +} diff --git a/grub-core/kern/arm/uboot/uboot.S b/grub-core/kern/arm/uboot/uboot.S new file mode 100644 index 000000000..d128775f1 --- /dev/null +++ b/grub-core/kern/arm/uboot/uboot.S @@ -0,0 +1,73 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include + + /* + * uboot_syscall(): + * This function is effectively a veneer, so it cannot + * modify the stack or corrupt any registers other than + * r12 (ip). Furthermore it needs to restore r8 for + * U-Boot (Global Data Pointer) and preserve it for Grub. + */ +FUNCTION(grub_uboot_syscall) + str r8, transition_space + str lr, transition_space + 4 + str r9, transition_space + 8 + + ldr ip, saved_registers_ptr + ldr r8, [ip, #4 * 8] + ldr r9, [ip, #4 * 9] + + bl do_syscall + + ldr r8, transition_space + ldr lr, transition_space + 4 + ldr r9, transition_space + 8 + + bx lr +do_syscall: + + ldr ip, grub_uboot_syscall_ptr + bx ip + +FUNCTION(grub_uboot_return) + ldr ip, saved_registers_ptr + ldr sp, [ip, #4 * 4] + pop {r4-r12, lr} + mov sp, r12 + bx lr + + + .align 3 + +@ GRUB context stack space +transition_space: + .long 0 @ r8 + .long 0 @ lr + .long 0 @ r9 + +saved_registers_ptr: + .long EXT_C(grub_arm_saved_registers) + +VARIABLE(grub_uboot_syscall_ptr) + .long 0 @ + + END diff --git a/grub-core/kern/arm64/cache.c b/grub-core/kern/arm64/cache.c new file mode 100644 index 000000000..b84383da1 --- /dev/null +++ b/grub-core/kern/arm64/cache.c @@ -0,0 +1,63 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +static grub_int64_t dlinesz; +static grub_int64_t ilinesz; + +/* Prototypes for asm functions. */ +void grub_arch_clean_dcache_range (grub_addr_t beg, grub_addr_t end, + grub_uint64_t line_size); +void grub_arch_invalidate_icache_range (grub_addr_t beg, grub_addr_t end, + grub_uint64_t line_size); + +static void +probe_caches (void) +{ + grub_uint64_t cache_type; + + /* Read Cache Type Register */ + asm volatile ("mrs %0, ctr_el0": "=r"(cache_type)); + + dlinesz = 4 << ((cache_type >> 16) & 0xf); + ilinesz = 4 << (cache_type & 0xf); + + grub_dprintf("cache", "D$ line size: %lld\n", (long long) dlinesz); + grub_dprintf("cache", "I$ line size: %lld\n", (long long) ilinesz); +} + +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ + grub_uint64_t start, end, max_align; + + if (dlinesz == 0) + probe_caches(); + if (dlinesz == 0) + grub_fatal ("Unknown cache line size!"); + + max_align = dlinesz > ilinesz ? dlinesz : ilinesz; + + start = ALIGN_DOWN ((grub_uint64_t) address, max_align); + end = ALIGN_UP ((grub_uint64_t) address + len, max_align); + + grub_arch_clean_dcache_range (start, end, dlinesz); + grub_arch_invalidate_icache_range (start, end, ilinesz); +} diff --git a/grub-core/kern/arm64/cache_flush.S b/grub-core/kern/arm64/cache_flush.S new file mode 100644 index 000000000..e064f7ece --- /dev/null +++ b/grub-core/kern/arm64/cache_flush.S @@ -0,0 +1,55 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include + + .file "cache_flush.S" + .text + +/* + * Simple cache maintenance functions + */ + +// x0 - *beg (inclusive) +// x1 - *end (exclusive) +// x2 - line size +FUNCTION(grub_arch_clean_dcache_range) + // Clean data cache for range to point-of-unification +1: cmp x0, x1 + b.ge 2f + dc cvau, x0 // Clean Virtual Address to PoU + add x0, x0, x2 // Next line + b 1b +2: dsb ish + isb + ret + +// x0 - *beg (inclusive) +// x1 - *end (exclusive) +// x2 - line size +FUNCTION(grub_arch_invalidate_icache_range) + // Invalidate instruction cache for range to point-of-unification +1: cmp x0, x1 + b.ge 2f + ic ivau, x0 // Invalidate Virtual Address to PoU + add x0, x0, x2 // Next line + b 1b + // Branch predictor invalidation not needed on AArch64 +2: dsb ish + isb + ret diff --git a/grub-core/kern/arm64/dl.c b/grub-core/kern/arm64/dl.c new file mode 100644 index 000000000..a2b5789a9 --- /dev/null +++ b/grub-core/kern/arm64/dl.c @@ -0,0 +1,198 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#define LDR 0x58000050 +#define BR 0xd61f0200 + + +/* + * Check if EHDR is a valid ELF header. + */ +grub_err_t +grub_arch_dl_check_header (void *ehdr) +{ + Elf_Ehdr *e = ehdr; + + /* Check the magic numbers. */ + if (e->e_ident[EI_CLASS] != ELFCLASS64 + || e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_AARCH64) + return grub_error (GRUB_ERR_BAD_OS, + N_("invalid arch-dependent ELF magic")); + + return GRUB_ERR_NONE; +} + +#pragma GCC diagnostic ignored "-Wcast-align" + +/* + * Unified function for both REL and RELA + */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg) +{ + Elf_Rel *rel, *max; + unsigned unmatched_adr_got_page = 0; + + for (rel = (Elf_Rel *) ((char *) ehdr + s->sh_offset), + max = (Elf_Rel *) ((char *) rel + s->sh_size); + rel < max; + rel = (Elf_Rel *) ((char *) rel + s->sh_entsize)) + { + Elf_Sym *sym; + void *place; + grub_uint64_t sym_addr; + + if (rel->r_offset >= seg->size) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + + sym = (Elf_Sym *) ((char *) mod->symtab + + mod->symsize * ELF_R_SYM (rel->r_info)); + + sym_addr = sym->st_value; + if (s->sh_type == SHT_RELA) + sym_addr += ((Elf_Rela *) rel)->r_addend; + + place = (void *) ((grub_addr_t) seg->addr + rel->r_offset); + + switch (ELF_R_TYPE (rel->r_info)) + { + case R_AARCH64_ABS64: + { + grub_uint64_t *abs_place = place; + + grub_dprintf ("dl", " reloc_abs64 %p => 0x%016llx\n", + place, (unsigned long long) sym_addr); + + *abs_place = (grub_uint64_t) sym_addr; + } + break; + case R_AARCH64_ADD_ABS_LO12_NC: + grub_arm64_set_abs_lo12 (place, sym_addr); + break; + case R_AARCH64_LDST64_ABS_LO12_NC: + grub_arm64_set_abs_lo12_ldst64 (place, sym_addr); + break; + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + { + grub_int64_t offset = sym_addr - (grub_uint64_t) place; + + if (!grub_arm_64_check_xxxx26_offset (offset)) + { + struct grub_arm64_trampoline *tp = mod->trampptr; + mod->trampptr = tp + 1; + tp->ldr = LDR; + tp->br = BR; + tp->addr = sym_addr; + offset = (grub_uint8_t *) tp - (grub_uint8_t *) place; + } + + if (!grub_arm_64_check_xxxx26_offset (offset)) + return grub_error (GRUB_ERR_BAD_MODULE, + "trampoline out of range"); + + grub_arm64_set_xxxx26_offset (place, offset); + } + break; + case R_AARCH64_PREL32: + { + grub_int64_t value; + Elf64_Word *addr32 = place; + value = ((grub_int32_t) *addr32) + sym_addr - + (Elf64_Xword) (grub_addr_t) seg->addr - rel->r_offset; + if (value != (grub_int32_t) value) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); + grub_dprintf("dl", " reloc_prel32 %p => 0x%016llx\n", + place, (unsigned long long) sym_addr); + *addr32 = value; + } + break; + case R_AARCH64_ADR_GOT_PAGE: + { + grub_uint64_t *gp = mod->gotptr; + Elf_Rela *rel2; + grub_int64_t gpoffset = ((grub_uint64_t) gp & ~0xfffULL) - (((grub_uint64_t) place) & ~0xfffULL); + *gp = (grub_uint64_t) sym_addr; + mod->gotptr = gp + 1; + unmatched_adr_got_page++; + grub_dprintf("dl", " reloc_got %p => 0x%016llx (0x%016llx)\n", + place, (unsigned long long) sym_addr, (unsigned long long) gp); + if (!grub_arm64_check_hi21_signed (gpoffset)) + return grub_error (GRUB_ERR_BAD_MODULE, + "HI21 out of range"); + grub_arm64_set_hi21(place, gpoffset); + for (rel2 = (Elf_Rela *) ((char *) rel + s->sh_entsize); + rel2 < (Elf_Rela *) max; + rel2 = (Elf_Rela *) ((char *) rel2 + s->sh_entsize)) + if (ELF_R_SYM (rel2->r_info) + == ELF_R_SYM (rel->r_info) + && ((Elf_Rela *) rel)->r_addend == rel2->r_addend + && ELF_R_TYPE (rel2->r_info) == R_AARCH64_LD64_GOT_LO12_NC) + { + grub_arm64_set_abs_lo12_ldst64 ((void *) ((grub_addr_t) seg->addr + rel2->r_offset), + (grub_uint64_t)gp); + break; + } + if (rel2 >= (Elf_Rela *) max) + return grub_error (GRUB_ERR_BAD_MODULE, + "ADR_GOT_PAGE without matching LD64_GOT_LO12_NC"); + } + break; + case R_AARCH64_LD64_GOT_LO12_NC: + if (unmatched_adr_got_page == 0) + return grub_error (GRUB_ERR_BAD_MODULE, + "LD64_GOT_LO12_NC without matching ADR_GOT_PAGE"); + unmatched_adr_got_page--; + break; + case R_AARCH64_ADR_PREL_PG_HI21: + { + grub_int64_t offset = (sym_addr & ~0xfffULL) - (((grub_uint64_t) place) & ~0xfffULL); + + if (!grub_arm64_check_hi21_signed (offset)) + return grub_error (GRUB_ERR_BAD_MODULE, + "HI21 out of range"); + + grub_arm64_set_hi21 (place, offset); + } + break; + + default: + { + char rel_info[17]; /* log16(2^64) = 16, plus NUL. */ + + grub_snprintf (rel_info, sizeof (rel_info) - 1, "%" PRIxGRUB_UINT64_T, + ELF_R_TYPE (rel->r_info)); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%s is not implemented yet"), rel_info); + } + } + } + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/arm64/dl_helper.c b/grub-core/kern/arm64/dl_helper.c new file mode 100644 index 000000000..10e3d1ec2 --- /dev/null +++ b/grub-core/kern/arm64/dl_helper.c @@ -0,0 +1,134 @@ +/* dl_helper.c - relocation helper functions for modules and grub-mkimage */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * grub_arm64_reloc_xxxx26(): + * + * JUMP26/CALL26 relocations for B and BL instructions. + */ + +int +grub_arm_64_check_xxxx26_offset (grub_int64_t offset) +{ + const grub_ssize_t offset_low = -(1 << 27), offset_high = (1 << 27) - 1; + + if ((offset < offset_low) || (offset > offset_high)) + return 0; + return 1; +} + +void +grub_arm64_set_xxxx26_offset (grub_uint32_t *place, grub_int64_t offset) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfc000000); + + grub_dprintf ("dl", " reloc_xxxx64 %p %c= 0x%" PRIxGRUB_INT64_T "\n", + place, offset > 0 ? '+' : '-', + offset < 0 ? -offset : offset); + + *place &= insmask; + *place |= grub_cpu_to_le32 (offset >> 2) & ~insmask; +} + +int +grub_arm64_check_hi21_signed (grub_int64_t offset) +{ + if (offset != (grub_int64_t)(grub_int32_t)offset) + return 0; + return 1; +} + +void +grub_arm64_set_hi21 (grub_uint32_t *place, grub_int64_t offset) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0x9f00001f); + grub_uint32_t val; + + offset >>= 12; + + val = ((offset & 3) << 29) | (((offset >> 2) & 0x7ffff) << 5); + + *place &= insmask; + *place |= grub_cpu_to_le32 (val) & ~insmask; +} + +void +grub_arm64_set_abs_lo12 (grub_uint32_t *place, grub_int64_t target) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff); + + *place &= insmask; + *place |= grub_cpu_to_le32 (target << 10) & ~insmask; +} + +void +grub_arm64_set_abs_lo12_ldst64 (grub_uint32_t *place, grub_int64_t target) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfff803ff); + + *place &= insmask; + *place |= grub_cpu_to_le32 (target << 7) & ~insmask; +} + +#pragma GCC diagnostic ignored "-Wcast-align" + +grub_err_t +grub_arm64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got) +{ + const Elf64_Ehdr *e = ehdr; + const Elf64_Shdr *s; + unsigned i; + + *tramp = 0; + *got = 0; + + for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu64 (e->e_shoff)); + i < grub_le_to_cpu16 (e->e_shnum); + i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) + if (s->sh_type == grub_cpu_to_le32_compile_time (SHT_REL) + || s->sh_type == grub_cpu_to_le32_compile_time (SHT_RELA)) + { + const Elf64_Rela *rel, *max; + + for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu64 (s->sh_offset)), + max = (const Elf64_Rela *) ((char *) rel + grub_le_to_cpu64 (s->sh_size)); + rel < max; rel = (const Elf64_Rela *) ((char *) rel + grub_le_to_cpu64 (s->sh_entsize))) + switch (ELF64_R_TYPE (rel->r_info)) + { + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + *tramp += sizeof (struct grub_arm64_trampoline); + break; + case R_AARCH64_ADR_GOT_PAGE: + *got += 8; + break; + } + } + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/arm64/efi/init.c b/grub-core/kern/arm64/efi/init.c new file mode 100644 index 000000000..5010caefd --- /dev/null +++ b/grub-core/kern/arm64/efi/init.c @@ -0,0 +1,63 @@ +/* init.c - initialize an arm-based EFI system */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +static grub_uint64_t timer_frequency_in_khz; + +static grub_uint64_t +grub_efi_get_time_ms (void) +{ + grub_uint64_t tmr; + asm volatile("mrs %0, cntvct_el0" : "=r" (tmr)); + + return tmr / timer_frequency_in_khz; +} + + +void +grub_machine_init (void) +{ + grub_uint64_t timer_frequency; + + grub_efi_init (); + + asm volatile("mrs %0, cntfrq_el0" : "=r" (timer_frequency)); + timer_frequency_in_khz = timer_frequency / 1000; + + grub_install_get_time_ms (grub_efi_get_time_ms); +} + +void +grub_machine_fini (int flags) +{ + if (!(flags & GRUB_LOADER_FLAG_NORETURN)) + return; + + grub_efi_fini (); + + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY)) + grub_efi_memory_fini (); +} diff --git a/grub-core/kern/arm64/efi/startup.S b/grub-core/kern/arm64/efi/startup.S new file mode 100644 index 000000000..666a7ee3c --- /dev/null +++ b/grub-core/kern/arm64/efi/startup.S @@ -0,0 +1,39 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include + + .file "startup.S" + .text +FUNCTION(_start) + /* + * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in x1/x0. + */ + ldr x2, efi_image_handle_val + str x0, [x2] + ldr x2, efi_system_table_val + str x1, [x2] + ldr x2, grub_main_val + br x2 +grub_main_val: + .quad EXT_C(grub_main) +efi_system_table_val: + .quad EXT_C(grub_efi_system_table) +efi_image_handle_val: + .quad EXT_C(grub_efi_image_handle) + diff --git a/grub-core/kern/buffer.c b/grub-core/kern/buffer.c new file mode 100644 index 000000000..a2587729c --- /dev/null +++ b/grub-core/kern/buffer.c @@ -0,0 +1,120 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2021 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +grub_buffer_t +grub_buffer_new (grub_size_t sz) +{ + struct grub_buffer *ret; + + ret = (struct grub_buffer *) grub_malloc (sizeof (*ret)); + if (ret == NULL) + return NULL; + + ret->data = (grub_uint8_t *) grub_malloc (sz); + if (ret->data == NULL) + { + grub_free (ret); + return NULL; + } + + ret->sz = sz; + ret->pos = 0; + ret->used = 0; + + return ret; +} + +void +grub_buffer_free (grub_buffer_t buf) +{ + if (buf != NULL) + { + grub_free (buf->data); + grub_free (buf); + } +} + +grub_err_t +grub_buffer_ensure_space (grub_buffer_t buf, grub_size_t req) +{ + grub_uint8_t *d; + grub_size_t newsz = 1; + + /* Is the current buffer size adequate? */ + if (buf->sz >= req) + return GRUB_ERR_NONE; + + /* Find the smallest power-of-2 size that satisfies the request. */ + while (newsz < req) + { + if (newsz == 0) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("requested buffer size is too large")); + newsz <<= 1; + } + + d = (grub_uint8_t *) grub_realloc (buf->data, newsz); + if (d == NULL) + return grub_errno; + + buf->data = d; + buf->sz = newsz; + + return GRUB_ERR_NONE; +} + +void * +grub_buffer_take_data (grub_buffer_t buf) +{ + void *data = buf->data; + + buf->data = NULL; + buf->sz = buf->pos = buf->used = 0; + + return data; +} + +void +grub_buffer_reset (grub_buffer_t buf) +{ + buf->pos = buf->used = 0; +} + +grub_err_t +grub_buffer_advance_read_pos (grub_buffer_t buf, grub_size_t n) +{ + grub_size_t newpos; + + if (grub_add (buf->pos, n, &newpos)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + + if (newpos > buf->used) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("new read is position beyond the end of the written data")); + + buf->pos = newpos; + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/command.c b/grub-core/kern/command.c index acd721879..5812e131c 100644 --- a/grub-core/kern/command.c +++ b/grub-core/kern/command.c @@ -17,6 +17,7 @@ * along with GRUB. If not, see . */ +#include #include #include @@ -45,7 +46,7 @@ grub_register_command_prio (const char *name, cmd->flags = 0; cmd->prio = prio; - + for (p = &grub_command_list, q = *p; q; p = &(q->next), q = q->next) { int r; @@ -77,6 +78,29 @@ grub_register_command_prio (const char *name, return cmd; } +static grub_err_t +grub_cmd_lockdown (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **argv __attribute__ ((unused))) + +{ + return grub_error (GRUB_ERR_ACCESS_DENIED, + N_("%s: the command is not allowed when lockdown is enforced"), + cmd->name); +} + +grub_command_t +grub_register_command_lockdown (const char *name, + grub_command_func_t func, + const char *summary, + const char *description) +{ + if (grub_is_lockdown () == GRUB_LOCKDOWN_ENABLED) + func = grub_cmd_lockdown; + + return grub_register_command_prio (name, func, summary, description, 0); +} + void grub_unregister_command (grub_command_t cmd) { diff --git a/grub-core/kern/compiler-rt.c b/grub-core/kern/compiler-rt.c new file mode 100644 index 000000000..eda689a0c --- /dev/null +++ b/grub-core/kern/compiler-rt.c @@ -0,0 +1,454 @@ +/* compiler-rt.c - compiler helpers. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010-2014 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +#ifndef GRUB_EMBED_DECOMPRESSOR +void * GRUB_BUILTIN_ATTR +memcpy (void *dest, const void *src, grub_size_t n) +{ + return grub_memmove (dest, src, n); +} +void * GRUB_BUILTIN_ATTR +memmove (void *dest, const void *src, grub_size_t n) +{ + return grub_memmove (dest, src, n); +} +int GRUB_BUILTIN_ATTR +memcmp (const void *s1, const void *s2, grub_size_t n) +{ + return grub_memcmp (s1, s2, n); +} +void * GRUB_BUILTIN_ATTR +memset (void *s, int c, grub_size_t n) +{ + return grub_memset (s, c, n); +} + +#ifdef __APPLE__ + +void GRUB_BUILTIN_ATTR +__bzero (void *s, grub_size_t n) +{ + grub_memset (s, 0, n); +} + +#endif + +#if GRUB_DIVISION_IN_SOFTWARE + +grub_uint32_t +__udivsi3 (grub_uint32_t a, grub_uint32_t b) +{ + return grub_divmod64 (a, b, 0); +} + +grub_int32_t +__divsi3 (grub_int32_t a, grub_int32_t b) +{ + return grub_divmod64s (a, b, 0); +} + +grub_uint32_t +__umodsi3 (grub_uint32_t a, grub_uint32_t b) +{ + grub_uint64_t ret; + grub_divmod64 (a, b, &ret); + return ret; +} + +grub_int32_t +__modsi3 (grub_int32_t a, grub_int32_t b) +{ + grub_int64_t ret; + grub_divmod64s (a, b, &ret); + return ret; +} + +grub_uint64_t +__udivdi3 (grub_uint64_t a, grub_uint64_t b) +{ + return grub_divmod64 (a, b, 0); +} + +grub_uint64_t +__umoddi3 (grub_uint64_t a, grub_uint64_t b) +{ + grub_uint64_t ret; + grub_divmod64 (a, b, &ret); + return ret; +} + +grub_int64_t +__divdi3 (grub_int64_t a, grub_int64_t b) +{ + return grub_divmod64s (a, b, 0); +} + +grub_int64_t +__moddi3 (grub_int64_t a, grub_int64_t b) +{ + grub_int64_t ret; + grub_divmod64s (a, b, &ret); + return ret; +} + +#endif + +#endif + +#ifdef NEED_CTZDI2 + +unsigned +__ctzdi2 (grub_uint64_t x) +{ + unsigned ret = 0; + if (!x) + return 64; + if (!(x & 0xffffffff)) + { + x >>= 32; + ret |= 32; + } + if (!(x & 0xffff)) + { + x >>= 16; + ret |= 16; + } + if (!(x & 0xff)) + { + x >>= 8; + ret |= 8; + } + if (!(x & 0xf)) + { + x >>= 4; + ret |= 4; + } + if (!(x & 0x3)) + { + x >>= 2; + ret |= 2; + } + if (!(x & 0x1)) + { + x >>= 1; + ret |= 1; + } + return ret; +} +#endif + +#ifdef NEED_CTZSI2 +unsigned +__ctzsi2 (grub_uint32_t x) +{ + unsigned ret = 0; + if (!x) + return 32; + + if (!(x & 0xffff)) + { + x >>= 16; + ret |= 16; + } + if (!(x & 0xff)) + { + x >>= 8; + ret |= 8; + } + if (!(x & 0xf)) + { + x >>= 4; + ret |= 4; + } + if (!(x & 0x3)) + { + x >>= 2; + ret |= 2; + } + if (!(x & 0x1)) + { + x >>= 1; + ret |= 1; + } + return ret; +} + +#endif + +#if (defined (__MINGW32__) || defined (__CYGWIN__)) +void __register_frame_info (void) +{ +} + +void __deregister_frame_info (void) +{ +} + +void ___chkstk_ms (void) +{ +} + +void __chkstk_ms (void) +{ +} +#endif + +union component64 +{ + grub_uint64_t full; + struct + { +#ifdef GRUB_CPU_WORDS_BIGENDIAN + grub_uint32_t high; + grub_uint32_t low; +#else + grub_uint32_t low; + grub_uint32_t high; +#endif + }; +}; + +#if defined (__powerpc__) || defined (__arm__) || defined(__mips__) || \ + (defined(__riscv) && (__riscv_xlen == 32)) + +/* Based on libgcc2.c from gcc suite. */ +grub_uint64_t +__lshrdi3 (grub_uint64_t u, int b) +{ + if (b == 0) + return u; + + const union component64 uu = {.full = u}; + const int bm = 32 - b; + union component64 w; + + if (bm <= 0) + { + w.high = 0; + w.low = (grub_uint32_t) uu.high >> -bm; + } + else + { + const grub_uint32_t carries = (grub_uint32_t) uu.high << bm; + + w.high = (grub_uint32_t) uu.high >> b; + w.low = ((grub_uint32_t) uu.low >> b) | carries; + } + + return w.full; +} + +/* Based on libgcc2.c from gcc suite. */ +grub_uint64_t +__ashrdi3 (grub_uint64_t u, int b) +{ + if (b == 0) + return u; + + const union component64 uu = {.full = u}; + const int bm = 32 - b; + union component64 w; + + if (bm <= 0) + { + /* w.high = 1..1 or 0..0 */ + w.high = ((grub_int32_t) uu.high) >> (32 - 1); + w.low = ((grub_int32_t) uu.high) >> -bm; + } + else + { + const grub_uint32_t carries = ((grub_uint32_t) uu.high) << bm; + + w.high = ((grub_int32_t) uu.high) >> b; + w.low = ((grub_uint32_t) uu.low >> b) | carries; + } + + return w.full; +} + +/* Based on libgcc2.c from gcc suite. */ +grub_uint64_t +__ashldi3 (grub_uint64_t u, int b) +{ + if (b == 0) + return u; + + const union component64 uu = {.full = u}; + const int bm = 32 - b; + union component64 w; + + if (bm <= 0) + { + w.low = 0; + w.high = (grub_uint32_t) uu.low << -bm; + } + else + { + const grub_uint32_t carries = (grub_uint32_t) uu.low >> bm; + + w.low = (grub_uint32_t) uu.low << b; + w.high = ((grub_uint32_t) uu.high << b) | carries; + } + + return w.full; +} + +/* Based on libgcc2.c from gcc suite. */ +int +__ucmpdi2 (grub_uint64_t a, grub_uint64_t b) +{ + union component64 ac, bc; + ac.full = a; + bc.full = b; + + if (ac.high < bc.high) + return 0; + else if (ac.high > bc.high) + return 2; + + if (ac.low < bc.low) + return 0; + else if (ac.low > bc.low) + return 2; + return 1; +} + +#endif + +#if defined (__powerpc__) || defined(__mips__) || defined(__sparc__) || \ + defined(__arm__) || defined(__riscv) + +/* Based on libgcc2.c from gcc suite. */ +grub_uint32_t +__bswapsi2 (grub_uint32_t u) +{ + return ((((u) & 0xff000000) >> 24) + | (((u) & 0x00ff0000) >> 8) + | (((u) & 0x0000ff00) << 8) + | (((u) & 0x000000ff) << 24)); +} + +/* Based on libgcc2.c from gcc suite. */ +grub_uint64_t +__bswapdi2 (grub_uint64_t u) +{ + return ((((u) & 0xff00000000000000ull) >> 56) + | (((u) & 0x00ff000000000000ull) >> 40) + | (((u) & 0x0000ff0000000000ull) >> 24) + | (((u) & 0x000000ff00000000ull) >> 8) + | (((u) & 0x00000000ff000000ull) << 8) + | (((u) & 0x0000000000ff0000ull) << 24) + | (((u) & 0x000000000000ff00ull) << 40) + | (((u) & 0x00000000000000ffull) << 56)); +} + + +#endif + +#ifdef __arm__ +grub_uint32_t +__aeabi_uidiv (grub_uint32_t a, grub_uint32_t b) + __attribute__ ((alias ("__udivsi3"))); +grub_int32_t +__aeabi_idiv (grub_int32_t a, grub_int32_t b) + __attribute__ ((alias ("__divsi3"))); +void *__aeabi_memcpy (void *dest, const void *src, grub_size_t n) + __attribute__ ((alias ("grub_memcpy"))); +void *__aeabi_memcpy4 (void *dest, const void *src, grub_size_t n) + __attribute__ ((alias ("grub_memcpy"))); +void *__aeabi_memcpy8 (void *dest, const void *src, grub_size_t n) + __attribute__ ((alias ("grub_memcpy"))); +void *__aeabi_memset (void *s, int c, grub_size_t n) + __attribute__ ((alias ("memset"))); + +void +__aeabi_memclr (void *s, grub_size_t n) +{ + grub_memset (s, 0, n); +} + +void __aeabi_memclr4 (void *s, grub_size_t n) + __attribute__ ((alias ("__aeabi_memclr"))); +void __aeabi_memclr8 (void *s, grub_size_t n) + __attribute__ ((alias ("__aeabi_memclr"))); + +int +__aeabi_ulcmp (grub_uint64_t a, grub_uint64_t b) +{ + return __ucmpdi2 (a, b) - 1; +} + +grub_uint64_t +__aeabi_lasr (grub_uint64_t u, int b) + __attribute__ ((alias ("__ashrdi3"))); +grub_uint64_t +__aeabi_llsr (grub_uint64_t u, int b) + __attribute__ ((alias ("__lshrdi3"))); + +grub_uint64_t +__aeabi_llsl (grub_uint64_t u, int b) + __attribute__ ((alias ("__ashldi3"))); + +#endif + +#if defined(__mips__) || defined(__riscv) || defined(__sparc__) +/* Based on libgcc from gcc suite. */ +int +__clzsi2 (grub_uint32_t val) +{ + int i = 32; + int j = 16; + int temp; + + for (; j; j >>= 1) + { + if ((temp = val >> j)) + { + if (j == 1) + { + return (i - 2); + } + else + { + i -= j; + val = temp; + } + } + } + return (i - val); +} +#endif + +#if defined(__mips__) || defined(__riscv) || defined(__sparc__) +int +__clzdi2 (grub_uint64_t val) +{ + if (val >> 32) + { + return __clzsi2 (val >> 32); + } + else + { + return __clzsi2 (val) + 32; + } +} +#endif diff --git a/grub-core/kern/coreboot/cbtable.c b/grub-core/kern/coreboot/cbtable.c new file mode 100644 index 000000000..b6d0801c1 --- /dev/null +++ b/grub-core/kern/coreboot/cbtable.c @@ -0,0 +1,72 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wcast-align" + +/* Helper for grub_linuxbios_table_iterate. */ +int +grub_linuxbios_check_signature (grub_linuxbios_table_header_t tbl_header) +{ + if (! grub_memcmp (tbl_header->signature, "LBIO", 4)) + return 1; + + return 0; +} + +grub_err_t +grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t, + void *), + void *hook_data) +{ + grub_linuxbios_table_header_t table_header = grub_linuxbios_get_tables (); + grub_linuxbios_table_item_t table_item; + + if (!table_header) + return 0; + +signature_found: + + table_item = + (grub_linuxbios_table_item_t) ((char *) table_header + + table_header->header_size); + for (; table_item < (grub_linuxbios_table_item_t) ((char *) table_header + + table_header->header_size + + table_header->table_size); + table_item = (grub_linuxbios_table_item_t) ((char *) table_item + table_item->size)) + { + if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK + && grub_linuxbios_check_signature ((grub_linuxbios_table_header_t) (grub_addr_t) + *(grub_uint64_t *) (table_item + 1))) + { + table_header = (grub_linuxbios_table_header_t) (grub_addr_t) + *(grub_uint64_t *) (table_item + 1); + goto signature_found; + } + if (hook (table_item, hook_data)) + return 1; + } + + return 0; +} diff --git a/grub-core/kern/coreboot/mmap.c b/grub-core/kern/coreboot/mmap.c new file mode 100644 index 000000000..caf8f7cef --- /dev/null +++ b/grub-core/kern/coreboot/mmap.c @@ -0,0 +1,100 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +/* Context for grub_machine_mmap_iterate. */ +struct grub_machine_mmap_iterate_ctx +{ + grub_memory_hook_t hook; + void *hook_data; +}; + +#define GRUB_MACHINE_MEMORY_BADRAM 5 + +/* Helper for grub_machine_mmap_iterate. */ +static int +iterate_linuxbios_table (grub_linuxbios_table_item_t table_item, void *data) +{ + struct grub_machine_mmap_iterate_ctx *ctx = data; + mem_region_t mem_region; + + if (table_item->tag != GRUB_LINUXBIOS_MEMBER_MEMORY) + return 0; + + mem_region = + (mem_region_t) ((long) table_item + + sizeof (struct grub_linuxbios_table_item)); + for (; (long) mem_region < (long) table_item + (long) table_item->size; + mem_region++) + { + grub_uint64_t start = mem_region->addr; + grub_uint64_t end = mem_region->addr + mem_region->size; +#ifdef __i386__ + /* Mark region 0xa0000 - 0x100000 as reserved. */ + if (start < 0x100000 && end >= 0xa0000 + && mem_region->type == GRUB_MACHINE_MEMORY_AVAILABLE) + { + if (start < 0xa0000 + && ctx->hook (start, 0xa0000 - start, + /* Multiboot mmaps match with the coreboot mmap + definition. Therefore, we can just pass type + through. */ + mem_region->type, + ctx->hook_data)) + return 1; + if (start < 0xa0000) + start = 0xa0000; + if (start >= end) + continue; + + if (ctx->hook (start, (end > 0x100000 ? 0x100000 : end) - start, + GRUB_MEMORY_RESERVED, + ctx->hook_data)) + return 1; + start = 0x100000; + + if (end <= start) + continue; + } +#endif + if (ctx->hook (start, end - start, + /* Multiboot mmaps match with the coreboot mmap + definition. Therefore, we can just pass type + through. */ + mem_region->type, + ctx->hook_data)) + return 1; + } + + return 0; +} + +grub_err_t +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) +{ + struct grub_machine_mmap_iterate_ctx ctx = { hook, hook_data }; + + grub_linuxbios_table_iterate (iterate_linuxbios_table, &ctx); + + return 0; +} diff --git a/grub-core/kern/corecmd.c b/grub-core/kern/corecmd.c index eec575c05..62d434ba9 100644 --- a/grub-core/kern/corecmd.c +++ b/grub-core/kern/corecmd.c @@ -36,17 +36,14 @@ grub_core_cmd_set (struct grub_command *cmd __attribute__ ((unused)), char *var; char *val; - auto int print_env (struct grub_env_var *env); - - int print_env (struct grub_env_var *env) - { - grub_printf ("%s=%s\n", env->name, env->value); - return 0; - } - if (argc < 1) { - grub_env_iterate (print_env); + struct grub_env_var *env; + FOR_SORTED_ENV (env) + { + val = (char *) grub_env_get (env->name); + grub_printf ("%s='%s'\n", env->name, val == NULL ? "" : val); + } return 0; } @@ -96,7 +93,7 @@ grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)), } static int -grub_mini_print_devices (const char *name) +grub_mini_print_devices (const char *name, void *data __attribute__ ((unused))) { grub_printf ("(%s) ", name); @@ -105,7 +102,8 @@ grub_mini_print_devices (const char *name) static int grub_mini_print_files (const char *filename, - const struct grub_dirhook_info *info) + const struct grub_dirhook_info *info, + void *data __attribute__ ((unused))) { grub_printf ("%s%s ", filename, info->dir ? "/" : ""); @@ -119,7 +117,7 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)), { if (argc < 1) { - grub_device_iterate (grub_mini_print_devices); + grub_device_iterate (grub_mini_print_devices, NULL); grub_xputs ("\n"); grub_refresh (); } @@ -144,13 +142,13 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)), else path++; - if (! path && ! device_name) + if (! *path && ! device_name) { grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument"); goto fail; } - if (! path) + if (! *path) { if (grub_errno == GRUB_ERR_UNKNOWN_FS) grub_errno = GRUB_ERR_NONE; @@ -160,7 +158,7 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)), } else if (fs) { - (fs->dir) (dev, path, grub_mini_print_files); + (fs->fs_dir) (dev, path, grub_mini_print_files, NULL); grub_xputs ("\n"); grub_refresh (); } diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 12615647d..670e213cf 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -56,7 +56,7 @@ grub_device_open (const char *name) if (grub_net_open && grub_errno == GRUB_ERR_UNKNOWN_DEVICE) { grub_errno = GRUB_ERR_NONE; - dev->net = grub_net_open (name); + dev->net = grub_net_open (name); } if (dev->net) @@ -71,6 +71,9 @@ grub_device_open (const char *name) grub_err_t grub_device_close (grub_device_t device) { + if (device == NULL) + return GRUB_ERR_NONE; + if (device->disk) grub_disk_close (device->disk); @@ -85,94 +88,107 @@ grub_device_close (grub_device_t device) return grub_errno; } -int -grub_device_iterate (int (*hook) (const char *name)) +struct part_ent { - auto int iterate_disk (const char *disk_name); - auto int iterate_partition (grub_disk_t disk, - const grub_partition_t partition); + struct part_ent *next; + char *name; +}; - struct part_ent - { - struct part_ent *next; - char *name; - } *ents; +/* Context for grub_device_iterate. */ +struct grub_device_iterate_ctx +{ + grub_device_iterate_hook_t hook; + void *hook_data; + struct part_ent *ents; +}; - int iterate_disk (const char *disk_name) +/* Helper for grub_device_iterate. */ +static int +iterate_partition (grub_disk_t disk, const grub_partition_t partition, + void *data) +{ + struct grub_device_iterate_ctx *ctx = data; + struct part_ent *p; + char *part_name; + + p = grub_malloc (sizeof (*p)); + if (!p) { - grub_device_t dev; + return 1; + } - if (hook (disk_name)) - return 1; + part_name = grub_partition_get_name (partition); + if (!part_name) + { + grub_free (p); + return 1; + } + p->name = grub_xasprintf ("%s,%s", disk->name, part_name); + grub_free (part_name); + if (!p->name) + { + grub_free (p); + return 1; + } - dev = grub_device_open (disk_name); - if (! dev) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } + p->next = ctx->ents; + ctx->ents = p; - if (dev->disk) - { - struct part_ent *p; - int ret = 0; + return 0; +} - ents = NULL; - (void) grub_partition_iterate (dev->disk, iterate_partition); - grub_device_close (dev); +/* Helper for grub_device_iterate. */ +static int +iterate_disk (const char *disk_name, void *data) +{ + struct grub_device_iterate_ctx *ctx = data; + grub_device_t dev; - grub_errno = GRUB_ERR_NONE; + if (ctx->hook (disk_name, ctx->hook_data)) + return 1; - p = ents; - while (p != NULL) - { - struct part_ent *next = p->next; - - if (!ret) - ret = hook (p->name); - grub_free (p->name); - grub_free (p); - p = next; - } - - return ret; - } - - grub_device_close (dev); + dev = grub_device_open (disk_name); + if (! dev) + { + grub_errno = GRUB_ERR_NONE; return 0; } - int iterate_partition (grub_disk_t disk, const grub_partition_t partition) + if (dev->disk) { struct part_ent *p; - char *part_name; + int ret = 0; - p = grub_malloc (sizeof (*p)); - if (!p) - { - return 1; - } + ctx->ents = NULL; + (void) grub_partition_iterate (dev->disk, iterate_partition, ctx); + grub_device_close (dev); - part_name = grub_partition_get_name (partition); - if (!part_name) + grub_errno = GRUB_ERR_NONE; + + p = ctx->ents; + while (p != NULL) { + struct part_ent *next = p->next; + + if (!ret) + ret = ctx->hook (p->name, ctx->hook_data); + grub_free (p->name); grub_free (p); - return 1; - } - p->name = grub_xasprintf ("%s,%s", disk->name, part_name); - grub_free (part_name); - if (!p->name) - { - grub_free (p); - return 1; + p = next; } - p->next = ents; - ents = p; - - return 0; + return ret; } - /* Only disk devices are supported at the moment. */ - return grub_disk_dev_iterate (iterate_disk); + grub_device_close (dev); + return 0; +} + +int +grub_device_iterate (grub_device_iterate_hook_t hook, void *hook_data) +{ + struct grub_device_iterate_ctx ctx = { hook, hook_data, NULL }; + + /* Only disk devices are supported at the moment. */ + return grub_disk_dev_iterate (iterate_disk, &ctx); } diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 1f55f90a8..82e04fd00 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -28,21 +28,14 @@ #define GRUB_CACHE_TIMEOUT 2 +/* Disk reads may trigger other disk reads. So, limit recursion depth. */ +#define MAX_READ_RECURSION_DEPTH 16 +static unsigned int read_recursion_depth = 0; + /* The last time the disk was used. */ static grub_uint64_t grub_last_time = 0; - -/* Disk cache. */ -struct grub_disk_cache -{ - enum grub_disk_dev_id dev_id; - unsigned long disk_id; - grub_disk_addr_t sector; - char *data; - int lock; -}; - -static struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM]; +struct grub_disk_cache grub_disk_cache_table[GRUB_DISK_CACHE_NUM]; void (*grub_disk_firmware_fini) (void); int grub_disk_firmware_is_tainted; @@ -59,35 +52,12 @@ grub_disk_cache_get_performance (unsigned long *hits, unsigned long *misses) } #endif -static unsigned -grub_disk_cache_get_index (unsigned long dev_id, unsigned long disk_id, - grub_disk_addr_t sector) -{ - return ((dev_id * 524287UL + disk_id * 2606459UL - + ((unsigned) (sector >> GRUB_DISK_CACHE_BITS))) - % GRUB_DISK_CACHE_NUM); -} - -static void -grub_disk_cache_invalidate (unsigned long dev_id, unsigned long disk_id, - grub_disk_addr_t sector) -{ - unsigned index; - struct grub_disk_cache *cache; - - sector &= ~(GRUB_DISK_CACHE_SIZE - 1); - index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + index; - - if (cache->dev_id == dev_id && cache->disk_id == disk_id - && cache->sector == sector && cache->data) - { - cache->lock = 1; - grub_free (cache->data); - cache->data = 0; - cache->lock = 0; - } -} +grub_err_t (*grub_disk_write_weak) (grub_disk_t disk, + grub_disk_addr_t sector, + grub_off_t offset, + grub_size_t size, + const void *buf); +#include "disk_common.c" void grub_disk_cache_invalidate_all (void) @@ -111,10 +81,10 @@ grub_disk_cache_fetch (unsigned long dev_id, unsigned long disk_id, grub_disk_addr_t sector) { struct grub_disk_cache *cache; - unsigned index; + unsigned cache_index; - index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + index; + cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); + cache = grub_disk_cache_table + cache_index; if (cache->dev_id == dev_id && cache->disk_id == disk_id && cache->sector == sector) @@ -138,10 +108,10 @@ grub_disk_cache_unlock (unsigned long dev_id, unsigned long disk_id, grub_disk_addr_t sector) { struct grub_disk_cache *cache; - unsigned index; + unsigned cache_index; - index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + index; + cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); + cache = grub_disk_cache_table + cache_index; if (cache->dev_id == dev_id && cache->disk_id == disk_id && cache->sector == sector) @@ -152,11 +122,11 @@ static grub_err_t grub_disk_cache_store (unsigned long dev_id, unsigned long disk_id, grub_disk_addr_t sector, const char *data) { - unsigned index; + unsigned cache_index; struct grub_disk_cache *cache; - index = grub_disk_cache_get_index (dev_id, disk_id, sector); - cache = grub_disk_cache_table + index; + cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); + cache = grub_disk_cache_table + cache_index; cache->lock = 1; grub_free (cache->data); @@ -233,6 +203,9 @@ grub_disk_open (const char *name) if (! disk) return 0; disk->log_sector_size = GRUB_DISK_SECTOR_BITS; + /* Default 1MiB of maximum agglomerate. */ + disk->max_agglomerate = 1048576 >> (GRUB_DISK_SECTOR_BITS + + GRUB_DISK_CACHE_BITS); p = find_part_sep (name); if (p) @@ -254,7 +227,7 @@ grub_disk_open (const char *name) for (dev = grub_disk_dev_list; dev; dev = dev->next) { - if ((dev->open) (raw, disk) == GRUB_ERR_NONE) + if ((dev->disk_open) (raw, disk) == GRUB_ERR_NONE) break; else if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE) grub_errno = GRUB_ERR_NONE; @@ -323,10 +296,14 @@ void grub_disk_close (grub_disk_t disk) { grub_partition_t part; + + if (disk == NULL) + return; + grub_dprintf ("disk", "Closing `%s'.\n", disk->name); - if (disk->dev && disk->dev->close) - (disk->dev->close) (disk); + if (disk->dev && disk->dev->disk_close) + (disk->dev->disk_close) (disk); /* Reset the timer. */ grub_last_time = grub_get_time_ms (); @@ -341,59 +318,12 @@ grub_disk_close (grub_disk_t disk) grub_free (disk); } -/* This function performs three tasks: - - Make sectors disk relative from partition relative. - - Normalize offset to be less than the sector size. - - Verify that the range is inside the partition. */ -static grub_err_t -grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector, - grub_off_t *offset, grub_size_t size) -{ - grub_partition_t part; - *sector += *offset >> GRUB_DISK_SECTOR_BITS; - *offset &= GRUB_DISK_SECTOR_SIZE - 1; - - for (part = disk->partition; part; part = part->parent) - { - grub_disk_addr_t start; - grub_uint64_t len; - - start = part->start; - len = part->len; - - if (*sector >= len - || len - *sector < ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - N_("attempt to read or write outside of partition")); - - *sector += start; - } - - if (disk->total_sectors != GRUB_DISK_SIZE_UNKNOWN - && ((disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) <= *sector - || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors - << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) - *sector)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - N_("attempt to read or write outside of disk `%s'"), disk->name); - - return GRUB_ERR_NONE; -} - -static inline grub_disk_addr_t -transform_sector (grub_disk_t disk, grub_disk_addr_t sector) -{ - return sector >> (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); -} - /* Small read (less than cache size and not pass across cache unit boundaries). sector is already adjusted and is divisible by cache unit size. */ static grub_err_t -grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, - grub_off_t offset, grub_size_t size, void *buf) +grub_disk_read_small_real (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, void *buf) { char *data; char *tmp_buf; @@ -419,10 +349,10 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, < (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS))) { grub_err_t err; - err = (disk->dev->read) (disk, transform_sector (disk, sector), - 1 << (GRUB_DISK_CACHE_BITS - + GRUB_DISK_SECTOR_BITS - - disk->log_sector_size), tmp_buf); + err = (disk->dev->disk_read) (disk, grub_disk_to_native_sector (disk, sector), + 1U << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size), tmp_buf); if (!err) { /* Copy it and store it in the disk cache. */ @@ -444,19 +374,19 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, sector += (offset >> GRUB_DISK_SECTOR_BITS); offset &= ((1 << GRUB_DISK_SECTOR_BITS) - 1); - aligned_sector = (sector & ~((1 << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) + aligned_sector = (sector & ~((1ULL << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) - 1)); offset += ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS); - num = ((size + offset + (1 << (disk->log_sector_size)) + num = ((size + offset + (1ULL << (disk->log_sector_size)) - 1) >> (disk->log_sector_size)); tmp_buf = grub_malloc (num << disk->log_sector_size); if (!tmp_buf) return grub_errno; - - if ((disk->dev->read) (disk, transform_sector (disk, aligned_sector), - num, tmp_buf)) + + if ((disk->dev->disk_read) (disk, grub_disk_to_native_sector (disk, aligned_sector), + num, tmp_buf)) { grub_error_push (); grub_dprintf ("disk", "%s read failed\n", disk->name); @@ -470,14 +400,28 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, } } +static grub_err_t +grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, void *buf) +{ + grub_err_t err; + + err = grub_disk_read_small_real (disk, sector, offset, size, buf); + if (err) + return err; + if (disk->read_hook) + err = (disk->read_hook) (sector + (offset >> GRUB_DISK_SECTOR_BITS), + offset & (GRUB_DISK_SECTOR_SIZE - 1), + size, buf, disk->read_hook_data); + return err; +} + /* Read data from the disk. */ grub_err_t grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_off_t offset, grub_size_t size, void *buf) { - grub_off_t real_offset; - grub_disk_addr_t real_sector; - grub_size_t real_size; + grub_err_t err = GRUB_ERR_NONE; /* First of all, check if the region is within the disk. */ if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) @@ -489,19 +433,20 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, return grub_errno; } - real_sector = sector; - real_offset = offset; - real_size = size; + if (++read_recursion_depth >= MAX_READ_RECURSION_DEPTH) + { + grub_error (GRUB_ERR_RECURSION_DEPTH, "grub_disk_read(): Maximum recursion depth exceeded"); + goto error; + } /* First read until first cache boundary. */ if (offset || (sector & (GRUB_DISK_CACHE_SIZE - 1))) { grub_disk_addr_t start_sector; grub_size_t pos; - grub_err_t err; grub_size_t len; - start_sector = sector & ~(GRUB_DISK_CACHE_SIZE - 1); + start_sector = sector & ~((grub_disk_addr_t) GRUB_DISK_CACHE_SIZE - 1); pos = (sector - start_sector) << GRUB_DISK_SECTOR_BITS; len = ((GRUB_DISK_SECTOR_SIZE << GRUB_DISK_CACHE_BITS) - pos - offset); @@ -510,7 +455,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, err = grub_disk_read_small (disk, start_sector, offset + pos, len, buf); if (err) - return err; + goto error; buf = (char *) buf + len; size -= len; offset += len; @@ -523,11 +468,11 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, { char *data = NULL; grub_disk_addr_t agglomerate; - grub_err_t err; /* agglomerate read until we find a first cached entry. */ for (agglomerate = 0; agglomerate - < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS)); + < (size >> (GRUB_DISK_SECTOR_BITS + GRUB_DISK_CACHE_BITS)) + && agglomerate < disk->max_agglomerate; agglomerate++) { data = grub_disk_cache_fetch (disk->dev->id, disk->id, @@ -552,14 +497,14 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, { grub_disk_addr_t i; - err = (disk->dev->read) (disk, transform_sector (disk, sector), - agglomerate << (GRUB_DISK_CACHE_BITS - + GRUB_DISK_SECTOR_BITS - - disk->log_sector_size), - buf); + err = (disk->dev->disk_read) (disk, grub_disk_to_native_sector (disk, sector), + agglomerate << (GRUB_DISK_CACHE_BITS + + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size), + buf); if (err) - return err; - + goto error; + for (i = 0; i < agglomerate; i ++) grub_disk_cache_store (disk->dev->id, disk->id, sector + (i << GRUB_DISK_CACHE_BITS), @@ -567,14 +512,22 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, + (i << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS))); + + if (disk->read_hook) + (disk->read_hook) (sector, 0, agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS), + buf, disk->read_hook_data); + sector += agglomerate << GRUB_DISK_CACHE_BITS; size -= agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS); - buf = (char *) buf + buf = (char *) buf + (agglomerate << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS)); } if (data) { + if (disk->read_hook) + (disk->read_hook) (sector, 0, (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS), + buf, disk->read_hook_data); sector += GRUB_DISK_CACHE_SIZE; buf = (char *) buf + (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); size -= (GRUB_DISK_CACHE_SIZE << GRUB_DISK_SECTOR_BITS); @@ -584,114 +537,20 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, /* And now read the last part. */ if (size) { - grub_err_t err; err = grub_disk_read_small (disk, sector, 0, size, buf); if (err) - return err; + goto error; } - /* Call the read hook, if any. */ - if (disk->read_hook) - { - grub_disk_addr_t s = real_sector; - grub_size_t l = real_size; - grub_off_t o = real_offset; + err = grub_errno; - while (l) - { - grub_size_t cl; - cl = GRUB_DISK_SECTOR_SIZE - o; - if (cl > l) - cl = l; - (disk->read_hook) (s, o, cl); - s++; - l -= cl; - o = 0; - } - } - - return grub_errno; -} - -grub_err_t -grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, - grub_off_t offset, grub_size_t size, const void *buf) -{ - unsigned real_offset; - grub_disk_addr_t aligned_sector; - - grub_dprintf ("disk", "Writing `%s'...\n", disk->name); - - if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) - return -1; - - aligned_sector = (sector & ~((1 << (disk->log_sector_size - - GRUB_DISK_SECTOR_BITS)) - 1)); - real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS); - sector = aligned_sector; - - while (size) - { - if (real_offset != 0 || (size < (1U << disk->log_sector_size) - && size != 0)) - { - char tmp_buf[1 << disk->log_sector_size]; - grub_size_t len; - grub_partition_t part; - - part = disk->partition; - disk->partition = 0; - if (grub_disk_read (disk, sector, - 0, (1 << disk->log_sector_size), tmp_buf) - != GRUB_ERR_NONE) - { - disk->partition = part; - goto finish; - } - disk->partition = part; - - len = (1 << disk->log_sector_size) - real_offset; - if (len > size) - len = size; - - grub_memcpy (tmp_buf + real_offset, buf, len); - - grub_disk_cache_invalidate (disk->dev->id, disk->id, sector); - - if ((disk->dev->write) (disk, sector, 1, tmp_buf) != GRUB_ERR_NONE) - goto finish; - - sector += (1 << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); - buf = (const char *) buf + len; - size -= len; - real_offset = 0; - } - else - { - grub_size_t len; - grub_size_t n; - - len = size & ~((1 << disk->log_sector_size) - 1); - n = size >> disk->log_sector_size; - - if ((disk->dev->write) (disk, sector, n, buf) != GRUB_ERR_NONE) - goto finish; - - while (n--) - grub_disk_cache_invalidate (disk->dev->id, disk->id, sector++); - - buf = (const char *) buf + len; - size -= len; - } - } - - finish: - - return grub_errno; + error: + read_recursion_depth--; + return err; } grub_uint64_t -grub_disk_get_size (grub_disk_t disk) +grub_disk_native_sectors (grub_disk_t disk) { if (disk->partition) return grub_partition_get_len (disk->partition); diff --git a/grub-core/kern/disk_common.c b/grub-core/kern/disk_common.c new file mode 100644 index 000000000..ab6cd0c2b --- /dev/null +++ b/grub-core/kern/disk_common.c @@ -0,0 +1,60 @@ +/* This function performs three tasks: + - Make sectors disk relative from partition relative. + - Normalize offset to be less than the sector size. + - Verify that the range is inside the partition. */ +static grub_err_t +grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector, + grub_off_t *offset, grub_size_t size) +{ + grub_partition_t part; + grub_disk_addr_t total_sectors; + + *sector += *offset >> GRUB_DISK_SECTOR_BITS; + *offset &= GRUB_DISK_SECTOR_SIZE - 1; + + for (part = disk->partition; part; part = part->parent) + { + grub_disk_addr_t start; + grub_uint64_t len; + + start = part->start; + len = part->len; + + if (*sector >= len + || len - *sector < ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) + >> GRUB_DISK_SECTOR_BITS)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("attempt to read or write outside of partition")); + + *sector += start; + } + + /* Transform total_sectors to number of 512B blocks. */ + total_sectors = disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS); + + /* + * Some drivers have problems with disks above reasonable sizes. + * Clamp the size to GRUB_DISK_MAX_SECTORS. Just one condition is enough + * since GRUB_DISK_SIZE_UNKNOWN is always above GRUB_DISK_MAX_SECTORS, + * assuming a maximum 4 KiB sector size. + */ + if (total_sectors > GRUB_DISK_MAX_SECTORS) + total_sectors = GRUB_DISK_MAX_SECTORS; + + if ((total_sectors <= *sector + || ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) + >> GRUB_DISK_SECTOR_BITS) > total_sectors - *sector)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("attempt to read or write outside of disk `%s'"), disk->name); + + return GRUB_ERR_NONE; +} + +static unsigned +grub_disk_cache_get_index (unsigned long dev_id, unsigned long disk_id, + grub_disk_addr_t sector) +{ + return ((dev_id * 524287UL + disk_id * 2606459UL + + ((unsigned) (sector >> GRUB_DISK_CACHE_BITS))) + % GRUB_DISK_CACHE_NUM); +} diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 5b0aa6582..de8c3aa8d 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -32,18 +32,23 @@ #include #include #include +#include + +#ifdef GRUB_MACHINE_EFI +#include +#endif /* Platforms where modules are in a readonly area of memory. */ #if defined(GRUB_MACHINE_QEMU) #define GRUB_MODULES_MACHINE_READONLY #endif -#ifdef GRUB_MACHINE_EMU -#include +#ifdef GRUB_MACHINE_EFI +#define DL_ALIGN GRUB_EFI_PAGE_SIZE +#else +#define DL_ALIGN 1 #endif - - #pragma GCC diagnostic ignored "-Wcast-align" grub_dl_t grub_dl_head = 0; @@ -51,6 +56,7 @@ grub_dl_t grub_dl_head = 0; grub_err_t grub_dl_add (grub_dl_t mod); +/* Keep global so that GDB scripts work. */ grub_err_t grub_dl_add (grub_dl_t mod) { @@ -58,9 +64,6 @@ grub_dl_add (grub_dl_t mod) return grub_error (GRUB_ERR_BAD_MODULE, "`%s' is already loaded", mod->name); - mod->next = grub_dl_head; - grub_dl_head = mod; - return GRUB_ERR_NONE; } @@ -77,18 +80,6 @@ grub_dl_remove (grub_dl_t mod) } } -grub_dl_t -grub_dl_get (const char *name) -{ - grub_dl_t l; - - for (l = grub_dl_head; l; l = l->next) - if (grub_strcmp (name, l->name) == 0) - return l; - - return 0; -} - struct grub_symbol @@ -241,55 +232,67 @@ static grub_err_t grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) { unsigned i; - Elf_Shdr *s; - grub_size_t tsize = 0, talign = 1; -#if defined (__ia64__) || defined (__powerpc__) + const Elf_Shdr *s; + grub_size_t tsize = 0, talign = 1, arch_addralign = 1; +#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \ + !defined (__loongarch__) grub_size_t tramp; + grub_size_t tramp_align; grub_size_t got; + grub_size_t got_align; + grub_err_t err; #endif char *ptr; - for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff); + arch_addralign = DL_ALIGN; + + for (i = 0, s = (const Elf_Shdr *)((const char *) e + e->e_shoff); i < e->e_shnum; - i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) + i++, s = (const Elf_Shdr *)((const char *) s + e->e_shentsize)) { - tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; - if (talign < s->sh_addralign) - talign = s->sh_addralign; + grub_size_t sh_addralign; + grub_size_t sh_size; + + if (s->sh_size == 0 || !(s->sh_flags & SHF_ALLOC)) + continue; + + sh_addralign = ALIGN_UP (s->sh_addralign, arch_addralign); + sh_size = ALIGN_UP (s->sh_size, sh_addralign); + + tsize = ALIGN_UP (tsize, sh_addralign) + sh_size; + talign = grub_max (talign, sh_addralign); } -#if defined (__ia64__) || defined (__powerpc__) - grub_arch_dl_get_tramp_got_size (e, &tramp, &got); - tramp *= GRUB_ARCH_DL_TRAMP_SIZE; - got *= sizeof (grub_uint64_t); - tsize += ALIGN_UP (tramp, GRUB_ARCH_DL_TRAMP_ALIGN); - if (talign < GRUB_ARCH_DL_TRAMP_ALIGN) - talign = GRUB_ARCH_DL_TRAMP_ALIGN; - tsize += ALIGN_UP (got, GRUB_ARCH_DL_GOT_ALIGN); - if (talign < GRUB_ARCH_DL_GOT_ALIGN) - talign = GRUB_ARCH_DL_GOT_ALIGN; +#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \ + !defined (__loongarch__) + err = grub_arch_dl_get_tramp_got_size (e, &tramp, &got); + if (err) + return err; + tramp_align = grub_max (GRUB_ARCH_DL_TRAMP_ALIGN, arch_addralign); + tsize += ALIGN_UP (tramp, tramp_align); + talign = grub_max (talign, tramp_align); + got_align = grub_max (GRUB_ARCH_DL_GOT_ALIGN, arch_addralign); + tsize += ALIGN_UP (got, got_align); + talign = grub_max (talign, got_align); #endif #ifdef GRUB_MACHINE_EMU - if (talign < 8192 * 16) - talign = 8192 * 16; - tsize = ALIGN_UP (tsize, 8192 * 16); -#endif - + mod->base = grub_osdep_dl_memalign (talign, tsize); +#else mod->base = grub_memalign (talign, tsize); +#endif if (!mod->base) return grub_errno; mod->sz = tsize; ptr = mod->base; -#ifdef GRUB_MACHINE_EMU - mprotect (mod->base, tsize, PROT_READ | PROT_WRITE | PROT_EXEC); -#endif - for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff); i < e->e_shnum; i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) { + grub_size_t sh_addralign = ALIGN_UP (s->sh_addralign, arch_addralign); + grub_size_t sh_size = ALIGN_UP (s->sh_size, sh_addralign); + if (s->sh_flags & SHF_ALLOC) { grub_dl_segment_t seg; @@ -302,17 +305,18 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) { void *addr; - ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, s->sh_addralign); + ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, sh_addralign); addr = ptr; - ptr += s->sh_size; + ptr += sh_size; switch (s->sh_type) { case SHT_PROGBITS: grub_memcpy (addr, (char *) e + s->sh_offset, s->sh_size); + grub_memset ((char *) addr + s->sh_size, 0, sh_size - s->sh_size); break; case SHT_NOBITS: - grub_memset (addr, 0, s->sh_size); + grub_memset (addr, 0, sh_size); break; } @@ -321,18 +325,21 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) else seg->addr = 0; - seg->size = s->sh_size; + seg->size = sh_size; seg->section = i; seg->next = mod->segment; mod->segment = seg; } } -#if defined (__ia64__) || defined (__powerpc__) - ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_TRAMP_ALIGN); +#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \ + !defined (__loongarch__) + ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, tramp_align); mod->tramp = ptr; + mod->trampptr = ptr; ptr += tramp; - ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, GRUB_ARCH_DL_GOT_ALIGN); + ptr = (char *) ALIGN_UP ((grub_addr_t) ptr, got_align); mod->got = ptr; + mod->gotptr = ptr; ptr += got; #endif @@ -354,15 +361,21 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) if (s->sh_type == SHT_SYMTAB) break; + /* Module without symbol table may still be used to pull in dependencies. + We verify at build time that such modules do not contain any relocations + that may reference symbol table. */ if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); + return GRUB_ERR_NONE; #ifdef GRUB_MODULES_MACHINE_READONLY mod->symtab = grub_malloc (s->sh_size); - memcpy (mod->symtab, (char *) e + s->sh_offset, s->sh_size); + if (!mod->symtab) + return grub_errno; + grub_memcpy (mod->symtab, (char *) e + s->sh_offset, s->sh_size); #else mod->symtab = (Elf_Sym *) ((char *) e + s->sh_offset); #endif + mod->symsize = s->sh_entsize; sym = mod->symtab; size = s->sh_size; entsize = s->sh_entsize; @@ -445,11 +458,22 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) return GRUB_ERR_NONE; } -static void -grub_dl_call_init (grub_dl_t mod) +static Elf_Shdr * +grub_dl_find_section (Elf_Ehdr *e, const char *name) { - if (mod->init) - (mod->init) (mod); + Elf_Shdr *s; + const char *str; + unsigned i; + + s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); + str = (char *) e + s->sh_offset; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (grub_strcmp (str + s->sh_name, name) == 0) + return s; + return NULL; } /* Me, Vladimir Serbinenko, hereby I add this module check as per new @@ -461,53 +485,37 @@ grub_dl_call_init (grub_dl_t mod) Be sure to understand your license obligations. */ static grub_err_t -grub_dl_check_license (Elf_Ehdr *e) +grub_dl_check_license (grub_dl_t mod, Elf_Ehdr *e) { - Elf_Shdr *s; - const char *str; - unsigned i; + Elf_Shdr *s = grub_dl_find_section (e, ".module_license"); - s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); - str = (char *) e + s->sh_offset; + if (s == NULL) + return grub_error (GRUB_ERR_BAD_MODULE, + "no license section in module %.63s", mod->name); - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (grub_strcmp (str + s->sh_name, ".module_license") == 0) - { - if (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 - || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0 - || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0) - return GRUB_ERR_NONE; - } + if (grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3") == 0 + || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv3+") == 0 + || grub_strcmp ((char *) e + s->sh_offset, "LICENSE=GPLv2+") == 0) + return GRUB_ERR_NONE; - return grub_error (GRUB_ERR_BAD_MODULE, "incompatible license"); + return grub_error (GRUB_ERR_BAD_MODULE, + "incompatible license in module %.63s: %.63s", mod->name, + (char *) e + s->sh_offset); } static grub_err_t grub_dl_resolve_name (grub_dl_t mod, Elf_Ehdr *e) { Elf_Shdr *s; - const char *str; - unsigned i; - s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); - str = (char *) e + s->sh_offset; - - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (grub_strcmp (str + s->sh_name, ".modname") == 0) - { - mod->name = grub_strdup ((char *) e + s->sh_offset); - if (! mod->name) - return grub_errno; - break; - } - - if (i == e->e_shnum) + s = grub_dl_find_section (e, ".modname"); + if (!s) return grub_error (GRUB_ERR_BAD_MODULE, "no module name found"); + mod->name = grub_strdup ((char *) e + s->sh_offset); + if (! mod->name) + return grub_errno; + return GRUB_ERR_NONE; } @@ -515,47 +523,41 @@ static grub_err_t grub_dl_resolve_dependencies (grub_dl_t mod, Elf_Ehdr *e) { Elf_Shdr *s; - const char *str; - unsigned i; - s = (Elf_Shdr *) ((char *) e + e->e_shoff + e->e_shstrndx * e->e_shentsize); - str = (char *) e + s->sh_offset; + s = grub_dl_find_section (e, ".moddeps"); - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (grub_strcmp (str + s->sh_name, ".moddeps") == 0) - { - const char *name = (char *) e + s->sh_offset; - const char *max = name + s->sh_size; + if (!s) + return GRUB_ERR_NONE; - while ((name < max) && (*name)) - { - grub_dl_t m; - grub_dl_dep_t dep; + const char *name = (char *) e + s->sh_offset; + const char *max = name + s->sh_size; - m = grub_dl_load (name); - if (! m) - return grub_errno; + while ((name < max) && (*name)) + { + grub_dl_t m; + grub_dl_dep_t dep; - grub_dl_ref (m); + m = grub_dl_load (name); + if (! m) + return grub_errno; - dep = (grub_dl_dep_t) grub_malloc (sizeof (*dep)); - if (! dep) - return grub_errno; + grub_dl_ref (m); - dep->mod = m; - dep->next = mod->dep; - mod->dep = dep; + dep = (grub_dl_dep_t) grub_malloc (sizeof (*dep)); + if (! dep) + return grub_errno; - name += grub_strlen (name) + 1; - } - } + dep->mod = m; + dep->next = mod->dep; + mod->dep = dep; + + name += grub_strlen (name) + 1; + } return GRUB_ERR_NONE; } -int +grub_uint64_t grub_dl_ref (grub_dl_t mod) { grub_dl_dep_t dep; @@ -566,10 +568,13 @@ grub_dl_ref (grub_dl_t mod) for (dep = mod->dep; dep; dep = dep->next) grub_dl_ref (dep->mod); - return ++mod->ref_count; + if (grub_add (mod->ref_count, 1, &mod->ref_count)) + grub_fatal ("Module reference count overflow"); + + return mod->ref_count; } -int +grub_uint64_t grub_dl_unref (grub_dl_t mod) { grub_dl_dep_t dep; @@ -580,7 +585,19 @@ grub_dl_unref (grub_dl_t mod) for (dep = mod->dep; dep; dep = dep->next) grub_dl_unref (dep->mod); - return --mod->ref_count; + if (grub_sub (mod->ref_count, 1, &mod->ref_count)) + grub_fatal ("Module reference count underflow"); + + return mod->ref_count; +} + +grub_uint64_t +grub_dl_ref_count (grub_dl_t mod) +{ + if (mod == NULL) + return 0; + + return mod->ref_count; } static void @@ -591,9 +608,134 @@ grub_dl_flush_cache (grub_dl_t mod) grub_arch_sync_caches (mod->base, mod->sz); } +static grub_err_t +grub_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +{ + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + unsigned i; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_REL || s->sh_type == SHT_RELA) + { + grub_dl_segment_t seg; + grub_err_t err; + + if (!(s->sh_flags & SHF_INFO_LINK)) + continue; + + /* Find the target segment. */ + for (seg = mod->segment; seg; seg = seg->next) + if (seg->section == s->sh_info) + break; + + if (seg) + { + if (!mod->symtab) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation without symbol table"); + + err = grub_arch_dl_relocate_symbols (mod, ehdr, s, seg); + if (err) + return err; + } + } + + return GRUB_ERR_NONE; +} + +/* Only define this on EFI to save space in core. */ +#ifdef GRUB_MACHINE_EFI +static grub_err_t +grub_dl_set_mem_attrs (grub_dl_t mod, void *ehdr) +{ + unsigned i; + const Elf_Shdr *s; + const Elf_Ehdr *e = ehdr; + grub_err_t err; +#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \ + !defined (__loongarch__) + grub_size_t arch_addralign = DL_ALIGN; + grub_addr_t tgaddr; + grub_size_t tgsz; +#endif + + for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize)) + { + grub_dl_segment_t seg; + grub_uint64_t set_attrs = GRUB_MEM_ATTR_R; + grub_uint64_t clear_attrs = GRUB_MEM_ATTR_W | GRUB_MEM_ATTR_X; + + for (seg = mod->segment; seg; seg = seg->next) + /* Does this ELF section's index match GRUB DL segment? */ + if (seg->section == i) + break; + + /* No GRUB DL segment found for this ELF section, skip it. */ + if (!seg) + continue; + + if (seg->size == 0 || !(s->sh_flags & SHF_ALLOC)) + continue; + + if (s->sh_flags & SHF_WRITE) + { + set_attrs |= GRUB_MEM_ATTR_W; + clear_attrs &= ~GRUB_MEM_ATTR_W; + } + + if (s->sh_flags & SHF_EXECINSTR) + { + set_attrs |= GRUB_MEM_ATTR_X; + clear_attrs &= ~GRUB_MEM_ATTR_X; + } + + err = grub_update_mem_attrs ((grub_addr_t) seg->addr, seg->size, + set_attrs, clear_attrs); + if (err != GRUB_ERR_NONE) + return err; + } + +#if !defined (__i386__) && !defined (__x86_64__) && !defined(__riscv) && \ + !defined (__loongarch__) + tgaddr = grub_min ((grub_addr_t) mod->tramp, (grub_addr_t) mod->got); + tgsz = grub_max ((grub_addr_t) mod->trampptr, (grub_addr_t) mod->gotptr) - tgaddr; + + if (tgsz) + { + tgsz = ALIGN_UP (tgsz, arch_addralign); + + if (tgaddr < (grub_addr_t) mod->base || + tgsz > (grub_addr_t) -1 - tgaddr || + tgaddr + tgsz > (grub_addr_t) mod->base + mod->sz) + return grub_error (GRUB_ERR_BUG, + "BUG: trying to protect pages outside of module " + "allocation (\"%s\"): module base %p, size 0x%" + PRIxGRUB_SIZE "; tramp/GOT base 0x%" PRIxGRUB_ADDR + ", size 0x%" PRIxGRUB_SIZE, + mod->name, mod->base, mod->sz, tgaddr, tgsz); + err = grub_update_mem_attrs (tgaddr, tgsz, GRUB_MEM_ATTR_R | GRUB_MEM_ATTR_X, GRUB_MEM_ATTR_W); + if (err != GRUB_ERR_NONE) + return err; + } +#endif + + return GRUB_ERR_NONE; +} +#else +static grub_err_t +grub_dl_set_mem_attrs (grub_dl_t mod __attribute__ ((unused)), void *ehdr __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} +#endif + /* Load a module from core memory. */ grub_dl_t -grub_dl_load_core (void *addr, grub_size_t size) +grub_dl_load_core_noinit (void *addr, grub_size_t size) { Elf_Ehdr *e; grub_dl_t mod; @@ -611,7 +753,7 @@ grub_dl_load_core (void *addr, grub_size_t size) } /* Make sure that every section is within the core. */ - if (size < e->e_shoff + e->e_shentsize * e->e_shnum) + if (size < e->e_shoff + (grub_uint32_t) e->e_shentsize * e->e_shnum) { grub_error (GRUB_ERR_BAD_OS, "ELF sections outside core"); return 0; @@ -632,12 +774,13 @@ grub_dl_load_core (void *addr, grub_size_t size) constitutes linking) and GRUB core being licensed under GPLv3+. Be sure to understand your license obligations. */ - if (grub_dl_check_license (e) - || grub_dl_resolve_name (mod, e) + if (grub_dl_resolve_name (mod, e) + || grub_dl_check_license (mod, e) || grub_dl_resolve_dependencies (mod, e) || grub_dl_load_segments (mod, e) || grub_dl_resolve_symbols (mod, e) - || grub_arch_dl_relocate_symbols (mod, e)) + || grub_dl_relocate_symbols (mod, e) + || grub_dl_set_mem_attrs (mod, e)) { mod->fini = 0; grub_dl_unload (mod); @@ -648,7 +791,6 @@ grub_dl_load_core (void *addr, grub_size_t size) grub_dprintf ("modules", "module name: %s\n", mod->name); grub_dprintf ("modules", "init function: %p\n", mod->init); - grub_dl_call_init (mod); if (grub_dl_add (mod)) { @@ -659,6 +801,25 @@ grub_dl_load_core (void *addr, grub_size_t size) return mod; } +grub_dl_t +grub_dl_load_core (void *addr, grub_size_t size) +{ + grub_dl_t mod; + + grub_boot_time ("Parsing module"); + + mod = grub_dl_load_core_noinit (addr, size); + + if (!mod) + return NULL; + + grub_boot_time ("Initing module %s", mod->name); + grub_dl_init (mod); + grub_boot_time ("Module %s inited", mod->name); + + return mod; +} + /* Load a module from the file FILENAME. */ grub_dl_t grub_dl_load_file (const char *filename) @@ -668,7 +829,9 @@ grub_dl_load_file (const char *filename) void *core = 0; grub_dl_t mod = 0; - file = grub_file_open (filename); + grub_boot_time ("Loading module %s", filename); + + file = grub_file_open (filename, GRUB_FILE_TYPE_GRUB_MODULE); if (! file) return 0; @@ -713,6 +876,9 @@ grub_dl_load (const char *name) if (mod) return mod; + if (grub_no_modules) + return 0; + if (! grub_dl_dir) { grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); return 0; @@ -759,7 +925,11 @@ grub_dl_unload (grub_dl_t mod) grub_free (dep); } +#ifdef GRUB_MACHINE_EMU + grub_dl_osdep_dl_free (mod->base); +#else grub_free (mod->base); +#endif grub_free (mod->name); #ifdef GRUB_MODULES_MACHINE_READONLY grub_free (mod->symtab); @@ -767,23 +937,3 @@ grub_dl_unload (grub_dl_t mod) grub_free (mod); return 1; } - -/* Unload unneeded modules. */ -void -grub_dl_unload_unneeded (void) -{ - /* Because grub_dl_remove modifies the list of modules, this - implementation is tricky. */ - grub_dl_t p = grub_dl_head; - - while (p) - { - if (grub_dl_unload (p)) - { - p = grub_dl_head; - continue; - } - - p = p->next; - } -} diff --git a/grub-core/kern/efi/acpi.c b/grub-core/kern/efi/acpi.c new file mode 100644 index 000000000..828e6dbb2 --- /dev/null +++ b/grub-core/kern/efi/acpi.c @@ -0,0 +1,37 @@ +/* acpi.c - get acpi tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +struct grub_acpi_rsdp_v10 * +grub_machine_acpi_get_rsdpv1 (void) +{ + static grub_guid_t acpi_guid = GRUB_EFI_ACPI_TABLE_GUID; + + return (struct grub_acpi_rsdp_v10 *) grub_efi_find_configuration_table (&acpi_guid); +} + +struct grub_acpi_rsdp_v20 * +grub_machine_acpi_get_rsdpv2 (void) +{ + static grub_guid_t acpi20_guid = GRUB_EFI_ACPI_20_TABLE_GUID; + + return (struct grub_acpi_rsdp_v20 *) grub_efi_find_configuration_table (&acpi20_guid); +} diff --git a/grub-core/kern/efi/debug.c b/grub-core/kern/efi/debug.c new file mode 100644 index 000000000..5d2ab1a36 --- /dev/null +++ b/grub-core/kern/efi/debug.c @@ -0,0 +1,38 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ +/* debug.c - aides for debugging the EFI application */ + +#include +#include +#include + +static grub_err_t +grub_cmd_gdbinfo (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_efi_print_gdb_info (); + return 0; +} + +void +grub_efi_register_debug_commands (void) +{ + grub_register_command ("gdbinfo", grub_cmd_gdbinfo, 0, + N_("Print infomation useful for GDB debugging")); +} diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index 02d2f9a00..b93ae3aba 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -27,6 +27,7 @@ #include #include #include +#include /* The handle of GRUB itself. Filled in by the startup code. */ grub_efi_handle_t grub_efi_image_handle; @@ -34,18 +35,19 @@ grub_efi_handle_t grub_efi_image_handle; /* The pointer to a system table. Filled in by the startup code. */ grub_efi_system_table_t *grub_efi_system_table; -static grub_efi_guid_t console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID; -static grub_efi_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID; -static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID; +static grub_guid_t console_control_guid = GRUB_EFI_CONSOLE_CONTROL_GUID; +static grub_guid_t loaded_image_guid = GRUB_EFI_LOADED_IMAGE_GUID; +static grub_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID; void * -grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration) +grub_efi_locate_protocol (grub_guid_t *protocol, void *registration) { void *interface; grub_efi_status_t status; - status = efi_call_3 (grub_efi_system_table->boot_services->locate_protocol, - protocol, registration, &interface); + status = grub_efi_system_table->boot_services->locate_protocol (protocol, + registration, + &interface); if (status != GRUB_EFI_SUCCESS) return 0; @@ -57,7 +59,7 @@ grub_efi_locate_protocol (grub_efi_guid_t *protocol, void *registration) from the heap. */ grub_efi_handle_t * grub_efi_locate_handle (grub_efi_locate_search_type_t search_type, - grub_efi_guid_t *protocol, + grub_guid_t *protocol, void *search_key, grub_efi_uintn_t *num_handles) { @@ -71,7 +73,7 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type, return 0; b = grub_efi_system_table->boot_services; - status = efi_call_5 (b->locate_handle, search_type, protocol, search_key, + status = b->locate_handle (search_type, protocol, search_key, &buffer_size, buffer); if (status == GRUB_EFI_BUFFER_TOO_SMALL) { @@ -80,7 +82,7 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type, if (! buffer) return 0; - status = efi_call_5 (b->locate_handle, search_type, protocol, search_key, + status = b->locate_handle (search_type, protocol, search_key, &buffer_size, buffer); } @@ -96,7 +98,7 @@ grub_efi_locate_handle (grub_efi_locate_search_type_t search_type, void * grub_efi_open_protocol (grub_efi_handle_t handle, - grub_efi_guid_t *protocol, + grub_guid_t *protocol, grub_efi_uint32_t attributes) { grub_efi_boot_services_t *b; @@ -104,18 +106,26 @@ grub_efi_open_protocol (grub_efi_handle_t handle, void *interface; b = grub_efi_system_table->boot_services; - status = efi_call_6 (b->open_protocol, handle, - protocol, - &interface, - grub_efi_image_handle, - 0, - attributes); + status = b->open_protocol (handle, + protocol, + &interface, + grub_efi_image_handle, + 0, + attributes); if (status != GRUB_EFI_SUCCESS) return 0; return interface; } +grub_efi_status_t +grub_efi_close_protocol (grub_efi_handle_t handle, grub_guid_t *protocol) +{ + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services; + + return b->close_protocol (handle, protocol, grub_efi_image_handle, NULL); +} + int grub_efi_set_text_mode (int on) { @@ -128,12 +138,12 @@ grub_efi_set_text_mode (int on) already in text mode. */ return 1; - if (efi_call_4 (c->get_mode, c, &mode, 0, 0) != GRUB_EFI_SUCCESS) + if (c->get_mode (c, &mode, 0, 0) != GRUB_EFI_SUCCESS) return 0; new_mode = on ? GRUB_EFI_SCREEN_TEXT : GRUB_EFI_SCREEN_GRAPHICS; if (mode != new_mode) - if (efi_call_2 (c->set_mode, c, new_mode) != GRUB_EFI_SUCCESS) + if (c->set_mode (c, new_mode) != GRUB_EFI_SUCCESS) return 0; return 1; @@ -142,7 +152,7 @@ grub_efi_set_text_mode (int on) void grub_efi_stall (grub_efi_uintn_t microseconds) { - efi_call_1 (grub_efi_system_table->boot_services->stall, microseconds); + grub_efi_system_table->boot_services->stall (microseconds); } grub_efi_loaded_image_t * @@ -153,12 +163,23 @@ grub_efi_get_loaded_image (grub_efi_handle_t image_handle) GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); } +void +grub_reboot (void) +{ + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN | + GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY); + grub_efi_system_table->runtime_services->reset_system (GRUB_EFI_RESET_COLD, + GRUB_EFI_SUCCESS, 0, + NULL); + for (;;) ; +} + void grub_exit (void) { - grub_efi_fini (); - efi_call_4 (grub_efi_system_table->boot_services->exit, - grub_efi_image_handle, GRUB_EFI_SUCCESS, 0, 0); + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); + grub_efi_system_table->boot_services->exit (grub_efi_image_handle, + GRUB_EFI_SUCCESS, 0, 0); for (;;) ; } @@ -172,8 +193,8 @@ grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size, grub_efi_status_t status; r = grub_efi_system_table->runtime_services; - status = efi_call_4 (r->set_virtual_address_map, memory_map_size, - descriptor_size, descriptor_version, virtual_map); + status = r->set_virtual_address_map (memory_map_size, descriptor_size, + descriptor_version, virtual_map); if (status == GRUB_EFI_SUCCESS) return GRUB_ERR_NONE; @@ -181,52 +202,117 @@ grub_efi_set_virtual_address_map (grub_efi_uintn_t memory_map_size, return grub_error (GRUB_ERR_IO, "set_virtual_address_map failed"); } -void * -grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, - grub_size_t *datasize_out) +grub_err_t +grub_efi_set_variable_with_attributes (const char *var, const grub_guid_t *guid, + void *data, grub_size_t datasize, grub_efi_uint32_t attributes) +{ + grub_efi_status_t status; + grub_efi_runtime_services_t *r; + grub_efi_char16_t *var16; + + grub_utf8_to_utf16_alloc (var, &var16, NULL); + + if (var16 == NULL) + return grub_errno; + + r = grub_efi_system_table->runtime_services; + + status = r->set_variable (var16, guid, attributes, datasize, data); + grub_free (var16); + if (status == GRUB_EFI_SUCCESS) + return GRUB_ERR_NONE; + + return grub_error (GRUB_ERR_IO, "could not set EFI variable `%s'", var); +} + +grub_err_t +grub_efi_set_variable (const char *var, const grub_guid_t *guid, + void *data, grub_size_t datasize) +{ + return grub_efi_set_variable_with_attributes (var, guid, data, datasize, + GRUB_EFI_VARIABLE_NON_VOLATILE + | GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS + | GRUB_EFI_VARIABLE_RUNTIME_ACCESS); +} + +grub_efi_status_t +grub_efi_get_variable_with_attributes (const char *var, + const grub_guid_t *guid, + grub_size_t *datasize_out, + void **data_out, + grub_efi_uint32_t *attributes) { grub_efi_status_t status; grub_efi_uintn_t datasize = 0; grub_efi_runtime_services_t *r; grub_efi_char16_t *var16; void *data; - grub_size_t len, len16; + *data_out = NULL; *datasize_out = 0; - len = grub_strlen (var); - len16 = len * GRUB_MAX_UTF16_PER_UTF8; - var16 = grub_malloc ((len16 + 1) * sizeof (var16[0])); - if (!var16) - return NULL; - len16 = grub_utf8_to_utf16 (var16, len16, (grub_uint8_t *) var, len, NULL); - var16[len16] = 0; + grub_utf8_to_utf16_alloc (var, &var16, NULL); + if (var16 == NULL) + return grub_errno; r = grub_efi_system_table->runtime_services; - status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, NULL); + status = r->get_variable (var16, guid, NULL, &datasize, NULL); - if (!datasize) - return NULL; + if (status != GRUB_EFI_BUFFER_TOO_SMALL || !datasize) + { + grub_free (var16); + return status; + } data = grub_malloc (datasize); if (!data) { grub_free (var16); - return NULL; + return GRUB_EFI_OUT_OF_RESOURCES; } - status = efi_call_5 (r->get_variable, var16, guid, NULL, &datasize, data); + status = r->get_variable (var16, guid, attributes, &datasize, data); grub_free (var16); if (status == GRUB_EFI_SUCCESS) { + *data_out = data; *datasize_out = datasize; - return data; + return status; } grub_free (data); - return NULL; + return status; +} + +grub_err_t +grub_efi_set_variable_to_string (const char *name, const grub_guid_t *guid, + const char *value, grub_efi_uint32_t attributes) +{ + grub_efi_char16_t *value_16; + grub_ssize_t len16; + grub_err_t status; + + len16 = grub_utf8_to_utf16_alloc (value, &value_16, NULL); + + if (len16 < 0) + return grub_errno; + + status = grub_efi_set_variable_with_attributes (name, guid, + (void *) value_16, (len16 + 1) * sizeof (value_16[0]), + attributes); + + grub_free (value_16); + + return status; +} + +grub_efi_status_t +grub_efi_get_variable (const char *var, const grub_guid_t *guid, + grub_size_t *datasize_out, void **data_out) +{ + return grub_efi_get_variable_with_attributes (var, guid, datasize_out, data_out, NULL); } #pragma GCC diagnostic ignored "-Wcast-align" @@ -234,10 +320,11 @@ grub_efi_get_variable (const char *var, const grub_efi_guid_t *guid, /* Search the mods section from the PE32/PE32+ image. This code uses a PE32 header, but should work with PE32+ as well. */ grub_addr_t -grub_efi_modules_addr (void) +grub_efi_section_addr (const char *section_name) { grub_efi_loaded_image_t *image; - struct grub_pe32_header *header; + struct grub_msdos_image_header *header; + struct grub_pe_image_header *pe_image_header; struct grub_pe32_coff_header *coff_header; struct grub_pe32_section_table *sections; struct grub_pe32_section_table *section; @@ -249,7 +336,10 @@ grub_efi_modules_addr (void) return 0; header = image->image_base; - coff_header = &(header->coff_header); + pe_image_header + = (struct grub_pe_image_header *) ((char *) header + + header->pe_image_header_offset); + coff_header = &(pe_image_header->coff_header); sections = (struct grub_pe32_section_table *) ((char *) coff_header + sizeof (*coff_header) @@ -259,29 +349,80 @@ grub_efi_modules_addr (void) i < coff_header->num_sections; i++, section++) { - if (grub_strcmp (section->name, "mods") == 0) + if (grub_strcmp (section->name, section_name) == 0) break; } if (i == coff_header->num_sections) - return 0; + { + grub_dprintf("sections", "section %d is last section; invalid.\n", i); + return 0; + } info = (struct grub_module_info *) ((char *) image->image_base + section->virtual_address); - if (info->magic != GRUB_MODULE_MAGIC) - return 0; + if (section->name[0] != '.' && info->magic != GRUB_MODULE_MAGIC) + { + grub_dprintf("sections", + "section %d has bad magic %08x, should be %08x\n", + i, info->magic, GRUB_MODULE_MAGIC); + return 0; + } + grub_dprintf("sections", "returning section info for section %d: \"%s\"\n", + i, section->name); return (grub_addr_t) info; } #pragma GCC diagnostic error "-Wcast-align" char * -grub_efi_get_filename (grub_efi_device_path_t *dp) +grub_efi_get_filename (grub_efi_device_path_t *dp0) { - char *name = 0; + char *name = 0, *p, *pi; + grub_size_t filesize = 0; + grub_efi_device_path_t *dp; - while (1) + if (!dp0) + return NULL; + + dp = dp0; + + while (dp) + { + grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); + grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); + + if (type == GRUB_EFI_END_DEVICE_PATH_TYPE) + break; + if (type == GRUB_EFI_MEDIA_DEVICE_PATH_TYPE + && subtype == GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE) + { + grub_efi_uint16_t len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); + + if (len < 4) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, + "malformed EFI Device Path node has length=%d", len); + return NULL; + } + len = (len - 4) / sizeof (grub_efi_char16_t); + filesize += GRUB_MAX_UTF8_PER_UTF16 * len + 2; + } + + dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); + } + + if (!filesize) + return NULL; + + dp = dp0; + + p = name = grub_malloc (filesize); + if (!name) + return NULL; + + while (dp) { grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); @@ -293,45 +434,55 @@ grub_efi_get_filename (grub_efi_device_path_t *dp) { grub_efi_file_path_device_path_t *fp; grub_efi_uint16_t len; - char *p; - grub_size_t size; + grub_efi_char16_t *dup_name; - if (name) + *p++ = '/'; + + len = GRUB_EFI_DEVICE_PATH_LENGTH (dp); + if (len < 4) { - size = grub_strlen (name); - name[size] = '/'; - size++; + grub_error (GRUB_ERR_OUT_OF_RANGE, + "malformed EFI Device Path node has length=%d", len); + grub_free (name); + return NULL; } - else - size = 0; - len = ((GRUB_EFI_DEVICE_PATH_LENGTH (dp) - 4) - / sizeof (grub_efi_char16_t)); - p = grub_realloc (name, size + len * 4 + 1); - if (! p) + len = (len - 4) / sizeof (grub_efi_char16_t); + fp = (grub_efi_file_path_device_path_t *) dp; + /* According to EFI spec Path Name is NULL terminated */ + while (len > 0 && fp->path_name[len - 1] == 0) + len--; + + dup_name = grub_calloc (len, sizeof (*dup_name)); + if (!dup_name) { grub_free (name); - return 0; + return NULL; } - - name = p; - fp = (grub_efi_file_path_device_path_t *) dp; - *grub_utf16_to_utf8 ((grub_uint8_t *) name + size, - fp->path_name, len) = '\0'; + p = (char *) grub_utf16_to_utf8 ((unsigned char *) p, + grub_memcpy (dup_name, fp->path_name, len * sizeof (*dup_name)), + len); + grub_free (dup_name); } dp = GRUB_EFI_NEXT_DEVICE_PATH (dp); } - if (name) + *p = '\0'; + + for (pi = name, p = name; *pi;) { /* EFI breaks paths with backslashes. */ - char *p; - - for (p = name; *p; p++) - if (*p == '\\') - *p = '/'; + if (*pi == '\\' || *pi == '/') + { + *p++ = '/'; + while (*pi == '\\' || *pi == '/') + pi++; + continue; + } + *p++ = *pi++; } + *p = '\0'; return name; } @@ -343,11 +494,86 @@ grub_efi_get_device_path (grub_efi_handle_t handle) GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); } +/* Return the device path node right before the end node. */ +grub_efi_device_path_t * +grub_efi_find_last_device_path (const grub_efi_device_path_t *dp) +{ + grub_efi_device_path_t *next, *p; + + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (dp)) + return 0; + + for (p = (grub_efi_device_path_t *) dp, next = GRUB_EFI_NEXT_DEVICE_PATH (p); + ! GRUB_EFI_END_ENTIRE_DEVICE_PATH (next); + p = next, next = GRUB_EFI_NEXT_DEVICE_PATH (next)) + ; + + return p; +} + +/* Duplicate a device path. */ +grub_efi_device_path_t * +grub_efi_duplicate_device_path (const grub_efi_device_path_t *dp) +{ + grub_efi_device_path_t *p; + grub_size_t total_size = 0; + + for (p = (grub_efi_device_path_t *) dp; + ; + p = GRUB_EFI_NEXT_DEVICE_PATH (p)) + { + grub_size_t len = GRUB_EFI_DEVICE_PATH_LENGTH (p); + + /* + * In the event that we find a node that's completely garbage, for + * example if we get to 0x7f 0x01 0x02 0x00 ... (EndInstance with a size + * of 2), GRUB_EFI_END_ENTIRE_DEVICE_PATH() will be true and + * GRUB_EFI_NEXT_DEVICE_PATH() will return NULL, so we won't continue, + * and neither should our consumers, but there won't be any error raised + * even though the device path is junk. + * + * This keeps us from passing junk down back to our caller. + */ + if (len < 4) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, + "malformed EFI Device Path node has length=%" PRIuGRUB_SIZE, len); + return NULL; + } + + total_size += len; + if (GRUB_EFI_END_ENTIRE_DEVICE_PATH (p)) + break; + } + + p = grub_malloc (total_size); + if (! p) + return 0; + + grub_memcpy (p, dp, total_size); + return p; +} + +static void +dump_vendor_path (const char *type, grub_efi_vendor_device_path_t *vendor) +{ + grub_uint32_t vendor_data_len = vendor->header.length - sizeof (*vendor); + grub_printf ("/%sVendor(%pG)[%x: ", type, &vendor->vendor_guid, vendor_data_len); + if (vendor->header.length > sizeof (*vendor)) + { + grub_uint32_t i; + for (i = 0; i < vendor_data_len; i++) + grub_printf ("%02x ", vendor->vendor_defined_data[i]); + } + grub_printf ("]"); +} + + /* Print the chain of Device Path nodes. This is mainly for debugging. */ void grub_efi_print_device_path (grub_efi_device_path_t *dp) { - while (1) + while (GRUB_EFI_DEVICE_PATH_VALID (dp)) { grub_efi_uint8_t type = GRUB_EFI_DEVICE_PATH_TYPE (dp); grub_efi_uint8_t subtype = GRUB_EFI_DEVICE_PATH_SUBTYPE (dp); @@ -377,54 +603,40 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) { case GRUB_EFI_PCI_DEVICE_PATH_SUBTYPE: { - grub_efi_pci_device_path_t pci; - grub_memcpy (&pci, dp, len); + grub_efi_pci_device_path_t *pci + = (grub_efi_pci_device_path_t *) dp; grub_printf ("/PCI(%x,%x)", - (unsigned) pci.function, (unsigned) pci.device); + (unsigned) pci->function, (unsigned) pci->device); } break; case GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE: { - grub_efi_pccard_device_path_t pccard; - grub_memcpy (&pccard, dp, len); + grub_efi_pccard_device_path_t *pccard + = (grub_efi_pccard_device_path_t *) dp; grub_printf ("/PCCARD(%x)", - (unsigned) pccard.function); + (unsigned) pccard->function); } break; case GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE: { - grub_efi_memory_mapped_device_path_t mmapped; - grub_memcpy (&mmapped, dp, len); + grub_efi_memory_mapped_device_path_t *mmapped + = (grub_efi_memory_mapped_device_path_t *) dp; grub_printf ("/MMap(%x,%llx,%llx)", - (unsigned) mmapped.memory_type, - (unsigned long long) mmapped.start_address, - (unsigned long long) mmapped.end_address); + (unsigned) mmapped->memory_type, + (unsigned long long) mmapped->start_address, + (unsigned long long) mmapped->end_address); } break; case GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE: - { - grub_efi_vendor_device_path_t vendor; - grub_memcpy (&vendor, dp, sizeof (vendor)); - grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)", - (unsigned) vendor.vendor_guid.data1, - (unsigned) vendor.vendor_guid.data2, - (unsigned) vendor.vendor_guid.data3, - (unsigned) vendor.vendor_guid.data4[0], - (unsigned) vendor.vendor_guid.data4[1], - (unsigned) vendor.vendor_guid.data4[2], - (unsigned) vendor.vendor_guid.data4[3], - (unsigned) vendor.vendor_guid.data4[4], - (unsigned) vendor.vendor_guid.data4[5], - (unsigned) vendor.vendor_guid.data4[6], - (unsigned) vendor.vendor_guid.data4[7]); - } + dump_vendor_path ("Hardware", + (grub_efi_vendor_device_path_t *) dp); break; case GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE: { - grub_efi_controller_device_path_t controller; - grub_memcpy (&controller, dp, len); + grub_efi_controller_device_path_t *controller + = (grub_efi_controller_device_path_t *) dp; grub_printf ("/Ctrl(%x)", - (unsigned) controller.controller_number); + (unsigned) controller->controller_number); } break; default: @@ -438,31 +650,31 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) { case GRUB_EFI_ACPI_DEVICE_PATH_SUBTYPE: { - grub_efi_acpi_device_path_t acpi; - grub_memcpy (&acpi, dp, len); + grub_efi_acpi_device_path_t *acpi + = (grub_efi_acpi_device_path_t *) dp; grub_printf ("/ACPI(%x,%x)", - (unsigned) acpi.hid, - (unsigned) acpi.uid); + (unsigned) acpi->hid, + (unsigned) acpi->uid); } break; case GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE: { - grub_efi_expanded_acpi_device_path_t eacpi; - grub_memcpy (&eacpi, dp, sizeof (eacpi)); + grub_efi_expanded_acpi_device_path_t *eacpi + = (grub_efi_expanded_acpi_device_path_t *) dp; grub_printf ("/ACPI("); if (GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)[0] == '\0') - grub_printf ("%x,", (unsigned) eacpi.hid); + grub_printf ("%x,", (unsigned) eacpi->hid); else grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_HIDSTR (dp)); if (GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)[0] == '\0') - grub_printf ("%x,", (unsigned) eacpi.uid); + grub_printf ("%x,", (unsigned) eacpi->uid); else grub_printf ("%s,", GRUB_EFI_EXPANDED_ACPI_UIDSTR (dp)); if (GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)[0] == '\0') - grub_printf ("%x)", (unsigned) eacpi.cid); + grub_printf ("%x)", (unsigned) eacpi->cid); else grub_printf ("%s)", GRUB_EFI_EXPANDED_ACPI_CIDSTR (dp)); } @@ -478,167 +690,172 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) { case GRUB_EFI_ATAPI_DEVICE_PATH_SUBTYPE: { - grub_efi_atapi_device_path_t atapi; - grub_memcpy (&atapi, dp, len); + grub_efi_atapi_device_path_t *atapi + = (grub_efi_atapi_device_path_t *) dp; grub_printf ("/ATAPI(%x,%x,%x)", - (unsigned) atapi.primary_secondary, - (unsigned) atapi.slave_master, - (unsigned) atapi.lun); + (unsigned) atapi->primary_secondary, + (unsigned) atapi->slave_master, + (unsigned) atapi->lun); } break; case GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE: { - grub_efi_scsi_device_path_t scsi; - grub_memcpy (&scsi, dp, len); + grub_efi_scsi_device_path_t *scsi + = (grub_efi_scsi_device_path_t *) dp; grub_printf ("/SCSI(%x,%x)", - (unsigned) scsi.pun, - (unsigned) scsi.lun); + (unsigned) scsi->pun, + (unsigned) scsi->lun); } break; case GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE: { - grub_efi_fibre_channel_device_path_t fc; - grub_memcpy (&fc, dp, len); + grub_efi_fibre_channel_device_path_t *fc + = (grub_efi_fibre_channel_device_path_t *) dp; grub_printf ("/FibreChannel(%llx,%llx)", - (unsigned long long) fc.wwn, - (unsigned long long) fc.lun); + (unsigned long long) fc->wwn, + (unsigned long long) fc->lun); } break; case GRUB_EFI_1394_DEVICE_PATH_SUBTYPE: { - grub_efi_1394_device_path_t firewire; - grub_memcpy (&firewire, dp, len); - grub_printf ("/1394(%llx)", (unsigned long long) firewire.guid); + grub_efi_1394_device_path_t *firewire + = (grub_efi_1394_device_path_t *) dp; + grub_printf ("/1394(%llx)", + (unsigned long long) firewire->guid); } break; case GRUB_EFI_USB_DEVICE_PATH_SUBTYPE: { - grub_efi_usb_device_path_t usb; - grub_memcpy (&usb, dp, len); + grub_efi_usb_device_path_t *usb + = (grub_efi_usb_device_path_t *) dp; grub_printf ("/USB(%x,%x)", - (unsigned) usb.parent_port_number, - (unsigned) usb.interface); + (unsigned) usb->parent_port_number, + (unsigned) usb->usb_interface); } break; case GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE: { - grub_efi_usb_class_device_path_t usb_class; - grub_memcpy (&usb_class, dp, len); + grub_efi_usb_class_device_path_t *usb_class + = (grub_efi_usb_class_device_path_t *) dp; grub_printf ("/USBClass(%x,%x,%x,%x,%x)", - (unsigned) usb_class.vendor_id, - (unsigned) usb_class.product_id, - (unsigned) usb_class.device_class, - (unsigned) usb_class.device_subclass, - (unsigned) usb_class.device_protocol); + (unsigned) usb_class->vendor_id, + (unsigned) usb_class->product_id, + (unsigned) usb_class->device_class, + (unsigned) usb_class->device_subclass, + (unsigned) usb_class->device_protocol); } break; case GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE: { - grub_efi_i2o_device_path_t i2o; - grub_memcpy (&i2o, dp, len); - grub_printf ("/I2O(%x)", (unsigned) i2o.tid); + grub_efi_i2o_device_path_t *i2o + = (grub_efi_i2o_device_path_t *) dp; + grub_printf ("/I2O(%x)", (unsigned) i2o->tid); } break; case GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE: { - grub_efi_mac_address_device_path_t mac; - grub_memcpy (&mac, dp, len); + grub_efi_mac_address_device_path_t *mac + = (grub_efi_mac_address_device_path_t *) dp; grub_printf ("/MacAddr(%02x:%02x:%02x:%02x:%02x:%02x,%x)", - (unsigned) mac.mac_address[0], - (unsigned) mac.mac_address[1], - (unsigned) mac.mac_address[2], - (unsigned) mac.mac_address[3], - (unsigned) mac.mac_address[4], - (unsigned) mac.mac_address[5], - (unsigned) mac.if_type); + (unsigned) mac->mac_address[0], + (unsigned) mac->mac_address[1], + (unsigned) mac->mac_address[2], + (unsigned) mac->mac_address[3], + (unsigned) mac->mac_address[4], + (unsigned) mac->mac_address[5], + (unsigned) mac->if_type); } break; case GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE: { - grub_efi_ipv4_device_path_t ipv4; - grub_memcpy (&ipv4, dp, len); + grub_efi_ipv4_device_path_t *ipv4 + = (grub_efi_ipv4_device_path_t *) dp; grub_printf ("/IPv4(%u.%u.%u.%u,%u.%u.%u.%u,%u,%u,%x,%x)", - (unsigned) ipv4.local_ip_address[0], - (unsigned) ipv4.local_ip_address[1], - (unsigned) ipv4.local_ip_address[2], - (unsigned) ipv4.local_ip_address[3], - (unsigned) ipv4.remote_ip_address[0], - (unsigned) ipv4.remote_ip_address[1], - (unsigned) ipv4.remote_ip_address[2], - (unsigned) ipv4.remote_ip_address[3], - (unsigned) ipv4.local_port, - (unsigned) ipv4.remote_port, - (unsigned) ipv4.protocol, - (unsigned) ipv4.static_ip_address); + (unsigned) ipv4->local_ip_address[0], + (unsigned) ipv4->local_ip_address[1], + (unsigned) ipv4->local_ip_address[2], + (unsigned) ipv4->local_ip_address[3], + (unsigned) ipv4->remote_ip_address[0], + (unsigned) ipv4->remote_ip_address[1], + (unsigned) ipv4->remote_ip_address[2], + (unsigned) ipv4->remote_ip_address[3], + (unsigned) ipv4->local_port, + (unsigned) ipv4->remote_port, + (unsigned) ipv4->protocol, + (unsigned) ipv4->static_ip_address); } break; case GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE: { - grub_efi_ipv6_device_path_t ipv6; - grub_memcpy (&ipv6, dp, len); + grub_efi_ipv6_device_path_t *ipv6 + = (grub_efi_ipv6_device_path_t *) dp; grub_printf ("/IPv6(%x:%x:%x:%x:%x:%x:%x:%x,%x:%x:%x:%x:%x:%x:%x:%x,%u,%u,%x,%x)", - (unsigned) ipv6.local_ip_address[0], - (unsigned) ipv6.local_ip_address[1], - (unsigned) ipv6.local_ip_address[2], - (unsigned) ipv6.local_ip_address[3], - (unsigned) ipv6.local_ip_address[4], - (unsigned) ipv6.local_ip_address[5], - (unsigned) ipv6.local_ip_address[6], - (unsigned) ipv6.local_ip_address[7], - (unsigned) ipv6.remote_ip_address[0], - (unsigned) ipv6.remote_ip_address[1], - (unsigned) ipv6.remote_ip_address[2], - (unsigned) ipv6.remote_ip_address[3], - (unsigned) ipv6.remote_ip_address[4], - (unsigned) ipv6.remote_ip_address[5], - (unsigned) ipv6.remote_ip_address[6], - (unsigned) ipv6.remote_ip_address[7], - (unsigned) ipv6.local_port, - (unsigned) ipv6.remote_port, - (unsigned) ipv6.protocol, - (unsigned) ipv6.static_ip_address); + (unsigned) ipv6->local_ip_address[0], + (unsigned) ipv6->local_ip_address[1], + (unsigned) ipv6->local_ip_address[2], + (unsigned) ipv6->local_ip_address[3], + (unsigned) ipv6->local_ip_address[4], + (unsigned) ipv6->local_ip_address[5], + (unsigned) ipv6->local_ip_address[6], + (unsigned) ipv6->local_ip_address[7], + (unsigned) ipv6->remote_ip_address[0], + (unsigned) ipv6->remote_ip_address[1], + (unsigned) ipv6->remote_ip_address[2], + (unsigned) ipv6->remote_ip_address[3], + (unsigned) ipv6->remote_ip_address[4], + (unsigned) ipv6->remote_ip_address[5], + (unsigned) ipv6->remote_ip_address[6], + (unsigned) ipv6->remote_ip_address[7], + (unsigned) ipv6->local_port, + (unsigned) ipv6->remote_port, + (unsigned) ipv6->protocol, + (unsigned) ipv6->static_ip_address); } break; case GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE: { - grub_efi_infiniband_device_path_t ib; - grub_memcpy (&ib, dp, len); + grub_efi_infiniband_device_path_t *ib + = (grub_efi_infiniband_device_path_t *) dp; grub_printf ("/InfiniBand(%x,%llx,%llx,%llx)", - (unsigned) ib.port_gid[0], /* XXX */ - (unsigned long long) ib.remote_id, - (unsigned long long) ib.target_port_id, - (unsigned long long) ib.device_id); + (unsigned) ib->port_gid[0], /* XXX */ + (unsigned long long) ib->remote_id, + (unsigned long long) ib->target_port_id, + (unsigned long long) ib->device_id); } break; case GRUB_EFI_UART_DEVICE_PATH_SUBTYPE: { - grub_efi_uart_device_path_t uart; - grub_memcpy (&uart, dp, len); + grub_efi_uart_device_path_t *uart + = (grub_efi_uart_device_path_t *) dp; grub_printf ("/UART(%llu,%u,%x,%x)", - (unsigned long long) uart.baud_rate, - uart.data_bits, - uart.parity, - uart.stop_bits); + (unsigned long long) uart->baud_rate, + uart->data_bits, + uart->parity, + uart->stop_bits); } break; - case GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE: + case GRUB_EFI_SATA_DEVICE_PATH_SUBTYPE: { - grub_efi_vendor_messaging_device_path_t vendor; - grub_memcpy (&vendor, dp, sizeof (vendor)); - grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)", - (unsigned) vendor.vendor_guid.data1, - (unsigned) vendor.vendor_guid.data2, - (unsigned) vendor.vendor_guid.data3, - (unsigned) vendor.vendor_guid.data4[0], - (unsigned) vendor.vendor_guid.data4[1], - (unsigned) vendor.vendor_guid.data4[2], - (unsigned) vendor.vendor_guid.data4[3], - (unsigned) vendor.vendor_guid.data4[4], - (unsigned) vendor.vendor_guid.data4[5], - (unsigned) vendor.vendor_guid.data4[6], - (unsigned) vendor.vendor_guid.data4[7]); + grub_efi_sata_device_path_t *sata; + sata = (grub_efi_sata_device_path_t *) dp; + grub_printf ("/Sata(%x,%x,%x)", + sata->hba_port, + sata->multiplier_port, + sata->lun); } break; + case GRUB_EFI_VLAN_DEVICE_PATH_SUBTYPE: + { + grub_efi_vlan_device_path_t *vlan; + vlan = (grub_efi_vlan_device_path_t *) dp; + grub_printf ("/Vlan(%u)", vlan->vlan_id); + } + break; + + case GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE: + dump_vendor_path ("Messaging", + (grub_efi_vendor_device_path_t *) dp); + break; default: grub_printf ("/UnknownMessaging(%x)", (unsigned) subtype); break; @@ -650,79 +867,69 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) { case GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE: { - grub_efi_hard_drive_device_path_t hd; - grub_memcpy (&hd, dp, len); + grub_efi_hard_drive_device_path_t *hd = (grub_efi_hard_drive_device_path_t *) dp; grub_printf ("/HD(%u,%llx,%llx,%02x%02x%02x%02x%02x%02x%02x%02x,%x,%x)", - hd.partition_number, - (unsigned long long) hd.partition_start, - (unsigned long long) hd.partition_size, - (unsigned) hd.partition_signature[0], - (unsigned) hd.partition_signature[1], - (unsigned) hd.partition_signature[2], - (unsigned) hd.partition_signature[3], - (unsigned) hd.partition_signature[4], - (unsigned) hd.partition_signature[5], - (unsigned) hd.partition_signature[6], - (unsigned) hd.partition_signature[7], - (unsigned) hd.mbr_type, - (unsigned) hd.signature_type); + hd->partition_number, + (unsigned long long) hd->partition_start, + (unsigned long long) hd->partition_size, + (unsigned) hd->partition_signature[0], + (unsigned) hd->partition_signature[1], + (unsigned) hd->partition_signature[2], + (unsigned) hd->partition_signature[3], + (unsigned) hd->partition_signature[4], + (unsigned) hd->partition_signature[5], + (unsigned) hd->partition_signature[6], + (unsigned) hd->partition_signature[7], + (unsigned) hd->partmap_type, + (unsigned) hd->signature_type); } break; case GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE: { - grub_efi_cdrom_device_path_t cd; - grub_memcpy (&cd, dp, len); + grub_efi_cdrom_device_path_t *cd + = (grub_efi_cdrom_device_path_t *) dp; grub_printf ("/CD(%u,%llx,%llx)", - cd.boot_entry, - (unsigned long long) cd.partition_start, - (unsigned long long) cd.partition_size); + cd->boot_entry, + (unsigned long long) cd->partition_start, + (unsigned long long) cd->partition_size); } break; case GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE: - { - grub_efi_vendor_media_device_path_t vendor; - grub_memcpy (&vendor, dp, sizeof (vendor)); - grub_printf ("/Vendor(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)", - (unsigned) vendor.vendor_guid.data1, - (unsigned) vendor.vendor_guid.data2, - (unsigned) vendor.vendor_guid.data3, - (unsigned) vendor.vendor_guid.data4[0], - (unsigned) vendor.vendor_guid.data4[1], - (unsigned) vendor.vendor_guid.data4[2], - (unsigned) vendor.vendor_guid.data4[3], - (unsigned) vendor.vendor_guid.data4[4], - (unsigned) vendor.vendor_guid.data4[5], - (unsigned) vendor.vendor_guid.data4[6], - (unsigned) vendor.vendor_guid.data4[7]); - } + dump_vendor_path ("Media", + (grub_efi_vendor_device_path_t *) dp); break; case GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE: { grub_efi_file_path_device_path_t *fp; - grub_uint8_t buf[(len - 4) * 2 + 1]; + grub_uint8_t *buf; fp = (grub_efi_file_path_device_path_t *) dp; - *grub_utf16_to_utf8 (buf, fp->path_name, - (len - 4) / sizeof (grub_efi_char16_t)) - = '\0'; + buf = grub_malloc ((len - 4) * 2 + 1); + if (buf) + { + grub_efi_char16_t *dup_name = grub_malloc (len - 4); + if (!dup_name) + { + grub_errno = GRUB_ERR_NONE; + grub_printf ("/File((null))"); + grub_free (buf); + break; + } + *grub_utf16_to_utf8 (buf, grub_memcpy (dup_name, fp->path_name, len - 4), + (len - 4) / sizeof (grub_efi_char16_t)) + = '\0'; + grub_free (dup_name); + } + else + grub_errno = GRUB_ERR_NONE; grub_printf ("/File(%s)", buf); + grub_free (buf); } break; case GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE: { - grub_efi_protocol_device_path_t proto; - grub_memcpy (&proto, dp, sizeof (proto)); - grub_printf ("/Protocol(%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x)", - (unsigned) proto.guid.data1, - (unsigned) proto.guid.data2, - (unsigned) proto.guid.data3, - (unsigned) proto.guid.data4[0], - (unsigned) proto.guid.data4[1], - (unsigned) proto.guid.data4[2], - (unsigned) proto.guid.data4[3], - (unsigned) proto.guid.data4[4], - (unsigned) proto.guid.data4[5], - (unsigned) proto.guid.data4[6], - (unsigned) proto.guid.data4[7]); + grub_efi_protocol_device_path_t *proto + = (grub_efi_protocol_device_path_t *) dp; + grub_printf ("/Protocol(%pG)",&proto->guid); } break; default: @@ -736,11 +943,11 @@ grub_efi_print_device_path (grub_efi_device_path_t *dp) { case GRUB_EFI_BIOS_DEVICE_PATH_SUBTYPE: { - grub_efi_bios_device_path_t bios; - grub_memcpy (&bios, dp, sizeof (bios)); + grub_efi_bios_device_path_t *bios + = (grub_efi_bios_device_path_t *) dp; grub_printf ("/BIOS(%x,%x,%s)", - (unsigned) bios.device_type, - (unsigned) bios.status_flags, + (unsigned) bios->device_type, + (unsigned) bios->status_flags, (char *) (dp + 1)); } break; @@ -774,7 +981,10 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, /* Return non-zero. */ return 1; - while (1) + if (dp1 == dp2) + return 0; + + while (GRUB_EFI_DEVICE_PATH_VALID (dp1) && GRUB_EFI_DEVICE_PATH_VALID (dp2)) { grub_efi_uint8_t type1, type2; grub_efi_uint8_t subtype1, subtype2; @@ -810,5 +1020,32 @@ grub_efi_compare_device_paths (const grub_efi_device_path_t *dp1, dp2 = (grub_efi_device_path_t *) ((char *) dp2 + len2); } + /* + * There's no "right" answer here, but we probably don't want to call a valid + * dp and an invalid dp equal, so pick one way or the other. + */ + if (GRUB_EFI_DEVICE_PATH_VALID (dp1) && !GRUB_EFI_DEVICE_PATH_VALID (dp2)) + return 1; + else if (!GRUB_EFI_DEVICE_PATH_VALID (dp1) && GRUB_EFI_DEVICE_PATH_VALID (dp2)) + return -1; + + return 0; +} + +void * +grub_efi_find_configuration_table (const grub_guid_t *target_guid) +{ + unsigned i; + + for (i = 0; i < grub_efi_system_table->num_table_entries; i++) + { + grub_packed_guid_t *guid = + &grub_efi_system_table->configuration_table[i].vendor_guid; + + if (! grub_memcmp (guid, target_guid, sizeof (grub_guid_t))) + return (void *) + grub_efi_system_table->configuration_table[i].vendor_table; + } + return 0; } diff --git a/grub-core/kern/efi/fdt.c b/grub-core/kern/efi/fdt.c new file mode 100644 index 000000000..15a495a34 --- /dev/null +++ b/grub-core/kern/efi/fdt.c @@ -0,0 +1,35 @@ +/* fdt.c - EFI Flattened Device Tree interaction */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +void * +grub_efi_get_firmware_fdt (void) +{ + static grub_guid_t fdt_guid = GRUB_EFI_DEVICE_TREE_GUID; + void *firmware_fdt = grub_efi_find_configuration_table (&fdt_guid); + + if (firmware_fdt) { + grub_dprintf ("linux", "found registered FDT @ %p\n", firmware_fdt); + } else { + grub_dprintf ("linux", "not found registered FDT\n"); + } + return firmware_fdt; +} diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index 942ab0256..1637077e1 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -19,19 +19,85 @@ #include #include +#include #include +#include +#include #include #include #include #include #include +#include + +#ifdef GRUB_STACK_PROTECTOR + +static grub_efi_char16_t stack_chk_fail_msg[] = + L"* GRUB: STACK SMASHING DETECTED!!! *\r\n" + L"* GRUB: ABORTED!!! *\r\n" + L"* GRUB: REBOOTING IN 5 SECONDS... *\r\n"; + +static grub_guid_t rng_protocol_guid = GRUB_EFI_RNG_PROTOCOL_GUID; + +/* Initialize canary in case there is no RNG protocol. */ +grub_addr_t __stack_chk_guard = (grub_addr_t) GRUB_STACK_PROTECTOR_INIT; + +void __attribute__ ((noreturn)) +__stack_chk_fail (void) +{ + grub_efi_simple_text_output_interface_t *o; + + /* + * Use ConOut here rather than StdErr. StdErr only goes to + * the serial console, at least on EDK2. + */ + o = grub_efi_system_table->con_out; + o->output_string (o, stack_chk_fail_msg); + + grub_efi_system_table->boot_services->stall (5000000); + grub_efi_system_table->runtime_services->reset_system (GRUB_EFI_RESET_SHUTDOWN, + GRUB_EFI_ABORTED, 0, NULL); + + /* + * We shouldn't get here. It's unsafe to return because the stack + * is compromised and this function is noreturn, so just busy + * loop forever. + */ + do + { + /* Do not optimize out the loop. */ + asm volatile (""); + } + while (1); +} + +grub_addr_t +grub_stack_protector_init (void) +{ + grub_efi_rng_protocol_t *rng; + + /* Set up the stack canary. Make errors here non-fatal for now. */ + rng = grub_efi_locate_protocol (&rng_protocol_guid, NULL); + if (rng != NULL) + { + grub_efi_status_t status; + grub_addr_t guard = 0; + + status = rng->get_rng (rng, NULL, sizeof (guard) - 1, + (grub_efi_uint8_t *) &guard); + if (status == GRUB_EFI_SUCCESS) + return guard; + } + return 0; +} +#endif grub_addr_t grub_modbase; void grub_efi_init (void) { - grub_modbase = grub_efi_modules_addr (); + grub_modbase = grub_efi_section_addr ("mods"); /* First of all, initialize the console so that GRUB can display messages. */ grub_console_init (); @@ -39,13 +105,24 @@ grub_efi_init (void) /* Initialize the memory management system. */ grub_efi_mm_init (); - efi_call_4 (grub_efi_system_table->boot_services->set_watchdog_timer, - 0, 0, 0, NULL); + /* + * Lockdown the GRUB and register the shim_lock verifier + * if the UEFI Secure Boot is enabled. + */ + if (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED) + { + grub_lockdown (); + grub_shim_lock_verifier_setup (); + } + + grub_efi_system_table->boot_services->set_watchdog_timer (0, 0, 0, NULL); grub_efidisk_init (); + + grub_efi_register_debug_commands (); } -void (*grub_efi_net_config) (grub_efi_handle_t hnd, +void (*grub_efi_net_config) (grub_efi_handle_t hnd, char **device, char **path); @@ -59,14 +136,20 @@ grub_machine_get_bootlocation (char **device, char **path) if (!image) return; *device = grub_efidisk_get_device_name (image->device_handle); - *path = grub_efi_get_filename (image->file_path); if (!*device && grub_efi_net_config) - grub_efi_net_config (image->device_handle, device, path); + { + grub_efi_net_config (image->device_handle, device, path); + return; + } - /* Get the directory. */ - p = grub_strrchr (*path, '/'); - if (p) - *p = '\0'; + *path = grub_efi_get_filename (image->file_path); + if (*path) + { + /* Get the directory. */ + p = grub_strrchr (*path, '/'); + if (p) + *p = '\0'; + } } void diff --git a/grub-core/kern/efi/mm.c b/grub-core/kern/efi/mm.c index a2edc84b3..df238b165 100644 --- a/grub-core/kern/efi/mm.c +++ b/grub-core/kern/efi/mm.c @@ -21,6 +21,7 @@ #include #include #include +#include #if defined (__i386__) || defined (__x86_64__) #include @@ -30,15 +31,15 @@ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) #define BYTES_TO_PAGES(bytes) (((bytes) + 0xfff) >> 12) +#define BYTES_TO_PAGES_DOWN(bytes) ((bytes) >> 12) #define PAGES_TO_BYTES(pages) ((pages) << 12) /* The size of a memory map obtained from the firmware. This must be a multiplier of 4KB. */ #define MEMORY_MAP_SIZE 0x3000 -/* The minimum and maximum heap size for GRUB itself. */ -#define MIN_HEAP_SIZE 0x100000 -#define MAX_HEAP_SIZE (1600 * 0x100000) +/* The default heap size for GRUB itself in bytes. */ +#define DEFAULT_HEAP_SIZE 0x2000000 static void *finish_mmap_buf = 0; static grub_efi_uintn_t finish_mmap_size = 0; @@ -47,55 +48,140 @@ static grub_efi_uintn_t finish_desc_size; static grub_efi_uint32_t finish_desc_version; int grub_efi_is_finished = 0; +/* + * We need to roll back EFI allocations on exit. Remember allocations that + * we'll free on exit. + */ +struct efi_allocation; +struct efi_allocation { + grub_efi_physical_address_t address; + grub_efi_uint64_t pages; + struct efi_allocation *next; +}; +static struct efi_allocation *efi_allocated_memory; + +static void +grub_efi_store_alloc (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) +{ + grub_efi_boot_services_t *b; + struct efi_allocation *alloc; + grub_efi_status_t status; + + b = grub_efi_system_table->boot_services; + status = b->allocate_pool (GRUB_EFI_LOADER_DATA, + sizeof(*alloc), (void**)&alloc); + + if (status == GRUB_EFI_SUCCESS) + { + alloc->next = efi_allocated_memory; + alloc->address = address; + alloc->pages = pages; + efi_allocated_memory = alloc; + } + else + grub_printf ("Could not malloc memory to remember EFI allocation. " + "Exiting GRUB won't free all memory.\n"); +} + +static void +grub_efi_drop_alloc (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) +{ + struct efi_allocation *ea, *eap; + grub_efi_boot_services_t *b; + + b = grub_efi_system_table->boot_services; + + for (eap = NULL, ea = efi_allocated_memory; ea; eap = ea, ea = ea->next) + { + if (ea->address != address) + continue; + if (ea->pages != pages) + grub_fatal ("grub_efi_drop_alloc() called with wrong page count"); + + /* Remove the current entry from the list. */ + if (eap) + eap->next = ea->next; + else + efi_allocated_memory = ea->next; + + /* Then free the memory backing it. */ + b->free_pool (ea); + + /* And leave, we're done. */ + break; + } +} + /* Allocate pages. Return the pointer to the first of allocated pages. */ void * -grub_efi_allocate_pages (grub_efi_physical_address_t address, - grub_efi_uintn_t pages) +grub_efi_allocate_pages_real (grub_efi_physical_address_t address, + grub_efi_uintn_t pages, + grub_efi_allocate_type_t alloctype, + grub_efi_memory_type_t memtype) { - grub_efi_allocate_type_t type; grub_efi_status_t status; grub_efi_boot_services_t *b; -#if 1 /* Limit the memory access to less than 4GB for 32-bit platforms. */ - if (address > 0xffffffff) - return 0; -#endif - -#if 1 - if (address == 0) + if (address > GRUB_EFI_MAX_USABLE_ADDRESS) { - type = GRUB_EFI_ALLOCATE_MAX_ADDRESS; - address = 0xffffffff; + char inv_addr[17], max_addr[17]; /* log16(2^64) = 16, plus NUL. */ + + grub_snprintf (inv_addr, sizeof (inv_addr) - 1, "%" PRIxGRUB_UINT64_T, + address); + grub_snprintf (max_addr, sizeof (max_addr) - 1, "%" PRIxGRUB_UINT64_T, + (grub_efi_uint64_t) GRUB_EFI_MAX_USABLE_ADDRESS); + grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("invalid memory address (0x%s > 0x%s)"), inv_addr, max_addr); + return NULL; } - else - type = GRUB_EFI_ALLOCATE_ADDRESS; -#else - if (address == 0) - type = GRUB_EFI_ALLOCATE_ANY_PAGES; - else - type = GRUB_EFI_ALLOCATE_ADDRESS; -#endif b = grub_efi_system_table->boot_services; - status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address); + status = b->allocate_pages (alloctype, memtype, pages, &address); if (status != GRUB_EFI_SUCCESS) - return 0; + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + return NULL; + } if (address == 0) { /* Uggh, the address 0 was allocated... This is too annoying, so reallocate another one. */ - address = 0xffffffff; - status = efi_call_4 (b->allocate_pages, type, GRUB_EFI_LOADER_DATA, pages, &address); - grub_efi_free_pages (0, pages); + address = GRUB_EFI_MAX_USABLE_ADDRESS; + status = b->allocate_pages (alloctype, memtype, pages, &address); + b->free_pages (0, pages); if (status != GRUB_EFI_SUCCESS) - return 0; + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + return NULL; + } } + grub_efi_store_alloc (address, pages); + return (void *) ((grub_addr_t) address); } +void * +grub_efi_allocate_any_pages (grub_efi_uintn_t pages) +{ + return grub_efi_allocate_pages_real (GRUB_EFI_MAX_USABLE_ADDRESS, + pages, GRUB_EFI_ALLOCATE_MAX_ADDRESS, + GRUB_EFI_LOADER_DATA); +} + +void * +grub_efi_allocate_fixed (grub_efi_physical_address_t address, + grub_efi_uintn_t pages) +{ + return grub_efi_allocate_pages_real (address, pages, + GRUB_EFI_ALLOCATE_ADDRESS, + GRUB_EFI_LOADER_DATA); +} + /* Free pages starting from ADDRESS. */ void grub_efi_free_pages (grub_efi_physical_address_t address, @@ -104,42 +190,43 @@ grub_efi_free_pages (grub_efi_physical_address_t address, grub_efi_boot_services_t *b; b = grub_efi_system_table->boot_services; - efi_call_2 (b->free_pages, address, pages); + b->free_pages (address, pages); + + grub_efi_drop_alloc (address, pages); } #if defined (__i386__) || defined (__x86_64__) +/* Helper for stop_broadcom. */ +static int +find_card (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + grub_pci_address_t addr; + grub_uint8_t cap; + grub_uint16_t pm_state; + + if ((pciid & 0xffff) != GRUB_PCI_VENDOR_BROADCOM) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + if (grub_pci_read (addr) >> 24 != GRUB_PCI_CLASS_NETWORK) + return 0; + cap = grub_pci_find_capability (dev, GRUB_PCI_CAP_POWER_MANAGEMENT); + if (!cap) + return 0; + addr = grub_pci_make_address (dev, cap + 4); + pm_state = grub_pci_read_word (addr); + pm_state = pm_state | 0x03; + grub_pci_write_word (addr, pm_state); + grub_pci_read_word (addr); + return 0; +} + static void stop_broadcom (void) { - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid); - - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid) - { - grub_pci_address_t addr; - grub_uint8_t cap; - grub_uint16_t pm_state; - - if ((pciid & 0xffff) != GRUB_PCI_VENDOR_BROADCOM) - return 0; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - if (grub_pci_read (addr) >> 24 != GRUB_PCI_CLASS_NETWORK) - return 0; - cap = grub_pci_find_capability (dev, GRUB_PCI_CAP_POWER_MANAGEMENT); - if (!cap) - return 0; - addr = grub_pci_make_address (dev, cap + 4); - pm_state = grub_pci_read_word (addr); - pm_state = pm_state | 0x03; - grub_pci_write_word (addr, pm_state); - grub_pci_read_word (addr); - return 0; - } - - grub_pci_iterate (find_card); + grub_pci_iterate (find_card, NULL); } #endif @@ -161,27 +248,43 @@ grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf, apple, sizeof (apple)) == 0); #endif - if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key, - &finish_desc_size, &finish_desc_version) < 0) - return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map"); + while (1) + { + if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key, + &finish_desc_size, &finish_desc_version) < 0) + return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map"); - if (outbuf && *outbuf_size < finish_mmap_size) - return grub_error (GRUB_ERR_IO, "memory map buffer is too small"); + if (outbuf && *outbuf_size < finish_mmap_size) + return grub_error (GRUB_ERR_IO, "memory map buffer is too small"); - finish_mmap_buf = grub_malloc (finish_mmap_size); - if (!finish_mmap_buf) - return grub_errno; + finish_mmap_buf = grub_malloc (finish_mmap_size); + if (!finish_mmap_buf) + return grub_errno; - if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key, - &finish_desc_size, &finish_desc_version) <= 0) - return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map"); + if (grub_efi_get_memory_map (&finish_mmap_size, finish_mmap_buf, &finish_key, + &finish_desc_size, &finish_desc_version) <= 0) + { + grub_free (finish_mmap_buf); + finish_mmap_buf = NULL; + return grub_error (GRUB_ERR_IO, "couldn't retrieve memory map"); + } - b = grub_efi_system_table->boot_services; - status = efi_call_2 (b->exit_boot_services, grub_efi_image_handle, - finish_key); - if (status != GRUB_EFI_SUCCESS) - return grub_error (GRUB_ERR_IO, "couldn't terminate EFI services"); + b = grub_efi_system_table->boot_services; + status = b->exit_boot_services (grub_efi_image_handle, finish_key); + if (status == GRUB_EFI_SUCCESS) + break; + if (status != GRUB_EFI_INVALID_PARAMETER) + { + grub_free (finish_mmap_buf); + finish_mmap_buf = NULL; + return grub_error (GRUB_ERR_IO, "couldn't terminate EFI services"); + } + + grub_free (finish_mmap_buf); + finish_mmap_buf = NULL; + grub_printf ("Trying to terminate EFI services again\n"); + } grub_efi_is_finished = 1; if (outbuf_size) *outbuf_size = finish_mmap_size; @@ -194,6 +297,12 @@ grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf, if (efi_desc_version) *efi_desc_version = finish_desc_version; + /* + * We cannot request new memory regions from the EFI Boot Services anymore. + * FIXME: Can we completely avoid memory allocations after this? + */ + grub_mm_add_region_fn = NULL; + #if defined (__i386__) || defined (__x86_64__) if (is_apple) stop_broadcom (); @@ -202,6 +311,30 @@ grub_efi_finish_boot_services (grub_efi_uintn_t *outbuf_size, void *outbuf, return GRUB_ERR_NONE; } +/* + * To obtain the UEFI memory map, we must pass a buffer of sufficient size + * to hold the entire map. This function returns a sane start value for + * buffer size. + */ +grub_efi_uintn_t +grub_efi_find_mmap_size (void) +{ + grub_efi_uintn_t mmap_size = 0; + grub_efi_uintn_t desc_size; + + if (grub_efi_get_memory_map (&mmap_size, NULL, NULL, &desc_size, 0) < 0) + { + grub_error (GRUB_ERR_IO, "cannot get EFI memory map size"); + return 0; + } + + /* + * Add an extra page, since UEFI can alter the memory map itself on + * callbacks or explicit calls, including console output. + */ + return ALIGN_UP (mmap_size + GRUB_EFI_PAGE_SIZE, GRUB_EFI_PAGE_SIZE); +} + /* Get the memory map as defined in the EFI spec. Return 1 if successful, return 0 if partial, or return -1 if an error occurs. */ int @@ -215,19 +348,29 @@ grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size, grub_efi_boot_services_t *b; grub_efi_uintn_t key; grub_efi_uint32_t version; + grub_efi_uintn_t size; if (grub_efi_is_finished) { int ret = 1; - if (*memory_map_size < finish_mmap_size) + + if (memory_map != NULL) { - grub_memcpy (memory_map, finish_mmap_buf, *memory_map_size); - ret = 0; + if (*memory_map_size < finish_mmap_size) + { + grub_memcpy (memory_map, finish_mmap_buf, *memory_map_size); + ret = 0; + } + else + grub_memcpy (memory_map, finish_mmap_buf, finish_mmap_size); } else { - grub_memcpy (memory_map, finish_mmap_buf, finish_mmap_size); - ret = 1; + /* + * Incomplete, no buffer to copy into, same as + * GRUB_EFI_BUFFER_TOO_SMALL below. + */ + ret = 0; } *memory_map_size = finish_mmap_size; if (map_key) @@ -244,10 +387,14 @@ grub_efi_get_memory_map (grub_efi_uintn_t *memory_map_size, map_key = &key; if (! descriptor_version) descriptor_version = &version; + if (! descriptor_size) + descriptor_size = &size; b = grub_efi_system_table->boot_services; - status = efi_call_5 (b->get_memory_map, memory_map_size, memory_map, map_key, + status = b->get_memory_map (memory_map_size, memory_map, map_key, descriptor_size, descriptor_version); + if (*descriptor_size == 0) + *descriptor_size = sizeof (grub_efi_memory_descriptor_t); if (status == GRUB_EFI_SUCCESS) return 1; else if (status == GRUB_EFI_BUFFER_TOO_SMALL) @@ -306,7 +453,7 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, { if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY #if 1 - && desc->physical_start <= 0xffffffff + && desc->physical_start <= GRUB_EFI_MAX_USABLE_ADDRESS #endif && desc->physical_start + PAGES_TO_BYTES (desc->num_pages) > 0x100000 && desc->num_pages != 0) @@ -324,9 +471,9 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, #if 1 if (BYTES_TO_PAGES (filtered_desc->physical_start) + filtered_desc->num_pages - > BYTES_TO_PAGES (0x100000000LL)) + > BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS)) filtered_desc->num_pages - = (BYTES_TO_PAGES (0x100000000LL) + = (BYTES_TO_PAGES_DOWN (GRUB_EFI_MAX_USABLE_ADDRESS) - BYTES_TO_PAGES (filtered_desc->physical_start)); #endif @@ -340,29 +487,13 @@ filter_memory_map (grub_efi_memory_descriptor_t *memory_map, return filtered_desc; } -/* Return the total number of pages. */ -static grub_efi_uint64_t -get_total_pages (grub_efi_memory_descriptor_t *memory_map, - grub_efi_uintn_t desc_size, - grub_efi_memory_descriptor_t *memory_map_end) -{ - grub_efi_memory_descriptor_t *desc; - grub_efi_uint64_t total = 0; - - for (desc = memory_map; - desc < memory_map_end; - desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) - total += desc->num_pages; - - return total; -} - /* Add memory regions. */ -static void +static grub_err_t add_memory_regions (grub_efi_memory_descriptor_t *memory_map, grub_efi_uintn_t desc_size, grub_efi_memory_descriptor_t *memory_map_end, - grub_efi_uint64_t required_pages) + grub_efi_uint64_t required_pages, + unsigned int flags) { grub_efi_memory_descriptor_t *desc; @@ -376,17 +507,23 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, start = desc->physical_start; pages = desc->num_pages; + + if (pages < required_pages && (flags & GRUB_MM_ADD_REGION_CONSECUTIVE)) + continue; + if (pages > required_pages) { start += PAGES_TO_BYTES (pages - required_pages); pages = required_pages; } - addr = grub_efi_allocate_pages (start, pages); + addr = grub_efi_allocate_pages_real (start, pages, + GRUB_EFI_ALLOCATE_ADDRESS, + GRUB_EFI_LOADER_CODE); if (! addr) - grub_fatal ("cannot allocate conventional memory %p with %u pages", - (void *) ((grub_addr_t) start), - (unsigned) pages); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "Memory starting at %p (%u pages) marked as free, but EFI would not allocate", + (void *) ((grub_addr_t) start), (unsigned) pages); grub_mm_init_region (addr, PAGES_TO_BYTES (pages)); @@ -396,7 +533,25 @@ add_memory_regions (grub_efi_memory_descriptor_t *memory_map, } if (required_pages > 0) - grub_fatal ("too little memory"); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + "could not allocate all requested memory: %" PRIuGRUB_UINT64_T " pages still required after iterating EFI memory map", + required_pages); + + return GRUB_ERR_NONE; +} + +void +grub_efi_memory_fini (void) +{ + /* + * Free all stale allocations. grub_efi_free_pages() will remove + * the found entry from the list and it will always find the first + * list entry (efi_allocated_memory is the list start). Hence we + * remove all entries from the list until none is left altogether. + */ + while (efi_allocated_memory) + grub_efi_free_pages (efi_allocated_memory->address, + efi_allocated_memory->pages); } #if 0 @@ -420,24 +575,24 @@ print_memory_map (grub_efi_memory_descriptor_t *memory_map, } #endif -void -grub_efi_mm_init (void) +static grub_err_t +grub_efi_mm_add_regions (grub_size_t required_bytes, unsigned int flags) { grub_efi_memory_descriptor_t *memory_map; grub_efi_memory_descriptor_t *memory_map_end; grub_efi_memory_descriptor_t *filtered_memory_map; grub_efi_memory_descriptor_t *filtered_memory_map_end; + grub_efi_uintn_t alloc_size; grub_efi_uintn_t map_size; grub_efi_uintn_t desc_size; - grub_efi_uint64_t total_pages; - grub_efi_uint64_t required_pages; + grub_err_t err; int mm_status; /* Prepare a memory region to store two memory maps. */ - memory_map = grub_efi_allocate_pages (0, - 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + alloc_size = 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE); + memory_map = grub_efi_allocate_any_pages (alloc_size); if (! memory_map) - grub_fatal ("cannot allocate memory"); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for memory map"); /* Obtain descriptors for available memory. */ map_size = MEMORY_MAP_SIZE; @@ -446,23 +601,22 @@ grub_efi_mm_init (void) if (mm_status == 0) { - grub_efi_free_pages - ((grub_efi_physical_address_t) ((grub_addr_t) memory_map), - 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) memory_map, alloc_size); /* Freeing/allocating operations may increase memory map size. */ map_size += desc_size * 32; - memory_map = grub_efi_allocate_pages (0, 2 * BYTES_TO_PAGES (map_size)); + alloc_size = 2 * BYTES_TO_PAGES (map_size); + memory_map = grub_efi_allocate_any_pages (alloc_size); if (! memory_map) - grub_fatal ("cannot allocate memory"); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory for new memory map"); mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0); } if (mm_status < 0) - grub_fatal ("cannot get memory map"); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "error fetching memory map from EFI"); memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size); @@ -471,22 +625,17 @@ grub_efi_mm_init (void) filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, desc_size, memory_map_end); - /* By default, request a quarter of the available memory. */ - total_pages = get_total_pages (filtered_memory_map, desc_size, - filtered_memory_map_end); - required_pages = (total_pages >> 2); - if (required_pages < BYTES_TO_PAGES (MIN_HEAP_SIZE)) - required_pages = BYTES_TO_PAGES (MIN_HEAP_SIZE); - else if (required_pages > BYTES_TO_PAGES (MAX_HEAP_SIZE)) - required_pages = BYTES_TO_PAGES (MAX_HEAP_SIZE); - /* Sort the filtered descriptors, so that GRUB can allocate pages from smaller regions. */ sort_memory_map (filtered_memory_map, desc_size, filtered_memory_map_end); /* Allocate memory regions for GRUB's memory management. */ - add_memory_regions (filtered_memory_map, desc_size, - filtered_memory_map_end, required_pages); + err = add_memory_regions (filtered_memory_map, desc_size, + filtered_memory_map_end, + BYTES_TO_PAGES (required_bytes), + flags); + if (err != GRUB_ERR_NONE) + return err; #if 0 /* For debug. */ @@ -498,10 +647,160 @@ grub_efi_mm_init (void) grub_printf ("printing memory map\n"); print_memory_map (memory_map, desc_size, NEXT_MEMORY_DESCRIPTOR (memory_map, map_size)); - grub_abort (); + grub_fatal ("Debug. "); #endif /* Release the memory maps. */ - grub_efi_free_pages ((grub_addr_t) memory_map, - 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + grub_efi_free_pages ((grub_efi_physical_address_t)(grub_addr_t) memory_map, alloc_size); + + return GRUB_ERR_NONE; +} + +void +grub_efi_mm_init (void) +{ + if (grub_efi_mm_add_regions (DEFAULT_HEAP_SIZE, GRUB_MM_ADD_REGION_NONE) != GRUB_ERR_NONE) + grub_fatal ("%s", grub_errmsg); + grub_mm_add_region_fn = grub_efi_mm_add_regions; +} + +#if defined (__aarch64__) || defined (__arm__) || defined (__riscv) || \ + defined (__loongarch__) +grub_err_t +grub_efi_get_ram_base(grub_addr_t *base_addr) +{ + grub_efi_memory_descriptor_t *memory_map, *desc; + grub_efi_uintn_t memory_map_size, desc_size; + int ret; + + memory_map_size = grub_efi_find_mmap_size(); + + memory_map = grub_malloc (memory_map_size); + if (! memory_map) + return GRUB_ERR_OUT_OF_MEMORY; + ret = grub_efi_get_memory_map (&memory_map_size, memory_map, NULL, + &desc_size, NULL); + + if (ret < 1) + return GRUB_ERR_BUG; + + for (desc = memory_map, *base_addr = GRUB_EFI_MAX_USABLE_ADDRESS; + (grub_addr_t) desc < ((grub_addr_t) memory_map + memory_map_size); + desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size)) + if (desc->attribute & GRUB_EFI_MEMORY_WB) + *base_addr = grub_min (*base_addr, desc->physical_start); + + grub_free(memory_map); + + return GRUB_ERR_NONE; +} +#endif + +static grub_uint64_t +grub_mem_attrs_to_uefi_mem_attrs (grub_mem_attr_t attrs) +{ + grub_efi_uint64_t ret = GRUB_EFI_MEMORY_RP | GRUB_EFI_MEMORY_RO | GRUB_EFI_MEMORY_XP; + + if (attrs & GRUB_MEM_ATTR_R) + ret &= ~GRUB_EFI_MEMORY_RP; + + if (attrs & GRUB_MEM_ATTR_W) + ret &= ~GRUB_EFI_MEMORY_RO; + + if (attrs & GRUB_MEM_ATTR_X) + ret &= ~GRUB_EFI_MEMORY_XP; + + return ret; +} + +static grub_mem_attr_t +uefi_mem_attrs_to_grub_mem_attrs (grub_efi_uint64_t attrs) +{ + grub_mem_attr_t ret = GRUB_MEM_ATTR_R | GRUB_MEM_ATTR_W | GRUB_MEM_ATTR_X; + + if (attrs & GRUB_EFI_MEMORY_RP) + ret &= ~GRUB_MEM_ATTR_R; + + if (attrs & GRUB_EFI_MEMORY_RO) + ret &= ~GRUB_MEM_ATTR_W; + + if (attrs & GRUB_EFI_MEMORY_XP) + ret &= ~GRUB_MEM_ATTR_X; + + return ret; +} + +grub_err_t +grub_get_mem_attrs (grub_addr_t addr, grub_size_t size, grub_mem_attr_t *attrs) +{ + grub_efi_memory_attribute_protocol_t *proto; + grub_efi_physical_address_t physaddr = addr; + static grub_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; + grub_efi_status_t efi_status; + grub_efi_uint64_t efi_attrs; + + if (physaddr & (GRUB_EFI_PAGE_SIZE - 1) || size & (GRUB_EFI_PAGE_SIZE - 1) || size == 0 || attrs == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "%s() called with invalid arguments", __FUNCTION__); + + proto = grub_efi_locate_protocol (&protocol_guid, 0); + if (proto == NULL) + { + /* No protocol -> do nothing, all memory is RWX in boot services */ + *attrs = GRUB_MEM_ATTR_R | GRUB_MEM_ATTR_W | GRUB_MEM_ATTR_X; + return GRUB_ERR_NONE; + } + + efi_status = proto->get_memory_attributes (proto, physaddr, size, &efi_attrs); + if (efi_status != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "%s() called with invalid arguments", __FUNCTION__); + + *attrs = uefi_mem_attrs_to_grub_mem_attrs (efi_attrs); + + grub_dprintf ("nx", "get 0x%" PRIxGRUB_ADDR "-0x%" PRIxGRUB_ADDR ":%c%c%c\n", + addr, addr + size - 1, + (*attrs & GRUB_MEM_ATTR_R) ? 'r' : '-', + (*attrs & GRUB_MEM_ATTR_W) ? 'w' : '-', + (*attrs & GRUB_MEM_ATTR_X) ? 'x' : '-'); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_update_mem_attrs (grub_addr_t addr, grub_size_t size, + grub_mem_attr_t set_attrs, grub_mem_attr_t clear_attrs) +{ + grub_efi_memory_attribute_protocol_t *proto; + grub_efi_physical_address_t physaddr = addr; + static grub_guid_t protocol_guid = GRUB_EFI_MEMORY_ATTRIBUTE_PROTOCOL_GUID; + grub_efi_status_t efi_status = GRUB_EFI_SUCCESS; + grub_efi_uint64_t uefi_set_attrs, uefi_clear_attrs; + + if (physaddr & (GRUB_EFI_PAGE_SIZE - 1) || size & (GRUB_EFI_PAGE_SIZE - 1) || size == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "%s() called with invalid arguments", __FUNCTION__); + + proto = grub_efi_locate_protocol (&protocol_guid, 0); + if (proto == NULL) + /* No protocol -> do nothing, all memory is RWX in boot services */ + return GRUB_ERR_NONE; + + uefi_set_attrs = grub_mem_attrs_to_uefi_mem_attrs (set_attrs); + uefi_clear_attrs = grub_mem_attrs_to_uefi_mem_attrs (clear_attrs); + if (uefi_set_attrs) + efi_status = proto->set_memory_attributes (proto, physaddr, size, uefi_set_attrs); + if (efi_status == GRUB_EFI_SUCCESS && uefi_clear_attrs) + efi_status = proto->clear_memory_attributes (proto, physaddr, size, uefi_clear_attrs); + + if (efi_status != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "%s() called with invalid arguments", __FUNCTION__); + + grub_dprintf ("nx", "set +%s%s%s -%s%s%s on 0x%" PRIxGRUB_ADDR "-0x%" PRIxGRUB_ADDR "\n", + (set_attrs & GRUB_MEM_ATTR_R) ? "r" : "", + (set_attrs & GRUB_MEM_ATTR_W) ? "w" : "", + (set_attrs & GRUB_MEM_ATTR_X) ? "x" : "", + (clear_attrs & GRUB_MEM_ATTR_R) ? "r" : "", + (clear_attrs & GRUB_MEM_ATTR_W) ? "w" : "", + (clear_attrs & GRUB_MEM_ATTR_X) ? "x" : "", + addr, addr + size - 1); + + return GRUB_ERR_NONE; } diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c new file mode 100644 index 000000000..8d3e41360 --- /dev/null +++ b/grub-core/kern/efi/sb.c @@ -0,0 +1,238 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2020 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + * + * UEFI Secure Boot related checkings. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static grub_guid_t shim_lock_guid = GRUB_EFI_SHIM_LOCK_GUID; + +static bool shim_lock_enabled = false; + +/* + * Determine whether we're in secure boot mode. + * + * Please keep the logic in sync with the Linux kernel, + * drivers/firmware/efi/libstub/secureboot.c:efi_get_secureboot(). + */ +grub_uint8_t +grub_efi_get_secureboot (void) +{ + static grub_guid_t efi_variable_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID; + grub_efi_status_t status; + grub_efi_uint32_t attr = 0; + grub_size_t size = 0; + grub_uint8_t *secboot = NULL; + grub_uint8_t *setupmode = NULL; + grub_uint8_t *moksbstate = NULL; + grub_uint8_t secureboot = GRUB_EFI_SECUREBOOT_MODE_UNKNOWN; + const char *secureboot_str = "UNKNOWN"; + + status = grub_efi_get_variable ("SecureBoot", &efi_variable_guid, + &size, (void **) &secboot); + + if (status == GRUB_EFI_NOT_FOUND) + { + secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED; + goto out; + } + + if (status != GRUB_EFI_SUCCESS) + goto out; + + status = grub_efi_get_variable ("SetupMode", &efi_variable_guid, + &size, (void **) &setupmode); + + if (status != GRUB_EFI_SUCCESS) + goto out; + + if ((*secboot == 0) || (*setupmode == 1)) + { + secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED; + goto out; + } + + /* + * See if a user has put the shim into insecure mode. If so, and if the + * variable doesn't have the runtime attribute set, we might as well + * honor that. + */ + status = grub_efi_get_variable_with_attributes ("MokSBState", &shim_lock_guid, + &size, (void **) &moksbstate, &attr); + + /* If it fails, we don't care why. Default to secure. */ + if (status != GRUB_EFI_SUCCESS) + { + secureboot = GRUB_EFI_SECUREBOOT_MODE_ENABLED; + goto out; + } + + if (!(attr & GRUB_EFI_VARIABLE_RUNTIME_ACCESS) && *moksbstate == 1) + { + secureboot = GRUB_EFI_SECUREBOOT_MODE_DISABLED; + /* + * TODO: Replace this all with shim's LoadImage protocol, delegating policy to it. + * + * We need to set shim_lock_enabled here because we disabled secure boot + * validation *inside* shim but not in the firmware, so we set this variable + * here to trigger that code path, whereas the actual verifier is not enabled. + */ + shim_lock_enabled = true; + goto out; + } + + secureboot = GRUB_EFI_SECUREBOOT_MODE_ENABLED; + + out: + grub_free (moksbstate); + grub_free (setupmode); + grub_free (secboot); + + if (secureboot == GRUB_EFI_SECUREBOOT_MODE_DISABLED) + secureboot_str = "Disabled"; + else if (secureboot == GRUB_EFI_SECUREBOOT_MODE_ENABLED) + secureboot_str = "Enabled"; + + grub_dprintf ("efi", "UEFI Secure Boot state: %s\n", secureboot_str); + + return secureboot; +} + +static grub_err_t +shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)), + enum grub_file_type type, + void **context __attribute__ ((unused)), + enum grub_verify_flags *flags) +{ + *flags = GRUB_VERIFY_FLAGS_NONE; + + switch (type & GRUB_FILE_TYPE_MASK) + { + /* Files we check. */ + case GRUB_FILE_TYPE_LINUX_KERNEL: + case GRUB_FILE_TYPE_MULTIBOOT_KERNEL: + case GRUB_FILE_TYPE_BSD_KERNEL: + case GRUB_FILE_TYPE_XNU_KERNEL: + case GRUB_FILE_TYPE_PLAN9_KERNEL: + case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE: + *flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK; + return GRUB_ERR_NONE; + + /* Files that do not affect secureboot state. */ + case GRUB_FILE_TYPE_NONE: + case GRUB_FILE_TYPE_LOOPBACK: + case GRUB_FILE_TYPE_LINUX_INITRD: + case GRUB_FILE_TYPE_OPENBSD_RAMDISK: + case GRUB_FILE_TYPE_XNU_RAMDISK: + case GRUB_FILE_TYPE_SIGNATURE: + case GRUB_FILE_TYPE_PUBLIC_KEY: + case GRUB_FILE_TYPE_PUBLIC_KEY_TRUST: + case GRUB_FILE_TYPE_PRINT_BLOCKLIST: + case GRUB_FILE_TYPE_TESTLOAD: + case GRUB_FILE_TYPE_GET_SIZE: + case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY: + case GRUB_FILE_TYPE_CAT: + case GRUB_FILE_TYPE_HEXCAT: + case GRUB_FILE_TYPE_CMP: + case GRUB_FILE_TYPE_HASHLIST: + case GRUB_FILE_TYPE_TO_HASH: + case GRUB_FILE_TYPE_KEYBOARD_LAYOUT: + case GRUB_FILE_TYPE_PIXMAP: + case GRUB_FILE_TYPE_GRUB_MODULE_LIST: + case GRUB_FILE_TYPE_CONFIG: + case GRUB_FILE_TYPE_THEME: + case GRUB_FILE_TYPE_GETTEXT_CATALOG: + case GRUB_FILE_TYPE_FS_SEARCH: + case GRUB_FILE_TYPE_LOADENV: + case GRUB_FILE_TYPE_SAVEENV: + case GRUB_FILE_TYPE_VERIFY_SIGNATURE: + *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; + return GRUB_ERR_NONE; + + /* Other files. */ + default: + return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by secure boot policy")); + } +} + +static grub_err_t +shim_lock_verifier_write (void *context __attribute__ ((unused)), void *buf, grub_size_t size) +{ + grub_efi_shim_lock_protocol_t *sl = grub_efi_locate_protocol (&shim_lock_guid, 0); + + if (!sl) + return grub_error (GRUB_ERR_ACCESS_DENIED, N_("shim_lock protocol not found")); + + if (sl->verify (buf, size) != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_BAD_SIGNATURE, N_("bad shim signature")); + + return GRUB_ERR_NONE; +} + +struct grub_file_verifier shim_lock_verifier = + { + .name = "shim_lock_verifier", + .init = shim_lock_verifier_init, + .write = shim_lock_verifier_write + }; + +void +grub_shim_lock_verifier_setup (void) +{ + struct grub_module_header *header; + grub_efi_shim_lock_protocol_t *sl = + grub_efi_locate_protocol (&shim_lock_guid, 0); + + /* shim_lock is missing, check if GRUB image is built with --disable-shim-lock. */ + if (!sl) + { + FOR_MODULES (header) + { + if (header->type == OBJ_TYPE_DISABLE_SHIM_LOCK) + return; + } + } + + /* Secure Boot is off. Do not load shim_lock. */ + if (grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED) + return; + + /* Enforce shim_lock_verifier. */ + grub_verifier_register (&shim_lock_verifier); + + shim_lock_enabled = true; + + grub_env_set ("shim_lock", "y"); + grub_env_export ("shim_lock"); +} + +bool +grub_is_shim_lock_enabled (void) +{ + return shim_lock_enabled; +} diff --git a/grub-core/kern/elf.c b/grub-core/kern/elf.c index 682cfbdb2..077a8500c 100644 --- a/grub-core/kern/elf.c +++ b/grub-core/kern/elf.c @@ -28,6 +28,25 @@ GRUB_MOD_LICENSE ("GPLv3+"); +#pragma GCC diagnostic ignored "-Wcast-align" + +#if defined(__powerpc__) && defined(GRUB_MACHINE_IEEE1275) +#define GRUB_ELF_ENABLE_BI_ENDIAN 1 +#else +#define GRUB_ELF_ENABLE_BI_ENDIAN 0 +#endif + +#if defined(GRUB_CPU_WORDS_BIGENDIAN) +#define GRUB_ELF_NATIVE_ENDIANNESS ELFDATA2MSB +#define GRUB_ELF_OPPOSITE_ENDIANNESS ELFDATA2LSB +#else +#define GRUB_ELF_NATIVE_ENDIANNESS ELFDATA2LSB +#define GRUB_ELF_OPPOSITE_ENDIANNESS ELFDATA2MSB +#endif + +static int grub_elf32_check_endianess_and_bswap_ehdr (grub_elf_t elf); +static int grub_elf64_check_endianess_and_bswap_ehdr (grub_elf_t elf); + /* Check if EHDR is a valid ELF header. */ static grub_err_t grub_elf_check_header (grub_elf_t elf) @@ -38,8 +57,25 @@ grub_elf_check_header (grub_elf_t elf) || e->e_ident[EI_MAG1] != ELFMAG1 || e->e_ident[EI_MAG2] != ELFMAG2 || e->e_ident[EI_MAG3] != ELFMAG3 - || e->e_ident[EI_VERSION] != EV_CURRENT - || e->e_version != EV_CURRENT) + || e->e_ident[EI_VERSION] != EV_CURRENT) + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic")); + + if (grub_elf_is_elf32 (elf)) + { + if (!grub_elf32_check_endianess_and_bswap_ehdr (elf)) { + return grub_error (GRUB_ERR_BAD_OS, "invalid ELF endianness magic"); + } + } + else if (grub_elf_is_elf64 (elf)) + { + if (!grub_elf64_check_endianess_and_bswap_ehdr (elf)) { + return grub_error (GRUB_ERR_BAD_OS, "invalid ELF endianness magic"); + } + } + else + return grub_error (GRUB_ERR_BAD_OS, "unknown ELF class"); + + if (e->e_version != EV_CURRENT) return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-independent ELF magic")); return GRUB_ERR_NONE; @@ -51,6 +87,7 @@ grub_elf_close (grub_elf_t elf) grub_file_t file = elf->file; grub_free (elf->phdrs); + grub_free (elf->filename); grub_free (elf); if (file) @@ -85,21 +122,26 @@ grub_elf_file (grub_file_t file, const char *filename) if (grub_elf_check_header (elf)) goto fail; + elf->filename = grub_strdup (filename); + if (!elf->filename) + goto fail; + return elf; fail: + grub_free (elf->filename); grub_free (elf->phdrs); grub_free (elf); return 0; } grub_elf_t -grub_elf_open (const char *name) +grub_elf_open (const char *name, enum grub_file_type type) { grub_file_t file; grub_elf_t elf; - file = grub_file_open (name); + file = grub_file_open (name, type); if (! file) return 0; @@ -111,382 +153,78 @@ grub_elf_open (const char *name) } +#define grub_swap_bytes_halfXX grub_swap_bytes16 +#define grub_swap_bytes_wordXX grub_swap_bytes32 + /* 32-bit */ +#define ehdrXX ehdr32 +#define ELFCLASSXX ELFCLASS32 +#define ElfXX_Addr Elf32_Addr +#define grub_elfXX_size grub_elf32_size +#define grub_elfXX_load grub_elf32_load +#define FOR_ELFXX_PHDRS FOR_ELF32_PHDRS +#define grub_elf_is_elfXX grub_elf_is_elf32 +#define grub_elfXX_load_phdrs grub_elf32_load_phdrs +#define ElfXX_Phdr Elf32_Phdr +#define ElfXX_Ehdr Elf32_Ehdr +#define ElfXX_Shdr Elf32_Shdr +#define ElfXX_Word Elf32_Word +#define ElfXX_Shnum Elf32_Shnum +#define grub_uintXX_t grub_uint32_t +#define grub_swap_bytes_addrXX grub_swap_bytes32 +#define grub_swap_bytes_offXX grub_swap_bytes32 +#define grub_swap_bytes_XwordXX grub_swap_bytes32 +#define grub_elfXX_check_endianess_and_bswap_ehdr grub_elf32_check_endianess_and_bswap_ehdr +#define grub_elfXX_get_shnum grub_elf32_get_shnum +#define grub_elfXX_get_shstrndx grub_elf32_get_shstrndx +#define grub_elfXX_get_phnum grub_elf32_get_phnum -int -grub_elf_is_elf32 (grub_elf_t elf) -{ - return elf->ehdr.ehdr32.e_ident[EI_CLASS] == ELFCLASS32; -} +#include "elfXX.c" -static grub_err_t -grub_elf32_load_phdrs (grub_elf_t elf, const char *filename) -{ - grub_ssize_t phdrs_size; - - phdrs_size = elf->ehdr.ehdr32.e_phnum * elf->ehdr.ehdr32.e_phentsize; - - grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n", - (unsigned long long) elf->ehdr.ehdr32.e_phoff, - (unsigned long) phdrs_size); - - elf->phdrs = grub_malloc (phdrs_size); - if (! elf->phdrs) - return grub_errno; - - if ((grub_file_seek (elf->file, elf->ehdr.ehdr32.e_phoff) == (grub_off_t) -1) - || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size)) - { - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - filename); - return grub_errno; - } - - return GRUB_ERR_NONE; -} - -grub_err_t -grub_elf32_phdr_iterate (grub_elf_t elf, - const char *filename, - int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf32_Phdr *, void *), - void *hook_arg) -{ - Elf32_Phdr *phdrs; - unsigned int i; - - if (! elf->phdrs) - if (grub_elf32_load_phdrs (elf, filename)) - return grub_errno; - phdrs = elf->phdrs; - - for (i = 0; i < elf->ehdr.ehdr32.e_phnum; i++) - { - Elf32_Phdr *phdr = phdrs + i; - grub_dprintf ("elf", - "Segment %u: type 0x%x paddr 0x%lx memsz 0x%lx " - "filesz %lx\n", - i, phdr->p_type, - (unsigned long) phdr->p_paddr, - (unsigned long) phdr->p_memsz, - (unsigned long) phdr->p_filesz); - if (hook (elf, phdr, hook_arg)) - break; - } - - return grub_errno; -} - -/* Calculate the amount of memory spanned by the segments. */ -grub_size_t -grub_elf32_size (grub_elf_t elf, const char *filename, - Elf32_Addr *base, grub_uint32_t *max_align) -{ - Elf32_Addr segments_start = (Elf32_Addr) -1; - Elf32_Addr segments_end = 0; - int nr_phdrs = 0; - grub_uint32_t curr_align = 1; - - /* Run through the program headers to calculate the total memory size we - * should claim. */ - auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf32_Phdr *phdr, void *_arg); - int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf __attribute__ ((unused)), - Elf32_Phdr *phdr, - void *_arg __attribute__ ((unused))) - { - /* Only consider loadable segments. */ - if (phdr->p_type != PT_LOAD) - return 0; - nr_phdrs++; - if (phdr->p_paddr < segments_start) - segments_start = phdr->p_paddr; - if (phdr->p_paddr + phdr->p_memsz > segments_end) - segments_end = phdr->p_paddr + phdr->p_memsz; - if (curr_align < phdr->p_align) - curr_align = phdr->p_align; - return 0; - } - - grub_elf32_phdr_iterate (elf, filename, calcsize, 0); - - if (base) - *base = 0; - - if (nr_phdrs == 0) - { - grub_error (GRUB_ERR_BAD_OS, "no program headers present"); - return 0; - } - - if (segments_end < segments_start) - { - /* Very bad addresses. */ - grub_error (GRUB_ERR_BAD_OS, "bad program header load addresses"); - return 0; - } - - if (base) - *base = segments_start; - if (max_align) - *max_align = curr_align; - return segments_end - segments_start; -} - -/* Load every loadable segment into memory specified by `_load_hook'. */ -grub_err_t -grub_elf32_load (grub_elf_t _elf, const char *filename, - grub_elf32_load_hook_t _load_hook, - grub_addr_t *base, grub_size_t *size) -{ - grub_addr_t load_base = (grub_addr_t) -1ULL; - grub_size_t load_size = 0; - grub_err_t err; - - auto int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook); - int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook) - { - grub_elf32_load_hook_t load_hook = (grub_elf32_load_hook_t) hook; - grub_addr_t load_addr; - int do_load = 1; - - load_addr = phdr->p_paddr; - if (load_hook && load_hook (phdr, &load_addr, &do_load)) - return 1; - - if (! do_load) - return 0; - - if (load_addr < load_base) - load_base = load_addr; - - grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", - (unsigned long long) load_addr, - (unsigned long long) phdr->p_memsz); - - if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) - return grub_errno; - - if (phdr->p_filesz) - { - grub_ssize_t read; - read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); - if (read != (grub_ssize_t) phdr->p_filesz) - { - /* XXX How can we free memory from `load_hook'? */ - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - filename); - return grub_errno; - } - } - - if (phdr->p_filesz < phdr->p_memsz) - grub_memset ((void *) (long) (load_addr + phdr->p_filesz), - 0, phdr->p_memsz - phdr->p_filesz); - - load_size += phdr->p_memsz; - - return 0; - } - - err = grub_elf32_phdr_iterate (_elf, filename, - grub_elf32_load_segment, _load_hook); - - if (base) - *base = load_base; - if (size) - *size = load_size; - - return err; -} +#undef ehdrXX +#undef ELFCLASSXX +#undef ElfXX_Addr +#undef grub_elfXX_size +#undef grub_elfXX_load +#undef FOR_ELFXX_PHDRS +#undef grub_elf_is_elfXX +#undef grub_elfXX_load_phdrs +#undef ElfXX_Phdr +#undef ElfXX_Ehdr +#undef ElfXX_Shdr +#undef ElfXX_Word +#undef ElfXX_Shnum +#undef grub_uintXX_t +#undef grub_swap_bytes_addrXX +#undef grub_swap_bytes_offXX +#undef grub_swap_bytes_XwordXX +#undef grub_elfXX_check_endianess_and_bswap_ehdr +#undef grub_elfXX_get_shnum +#undef grub_elfXX_get_shstrndx +#undef grub_elfXX_get_phnum /* 64-bit */ +#define ehdrXX ehdr64 +#define ELFCLASSXX ELFCLASS64 +#define ElfXX_Addr Elf64_Addr +#define grub_elfXX_size grub_elf64_size +#define grub_elfXX_load grub_elf64_load +#define FOR_ELFXX_PHDRS FOR_ELF64_PHDRS +#define grub_elf_is_elfXX grub_elf_is_elf64 +#define grub_elfXX_load_phdrs grub_elf64_load_phdrs +#define ElfXX_Phdr Elf64_Phdr +#define ElfXX_Ehdr Elf64_Ehdr +#define ElfXX_Shdr Elf64_Shdr +#define ElfXX_Word Elf64_Word +#define ElfXX_Shnum Elf64_Shnum +#define grub_uintXX_t grub_uint64_t +#define grub_swap_bytes_addrXX grub_swap_bytes64 +#define grub_swap_bytes_offXX grub_swap_bytes64 +#define grub_swap_bytes_XwordXX grub_swap_bytes64 +#define grub_elfXX_check_endianess_and_bswap_ehdr grub_elf64_check_endianess_and_bswap_ehdr +#define grub_elfXX_get_shnum grub_elf64_get_shnum +#define grub_elfXX_get_shstrndx grub_elf64_get_shstrndx +#define grub_elfXX_get_phnum grub_elf64_get_phnum -int -grub_elf_is_elf64 (grub_elf_t elf) -{ - return elf->ehdr.ehdr64.e_ident[EI_CLASS] == ELFCLASS64; -} - -static grub_err_t -grub_elf64_load_phdrs (grub_elf_t elf, const char *filename) -{ - grub_ssize_t phdrs_size; - - phdrs_size = elf->ehdr.ehdr64.e_phnum * elf->ehdr.ehdr64.e_phentsize; - - grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n", - (unsigned long long) elf->ehdr.ehdr64.e_phoff, - (unsigned long) phdrs_size); - - elf->phdrs = grub_malloc (phdrs_size); - if (! elf->phdrs) - return grub_errno; - - if ((grub_file_seek (elf->file, elf->ehdr.ehdr64.e_phoff) == (grub_off_t) -1) - || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size)) - { - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - filename); - return grub_errno; - } - - return GRUB_ERR_NONE; -} - -grub_err_t -grub_elf64_phdr_iterate (grub_elf_t elf, - const char *filename, - int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf64_Phdr *, void *), - void *hook_arg) -{ - Elf64_Phdr *phdrs; - unsigned int i; - - if (! elf->phdrs) - if (grub_elf64_load_phdrs (elf, filename)) - return grub_errno; - phdrs = elf->phdrs; - - for (i = 0; i < elf->ehdr.ehdr64.e_phnum; i++) - { - Elf64_Phdr *phdr = phdrs + i; - grub_dprintf ("elf", - "Segment %u: type 0x%x paddr 0x%lx memsz 0x%lx " - "filesz %lx\n", - i, phdr->p_type, - (unsigned long) phdr->p_paddr, - (unsigned long) phdr->p_memsz, - (unsigned long) phdr->p_filesz); - if (hook (elf, phdr, hook_arg)) - break; - } - - return grub_errno; -} - -/* Calculate the amount of memory spanned by the segments. */ -grub_size_t -grub_elf64_size (grub_elf_t elf, const char *filename, - Elf64_Addr *base, grub_uint64_t *max_align) -{ - Elf64_Addr segments_start = (Elf64_Addr) -1; - Elf64_Addr segments_end = 0; - int nr_phdrs = 0; - grub_uint64_t curr_align = 1; - - /* Run through the program headers to calculate the total memory size we - * should claim. */ - auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf64_Phdr *phdr, void *_arg); - int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf __attribute__ ((unused)), - Elf64_Phdr *phdr, - void *_arg __attribute__ ((unused))) - { - /* Only consider loadable segments. */ - if (phdr->p_type != PT_LOAD) - return 0; - nr_phdrs++; - if (phdr->p_paddr < segments_start) - segments_start = phdr->p_paddr; - if (phdr->p_paddr + phdr->p_memsz > segments_end) - segments_end = phdr->p_paddr + phdr->p_memsz; - if (curr_align < phdr->p_align) - curr_align = phdr->p_align; - return 0; - } - - grub_elf64_phdr_iterate (elf, filename, calcsize, 0); - - if (base) - *base = 0; - - if (nr_phdrs == 0) - { - grub_error (GRUB_ERR_BAD_OS, "no program headers present"); - return 0; - } - - if (segments_end < segments_start) - { - /* Very bad addresses. */ - grub_error (GRUB_ERR_BAD_OS, "bad program header load addresses"); - return 0; - } - - if (base) - *base = segments_start; - if (max_align) - *max_align = curr_align; - return segments_end - segments_start; -} - -/* Load every loadable segment into memory specified by `_load_hook'. */ -grub_err_t -grub_elf64_load (grub_elf_t _elf, const char *filename, - grub_elf64_load_hook_t _load_hook, - grub_addr_t *base, grub_size_t *size) -{ - grub_addr_t load_base = (grub_addr_t) -1ULL; - grub_size_t load_size = 0; - grub_err_t err; - - auto int NESTED_FUNC_ATTR grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr, - void *hook); - int NESTED_FUNC_ATTR grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr, void *hook) - { - grub_elf64_load_hook_t load_hook = (grub_elf64_load_hook_t) hook; - grub_addr_t load_addr; - int do_load = 1; - - load_addr = phdr->p_paddr; - if (load_hook && load_hook (phdr, &load_addr, &do_load)) - return 1; - - if (! do_load) - return 0; - - if (load_addr < load_base) - load_base = load_addr; - - grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", - (unsigned long long) load_addr, - (unsigned long long) phdr->p_memsz); - - if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) - return grub_errno; - - if (phdr->p_filesz) - { - grub_ssize_t read; - read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); - if (read != (grub_ssize_t) phdr->p_filesz) - { - /* XXX How can we free memory from `load_hook'? */ - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - filename); - return grub_errno; - } - } - - if (phdr->p_filesz < phdr->p_memsz) - grub_memset ((void *) (long) (load_addr + phdr->p_filesz), - 0, phdr->p_memsz - phdr->p_filesz); - - load_size += phdr->p_memsz; - - return 0; - } - - err = grub_elf64_phdr_iterate (_elf, filename, - grub_elf64_load_segment, _load_hook); - - if (base) - *base = load_base; - if (size) - *size = load_size; - - return err; -} +#include "elfXX.c" diff --git a/grub-core/kern/elfXX.c b/grub-core/kern/elfXX.c new file mode 100644 index 000000000..aabf4b9d7 --- /dev/null +++ b/grub-core/kern/elfXX.c @@ -0,0 +1,308 @@ +int +grub_elf_is_elfXX (grub_elf_t elf) +{ + return elf->ehdr.ehdrXX.e_ident[EI_CLASS] == ELFCLASSXX; +} + +grub_err_t +grub_elfXX_load_phdrs (grub_elf_t elf) +{ + grub_ssize_t phdrs_size; + + if (elf->phdrs) + return GRUB_ERR_NONE; + + phdrs_size = (grub_uint32_t) elf->ehdr.ehdrXX.e_phnum * elf->ehdr.ehdrXX.e_phentsize; + + grub_dprintf ("elf", "Loading program headers at 0x%llx, size 0x%lx.\n", + (unsigned long long) elf->ehdr.ehdrXX.e_phoff, + (unsigned long) phdrs_size); + + elf->phdrs = grub_malloc (phdrs_size); + if (! elf->phdrs) + return grub_errno; + + if ((grub_file_seek (elf->file, elf->ehdr.ehdrXX.e_phoff) == (grub_off_t) -1) + || (grub_file_read (elf->file, elf->phdrs, phdrs_size) != phdrs_size)) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + elf->filename); + return grub_errno; + } + +#if GRUB_ELF_ENABLE_BI_ENDIAN + if (elf->ehdr.ehdrXX.e_ident[EI_DATA] == GRUB_ELF_OPPOSITE_ENDIANNESS) + { + ElfXX_Phdr *phdr; + for (phdr = elf->phdrs; (char *) phdr < (char *) elf->phdrs + phdrs_size; + phdr = (ElfXX_Phdr *) ((char *) phdr + elf->ehdr.ehdrXX.e_phentsize)) + { + phdr->p_type = grub_swap_bytes_wordXX (phdr->p_type); + phdr->p_flags = grub_swap_bytes_wordXX (phdr->p_flags); + phdr->p_offset = grub_swap_bytes_offXX (phdr->p_offset); + phdr->p_vaddr = grub_swap_bytes_addrXX (phdr->p_vaddr); + phdr->p_paddr = grub_swap_bytes_addrXX (phdr->p_paddr); + phdr->p_filesz = grub_swap_bytes_XwordXX (phdr->p_filesz); + phdr->p_memsz = grub_swap_bytes_XwordXX (phdr->p_memsz); + phdr->p_align = grub_swap_bytes_XwordXX (phdr->p_align); + } + } +#endif /* GRUB_ELF_ENABLE_BI_ENDIAN */ + + return GRUB_ERR_NONE; +} + +/* Calculate the amount of memory spanned by the segments. */ +grub_size_t +grub_elfXX_size (grub_elf_t elf, + ElfXX_Addr *base, grub_uintXX_t *max_align) +{ + ElfXX_Addr segments_start = (ElfXX_Addr) -1; + ElfXX_Addr segments_end = 0; + int nr_phdrs = 0; + grub_uint32_t curr_align = 1; + ElfXX_Phdr *phdr; + + /* Run through the program headers to calculate the total memory size we + * should claim. */ + FOR_ELFXX_PHDRS (elf, phdr) + { + /* Only consider loadable segments. */ + if (phdr->p_type != PT_LOAD) + continue; + nr_phdrs++; + if (phdr->p_paddr < segments_start) + segments_start = phdr->p_paddr; + if (phdr->p_paddr + phdr->p_memsz > segments_end) + segments_end = phdr->p_paddr + phdr->p_memsz; + if (curr_align < phdr->p_align) + curr_align = phdr->p_align; + } + + if (base) + *base = 0; + + if (nr_phdrs == 0) + { + grub_error (GRUB_ERR_BAD_OS, "no program headers present"); + return 0; + } + + if (segments_end < segments_start) + { + /* Very bad addresses. */ + grub_error (GRUB_ERR_BAD_OS, "bad program header load addresses"); + return 0; + } + + if (base) + *base = segments_start; + if (max_align) + *max_align = curr_align; + return segments_end - segments_start; +} + +grub_err_t +grub_elfXX_load (grub_elf_t elf, const char *filename, + void *load_offset, enum grub_elf_load_flags load_flags, + grub_addr_t *base, grub_size_t *size) +{ + grub_addr_t load_base = (grub_addr_t) -1ULL; + grub_size_t load_size = 0; + ElfXX_Phdr *phdr; + + FOR_ELFXX_PHDRS(elf, phdr) + { + grub_addr_t load_addr; + + if (phdr->p_type != PT_LOAD && !((load_flags & GRUB_ELF_LOAD_FLAGS_LOAD_PT_DYNAMIC) && phdr->p_type == PT_DYNAMIC)) + continue; + + load_addr = (grub_addr_t) phdr->p_paddr; + switch (load_flags & GRUB_ELF_LOAD_FLAGS_BITS) + { + case GRUB_ELF_LOAD_FLAGS_ALL_BITS: + break; + case GRUB_ELF_LOAD_FLAGS_28BITS: + load_addr &= 0xFFFFFFF; + break; + case GRUB_ELF_LOAD_FLAGS_30BITS: + load_addr &= 0x3FFFFFFF; + break; + case GRUB_ELF_LOAD_FLAGS_62BITS: + load_addr &= 0x3FFFFFFFFFFFFFFFULL; + break; + } + load_addr += (grub_addr_t) load_offset; + + if (load_addr < load_base) + load_base = load_addr; + + grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", + (unsigned long long) load_addr, + (unsigned long long) phdr->p_memsz); + + if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) + return grub_errno; + + if (phdr->p_filesz) + { + grub_ssize_t read; + read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); + if (read != (grub_ssize_t) phdr->p_filesz) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); + return grub_errno; + } + } + + if (phdr->p_filesz < phdr->p_memsz) + grub_memset ((void *) (grub_addr_t) (load_addr + phdr->p_filesz), + 0, phdr->p_memsz - phdr->p_filesz); + + load_size += phdr->p_memsz; + } + + if (base) + *base = load_base; + if (size) + *size = load_size; + + return grub_errno; +} + +static int +grub_elfXX_check_endianess_and_bswap_ehdr (grub_elf_t elf) +{ + ElfXX_Ehdr *e = &(elf->ehdr.ehdrXX); + if (e->e_ident[EI_DATA] == GRUB_ELF_NATIVE_ENDIANNESS) + { + return 1; + } + +#if GRUB_ELF_ENABLE_BI_ENDIAN + if (e->e_ident[EI_DATA] == GRUB_ELF_OPPOSITE_ENDIANNESS) + { + e->e_type = grub_swap_bytes_halfXX (e->e_type); + e->e_machine = grub_swap_bytes_halfXX (e->e_machine); + e->e_version = grub_swap_bytes_wordXX (e->e_version); + e->e_entry = grub_swap_bytes_addrXX (e->e_entry); + e->e_phoff = grub_swap_bytes_offXX (e->e_phoff); + e->e_shoff = grub_swap_bytes_offXX (e->e_shoff); + e->e_flags = grub_swap_bytes_wordXX (e->e_flags); + e->e_ehsize = grub_swap_bytes_halfXX (e->e_ehsize); + e->e_phentsize = grub_swap_bytes_halfXX (e->e_phentsize); + e->e_phnum = grub_swap_bytes_halfXX (e->e_phnum); + e->e_shentsize = grub_swap_bytes_halfXX (e->e_shentsize); + e->e_shnum = grub_swap_bytes_halfXX (e->e_shnum); + e->e_shstrndx = grub_swap_bytes_halfXX (e->e_shstrndx); + return 1; + } +#endif /* GRUB_ELF_ENABLE_BI_ENDIAN */ + + return 0; +} + +grub_err_t +grub_elfXX_get_shnum (ElfXX_Ehdr *e, ElfXX_Shnum *shnum) +{ + ElfXX_Shdr *s; + + if (shnum == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("NULL pointer passed for shnum")); + + /* Set *shnum to 0 so that shnum doesn't return junk on error */ + *shnum = 0; + + if (e == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("NULL pointer passed for elf header")); + + *shnum = e->e_shnum; + if (*shnum == SHN_UNDEF) + { + if (e->e_shoff == 0) + return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid section header table offset in e_shoff")); + + s = (ElfXX_Shdr *) ((grub_uint8_t *) e + e->e_shoff); + *shnum = s->sh_size; + if (*shnum < SHN_LORESERVE) + return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid number of section header table entries in sh_size: %" PRIuGRUB_UINT64_T), (grub_uint64_t) *shnum); + } + else + { + if (*shnum >= SHN_LORESERVE) + return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid number of section header table entries in e_shnum: %" PRIuGRUB_UINT64_T), (grub_uint64_t) *shnum); + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_elfXX_get_shstrndx (ElfXX_Ehdr *e, ElfXX_Word *shstrndx) +{ + ElfXX_Shdr *s; + + if (shstrndx == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("NULL pointer passed for shstrndx")); + + /* Set *shstrndx to 0 so that shstrndx doesn't return junk on error */ + *shstrndx = 0; + + if (e == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("NULL pointer passed for elf header")); + + *shstrndx = e->e_shstrndx; + if (*shstrndx == SHN_XINDEX) + { + if (e->e_shoff == 0) + return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid section header table offset in e_shoff")); + + s = (ElfXX_Shdr *) ((grub_uint8_t *) e + e->e_shoff); + *shstrndx = s->sh_link; + if (*shstrndx < SHN_LORESERVE) + return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid section header table index in sh_link: %d"), *shstrndx); + } + else + { + if (*shstrndx >= SHN_LORESERVE) + return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid section header table index in e_shstrndx: %d"), *shstrndx); + } + return GRUB_ERR_NONE; +} + +grub_err_t +grub_elfXX_get_phnum (ElfXX_Ehdr *e, ElfXX_Word *phnum) +{ + ElfXX_Shdr *s; + + if (phnum == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("NULL pointer passed for phnum")); + + /* Set *phnum to 0 so that phnum doesn't return junk on error */ + *phnum = 0; + + if (e == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("NULL pointer passed for elf header")); + + *phnum = e->e_phnum; + if (*phnum == PN_XNUM) + { + if (e->e_shoff == 0) + return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid section header table offset in e_shoff")); + + s = (ElfXX_Shdr *) ((grub_uint8_t *) e + e->e_shoff); + *phnum = s->sh_info; + if (*phnum < PN_XNUM) + return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid number of program header table entries in sh_info: %d"), *phnum); + } + else + { + if (*phnum >= PN_XNUM) + return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid number of program header table entries in e_phnum: %d"), *phnum); + } + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/emu/argp_common.c b/grub-core/kern/emu/argp_common.c index d6080ba25..8cb4608c3 100644 --- a/grub-core/kern/emu/argp_common.c +++ b/grub-core/kern/emu/argp_common.c @@ -17,8 +17,12 @@ * along with GRUB. If not, see . */ +#include #include +#pragma GCC diagnostic ignored "-Wmissing-prototypes" +#pragma GCC diagnostic ignored "-Wmissing-declarations" + #define _GNU_SOURCE 1 #include #include diff --git a/grub-core/kern/emu/cache.c b/grub-core/kern/emu/cache.c index 543e457e5..113682cc4 100644 --- a/grub-core/kern/emu/cache.c +++ b/grub-core/kern/emu/cache.c @@ -1,13 +1,35 @@ +#ifndef GRUB_MACHINE_EMU +#error "This source is only meant for grub-emu platform" +#endif -#if defined(__ia64__) #include -void __clear_cache (char *beg, char *end); +#if defined(__ia64__) +#include "../ia64/cache.c" +#elif defined (__arm__) || defined (__aarch64__) + +void __clear_cache (void *beg, void *end); void grub_arch_sync_caches (void *address, grub_size_t len) { __clear_cache (address, (char *) address + len); } + +#elif defined (__mips__) +void _flush_cache (void *address, grub_size_t len, int type); + +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ + return _flush_cache (address, len, 0); +} + +#elif defined(__riscv) +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ +} + #endif diff --git a/grub-core/kern/emu/cache_s.S b/grub-core/kern/emu/cache_s.S index 8ca695c28..6885ffd69 100644 --- a/grub-core/kern/emu/cache_s.S +++ b/grub-core/kern/emu/cache_s.S @@ -2,28 +2,19 @@ #error "This source is only meant for grub-emu platform" #endif +/* An executable stack is not required for these functions. */ +#if defined (__linux__) && defined (__ELF__) +.section .note.GNU-stack,"",%progbits +#endif + #if defined(__i386__) || defined(__x86_64__) /* Nothing is necessary. */ #elif defined(__sparc__) #include "../sparc64/cache.S" -#elif defined(__mips__) -/* On MIPS we must go through standard functions. */ -#include - -FUNCTION (grub_cpu_flush_cache) -FUNCTION (grub_arch_sync_caches) - .set nomacro - .set noreorder - lui $t0, %hi(_flush_cache) - addui $t0, $t0, %lo(_flush_cache) - move $a3, $zero - jr $t0 - nop - .set reorder - .set macro #elif defined(__powerpc__) #include "../powerpc/cache.S" -#elif defined(__ia64__) +#elif defined(__ia64__) || defined(__arm__) || defined(__aarch64__) || \ + defined(__mips__) || defined(__riscv) #else #error "No target cpu type is defined" #endif diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c index b167a141b..e8d63b1f5 100644 --- a/grub-core/kern/emu/full.c +++ b/grub-core/kern/emu/full.c @@ -24,6 +24,8 @@ #include #include +const int grub_no_modules = 1; + void grub_register_exported_symbols (void) { @@ -37,25 +39,24 @@ grub_arch_dl_check_header (void *ehdr) } grub_err_t -grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg) { (void) mod; (void) ehdr; + (void) s; + (void) seg; return GRUB_ERR_BAD_MODULE; } -void -grub_emu_init (void) -{ - grub_no_autoload = 1; -} - -#if defined (__ia64__) || defined (__powerpc__) -void grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)), - grub_size_t *tramp, grub_size_t *got) +#if !defined (__i386__) && !defined (__x86_64__) +grub_err_t +grub_arch_dl_get_tramp_got_size (const void *ehdr __attribute__ ((unused)), + grub_size_t *tramp, grub_size_t *got) { *tramp = 0; *got = 0; + return GRUB_ERR_BAD_MODULE; } #endif @@ -66,7 +67,3 @@ grub_arch_dl_init_linker (void) } #endif -void -grub_emu_post_init (void) -{ -} diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index b8c376643..0e6eebdc8 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -17,6 +17,8 @@ * along with GRUB. If not, see . */ +#include + #include #include #include @@ -44,77 +46,11 @@ #ifdef __linux__ # include /* ioctl */ # include -# if !defined(__GLIBC__) || \ - ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))) -/* Maybe libc doesn't have large file support. */ -# include /* _llseek */ -# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */ # ifndef BLKFLSBUF # define BLKFLSBUF _IO (0x12,97) /* flush buffer cache */ # endif /* ! BLKFLSBUF */ -# include /* ioctl */ -# ifndef HDIO_GETGEO -# define HDIO_GETGEO 0x0301 /* get device geometry */ -/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is - defined. */ -struct hd_geometry -{ - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - unsigned long start; -}; -# endif /* ! HDIO_GETGEO */ -# ifndef BLKGETSIZE64 -# define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size */ -# endif /* ! BLKGETSIZE64 */ #endif /* __linux__ */ -#ifdef __CYGWIN__ -# include -# include /* BLKGETSIZE64 */ -# include /* HDIO_GETGEO */ -#endif - -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -# include /* DIOCGMEDIASIZE */ -# include -# include -# include -#include -#endif - -#if defined (__sun__) -# include -#endif - -#if defined(__APPLE__) -# include -#endif - -#ifdef HAVE_DEVICE_MAPPER -# include -#endif - -#if defined(__NetBSD__) -# define HAVE_DIOCGDINFO -# include -# include /* struct disklabel */ -# include /* struct dkwedge_info */ -#else /* !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) */ -# undef HAVE_DIOCGDINFO -#endif /* defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */ - -#if defined(__NetBSD__) -# ifdef HAVE_GETRAWPARTITION -# include /* getrawpartition */ -# endif /* HAVE_GETRAWPARTITION */ -# include -# ifndef RAW_FLOPPY_MAJOR -# define RAW_FLOPPY_MAJOR 9 -# endif /* ! RAW_FLOPPY_MAJOR */ -#endif /* defined(__NetBSD__) */ - static struct { char *drive; @@ -122,58 +58,6 @@ static struct int device_map; } map[256]; -struct grub_util_biosdisk_data -{ - char *dev; - int access_mode; - int fd; - int is_disk; - int device_map; -}; - -#ifdef __linux__ -/* Check if we have devfs support. */ -static int -have_devfs (void) -{ - static int dev_devfsd_exists = -1; - - if (dev_devfsd_exists < 0) - { - struct stat st; - - dev_devfsd_exists = stat ("/dev/.devfsd", &st) == 0; - } - - return dev_devfsd_exists; -} -#endif /* __linux__ */ - -#if defined(__NetBSD__) -/* Adjust device driver parameters. This function should be called just - after successfully opening the device. For now, it simply prevents the - floppy driver from retrying operations on failure, as otherwise the - driver takes a while to abort when there is no floppy in the drive. */ -static void -configure_device_driver (int fd) -{ - struct stat st; - - if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode)) - return; - if (major(st.st_rdev) == RAW_FLOPPY_MAJOR) - { - int floppy_opts; - - if (ioctl (fd, FDIOCGETOPTS, &floppy_opts) == -1) - return; - floppy_opts |= FDOPT_NORETRY; - if (ioctl (fd, FDIOCSETOPTS, &floppy_opts) == -1) - return; - } -} -#endif /* defined(__NetBSD__) */ - static int unescape_cmp (const char *a, const char *b_escaped) { @@ -215,7 +99,7 @@ find_free_slot (void) { unsigned int i; - for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) + for (i = 0; i < ARRAY_SIZE (map); i++) if (! map[i].drive) return i; @@ -223,7 +107,7 @@ find_free_slot (void) } static int -grub_util_biosdisk_iterate (int (*hook) (const char *name), +grub_util_biosdisk_iterate (grub_disk_dev_iterate_hook_t hook, void *hook_data, grub_disk_pull_t pull) { unsigned i; @@ -231,735 +115,120 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name), if (pull != GRUB_DISK_PULL_NONE) return 0; - for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) - if (map[i].drive && hook (map[i].drive)) + for (i = 0; i < ARRAY_SIZE (map); i++) + if (map[i].drive && hook (map[i].drive, hook_data)) return 1; return 0; } -#if !defined(__MINGW32__) -grub_uint64_t -grub_util_get_fd_size (int fd, const char *name, unsigned *log_secsize) -{ -#if !defined (__GNU__) -# if defined(__NetBSD__) - struct disklabel label; -# elif defined (__sun__) - struct dk_minfo minfo; -# else - unsigned long long nr; -# endif -#endif - unsigned sector_size, log_sector_size; - struct stat st; - - if (fstat (fd, &st) < 0) - /* TRANSLATORS: "stat" comes from the name of POSIX function. */ - grub_util_error (_("cannot stat `%s': %s"), name, strerror (errno)); - -#if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \ - defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) \ - || defined (__sun__) - -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) || defined (__sun__) - if (! S_ISCHR (st.st_mode)) -# else - if (! S_ISBLK (st.st_mode)) -# endif - goto fail; - -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - if (ioctl (fd, DIOCGMEDIASIZE, &nr)) -# elif defined(__APPLE__) - if (ioctl (fd, DKIOCGETBLOCKCOUNT, &nr)) -# elif defined(__NetBSD__) - configure_device_driver (fd); - if (ioctl (fd, DIOCGDINFO, &label) == -1) -# elif defined (__sun__) - if (!ioctl (fd, DKIOCGMEDIAINFO, &minfo)) -# else - if (ioctl (fd, BLKGETSIZE64, &nr)) -# endif - goto fail; - -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - if (ioctl (fd, DIOCGSECTORSIZE, §or_size)) - goto fail; -# elif defined(__APPLE__) - if (ioctl (fd, DKIOCGETBLOCKSIZE, §or_size)) - goto fail; -# elif defined(__sun__) - sector_size = minfo.dki_lbsize; -# elif defined(__NetBSD__) - sector_size = label.d_secsize; -# else - if (ioctl (fd, BLKSSZGET, §or_size)) - goto fail; -# endif - if (sector_size & (sector_size - 1) || !sector_size) - goto fail; - for (log_sector_size = 0; - (1 << log_sector_size) < sector_size; - log_sector_size++); - - if (log_secsize) - *log_secsize = log_sector_size; - -# if defined (__APPLE__) - return nr << log_sector_size; -# elif defined(__NetBSD__) - return (grub_uint64_t) label.d_secperunit << log_sector_size; -# elif defined (__sun__) - return minfo.dki_capacity << log_sector_size; -# else - if (nr & ((1 << log_sector_size) - 1)) - grub_util_error ("%s", _("unaligned device size")); - - return nr; -# endif - - fail: - - /* In GNU/Hurd, stat() will return the right size. */ -#elif !defined (__GNU__) -# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal." -#endif - - sector_size = 512; - log_sector_size = 9; - - if (log_secsize) - *log_secsize = 9; - - return st.st_size; -} -#endif - static grub_err_t grub_util_biosdisk_open (const char *name, grub_disk_t disk) { int drive; - struct stat st; - struct grub_util_biosdisk_data *data; + struct grub_util_hostdisk_data *data; drive = find_grub_drive (name); + grub_util_info ("drive = %d", drive); if (drive < 0) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no mapping exists for `%s'", name); disk->id = drive; - disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data)); + disk->data = data = xmalloc (sizeof (struct grub_util_hostdisk_data)); data->dev = NULL; data->access_mode = 0; - data->fd = -1; + data->fd = GRUB_UTIL_FD_INVALID; data->is_disk = 0; data->device_map = map[drive].device_map; /* Get the size. */ -#if defined(__MINGW32__) { - grub_uint64_t size; + grub_util_fd_t fd; - size = grub_util_get_disk_size (map[drive].device); + fd = grub_util_fd_open (map[drive].device, GRUB_UTIL_FD_O_RDONLY); - if (size % 512) - grub_util_error (_("unaligned device size")); - - disk->total_sectors = size >> 9; - - grub_util_info ("the size of %s is %llu", name, disk->total_sectors); - - return GRUB_ERR_NONE; - } -#else - { - int fd; - - fd = open (map[drive].device, O_RDONLY); - if (fd == -1) + if (!GRUB_UTIL_FD_IS_VALID(fd)) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("cannot open `%s': %s"), - map[drive].device, strerror (errno)); + map[drive].device, grub_util_fd_strerror ()); disk->total_sectors = grub_util_get_fd_size (fd, map[drive].device, &disk->log_sector_size); disk->total_sectors >>= disk->log_sector_size; + disk->max_agglomerate = GRUB_DISK_MAX_MAX_AGGLOMERATE; -# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) - if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode)) +#if GRUB_UTIL_FD_STAT_IS_FUNCTIONAL + { + struct stat st; +# if GRUB_DISK_DEVS_ARE_CHAR + if (fstat (fd, &st) >= 0 && S_ISCHR (st.st_mode)) # else - if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode)) + if (fstat (fd, &st) >= 0 && S_ISBLK (st.st_mode)) # endif - data->is_disk = 1; + data->is_disk = 1; + } +#endif - close (fd); + grub_util_fd_close (fd); - grub_util_info ("the size of %s is %" PRIuGRUB_UINT64_T, - name, disk->total_sectors); + grub_util_info ("the size of %s is %" GRUB_HOST_PRIuLONG_LONG, + name, (unsigned long long) disk->total_sectors); return GRUB_ERR_NONE; } -#endif -} - -int -grub_util_device_is_mapped (const char *dev) -{ -#ifdef HAVE_DEVICE_MAPPER - struct stat st; - - if (!grub_device_mapper_supported ()) - return 0; - - if (stat (dev, &st) < 0) - return 0; - - return dm_is_dm_major (major (st.st_rdev)); -#else - return 0; -#endif /* HAVE_DEVICE_MAPPER */ -} - -#ifdef HAVE_DEVICE_MAPPER -int -grub_util_get_dm_node_linear_info (const char *dev, - int *maj, int *min, - grub_disk_addr_t *st) -{ - struct dm_task *dmt; - void *next = NULL; - uint64_t length, start; - char *target, *params; - char *ptr; - int major, minor; - int first = 1; - grub_disk_addr_t partstart = 0; - - while (1) - { - dmt = dm_task_create(DM_DEVICE_TABLE); - if (!dmt) - break; - - if (! (first ? dm_task_set_name (dmt, dev) - : dm_task_set_major_minor (dmt, major, minor, 0))) - { - dm_task_destroy (dmt); - break; - } - dm_task_no_open_count(dmt); - if (!dm_task_run(dmt)) - { - dm_task_destroy (dmt); - break; - } - next = dm_get_next_target(dmt, next, &start, &length, - &target, ¶ms); - if (grub_strcmp (target, "linear") != 0) - { - dm_task_destroy (dmt); - break; - } - major = grub_strtoul (params, &ptr, 10); - if (grub_errno) - { - dm_task_destroy (dmt); - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (*ptr != ':') - { - dm_task_destroy (dmt); - return 0; - } - ptr++; - minor = grub_strtoul (ptr, &ptr, 10); - if (grub_errno) - { - grub_errno = GRUB_ERR_NONE; - dm_task_destroy (dmt); - return 0; - } - - if (*ptr != ' ') - { - dm_task_destroy (dmt); - return 0; - } - ptr++; - partstart += grub_strtoull (ptr, &ptr, 10); - if (grub_errno) - { - grub_errno = GRUB_ERR_NONE; - dm_task_destroy (dmt); - return 0; - } - - dm_task_destroy (dmt); - first = 0; - } - if (first) - return 0; - if (maj) - *maj = major; - if (min) - *min = minor; - if (st) - *st = partstart; - return 1; -} -#endif - -#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) - -/* FIXME: geom actually gives us the whole container hierarchy. - It can be used more efficiently than this. */ -void -grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, char **name_out) -{ - struct gmesh mesh; - struct gclass *class; - int error; - struct ggeom *geom; - - grub_util_info ("following geom '%s'", name); - - error = geom_gettree (&mesh); - if (error != 0) - /* TRANSLATORS: geom is the name of (k)FreeBSD device framework. - Usually left untranslated. - */ - grub_util_error ("%s", _("couldn't open geom")); - - LIST_FOREACH (class, &mesh.lg_class, lg_class) - if (strcasecmp (class->lg_name, "part") == 0) - break; - if (!class) - /* TRANSLATORS: geom is the name of (k)FreeBSD device framework. - Usually left untranslated. "part" is the identifier of one of its - classes. */ - grub_util_error ("%s", _("couldn't find geom `part' class")); - - LIST_FOREACH (geom, &class->lg_geom, lg_geom) - { - struct gprovider *provider; - LIST_FOREACH (provider, &geom->lg_provider, lg_provider) - if (strcmp (provider->lg_name, name) == 0) - { - char *name_tmp = xstrdup (geom->lg_name); - grub_disk_addr_t off = 0; - struct gconfig *config; - grub_util_info ("geom '%s' has parent '%s'", name, geom->lg_name); - - grub_util_follow_gpart_up (name_tmp, &off, name_out); - free (name_tmp); - LIST_FOREACH (config, &provider->lg_config, lg_config) - if (strcasecmp (config->lg_name, "start") == 0) - off += strtoull (config->lg_val, 0, 10); - if (off_out) - *off_out = off; - return; - } - } - grub_util_info ("geom '%s' has no parent", name); - if (name_out) - *name_out = xstrdup (name); - if (off_out) - *off_out = 0; -} - -grub_disk_addr_t -grub_hostdisk_find_partition_start (const char *dev) -{ - grub_disk_addr_t out; - if (strncmp (dev, "/dev/", sizeof ("/dev/") - 1) != 0) - return 0; - grub_util_follow_gpart_up (dev + sizeof ("/dev/") - 1, &out, NULL); - - return out; -} - -#elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined (__sun__) -grub_disk_addr_t -grub_hostdisk_find_partition_start (const char *dev) -{ - int fd; -#ifdef __sun__ - struct extpart_info pinfo; -# elif !defined(HAVE_DIOCGDINFO) - struct hd_geometry hdg; -# else /* defined(HAVE_DIOCGDINFO) */ -# if defined(__NetBSD__) - struct dkwedge_info dkw; -# endif /* defined(__NetBSD__) */ - struct disklabel label; - int p_index; -# endif /* !defined(HAVE_DIOCGDINFO) */ - -# ifdef HAVE_DEVICE_MAPPER - grub_disk_addr_t partition_start; - if (grub_util_device_is_mapped (dev) - && grub_util_get_dm_node_linear_info (dev, 0, 0, &partition_start)) - return partition_start; -# endif /* HAVE_DEVICE_MAPPER */ - - fd = open (dev, O_RDONLY); - if (fd == -1) - { - grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"), - dev, strerror (errno)); - return 0; - } - -#if defined(__sun__) - if (ioctl (fd, DKIOCEXTPARTINFO, &pinfo)) -# elif !defined(HAVE_DIOCGDINFO) - if (ioctl (fd, HDIO_GETGEO, &hdg)) -# else /* defined(HAVE_DIOCGDINFO) */ -# if defined(__NetBSD__) - configure_device_driver (fd); - /* First handle the case of disk wedges. */ - if (ioctl (fd, DIOCGWEDGEINFO, &dkw) == 0) - { - close (fd); - return (grub_disk_addr_t) dkw.dkw_offset; - } -# endif /* defined(__NetBSD__) */ - if (ioctl (fd, DIOCGDINFO, &label) == -1) -# endif /* !defined(HAVE_DIOCGDINFO) */ - { - grub_error (GRUB_ERR_BAD_DEVICE, -# if !defined(HAVE_DIOCGDINFO) - "cannot get disk geometry of `%s'", dev); -# else /* defined(HAVE_DIOCGDINFO) */ - "cannot get disk label of `%s'", dev); -# endif /* !defined(HAVE_DIOCGDINFO) */ - close (fd); - return 0; - } - - close (fd); - -#ifdef __sun__ - return pinfo.p_start; -# elif !defined(HAVE_DIOCGDINFO) - return hdg.start; -# else /* defined(HAVE_DIOCGDINFO) */ - if (dev[0]) - p_index = dev[strlen(dev) - 1] - 'a'; - else - p_index = -1; - - if (p_index >= label.d_npartitions || p_index < 0) - { - grub_error (GRUB_ERR_BAD_DEVICE, - "no disk label entry for `%s'", dev); - return 0; - } - return (grub_disk_addr_t) label.d_partitions[p_index].p_offset; -# endif /* !defined(HAVE_DIOCGDINFO) */ -} -#endif /* __linux__ || __CYGWIN__ || HAVE_DIOCGDINFO */ - -#ifdef __linux__ -/* Cache of partition start sectors for each disk. */ -struct linux_partition_cache -{ - struct linux_partition_cache *next; - struct linux_partition_cache **prev; - char *dev; - unsigned long start; - int partno; -}; - -struct linux_partition_cache *linux_partition_cache_list; - -static int -linux_find_partition (char *dev, grub_disk_addr_t sector) -{ - size_t len = strlen (dev); - const char *format; - char *p; - int i; - char real_dev[PATH_MAX]; - struct linux_partition_cache *cache; - int missing = 0; - - strcpy(real_dev, dev); - - if (have_devfs () && strcmp (real_dev + len - 5, "/disc") == 0) - { - p = real_dev + len - 4; - format = "part%d"; - } - else if (strncmp (real_dev, "/dev/disk/by-id/", - sizeof ("/dev/disk/by-id/") - 1) == 0) - { - p = real_dev + len; - format = "-part%d"; - } - else if (real_dev[len - 1] >= '0' && real_dev[len - 1] <= '9') - { - p = real_dev + len; - format = "p%d"; - } - else - { - p = real_dev + len; - format = "%d"; - } - - for (cache = linux_partition_cache_list; cache; cache = cache->next) - { - if (strcmp (cache->dev, dev) == 0 && cache->start == sector) - { - sprintf (p, format, cache->partno); - strcpy (dev, real_dev); - return 1; - } - } - - for (i = 1; i < 10000; i++) - { - int fd; - grub_disk_addr_t start; - - sprintf (p, format, i); - - fd = open (real_dev, O_RDONLY); - if (fd == -1) - { - if (missing++ < 10) - continue; - else - return 0; - } - missing = 0; - close (fd); - - start = grub_hostdisk_find_partition_start (real_dev); - /* We don't care about errors here. */ - grub_errno = GRUB_ERR_NONE; - - if (start == sector) - { - struct linux_partition_cache *new_cache_item; - - new_cache_item = xmalloc (sizeof *new_cache_item); - new_cache_item->dev = xstrdup (dev); - new_cache_item->start = start; - new_cache_item->partno = i; - grub_list_push (GRUB_AS_LIST_P (&linux_partition_cache_list), - GRUB_AS_LIST (new_cache_item)); - - strcpy (dev, real_dev); - return 1; - } - } - - return 0; -} -#endif /* __linux__ */ - -#if defined(__linux__) && (!defined(__GLIBC__) || \ - ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))) - /* Maybe libc doesn't have large file support. */ -grub_err_t -grub_util_fd_seek (int fd, const char *name, grub_uint64_t off) -{ - loff_t offset, result; - static int _llseek (uint filedes, ulong hi, ulong lo, - loff_t *res, uint wh); - _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo, - loff_t *, res, uint, wh); - - offset = (loff_t) off; - if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) - return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), - name, strerror (errno)); - return GRUB_ERR_NONE; -} -#else -grub_err_t -grub_util_fd_seek (int fd, const char *name, grub_uint64_t off) -{ - off_t offset = (off_t) off; - - if (lseek (fd, offset, SEEK_SET) != offset) - return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), - name, strerror (errno)); - return 0; -} -#endif - -static void -flush_initial_buffer (const char *os_dev __attribute__ ((unused))) -{ -#ifdef __linux__ - int fd; - struct stat st; - - fd = open (os_dev, O_RDONLY); - if (fd >= 0 && fstat (fd, &st) >= 0 && S_ISBLK (st.st_mode)) - ioctl (fd, BLKFLSBUF, 0); - if (fd >= 0) - close (fd); -#endif } const char * grub_hostdisk_os_dev_to_grub_drive (const char *os_disk, int add) { unsigned int i; + char *canon; + + canon = grub_canonicalize_file_name (os_disk); + if (!canon) + canon = xstrdup (os_disk); for (i = 0; i < ARRAY_SIZE (map); i++) if (! map[i].device) break; - else if (strcmp (map[i].device, os_disk) == 0) - return map[i].drive; + else if (strcmp (map[i].device, canon) == 0) + { + free (canon); + return map[i].drive; + } if (!add) - return NULL; + { + free (canon); + return NULL; + } if (i == ARRAY_SIZE (map)) /* TRANSLATORS: it refers to the lack of free slots. */ grub_util_error ("%s", _("device count exceeds limit")); - map[i].device = xstrdup (os_disk); + map[i].device = canon; map[i].drive = xmalloc (sizeof ("hostdisk/") + strlen (os_disk)); strcpy (map[i].drive, "hostdisk/"); strcpy (map[i].drive + sizeof ("hostdisk/") - 1, os_disk); map[i].device_map = 0; - flush_initial_buffer (os_disk); + grub_hostdisk_flush_initial_buffer (os_disk); return map[i].drive; } -static int -open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags, - grub_disk_addr_t *max) +#ifndef __linux__ +grub_util_fd_t +grub_util_fd_open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags, + grub_disk_addr_t *max) { - int fd; - struct grub_util_biosdisk_data *data = disk->data; + grub_util_fd_t fd; + struct grub_util_hostdisk_data *data = disk->data; *max = ~0ULL; -#ifdef O_LARGEFILE - flags |= O_LARGEFILE; -#endif -#ifdef O_SYNC - flags |= O_SYNC; -#endif -#ifdef O_FSYNC - flags |= O_FSYNC; -#endif -#ifdef O_BINARY - flags |= O_BINARY; -#endif - -#ifdef __linux__ - /* Linux has a bug that the disk cache for a whole disk is not consistent - with the one for a partition of the disk. */ - { - int is_partition = 0; - char dev[PATH_MAX]; - grub_disk_addr_t part_start = 0; - - part_start = grub_partition_get_start (disk->partition); - - strcpy (dev, map[disk->id].device); - if (disk->partition - && strncmp (map[disk->id].device, "/dev/", 5) == 0) - { - if (sector >= part_start) - is_partition = linux_find_partition (dev, part_start); - else - *max = part_start - sector; - } - - reopen: - - if (data->dev && strcmp (data->dev, dev) == 0 && - data->access_mode == (flags & O_ACCMODE)) - { - grub_dprintf ("hostdisk", "reusing open device `%s'\n", dev); - fd = data->fd; - } - else - { - free (data->dev); - data->dev = 0; - if (data->fd != -1) - { - if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY) - { - fsync (data->fd); -#ifdef __linux__ - if (data->is_disk) - ioctl (data->fd, BLKFLSBUF, 0); -#endif - } - - close (data->fd); - data->fd = -1; - } - - /* Open the partition. */ - grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev); - fd = open (dev, flags); - if (fd < 0) - { - grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"), - dev, strerror (errno)); - return -1; - } - - data->dev = xstrdup (dev); - data->access_mode = (flags & O_ACCMODE); - data->fd = fd; - -#ifdef __linux__ - if (data->is_disk) - ioctl (data->fd, BLKFLSBUF, 0); -#endif - } - - if (is_partition) - { - *max = grub_util_get_fd_size (fd, dev, 0); - *max >>= disk->log_sector_size; - if (sector - part_start >= *max) - { - *max = disk->partition->len - (sector - part_start); - if (*max == 0) - *max = ~0ULL; - is_partition = 0; - strcpy (dev, map[disk->id].device); - goto reopen; - } - sector -= part_start; - *max -= sector; - } - } -#else /* ! __linux__ */ -#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) - int sysctl_flags, sysctl_oldflags; - size_t sysctl_size = sizeof (sysctl_flags); - - if (sysctlbyname ("kern.geom.debugflags", &sysctl_oldflags, &sysctl_size, NULL, 0)) - { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot get current flags of sysctl kern.geom.debugflags"); - return -1; - } - sysctl_flags = sysctl_oldflags | 0x10; - if (! (sysctl_oldflags & 0x10) - && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_flags, sysctl_size)) - { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags of sysctl kern.geom.debugflags"); - return -1; - } -#endif + flags |= GRUB_UTIL_FD_O_SYNC; if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 && data->access_mode == (flags & O_ACCMODE)) @@ -971,22 +240,16 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags, { free (data->dev); data->dev = 0; - if (data->fd != -1) + if (GRUB_UTIL_FD_IS_VALID(data->fd)) { if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY) - { - fsync (data->fd); -#ifdef __linux__ - if (data->is_disk) - ioctl (data->fd, BLKFLSBUF, 0); -#endif - } - close (data->fd); - data->fd = -1; + grub_util_fd_sync (data->fd); + grub_util_fd_close (data->fd); + data->fd = GRUB_UTIL_FD_INVALID; } - fd = open (map[disk->id].device, flags); - if (fd >= 0) + fd = grub_util_fd_open (map[disk->id].device, flags); + if (GRUB_UTIL_FD_IS_VALID(fd)) { data->dev = xstrdup (map[disk->id].device); data->access_mode = (flags & O_ACCMODE); @@ -994,94 +257,26 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags, } } -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - if (! (sysctl_oldflags & 0x10) - && sysctlbyname ("kern.geom.debugflags", NULL , 0, &sysctl_oldflags, sysctl_size)) - { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags back to the old value for sysctl kern.geom.debugflags"); - return -1; - } -#endif - -#if defined(__APPLE__) - /* If we can't have exclusive access, try shared access */ - if (fd < 0) - fd = open(map[disk->id].device, flags | O_SHLOCK); -#endif - - if (fd < 0) + if (!GRUB_UTIL_FD_IS_VALID(data->fd)) { grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"), - map[disk->id].device, strerror (errno)); - return -1; + map[disk->id].device, grub_util_fd_strerror ()); + return GRUB_UTIL_FD_INVALID; } -#endif /* ! __linux__ */ -#if defined(__NetBSD__) - configure_device_driver (fd); -#endif /* defined(__NetBSD__) */ - - if (grub_util_fd_seek (fd, map[disk->id].device, - sector << disk->log_sector_size)) + if (grub_util_fd_seek (fd, sector << disk->log_sector_size)) { - close (fd); - return -1; + grub_util_fd_close (fd); + grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), + map[disk->id].device, grub_util_fd_strerror ()); + + return GRUB_UTIL_FD_INVALID; } return fd; } +#endif -/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an - error occurs, otherwise return LEN. */ -ssize_t -grub_util_fd_read (int fd, char *buf, size_t len) -{ - ssize_t size = len; - - while (len) - { - ssize_t ret = read (fd, buf, len); - - if (ret <= 0) - { - if (errno == EINTR) - continue; - else - return ret; - } - - len -= ret; - buf += ret; - } - - return size; -} - -/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an - error occurs, otherwise return LEN. */ -ssize_t -grub_util_fd_write (int fd, const char *buf, size_t len) -{ - ssize_t size = len; - - while (len) - { - ssize_t ret = write (fd, buf, len); - - if (ret <= 0) - { - if (errno == EINTR) - continue; - else - return ret; - } - - len -= ret; - buf += ret; - } - - return size; -} static grub_err_t grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, @@ -1089,10 +284,10 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, { while (size) { - int fd; + grub_util_fd_t fd; grub_disk_addr_t max = ~0ULL; - fd = open_device (disk, sector, O_RDONLY, &max); - if (fd < 0) + fd = grub_util_fd_open_device (disk, sector, GRUB_UTIL_FD_O_RDONLY, &max); + if (!GRUB_UTIL_FD_IS_VALID (fd)) return grub_errno; #ifdef __linux__ @@ -1110,7 +305,7 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, if (grub_util_fd_read (fd, buf, max << disk->log_sector_size) != (ssize_t) (max << disk->log_sector_size)) return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"), - map[disk->id].device, strerror (errno)); + map[disk->id].device, grub_util_fd_strerror ()); size -= max; buf += (max << disk->log_sector_size); sector += max; @@ -1124,10 +319,10 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, { while (size) { - int fd; + grub_util_fd_t fd; grub_disk_addr_t max = ~0ULL; - fd = open_device (disk, sector, O_WRONLY, &max); - if (fd < 0) + fd = grub_util_fd_open_device (disk, sector, GRUB_UTIL_FD_O_WRONLY, &max); + if (!GRUB_UTIL_FD_IS_VALID (fd)) return grub_errno; #ifdef __linux__ @@ -1145,7 +340,7 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, if (grub_util_fd_write (fd, buf, max << disk->log_sector_size) != (ssize_t) (max << disk->log_sector_size)) return grub_error (GRUB_ERR_WRITE_ERROR, N_("cannot write to `%s': %s"), - map[disk->id].device, strerror (errno)); + map[disk->id].device, grub_util_fd_strerror ()); size -= max; buf += (max << disk->log_sector_size); } @@ -1155,18 +350,18 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, grub_err_t grub_util_biosdisk_flush (struct grub_disk *disk) { - struct grub_util_biosdisk_data *data = disk->data; + struct grub_util_hostdisk_data *data = disk->data; if (disk->dev->id != GRUB_DISK_DEVICE_BIOSDISK_ID) return GRUB_ERR_NONE; - if (data->fd == -1) + if (!GRUB_UTIL_FD_IS_VALID (data->fd)) { grub_disk_addr_t max; - data->fd = open_device (disk, 0, O_RDONLY, &max); - if (data->fd < 0) + data->fd = grub_util_fd_open_device (disk, 0, GRUB_UTIL_FD_O_RDONLY, &max); + if (!GRUB_UTIL_FD_IS_VALID (data->fd)) return grub_errno; } - fsync (data->fd); + grub_util_fd_sync (data->fd); #ifdef __linux__ if (data->is_disk) ioctl (data->fd, BLKFLSBUF, 0); @@ -1177,14 +372,14 @@ grub_util_biosdisk_flush (struct grub_disk *disk) static void grub_util_biosdisk_close (struct grub_disk *disk) { - struct grub_util_biosdisk_data *data = disk->data; + struct grub_util_hostdisk_data *data = disk->data; free (data->dev); - if (data->fd != -1) + if (GRUB_UTIL_FD_IS_VALID (data->fd)) { if (data->access_mode == O_RDWR || data->access_mode == O_WRONLY) grub_util_biosdisk_flush (disk); - close (data->fd); + grub_util_fd_close (data->fd); } free (data); } @@ -1193,36 +388,47 @@ static struct grub_disk_dev grub_util_biosdisk_dev = { .name = "hostdisk", .id = GRUB_DISK_DEVICE_HOSTDISK_ID, - .iterate = grub_util_biosdisk_iterate, - .open = grub_util_biosdisk_open, - .close = grub_util_biosdisk_close, - .read = grub_util_biosdisk_read, - .write = grub_util_biosdisk_write, + .disk_iterate = grub_util_biosdisk_iterate, + .disk_open = grub_util_biosdisk_open, + .disk_close = grub_util_biosdisk_close, + .disk_read = grub_util_biosdisk_read, + .disk_write = grub_util_biosdisk_write, .next = 0 }; +static int +grub_util_check_file_presence (const char *p) +{ +#if !GRUB_UTIL_FD_STAT_IS_FUNCTIONAL + grub_util_fd_t h; + h = grub_util_fd_open (p, GRUB_UTIL_FD_O_RDONLY); + if (!GRUB_UTIL_FD_IS_VALID(h)) + return 0; + grub_util_fd_close (h); + return 1; +#else + struct stat st; + + if (stat (p, &st) == -1) + return 0; + return 1; +#endif +} + static void read_device_map (const char *dev_map) { FILE *fp; char buf[1024]; /* XXX */ int lineno = 0; - struct stat st; - auto void show_error (const char *msg) - __attribute__ ((noreturn)); - void __attribute__ ((noreturn)) show_error (const char *msg) - { - grub_util_error ("%s:%d: %s", dev_map, lineno, msg); - } - - if (dev_map[0] == '\0') + if (!dev_map || dev_map[0] == '\0') { grub_util_info ("no device.map"); return; } - fp = fopen (dev_map, "r"); + fp = grub_util_fopen (dev_map, "r"); if (! fp) { grub_util_info (_("cannot open `%s': %s"), dev_map, strerror (errno)); @@ -1250,14 +456,14 @@ read_device_map (const char *dev_map) { char *tmp; tmp = xasprintf (_("missing `%c' symbol"), '('); - show_error (tmp); + grub_util_error ("%s:%d: %s", dev_map, lineno, tmp); } p++; /* Find a free slot. */ drive = find_free_slot (); if (drive < 0) - show_error (_("device count exceeds limit")); + grub_util_error ("%s:%d: %s", dev_map, lineno, _("device count exceeds limit")); e = p; p = strchr (p, ')'); @@ -1265,7 +471,7 @@ read_device_map (const char *dev_map) { char *tmp; tmp = xasprintf (_("missing `%c' symbol"), ')'); - show_error (tmp); + grub_util_error ("%s:%d: %s", dev_map, lineno, tmp); } map[drive].drive = 0; @@ -1310,7 +516,7 @@ read_device_map (const char *dev_map) p++; if (*p == '\0') - show_error (_("filename expected")); + grub_util_error ("%s:%d: %s", dev_map, lineno, _("filename expected")); /* NUL-terminate the filename. */ e = p; @@ -1318,12 +524,7 @@ read_device_map (const char *dev_map) e++; *e = '\0'; -#ifdef __MINGW32__ - (void) st; - if (grub_util_get_disk_size (p) == -1LL) -#else - if (stat (p, &st) == -1) -#endif + if (!grub_util_check_file_presence (p)) { free (map[drive].drive); map[drive].drive = NULL; @@ -1331,19 +532,13 @@ read_device_map (const char *dev_map) continue; } -#ifdef __linux__ /* On Linux, the devfs uses symbolic links horribly, and that confuses the interface very much, so use realpath to expand - symbolic links. Leave /dev/mapper/ alone, though. */ - if (strncmp (p, "/dev/mapper/", 12) != 0) - { - map[drive].device = xmalloc (PATH_MAX); - if (! realpath (p, map[drive].device)) - grub_util_error (_("failed to get canonical path of %s"), p); - } - else -#endif - map[drive].device = xstrdup (p); + symbolic links. */ + map[drive].device = grub_canonicalize_file_name (p); + if (! map[drive].device) + map[drive].device = xstrdup (p); + if (!map[drive].drive) { char c; @@ -1365,7 +560,10 @@ read_device_map (const char *dev_map) *drive_p = c; } - flush_initial_buffer (map[drive].device); + grub_util_info ("adding `%s' -> `%s' from device.map", map[drive].drive, + map[drive].device); + + grub_hostdisk_flush_initial_buffer (map[drive].device); } fclose (fp); @@ -1383,7 +581,7 @@ grub_util_biosdisk_fini (void) { unsigned i; - for (i = 0; i < sizeof (map) / sizeof (map[0]); i++) + for (i = 0; i < ARRAY_SIZE(map); i++) { if (map[i].drive) free (map[i].drive); @@ -1411,3 +609,78 @@ grub_util_biosdisk_get_osdev (grub_disk_t disk) return map[disk->id].device; } + + +static char * +grub_util_path_concat_real (size_t n, int ext, va_list ap) +{ + size_t totlen = 0; + char **l = xcalloc (n + ext, sizeof (l[0])); + char *r, *p, *pi; + size_t i; + int first = 1; + + for (i = 0; i < n + ext; i++) + { + l[i] = va_arg (ap, char *); + if (l[i]) + totlen += strlen (l[i]) + 1; + } + + r = xmalloc (totlen + 10); + + p = r; + for (i = 0; i < n; i++) + { + pi = l[i]; + if (!pi) + continue; + while (*pi == '/') + pi++; + if ((p != r || (pi != l[i] && first)) && (p == r || *(p - 1) != '/')) + *p++ = '/'; + first = 0; + p = grub_stpcpy (p, pi); + while (p != r && p != r + 1 && *(p - 1) == '/') + p--; + } + + if (ext && l[i]) + p = grub_stpcpy (p, l[i]); + + *p = '\0'; + + free (l); + + return r; +} + +char * +grub_util_path_concat (size_t n, ...) +{ + va_list ap; + char *r; + + va_start (ap, n); + + r = grub_util_path_concat_real (n, 0, ap); + + va_end (ap); + + return r; +} + +char * +grub_util_path_concat_ext (size_t n, ...) +{ + va_list ap; + char *r; + + va_start (ap, n); + + r = grub_util_path_concat_real (n, 1, ap); + + va_end (ap); + + return r; +} diff --git a/grub-core/kern/emu/hostfs.c b/grub-core/kern/emu/hostfs.c index 3cb089c3f..ccbe13f98 100644 --- a/grub-core/kern/emu/hostfs.c +++ b/grub-core/kern/emu/hostfs.c @@ -16,7 +16,9 @@ * You should have received a copy of the GNU General Public License * along with GRUB. If not, see . */ -#define _BSD_SOURCE + +#include + #include #include #include @@ -27,13 +29,8 @@ #include #include -#include #include #include - - -/* dirent.d_type is a BSD extension, not part of POSIX */ -#include #include static int @@ -41,8 +38,9 @@ is_dir (const char *path, const char *name) { int len1 = strlen(path); int len2 = strlen(name); + int ret; - char pathname[len1 + 1 + len2 + 1 + 13]; + char *pathname = xmalloc (len1 + 1 + len2 + 1 + 13); strcpy (pathname, path); /* Avoid UNC-path "//name" on Cygwin. */ @@ -51,51 +49,49 @@ is_dir (const char *path, const char *name) strcat (pathname, name); - struct stat st; - if (stat (pathname, &st)) - return 0; - return S_ISDIR (st.st_mode); + ret = grub_util_is_directory (pathname); + free (pathname); + return ret; } struct grub_hostfs_data { char *filename; - FILE *f; + grub_util_fd_t f; }; static grub_err_t grub_hostfs_dir (grub_device_t device, const char *path, - int (*hook) (const char *filename, - const struct grub_dirhook_info *info)) + grub_fs_dir_hook_t hook, void *hook_data) { - DIR *dir; + grub_util_fd_dir_t dir; /* Check if the disk is our dummy disk. */ if (grub_strcmp (device->disk->name, "host")) return grub_error (GRUB_ERR_BAD_FS, "not a hostfs"); - dir = opendir (path); + dir = grub_util_fd_opendir (path); if (! dir) return grub_error (GRUB_ERR_BAD_FILENAME, N_("can't open `%s': %s"), path, - strerror (errno)); + grub_util_fd_strerror ()); while (1) { - struct dirent *de; + grub_util_fd_dirent_t de; struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); - de = readdir (dir); + de = grub_util_fd_readdir (dir); if (! de) break; info.dir = !! is_dir (path, de->d_name); - hook (de->d_name, &info); + hook (de->d_name, &info, hook_data); } - closedir (dir); + grub_util_fd_closedir (dir); return GRUB_ERR_NONE; } @@ -104,37 +100,33 @@ grub_hostfs_dir (grub_device_t device, const char *path, static grub_err_t grub_hostfs_open (struct grub_file *file, const char *name) { - FILE *f; + grub_util_fd_t f; struct grub_hostfs_data *data; - f = fopen (name, "rb"); - if (! f) + f = grub_util_fd_open (name, GRUB_UTIL_FD_O_RDONLY); + if (! GRUB_UTIL_FD_IS_VALID (f)) return grub_error (GRUB_ERR_BAD_FILENAME, N_("can't open `%s': %s"), name, strerror (errno)); data = grub_malloc (sizeof (*data)); if (!data) { - fclose (f); + grub_util_fd_close (f); return grub_errno; } data->filename = grub_strdup (name); if (!data->filename) { grub_free (data); - fclose (f); + grub_util_fd_close (f); return grub_errno; } - data->f = f; + data->f = f; file->data = data; -#ifdef __MINGW32__ - file->size = grub_util_get_disk_size (name); -#else - file->size = grub_util_get_fd_size (fileno (f), name, NULL); -#endif + file->size = grub_util_get_fd_size (f, name, NULL); return GRUB_ERR_NONE; } @@ -145,17 +137,17 @@ grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len) struct grub_hostfs_data *data; data = file->data; - if (fseeko (data->f, file->offset, SEEK_SET) != 0) + if (grub_util_fd_seek (data->f, file->offset) != 0) { grub_error (GRUB_ERR_OUT_OF_RANGE, N_("cannot seek `%s': %s"), - data->filename, strerror (errno)); + data->filename, grub_util_fd_strerror ()); return -1; } - unsigned int s = fread (buf, 1, len, data->f); + unsigned int s = grub_util_fd_read (data->f, buf, len); if (s != len) grub_error (GRUB_ERR_FILE_READ_ERROR, N_("cannot read `%s': %s"), - data->filename, strerror (errno)); + data->filename, grub_util_fd_strerror ()); return (signed) s; } @@ -166,7 +158,7 @@ grub_hostfs_close (grub_file_t file) struct grub_hostfs_data *data; data = file->data; - fclose (data->f); + grub_util_fd_close (data->f); grub_free (data->filename); grub_free (data); @@ -181,14 +173,17 @@ grub_hostfs_label (grub_device_t device __attribute ((unused)), return GRUB_ERR_NONE; } +#undef open +#undef close + static struct grub_fs grub_hostfs_fs = { .name = "hostfs", - .dir = grub_hostfs_dir, - .open = grub_hostfs_open, - .read = grub_hostfs_read, - .close = grub_hostfs_close, - .label = grub_hostfs_label, + .fs_dir = grub_hostfs_dir, + .fs_open = grub_hostfs_open, + .fs_read = grub_hostfs_read, + .fs_close = grub_hostfs_close, + .fs_label = grub_hostfs_label, .next = 0 }; diff --git a/grub-core/kern/emu/lite.c b/grub-core/kern/emu/lite.c index 947c669aa..b327d4e41 100644 --- a/grub-core/kern/emu/lite.c +++ b/grub-core/kern/emu/lite.c @@ -16,11 +16,22 @@ #elif defined(__powerpc__) #include "../powerpc/dl.c" #elif defined(__ia64__) +#include "../ia64/dl_helper.c" #include "../ia64/dl.c" +#elif defined(__arm__) +#include "../arm/dl_helper.c" +#include "../arm/dl.c" +#elif defined(__aarch64__) +#include "../arm64/dl_helper.c" +#include "../arm64/dl.c" +#elif defined(__riscv) +#include "../riscv/dl.c" #else #error "No target cpu type is defined" #endif +const int grub_no_modules = 0; + /* grub-emu-lite supports dynamic module loading, so it won't have any embedded modules. */ void @@ -34,14 +45,3 @@ grub_fini_all (void) { return; } - -void -grub_emu_init (void) -{ - return; -} - -void -grub_emu_post_init (void) -{ -} diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 0418aae64..8a70bd7d6 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -16,15 +16,16 @@ * along with GRUB. If not, see . */ +#include +#include + #include #include #include #include -#include #include #include #include -#include #include #include @@ -40,6 +41,10 @@ #include #include #include +#include +#include + +#pragma GCC diagnostic ignored "-Wmissing-prototypes" #include "progname.h" #include @@ -50,9 +55,7 @@ static jmp_buf main_env; /* Store the prefix specified by an argument. */ -static char *root_dev = NULL, *dir = NULL; - -int grub_no_autoload; +static char *root_dev = NULL, *dir = NULL, *tpm_dev = NULL; grub_addr_t grub_modbase = 0; @@ -60,6 +63,13 @@ void grub_reboot (void) { longjmp (main_env, 1); + grub_fatal ("longjmp failed"); +} + +void +grub_exit (void) +{ + grub_reboot (); } void @@ -75,25 +85,35 @@ grub_machine_get_bootlocation (char **device, char **path) } void -grub_machine_fini (void) +grub_machine_fini (int flags) { - grub_console_fini (); + if (flags & GRUB_LOADER_FLAG_NORETURN) + grub_console_fini (); } +#define OPT_MEMDISK 257 + static struct argp_option options[] = { {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2}, {"device-map", 'm', N_("FILE"), 0, /* TRANSLATORS: There are many devices in device map. */ N_("use FILE as the device map [default=%s]"), 0}, + {"memdisk", OPT_MEMDISK, N_("FILE"), 0, + /* TRANSLATORS: There are many devices in device map. */ + N_("use FILE as memdisk"), 0}, {"directory", 'd', N_("DIR"), 0, N_("use GRUB files in the directory DIR [default=%s]"), 0}, {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, {"hold", 'H', N_("SECS"), OPTION_ARG_OPTIONAL, N_("wait until a debugger will attach"), 0}, + {"kexec", 'X', 0, 0, N_("use kexec to boot Linux kernels via systemctl (pass twice to enable dangerous fallback to non-systemctl)."), 0}, + {"tpm-device", 't', N_("DEV"), 0, N_("set TPM device."), 0}, { 0, 0, 0, 0, 0, 0 } }; +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + static char * help_filter (int key, const char *text, void *input __attribute__ ((unused))) { @@ -108,9 +128,12 @@ help_filter (int key, const char *text, void *input __attribute__ ((unused))) } } +#pragma GCC diagnostic error "-Wformat-nonliteral" + struct arguments { const char *dev_map; + const char *mem_disk; int hold; }; @@ -123,6 +146,9 @@ argp_parser (int key, char *arg, struct argp_state *state) switch (key) { + case OPT_MEMDISK: + arguments->mem_disk = arg; + break; case 'r': free (root_dev); root_dev = xstrdup (arg); @@ -140,6 +166,13 @@ argp_parser (int key, char *arg, struct argp_state *state) case 'v': verbosity++; break; + case 'X': + grub_util_set_kexecute (); + break; + case 't': + free (tpm_dev); + tpm_dev = xstrdup (arg); + break; case ARGP_KEY_ARG: { @@ -164,23 +197,23 @@ static struct argp argp = { -void grub_hostfs_init (void); -void grub_hostfs_fini (void); -void grub_host_init (void); -void grub_host_fini (void); -void grub_emu_init (void); +#pragma GCC diagnostic ignored "-Wmissing-prototypes" int main (int argc, char *argv[]) { struct arguments arguments = - { + { .dev_map = DEFAULT_DEVICE_MAP, - .hold = 0 + .hold = 0, + .mem_disk = 0, }; volatile int hold = 0; + size_t total_module_size = sizeof (struct grub_module_info), memdisk_size = 0; + struct grub_module_info *modinfo; + void *mods; - set_program_name (argv[0]); + grub_util_host_init (&argc, &argv); dir = xstrdup (DEFAULT_DIRECTORY); @@ -190,6 +223,33 @@ main (int argc, char *argv[]) exit(1); } + if (arguments.mem_disk) + { + memdisk_size = ALIGN_UP(grub_util_get_image_size (arguments.mem_disk), 512); + total_module_size += memdisk_size + sizeof (struct grub_module_header); + } + + mods = xmalloc (total_module_size); + modinfo = grub_memset (mods, 0, total_module_size); + mods = (char *) (modinfo + 1); + + modinfo->magic = GRUB_MODULE_MAGIC; + modinfo->offset = sizeof (struct grub_module_info); + modinfo->size = total_module_size; + + if (arguments.mem_disk) + { + struct grub_module_header *header = (struct grub_module_header *) mods; + header->type = OBJ_TYPE_MEMDISK; + header->size = memdisk_size + sizeof (*header); + mods = header + 1; + + grub_util_load_image (arguments.mem_disk, mods); + mods = (char *) mods + memdisk_size; + } + + grub_modbase = (grub_addr_t) modinfo; + hold = arguments.hold; /* Wait until the ARGS.HOLD variable is cleared by an attached debugger. */ if (hold && verbosity > 0) @@ -205,7 +265,6 @@ main (int argc, char *argv[]) } signal (SIGINT, SIG_IGN); - grub_emu_init (); grub_console_init (); grub_host_init (); @@ -216,14 +275,15 @@ main (int argc, char *argv[]) grub_hostfs_init (); - grub_emu_post_init (); - /* Make sure that there is a root device. */ if (! root_dev) root_dev = grub_strdup ("host"); dir = xstrdup (dir); + if (tpm_dev) + grub_util_tpm_open (tpm_dev); + /* Start GRUB! */ if (setjmp (main_env) == 0) grub_main (); @@ -231,30 +291,9 @@ main (int argc, char *argv[]) grub_fini_all (); grub_hostfs_fini (); grub_host_fini (); + grub_util_tpm_close (); - grub_machine_fini (); + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); return 0; } - -#ifdef __MINGW32__ - -void -grub_millisleep (grub_uint32_t ms) -{ - Sleep (ms); -} - -#else - -void -grub_millisleep (grub_uint32_t ms) -{ - struct timespec ts; - - ts.tv_sec = ms / 1000; - ts.tv_nsec = (ms % 1000) * 1000000; - nanosleep (&ts, NULL); -} - -#endif diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c index 21954ed50..1db24fde7 100644 --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -16,11 +16,12 @@ * along with GRUB. If not, see . */ +#ifndef GRUB_BUILD #include +#endif #include #include -#include #include #include #include @@ -28,10 +29,7 @@ #include #include #include -#include -#ifdef HAVE_LIMITS_H -#include -#endif +#include #include #include @@ -42,28 +40,10 @@ #include #include -#ifdef HAVE_DEVICE_MAPPER -# include -#endif - -#ifdef HAVE_SYS_PARAM_H -# include -#endif - -#ifdef HAVE_SYS_MOUNT_H -# include -#endif - -#ifdef HAVE_SYS_MNTTAB_H -# include /* Needed by sys/mnttab.h. */ -# include -#endif - -#ifdef HAVE_SYS_MKDEV_H -# include /* makedev */ -#endif - int verbosity; +int kexecute; + +static int grub_util_tpm_fd = -1; void grub_util_warn (const char *fmt, ...) @@ -107,7 +87,19 @@ grub_util_error (const char *fmt, ...) vfprintf (stderr, fmt, ap); va_end (ap); fprintf (stderr, ".\n"); - exit (1); + grub_exit (); +} + +void * +xcalloc (grub_size_t nmemb, grub_size_t size) +{ + void *p; + + p = calloc (nmemb, size); + if (!p) + grub_util_error ("%s", _("out of memory")); + + return p; } void * @@ -145,58 +137,33 @@ xstrdup (const char *str) return newstr; } -#ifndef HAVE_VASPRINTF - -int -vasprintf (char **buf, const char *fmt, va_list ap) -{ - /* Should be large enough. */ - *buf = xmalloc (512); - - return vsnprintf (*buf, 512, fmt, ap); -} - -#endif - -#ifndef HAVE_ASPRINTF - -int -asprintf (char **buf, const char *fmt, ...) -{ - int status; - va_list ap; - - va_start (ap, fmt); - status = vasprintf (buf, fmt, ap); - va_end (ap); - - return status; -} - -#endif - +#if !defined (GRUB_MKFONT) && !defined (GRUB_BUILD) char * xasprintf (const char *fmt, ...) -{ +{ va_list ap; char *result; - + va_start (ap, fmt); - if (vasprintf (&result, fmt, ap) < 0) - { - if (errno == ENOMEM) - grub_util_error ("%s", _("out of memory")); - return NULL; - } - + result = grub_xvasprintf (fmt, ap); + va_end (ap); + if (!result) + grub_util_error ("%s", _("out of memory")); + return result; } +#endif +#if !defined (GRUB_MACHINE_EMU) || defined (GRUB_UTIL) void grub_exit (void) { +#if defined (GRUB_KERNEL) + grub_reboot (); +#endif exit (1); } +#endif grub_uint64_t grub_get_time_ms (void) @@ -208,67 +175,109 @@ grub_get_time_ms (void) return (tv.tv_sec * 1000 + tv.tv_usec / 1000); } -grub_uint32_t -grub_get_rtc (void) +size_t +grub_util_get_image_size (const char *path) { - struct timeval tv; + FILE *f; + size_t ret; + off_t sz; - gettimeofday (&tv, 0); + f = grub_util_fopen (path, "rb"); - return (tv.tv_sec * GRUB_TICKS_PER_SECOND - + (((tv.tv_sec % GRUB_TICKS_PER_SECOND) * 1000000 + tv.tv_usec) - * GRUB_TICKS_PER_SECOND / 1000000)); -} + if (!f) + grub_util_error (_("cannot open `%s': %s"), path, strerror (errno)); + + fseeko (f, 0, SEEK_END); + + sz = ftello (f); + if (sz < 0) + grub_util_error (_("cannot open `%s': %s"), path, strerror (errno)); + if (sz != (size_t) sz) + grub_util_error (_("file `%s' is too big"), path); + ret = (size_t) sz; + + fclose (f); -char * -canonicalize_file_name (const char *path) -{ - char *ret; -#ifdef __MINGW32__ - ret = xmalloc (PATH_MAX); - if (!_fullpath (ret, path, PATH_MAX)) - return NULL; -#elif defined (PATH_MAX) - ret = xmalloc (PATH_MAX); - if (!realpath (path, ret)) - return NULL; -#else - ret = realpath (path, NULL); -#endif return ret; } -#ifdef HAVE_DEVICE_MAPPER -static void device_mapper_null_log (int level __attribute__ ((unused)), - const char *file __attribute__ ((unused)), - int line __attribute__ ((unused)), - int dm_errno __attribute__ ((unused)), - const char *f __attribute__ ((unused)), - ...) +void +grub_util_load_image (const char *path, char *buf) { + FILE *fp; + size_t size; + + grub_util_info ("reading %s", path); + + size = grub_util_get_image_size (path); + + fp = grub_util_fopen (path, "rb"); + if (! fp) + grub_util_error (_("cannot open `%s': %s"), path, + strerror (errno)); + + if (fread (buf, 1, size, fp) != size) + grub_util_error (_("cannot read `%s': %s"), path, + strerror (errno)); + + fclose (fp); +} + +void +grub_util_set_kexecute (void) +{ + kexecute++; } int -grub_device_mapper_supported (void) +grub_util_get_kexecute (void) { - static int supported = -1; - - if (supported == -1) - { - struct dm_task *dmt; - - /* Suppress annoying log messages. */ - dm_log_with_errno_init (&device_mapper_null_log); - - dmt = dm_task_create (DM_DEVICE_VERSION); - supported = (dmt != NULL); - if (dmt) - dm_task_destroy (dmt); - - /* Restore the original logger. */ - dm_log_with_errno_init (NULL); - } - - return supported; + return kexecute; +} + +grub_err_t +grub_util_tpm_open (const char *tpm_dev) +{ + if (grub_util_tpm_fd != -1) + return GRUB_ERR_NONE; + + grub_util_tpm_fd = open (tpm_dev, O_RDWR); + if (grub_util_tpm_fd == -1) + grub_util_error (_("cannot open TPM device '%s': %s"), tpm_dev, strerror (errno)); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_util_tpm_close (void) +{ + int err; + + if (grub_util_tpm_fd == -1) + return GRUB_ERR_NONE; + + err = close (grub_util_tpm_fd); + if (err != GRUB_ERR_NONE) + grub_util_error (_("cannot close TPM device: %s"), strerror (errno)); + + grub_util_tpm_fd = -1; + return GRUB_ERR_NONE; +} + +grub_size_t +grub_util_tpm_read (void *output, grub_size_t size) +{ + if (grub_util_tpm_fd == -1) + return -1; + + return read (grub_util_tpm_fd, output, size); +} + +grub_size_t +grub_util_tpm_write (const void *input, grub_size_t size) +{ + if (grub_util_tpm_fd == -1) + return -1; + + return write (grub_util_tpm_fd, input, size); } -#endif /* HAVE_DEVICE_MAPPER */ diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c index 0461ea51c..4d1046a21 100644 --- a/grub-core/kern/emu/mm.c +++ b/grub-core/kern/emu/mm.c @@ -25,6 +25,16 @@ #include #include +void * +grub_calloc (grub_size_t nmemb, grub_size_t size) +{ + void *ret; + ret = calloc (nmemb, size); + if (!ret) + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); + return ret; +} + void * grub_malloc (grub_size_t size) { @@ -50,7 +60,8 @@ grub_zalloc (grub_size_t size) void grub_free (void *ptr) { - free (ptr); + if (ptr) + free (ptr); } void * @@ -62,27 +73,3 @@ grub_realloc (void *ptr, grub_size_t size) grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); return ret; } - -void * -grub_memalign (grub_size_t align, grub_size_t size) -{ - void *p; - -#if defined(HAVE_POSIX_MEMALIGN) - if (align < sizeof (void *)) - align = sizeof (void *); - if (posix_memalign (&p, align, size) != 0) - p = 0; -#elif defined(HAVE_MEMALIGN) - p = memalign (align, size); -#else - (void) align; - (void) size; - grub_util_error (_("grub_memalign is not supported on your system")); -#endif - - if (!p) - grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); - - return p; -} diff --git a/grub-core/kern/env.c b/grub-core/kern/env.c index 7bfa238e1..764068896 100644 --- a/grub-core/kern/env.c +++ b/grub-core/kern/env.c @@ -144,6 +144,19 @@ grub_env_get (const char *name) return var->value; } +bool +grub_env_get_bool (const char *name, bool if_unset) +{ + const char *val = grub_env_get (name); + + if (val == NULL || grub_strlen (val) < 1) + return if_unset; + if (grub_strcmp (val, "0") == 0 || grub_strcmp (val, "false") == 0 || + grub_strcmp (val, "disable") == 0 || grub_strcmp (val, "no") == 0) + return false; + return true; +} + void grub_env_unset (const char *name) { @@ -166,11 +179,10 @@ grub_env_unset (const char *name) grub_free (var); } -void -grub_env_iterate (int (*func) (struct grub_env_var *var)) +struct grub_env_var * +grub_env_update_get_sorted (void) { - struct grub_env_sorted_var *sorted_list = 0; - struct grub_env_sorted_var *sorted_var; + struct grub_env_var *sorted_list = 0; int i; /* Add variables associated with this context into a sorted list. */ @@ -180,40 +192,20 @@ grub_env_iterate (int (*func) (struct grub_env_var *var)) for (var = grub_current_context->vars[i]; var; var = var->next) { - struct grub_env_sorted_var *p, **q; + struct grub_env_var *p, **q; - sorted_var = grub_malloc (sizeof (*sorted_var)); - if (! sorted_var) - goto fail; - - sorted_var->var = var; - - for (q = &sorted_list, p = *q; p; q = &((*q)->next), p = *q) + for (q = &sorted_list, p = *q; p; q = &((*q)->sorted_next), p = *q) { - if (grub_strcmp (p->var->name, var->name) > 0) + if (grub_strcmp (p->name, var->name) > 0) break; } - sorted_var->next = *q; - *q = sorted_var; + var->sorted_next = *q; + *q = var; } } - /* Iterate FUNC on the sorted list. */ - for (sorted_var = sorted_list; sorted_var; sorted_var = sorted_var->next) - if (func (sorted_var->var)) - break; - - fail: - - /* Free the sorted list. */ - for (sorted_var = sorted_list; sorted_var; ) - { - struct grub_env_sorted_var *tmp = sorted_var->next; - - grub_free (sorted_var); - sorted_var = tmp; - } + return sorted_list; } grub_err_t @@ -247,12 +239,12 @@ grub_env_export (const char *name) if (! var) { grub_err_t err; - + err = grub_env_set (name, ""); if (err) return err; var = grub_env_find (name); - } + } var->global = 1; return GRUB_ERR_NONE; diff --git a/grub-core/kern/err.c b/grub-core/kern/err.c index 52ba6de62..53c734de7 100644 --- a/grub-core/kern/err.c +++ b/grub-core/kern/err.c @@ -47,18 +47,6 @@ grub_error (grub_err_t n, const char *fmt, ...) return n; } -void -grub_fatal (const char *fmt, ...) -{ - va_list ap; - - va_start (ap, fmt); - grub_vprintf (_(fmt), ap); - va_end (ap); - - grub_abort (); -} - void grub_error_push (void) { diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index 495326f12..6e7efe89a 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -25,11 +25,11 @@ #include #include #include +#include void (*EXPORT_VAR (grub_grubnet_fini)) (void); -grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX]; -grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX]; +grub_file_filter_t grub_file_filters[GRUB_FILE_FILTER_MAX]; /* Get the device part of the filename NAME. It is enclosed by parentheses. */ char * @@ -59,14 +59,17 @@ grub_file_get_device_name (const char *name) } grub_file_t -grub_file_open (const char *name) +grub_file_open (const char *name, enum grub_file_type type) { grub_device_t device = 0; grub_file_t file = 0, last_file = 0; char *device_name; - char *file_name; + const char *file_name; grub_file_filter_id_t filter; + /* Reset grub_errno before we start. */ + grub_errno = GRUB_ERR_NONE; + device_name = grub_file_get_device_name (name); if (grub_errno) goto fail; @@ -76,10 +79,11 @@ grub_file_open (const char *name) if (file_name) file_name++; else - file_name = (char *) name; + file_name = name; device = grub_device_open (device_name); grub_free (device_name); + device_name = NULL; if (! device) goto fail; @@ -89,7 +93,16 @@ grub_file_open (const char *name) file->device = device; - if (device->disk && file_name[0] != '/') + /* In case of relative pathnames and non-Unix systems (like Windows) + * name of host files may not start with `/'. Blocklists for host files + * are meaningless as well (for a start, host disk does not allow any direct + * access - it is just a marker). So skip host disk in this case. + */ + if (device->disk && file_name[0] != '/' +#if defined(GRUB_UTIL) || defined(GRUB_MACHINE_EMU) + && grub_strcmp (device->disk->name, "host") +#endif + ) /* This is a block list. */ file->fs = &grub_fs_blocklist; else @@ -99,25 +112,37 @@ grub_file_open (const char *name) goto fail; } - if ((file->fs->open) (file, file_name) != GRUB_ERR_NONE) + if ((file->fs->fs_open) (file, file_name) != GRUB_ERR_NONE) goto fail; - for (filter = 0; file && filter < ARRAY_SIZE (grub_file_filters_enabled); + if (file->data == NULL) + goto fail; + + if (file->fs->mod) + grub_dl_ref (file->fs->mod); + + file->name = grub_strdup (name); + grub_errno = GRUB_ERR_NONE; + + for (filter = 0; file && filter < ARRAY_SIZE (grub_file_filters); filter++) - if (grub_file_filters_enabled[filter]) + if (grub_file_filters[filter]) { last_file = file; - file = grub_file_filters_enabled[filter] (file); + file = grub_file_filters[filter] (file, type); + if (file && file != last_file) + { + file->name = grub_strdup (name); + grub_errno = GRUB_ERR_NONE; + } } if (!file) grub_file_close (last_file); - - grub_memcpy (grub_file_filters_enabled, grub_file_filters_all, - sizeof (grub_file_filters_enabled)); return file; fail: + grub_free (device_name); if (device) grub_device_close (device); @@ -125,16 +150,17 @@ grub_file_open (const char *name) grub_free (file); - grub_memcpy (grub_file_filters_enabled, grub_file_filters_all, - sizeof (grub_file_filters_enabled)); - return 0; } +grub_disk_read_hook_t grub_file_progress_hook; + grub_ssize_t grub_file_read (grub_file_t file, void *buf, grub_size_t len) { grub_ssize_t res; + grub_disk_read_hook_t read_hook; + void *read_hook_data; if (file->offset > file->size) { @@ -155,7 +181,17 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) if (len == 0) return 0; - res = (file->fs->read) (file, buf, len); + read_hook = file->read_hook; + read_hook_data = file->read_hook_data; + if (!file->read_hook) + { + file->read_hook = grub_file_progress_hook; + file->read_hook_data = file; + file->progress_offset = file->offset; + } + res = (file->fs->fs_read) (file, buf, len); + file->read_hook = read_hook; + file->read_hook_data = read_hook_data; if (res > 0) file->offset += res; @@ -165,11 +201,15 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) grub_err_t grub_file_close (grub_file_t file) { - if (file->fs->close) - (file->fs->close) (file); + if (file->fs->mod) + grub_dl_unref (file->fs->mod); + + if (file->fs->fs_close) + (file->fs->fs_close) (file); if (file->device) grub_device_close (file->device); + grub_free (file->name); grub_free (file); return grub_errno; } @@ -185,9 +225,9 @@ grub_file_seek (grub_file_t file, grub_off_t offset) N_("attempt to seek outside of the file")); return -1; } - + old = file->offset; file->offset = offset; - + return old; } diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c index 51d89d1b8..80d325868 100644 --- a/grub-core/kern/fs.c +++ b/grub-core/kern/fs.c @@ -32,18 +32,19 @@ grub_fs_t grub_fs_list = 0; grub_fs_autoload_hook_t grub_fs_autoload_hook = 0; +/* Helper for grub_fs_probe. */ +static int +probe_dummy_iter (const char *filename __attribute__ ((unused)), + const struct grub_dirhook_info *info __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + return 1; +} + grub_fs_t grub_fs_probe (grub_device_t device) { grub_fs_t p; - auto int dummy_func (const char *filename, - const struct grub_dirhook_info *info); - - int dummy_func (const char *filename __attribute__ ((unused)), - const struct grub_dirhook_info *info __attribute__ ((unused))) - { - return 1; - } if (device->disk) { @@ -63,17 +64,19 @@ grub_fs_probe (grub_device_t device) if (grub_strcmp (p->name, "btrfs") == 0) { char *label = 0; - p->uuid (device, &label); + p->fs_uuid (device, &label); if (label) grub_free (label); } else #endif - (p->dir) (device, "/", dummy_func); + (p->fs_dir) (device, "/", probe_dummy_iter, NULL); if (grub_errno == GRUB_ERR_NONE) return p; grub_error_push (); + /* The grub_error_push() does not touch grub_errmsg. */ + grub_dprintf ("fs", _("error: %s.\n"), grub_errmsg); grub_dprintf ("fs", "%s detection failed.\n", p->name); grub_error_pop (); @@ -93,7 +96,7 @@ grub_fs_probe (grub_device_t device) { p = grub_fs_list; - (p->dir) (device, "/", dummy_func); + (p->fs_dir) (device, "/", probe_dummy_iter, NULL); if (grub_errno == GRUB_ERR_NONE) { count--; @@ -127,17 +130,18 @@ grub_fs_probe (grub_device_t device) struct grub_fs_block { grub_disk_addr_t offset; - unsigned long length; + grub_disk_addr_t length; }; static grub_err_t grub_fs_blocklist_open (grub_file_t file, const char *name) { - char *p = (char *) name; + const char *p = name; unsigned num = 0; unsigned i; grub_disk_t disk = file->device->disk; struct grub_fs_block *blocks; + grub_size_t max_sectors; /* First, count the number of blocks. */ do @@ -150,11 +154,12 @@ grub_fs_blocklist_open (grub_file_t file, const char *name) while (p); /* Allocate a block list. */ - blocks = grub_zalloc (sizeof (struct grub_fs_block) * (num + 1)); + blocks = grub_calloc (num + 1, sizeof (struct grub_fs_block)); if (! blocks) return 0; file->size = 0; + max_sectors = grub_disk_from_native_sector (disk, disk->total_sectors); p = (char *) name; for (i = 0; i < num; i++) { @@ -170,7 +175,11 @@ grub_fs_blocklist_open (grub_file_t file, const char *name) } p++; - blocks[i].length = grub_strtoul (p, &p, 0); + if (*p == '\0' || *p == ',') + blocks[i].length = max_sectors - blocks[i].offset; + else + blocks[i].length = grub_strtoul (p, &p, 0); + if (grub_errno != GRUB_ERR_NONE || blocks[i].length == 0 || (*p && *p != ',' && ! grub_isspace (*p))) @@ -180,7 +189,7 @@ grub_fs_blocklist_open (grub_file_t file, const char *name) goto fail; } - if (disk->total_sectors < blocks[i].offset + blocks[i].length) + if (max_sectors < blocks[i].offset + blocks[i].length) { grub_error (GRUB_ERR_BAD_FILENAME, "beyond the total sectors"); goto fail; @@ -206,12 +215,15 @@ grub_fs_blocklist_read (grub_file_t file, char *buf, grub_size_t len) grub_disk_addr_t sector; grub_off_t offset; grub_ssize_t ret = 0; + grub_disk_t disk = file->device->disk; if (len > file->size - file->offset) len = file->size - file->offset; sector = (file->offset >> GRUB_DISK_SECTOR_BITS); offset = (file->offset & (GRUB_DISK_SECTOR_SIZE - 1)); + disk->read_hook = file->read_hook; + disk->read_hook_data = file->read_hook_data; for (p = file->data; p->length && len > 0; p++) { if (sector < p->length) @@ -223,9 +235,12 @@ grub_fs_blocklist_read (grub_file_t file, char *buf, grub_size_t len) >> GRUB_DISK_SECTOR_BITS) > p->length - sector) size = ((p->length - sector) << GRUB_DISK_SECTOR_BITS) - offset; - if (grub_disk_read (file->device->disk, p->offset + sector, offset, + if (grub_disk_read (disk, p->offset + sector, offset, size, buf) != GRUB_ERR_NONE) - return -1; + { + ret = -1; + break; + } ret += size; len -= size; @@ -235,6 +250,8 @@ grub_fs_blocklist_read (grub_file_t file, char *buf, grub_size_t len) else sector -= p->length; } + disk->read_hook = NULL; + disk->read_hook_data = NULL; return ret; } @@ -242,9 +259,9 @@ grub_fs_blocklist_read (grub_file_t file, char *buf, grub_size_t len) struct grub_fs grub_fs_blocklist = { .name = "blocklist", - .dir = 0, - .open = grub_fs_blocklist_open, - .read = grub_fs_blocklist_read, - .close = 0, + .fs_dir = 0, + .fs_open = grub_fs_blocklist_open, + .fs_read = grub_fs_blocklist_read, + .fs_close = 0, .next = 0 }; diff --git a/grub-core/kern/generic/rtc_get_time_ms.c b/grub-core/kern/generic/rtc_get_time_ms.c index 49f2acac9..3e39c8fe1 100644 --- a/grub-core/kern/generic/rtc_get_time_ms.c +++ b/grub-core/kern/generic/rtc_get_time_ms.c @@ -34,5 +34,5 @@ grub_rtc_get_time_ms (void) 1 s 1 T rtc ticks */ grub_uint64_t ticks_ms_per_sec = ((grub_uint64_t) 1000) * grub_get_rtc (); - return grub_divmod64 (ticks_ms_per_sec, GRUB_TICKS_PER_SECOND, 0); + return grub_divmod64 (ticks_ms_per_sec, GRUB_TICKS_PER_SECOND ? : 1000, 0); } diff --git a/grub-core/kern/i386/coreboot/cbtable.c b/grub-core/kern/i386/coreboot/cbtable.c new file mode 100644 index 000000000..34a2b59be --- /dev/null +++ b/grub-core/kern/i386/coreboot/cbtable.c @@ -0,0 +1,44 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +grub_linuxbios_table_header_t +grub_linuxbios_get_tables (void) +{ + grub_linuxbios_table_header_t table_header; + /* Assuming table_header is aligned to its size (8 bytes). */ + for (table_header = (grub_linuxbios_table_header_t) 0x500; + table_header < (grub_linuxbios_table_header_t) 0x1000; table_header++) + if (grub_linuxbios_check_signature (table_header)) + return table_header; + + for (table_header = (grub_linuxbios_table_header_t) 0xf0000; + table_header < (grub_linuxbios_table_header_t) 0x100000; table_header++) + if (grub_linuxbios_check_signature (table_header)) + return table_header; + + return 0; +} diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c index 52fbba4e8..4fae8b571 100644 --- a/grub-core/kern/i386/coreboot/init.c +++ b/grub-core/kern/i386/coreboot/init.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2013 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,9 +34,7 @@ #include #include #include -#ifdef GRUB_MACHINE_QEMU -#include -#endif +#include extern grub_uint8_t _start[]; extern grub_uint8_t _end[]; @@ -51,64 +49,85 @@ grub_exit (void) grub_cpu_idle (); } -#ifdef GRUB_MACHINE_QEMU -grub_addr_t grub_modbase; -#else -grub_addr_t grub_modbase = ALIGN_UP((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN); +grub_addr_t grub_modbase = GRUB_KERNEL_I386_COREBOOT_MODULES_ADDR; +static grub_uint64_t modend; +static int have_memory = 0; + +/* Helper for grub_machine_init. */ +static int +heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + void *data __attribute__ ((unused))) +{ + grub_uint64_t begin = addr, end = addr + size; + +#if GRUB_CPU_SIZEOF_VOID_P == 4 + /* Restrict ourselves to 32-bit memory space. */ + if (begin > GRUB_ULONG_MAX) + return 0; + if (end > GRUB_ULONG_MAX) + end = GRUB_ULONG_MAX; #endif + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + /* Avoid the lower memory. */ + if (begin < GRUB_MEMORY_MACHINE_LOWER_SIZE) + begin = GRUB_MEMORY_MACHINE_LOWER_SIZE; + + if (modend && begin < modend) + begin = modend; + + if (end <= begin) + return 0; + + grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin)); + + have_memory = 1; + + return 0; +} + +#ifndef GRUB_MACHINE_MULTIBOOT + void grub_machine_init (void) { -#ifdef GRUB_MACHINE_QEMU - grub_modbase = grub_core_entry_addr + (_edata - _start); + modend = grub_modules_get_end (); + + grub_video_coreboot_fb_early_init (); - grub_qemu_init_cirrus (); -#endif - /* Initialize the console as early as possible. */ grub_vga_text_init (); - auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t, grub_uint64_t, - grub_memory_type_t); - int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t size, - grub_memory_type_t type) - { -#if GRUB_CPU_SIZEOF_VOID_P == 4 - /* Restrict ourselves to 32-bit memory space. */ - if (addr > GRUB_ULONG_MAX) - return 0; - if (addr + size > GRUB_ULONG_MAX) - size = GRUB_ULONG_MAX - addr; -#endif + grub_machine_mmap_iterate (heap_init, NULL); + if (!have_memory) + grub_fatal ("No memory found"); - if (type != GRUB_MEMORY_AVAILABLE) - return 0; + grub_video_coreboot_fb_late_init (); - /* Avoid the lower memory. */ - if (addr < GRUB_MEMORY_MACHINE_LOWER_SIZE) - { - if (addr + size <= GRUB_MEMORY_MACHINE_LOWER_SIZE) - return 0; - else - { - size -= GRUB_MEMORY_MACHINE_LOWER_SIZE - addr; - addr = GRUB_MEMORY_MACHINE_LOWER_SIZE; - } - } - - grub_mm_init_region ((void *) (grub_addr_t) addr, (grub_size_t) size); - - return 0; - } - -#if defined (GRUB_MACHINE_MULTIBOOT) || defined (GRUB_MACHINE_QEMU) - grub_machine_mmap_init (); -#endif - grub_machine_mmap_iterate (heap_init); + grub_font_init (); + grub_gfxterm_init (); grub_tsc_init (); } +#else + +void +grub_machine_init (void) +{ + modend = grub_modules_get_end (); + + grub_vga_text_init (); + + grub_machine_mmap_init (); + grub_machine_mmap_iterate (heap_init, NULL); + + grub_tsc_init (); +} + +#endif + void grub_machine_get_bootlocation (char **device __attribute__ ((unused)), char **path __attribute__ ((unused))) @@ -116,8 +135,9 @@ grub_machine_get_bootlocation (char **device __attribute__ ((unused)), } void -grub_machine_fini (void) +grub_machine_fini (int flags) { - grub_vga_text_fini (); + if (flags & GRUB_LOADER_FLAG_NORETURN) + grub_vga_text_fini (); grub_stop_floppy (); } diff --git a/grub-core/kern/i386/coreboot/mmap.c b/grub-core/kern/i386/coreboot/mmap.c deleted file mode 100644 index 8b0b20265..000000000 --- a/grub-core/kern/i386/coreboot/mmap.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2007,2008 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB 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 GRUB. If not, see . - */ - -#include -#include -#include -#include -#include - -static grub_err_t -grub_linuxbios_table_iterate (int (*hook) (grub_linuxbios_table_item_t)) -{ - grub_linuxbios_table_header_t table_header; - grub_linuxbios_table_item_t table_item; - - auto int check_signature (grub_linuxbios_table_header_t); - int check_signature (grub_linuxbios_table_header_t tbl_header) - { - if (! grub_memcmp (tbl_header->signature, "LBIO", 4)) - return 1; - - return 0; - } - - /* Assuming table_header is aligned to its size (8 bytes). */ - - for (table_header = (grub_linuxbios_table_header_t) 0x500; - table_header < (grub_linuxbios_table_header_t) 0x1000; table_header++) - if (check_signature (table_header)) - goto signature_found; - - for (table_header = (grub_linuxbios_table_header_t) 0xf0000; - table_header < (grub_linuxbios_table_header_t) 0x100000; table_header++) - if (check_signature (table_header)) - goto signature_found; - - grub_fatal ("Could not find coreboot table\n"); - -signature_found: - - table_item = - (grub_linuxbios_table_item_t) ((long) table_header + - (long) table_header->size); - for (; table_item->size; - table_item = (grub_linuxbios_table_item_t) ((long) table_item + (long) table_item->size)) - { - if (table_item->tag == GRUB_LINUXBIOS_MEMBER_LINK - && check_signature ((grub_linuxbios_table_header_t) (grub_addr_t) - *(grub_uint64_t *) (table_item + 1))) - { - table_header = (grub_linuxbios_table_header_t) (grub_addr_t) - *(grub_uint64_t *) (table_item + 1); - goto signature_found; - } - if (hook (table_item)) - return 1; - } - - return 0; -} - -grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) -{ - mem_region_t mem_region; - - auto int iterate_linuxbios_table (grub_linuxbios_table_item_t); - int iterate_linuxbios_table (grub_linuxbios_table_item_t table_item) - { - if (table_item->tag != GRUB_LINUXBIOS_MEMBER_MEMORY) - return 0; - - mem_region = - (mem_region_t) ((long) table_item + - sizeof (struct grub_linuxbios_table_item)); - while ((long) mem_region < (long) table_item + (long) table_item->size) - { - if (hook (mem_region->addr, mem_region->size, - /* Multiboot mmaps match with the coreboot mmap definition. - Therefore, we can just pass type through. */ - mem_region->type)) - return 1; - - mem_region++; - } - - return 0; - } - - grub_linuxbios_table_iterate (iterate_linuxbios_table); - - return 0; -} diff --git a/grub-core/kern/i386/coreboot/startup.S b/grub-core/kern/i386/coreboot/startup.S index dc2c62a25..df6adbabb 100644 --- a/grub-core/kern/i386/coreboot/startup.S +++ b/grub-core/kern/i386/coreboot/startup.S @@ -17,10 +17,7 @@ */ #include -/* For stack parameters. */ -#include #include -#include #include #include #include @@ -63,10 +60,3 @@ multiboot_header: /* checksum */ .long -0x1BADB002 - MULTIBOOT_MEMORY_INFO -/* - * prot_to_real and associated structures (but NOT real_to_prot, that is - * only needed for BIOS gates). - */ -#include "../realmode.S" - -#include "../int.S" diff --git a/grub-core/kern/i386/dl.c b/grub-core/kern/i386/dl.c index c5539cb05..1346da5cc 100644 --- a/grub-core/kern/i386/dl.c +++ b/grub-core/kern/i386/dl.c @@ -40,75 +40,42 @@ grub_arch_dl_check_header (void *ehdr) /* Relocate symbols. */ grub_err_t -grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg) { - Elf_Ehdr *e = ehdr; - Elf_Shdr *s; - Elf_Word entsize; - unsigned i; + Elf_Rel *rel, *max; - /* Find a symbol table. */ - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_SYMTAB) - break; + for (rel = (Elf_Rel *) ((char *) ehdr + s->sh_offset), + max = (Elf_Rel *) ((char *) rel + s->sh_size); + rel < max; + rel = (Elf_Rel *) ((char *) rel + s->sh_entsize)) + { + Elf_Word *addr; + Elf_Sym *sym; - if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); + if (seg->size < rel->r_offset) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); - entsize = s->sh_entsize; + addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset); + sym = (Elf_Sym *) ((char *) mod->symtab + + mod->symsize * ELF_R_SYM (rel->r_info)); - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_REL) - { - grub_dl_segment_t seg; + switch (ELF_R_TYPE (rel->r_info)) + { + case R_386_32: + *addr += sym->st_value; + break; - /* Find the target segment. */ - for (seg = mod->segment; seg; seg = seg->next) - if (seg->section == s->sh_info) - break; - - if (seg) - { - Elf_Rel *rel, *max; - - for (rel = (Elf_Rel *) ((char *) e + s->sh_offset), - max = rel + s->sh_size / s->sh_entsize; - rel < max; - rel++) - { - Elf_Word *addr; - Elf_Sym *sym; - - if (seg->size < rel->r_offset) - return grub_error (GRUB_ERR_BAD_MODULE, - "reloc offset is out of the segment"); - - addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset); - sym = (Elf_Sym *) ((char *) mod->symtab - + entsize * ELF_R_SYM (rel->r_info)); - - switch (ELF_R_TYPE (rel->r_info)) - { - case R_386_32: - *addr += sym->st_value; - break; - - case R_386_PC32: - *addr += (sym->st_value - (Elf_Word) seg->addr - - rel->r_offset); - break; - default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("relocation 0x%x is not implemented yet"), - ELF_R_TYPE (rel->r_info)); - } - } - } - } + case R_386_PC32: + *addr += (sym->st_value - (grub_addr_t) addr); + break; + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%x is not implemented yet"), + ELF_R_TYPE (rel->r_info)); + } + } return GRUB_ERR_NONE; } diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c index 6bd8f3e87..46476e27e 100644 --- a/grub-core/kern/i386/efi/init.c +++ b/grub-core/kern/i386/efi/init.c @@ -26,6 +26,7 @@ #include #include #include +#include void grub_machine_init (void) @@ -35,7 +36,13 @@ grub_machine_init (void) } void -grub_machine_fini (void) +grub_machine_fini (int flags) { + if (!(flags & GRUB_LOADER_FLAG_NORETURN)) + return; + grub_efi_fini (); + + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY)) + grub_efi_memory_fini (); } diff --git a/grub-core/kern/i386/efi/tsc.c b/grub-core/kern/i386/efi/tsc.c new file mode 100644 index 000000000..e41dc6526 --- /dev/null +++ b/grub-core/kern/i386/efi/tsc.c @@ -0,0 +1,40 @@ +/* kern/i386/tsc.c - x86 TSC time source implementation + * Requires Pentium or better x86 CPU that supports the RDTSC instruction. + * This module uses the PIT to calibrate the TSC to + * real time. + * + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +int +grub_tsc_calibrate_from_efi (void) +{ + grub_uint64_t start_tsc, end_tsc; + /* Use EFI Time Service to calibrate TSC */ + start_tsc = grub_get_tsc (); + grub_efi_system_table->boot_services->stall (1000); + end_tsc = grub_get_tsc (); + grub_tsc_rate = grub_divmod64 ((1ULL << 32), end_tsc - start_tsc, 0); + return 1; +} diff --git a/grub-core/kern/i386/ieee1275/startup.S b/grub-core/kern/i386/ieee1275/startup.S index 245583bdb..62cf348e0 100644 --- a/grub-core/kern/i386/ieee1275/startup.S +++ b/grub-core/kern/i386/ieee1275/startup.S @@ -18,7 +18,6 @@ #include #include -#include #include #include diff --git a/grub-core/kern/i386/int.S b/grub-core/kern/i386/int.S index 7edace404..862a54202 100644 --- a/grub-core/kern/i386/int.S +++ b/grub-core/kern/i386/int.S @@ -44,6 +44,13 @@ FUNCTION(grub_bios_interrupt) movl 24(%edx), %esi movl 28(%edx), %edx + /* + Via C3 CPUs have cache coherence problems, so we need to call + wbinvd at these 2 points. As wbinvd slows down boot, don't do + it on non-VIA. 9090 is nop nop. */ +VARIABLE(grub_bios_via_workaround1) + .byte 0x90, 0x90 + PROT_TO_REAL .code16 pushf @@ -92,6 +99,10 @@ intno: movw %ax, LOCAL(bios_register_es) popf + +VARIABLE(grub_bios_via_workaround2) + .byte 0x90, 0x90 + REAL_TO_PROT .code32 diff --git a/grub-core/kern/i386/multiboot_mmap.c b/grub-core/kern/i386/multiboot_mmap.c index 1cb422fef..e8f4f34b9 100644 --- a/grub-core/kern/i386/multiboot_mmap.c +++ b/grub-core/kern/i386/multiboot_mmap.c @@ -57,13 +57,13 @@ grub_machine_mmap_init (void) } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { struct multiboot_mmap_entry *entry = (void *) kern_multiboot_info.mmap_addr; while ((unsigned long) entry < kern_multiboot_info.mmap_addr + kern_multiboot_info.mmap_length) { - if (hook (entry->addr, entry->len, entry->type)) + if (hook (entry->addr, entry->len, entry->type, hook_data)) break; entry = (void *) ((grub_addr_t) entry + entry->size + sizeof (entry->size)); diff --git a/grub-core/commands/i386/pc/acpi.c b/grub-core/kern/i386/pc/acpi.c similarity index 79% rename from grub-core/commands/i386/pc/acpi.c rename to grub-core/kern/i386/pc/acpi.c index 88e4f55cf..0a69eba7b 100644 --- a/grub-core/commands/i386/pc/acpi.c +++ b/grub-core/kern/i386/pc/acpi.c @@ -27,20 +27,21 @@ grub_machine_acpi_get_rsdpv1 (void) grub_uint8_t *ebda, *ptr; grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n"); - ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4); + ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) grub_absolute_pointer (0x40e))) << 4); ebda_len = * (grub_uint16_t *) ebda; - if (! ebda_len) - return 0; + if (! ebda_len) /* FIXME do we really need this check? */ + goto scan_bios; for (ptr = ebda; ptr < ebda + 0x400; ptr += 16) - if (grub_memcmp (ptr, "RSD PTR ", 8) == 0 + if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0) return (struct grub_acpi_rsdp_v10 *) ptr; +scan_bios: grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n"); for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000; ptr += 16) - if (grub_memcmp (ptr, "RSD PTR ", 8) == 0 + if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) ptr)->revision == 0) return (struct grub_acpi_rsdp_v10 *) ptr; @@ -54,12 +55,12 @@ grub_machine_acpi_get_rsdpv2 (void) grub_uint8_t *ebda, *ptr; grub_dprintf ("acpi", "Looking for RSDP. Scanning EBDA\n"); - ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) 0x40e)) << 4); + ebda = (grub_uint8_t *) ((* ((grub_uint16_t *) grub_absolute_pointer (0x40e))) << 4); ebda_len = * (grub_uint16_t *) ebda; - if (! ebda_len) - return 0; + if (! ebda_len) /* FIXME do we really need this check? */ + goto scan_bios; for (ptr = ebda; ptr < ebda + 0x400; ptr += 16) - if (grub_memcmp (ptr, "RSD PTR ", 8) == 0 + if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) ptr)->revision != 0 && ((struct grub_acpi_rsdp_v20 *) ptr)->length < 1024 @@ -67,10 +68,11 @@ grub_machine_acpi_get_rsdpv2 (void) == 0) return (struct grub_acpi_rsdp_v20 *) ptr; +scan_bios: grub_dprintf ("acpi", "Looking for RSDP. Scanning BIOS\n"); for (ptr = (grub_uint8_t *) 0xe0000; ptr < (grub_uint8_t *) 0x100000; ptr += 16) - if (grub_memcmp (ptr, "RSD PTR ", 8) == 0 + if (grub_memcmp (ptr, GRUB_RSDP_SIGNATURE, GRUB_RSDP_SIGNATURE_SIZE) == 0 && grub_byte_checksum (ptr, sizeof (struct grub_acpi_rsdp_v10)) == 0 && ((struct grub_acpi_rsdp_v10 *) ptr)->revision != 0 && ((struct grub_acpi_rsdp_v20 *) ptr)->length < 1024 diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 0841d8bb1..326d491c5 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -52,8 +53,8 @@ void (*grub_pc_net_config) (char **device, char **path); * return the real time in ticks, of which there are about * 18-20 per second */ -grub_uint32_t -grub_get_rtc (void) +grub_uint64_t +grub_rtc_get_time_ms (void) { struct grub_bios_int_registers regs; @@ -61,7 +62,7 @@ grub_get_rtc (void) regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; grub_bios_interrupt (0x1a, ®s); - return (regs.ecx << 16) | (regs.edx & 0xffff); + return ((regs.ecx << 16) | (regs.edx & 0xffff)) * 55ULL; } void @@ -154,6 +155,65 @@ compact_mem_regions (void) grub_addr_t grub_modbase; extern grub_uint8_t _start[], _edata[]; +/* Helper for grub_machine_init. */ +static int +mmap_iterate_hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type, + void *data __attribute__ ((unused))) +{ + /* Avoid the lower memory. */ + if (addr < GRUB_MEMORY_MACHINE_UPPER_START) + { + if (size <= GRUB_MEMORY_MACHINE_UPPER_START - addr) + return 0; + + size -= GRUB_MEMORY_MACHINE_UPPER_START - addr; + addr = GRUB_MEMORY_MACHINE_UPPER_START; + } + + /* Ignore >4GB. */ + if (addr <= 0xFFFFFFFF && type == GRUB_MEMORY_AVAILABLE) + { + grub_size_t len; + + len = (grub_size_t) ((addr + size > 0xFFFFFFFF) + ? 0xFFFFFFFF - addr + : size); + add_mem_region (addr, len); + } + + return 0; +} + +extern grub_uint16_t grub_bios_via_workaround1, grub_bios_via_workaround2; + +/* Via needs additional wbinvd. */ +static void +grub_via_workaround_init (void) +{ + grub_uint32_t manufacturer[3], max_cpuid, proc_info; + if (! grub_cpu_is_cpuid_supported ()) + return; + + grub_cpuid (0, max_cpuid, manufacturer[0], manufacturer[2], manufacturer[1]); + + if (grub_memcmp (manufacturer, "CentaurHauls", 12) != 0) + return; + + if (max_cpuid > 0) + { + grub_cpuid (1, proc_info, /* Don't care. */ manufacturer[0], + manufacturer[2], manufacturer[1]); + /* Check model, apply only to VIA C3 and lower. */ + if (((proc_info & 0xf0) >> 4 | (proc_info & 0xf0000) >> 12) > 10) + return; + } + + grub_bios_via_workaround1 = 0x090f; + grub_bios_via_workaround2 = 0x090f; + asm volatile ("wbinvd"); +} + void grub_machine_init (void) { @@ -161,6 +221,10 @@ grub_machine_init (void) #if 0 int grub_lower_mem; #endif + grub_addr_t modend; + + /* This has to happen before any BIOS calls. */ + grub_via_workaround_init (); grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start); @@ -188,48 +252,29 @@ grub_machine_init (void) grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END); #endif - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, - grub_memory_type_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_memory_type_t type) - { - /* Avoid the lower memory. */ - if (addr < 0x100000) - { - if (size <= 0x100000 - addr) - return 0; - - size -= 0x100000 - addr; - addr = 0x100000; - } - - /* Ignore >4GB. */ - if (addr <= 0xFFFFFFFF && type == GRUB_MEMORY_AVAILABLE) - { - grub_size_t len; - - len = (grub_size_t) ((addr + size > 0xFFFFFFFF) - ? 0xFFFFFFFF - addr - : size); - add_mem_region (addr, len); - } - - return 0; - } - - grub_machine_mmap_iterate (hook); + grub_machine_mmap_iterate (mmap_iterate_hook, NULL); compact_mem_regions (); + modend = grub_modules_get_end (); for (i = 0; i < num_regions; i++) - grub_mm_init_region ((void *) mem_regions[i].addr, mem_regions[i].size); + { + grub_addr_t beg = mem_regions[i].addr; + grub_addr_t fin = mem_regions[i].addr + mem_regions[i].size; + if (modend && beg < modend) + beg = modend; + if (beg >= fin) + continue; + grub_mm_init_region ((void *) beg, fin - beg); + } grub_tsc_init (); } void -grub_machine_fini (void) +grub_machine_fini (int flags) { - grub_console_fini (); + if (flags & GRUB_LOADER_FLAG_NORETURN) + grub_console_fini (); grub_stop_floppy (); } diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c index 480ffa949..53fcf45af 100644 --- a/grub-core/kern/i386/pc/mmap.c +++ b/grub-core/kern/i386/pc/mmap.c @@ -33,7 +33,7 @@ struct grub_machine_mmap_entry #define GRUB_MACHINE_MEMORY_NVS 4 #define GRUB_MACHINE_MEMORY_BADRAM 5 grub_uint32_t type; -} __attribute__((packed)); +} GRUB_PACKED; /* @@ -73,9 +73,9 @@ grub_get_ext_memsize (void) in 1KB parts, and upper 16 bits are above 16MB in 64KB parts. If error, return zero. BIOS call "INT 15H, AH=E801H" to get EISA memory map, AX = memory between 1M and 16M in 1K parts. - BX = memory above 16M in 64K parts. + BX = memory above 16M in 64K parts. */ - + static inline grub_uint32_t grub_get_eisa_mmap (void) { @@ -114,7 +114,7 @@ grub_get_mmap_entry (struct grub_machine_mmap_entry *entry, /* place address (+4) in ES:DI */ regs.es = ((grub_addr_t) &entry->addr) >> 4; regs.edi = ((grub_addr_t) &entry->addr) & 0xf; - + /* set continuation value */ regs.ebx = cont; @@ -127,7 +127,7 @@ grub_get_mmap_entry (struct grub_machine_mmap_entry *entry, regs.eax = 0xe820; grub_bios_interrupt (0x15, ®s); - /* write length of buffer (zero if error) into ADDR */ + /* write length of buffer (zero if error) into ADDR */ if ((regs.flags & GRUB_CPU_INT_FLAGS_CARRY) || regs.eax != 0x534d4150 || regs.ecx < 0x14 || regs.ecx > 0x400) entry->size = 0; @@ -139,51 +139,54 @@ grub_get_mmap_entry (struct grub_machine_mmap_entry *entry, } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { - grub_uint32_t cont; + grub_uint32_t cont = 0; struct grub_machine_mmap_entry *entry - = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + = (struct grub_machine_mmap_entry *) grub_absolute_pointer (GRUB_MEMORY_MACHINE_SCRATCH_ADDR); + int e820_works = 0; - grub_memset (entry, 0, sizeof (entry)); + while (1) + { + grub_memset (entry, 0, sizeof (*entry)); - /* Check if grub_get_mmap_entry works. */ - cont = grub_get_mmap_entry (entry, 0); + cont = grub_get_mmap_entry (entry, cont); - if (entry->size) - do - { - if (hook (entry->addr, entry->len, - /* GRUB mmaps have been defined to match with the E820 definition. - Therefore, we can just pass type through. */ - ((entry->type <= GRUB_MACHINE_MEMORY_BADRAM) && (entry->type >= GRUB_MACHINE_MEMORY_AVAILABLE)) ? entry->type : GRUB_MEMORY_RESERVED)) - break; + if (!entry->size) + break; - if (! cont) - break; + if (entry->len) + e820_works = 1; + if (entry->len + && hook (entry->addr, entry->len, + /* GRUB mmaps have been defined to match with + the E820 definition. + Therefore, we can just pass type through. */ + entry->type, hook_data)) + break; - grub_memset (entry, 0, sizeof (entry)); + if (! cont) + break; + } - cont = grub_get_mmap_entry (entry, cont); - } - while (entry->size); - else + if (!e820_works) { grub_uint32_t eisa_mmap = grub_get_eisa_mmap (); if (hook (0x0, ((grub_uint32_t) grub_get_conv_memsize ()) << 10, - GRUB_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE, hook_data)) return 0; if (eisa_mmap) { if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, - GRUB_MEMORY_AVAILABLE) == 0) - hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE, hook_data) == 0) + hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MEMORY_AVAILABLE, + hook_data); } else hook (0x100000, ((grub_uint32_t) grub_get_ext_memsize ()) << 10, - GRUB_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE, hook_data); } return 0; diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index 6bb36c603..b8a9b33b4 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -135,7 +135,7 @@ LOCAL(prot_to_real_addr): .macro REAL_TO_PROT movl LOCAL(real_to_prot_addr), %eax - DATA32 call *%ax + calll *%eax .endm /* diff --git a/grub-core/kern/i386/pit.c b/grub-core/kern/i386/pit.c deleted file mode 100644 index 82a17d3e0..000000000 --- a/grub-core/kern/i386/pit.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB 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 GRUB. If not, see . - */ - -#include -#include -#include - -#define TIMER2_REG_CONTROL 0x42 -#define TIMER_REG_COMMAND 0x43 -#define TIMER2_REG_LATCH 0x61 - -#define TIMER2_SELECT 0x80 -#define TIMER_ENABLE_LSB 0x20 -#define TIMER_ENABLE_MSB 0x10 -#define TIMER2_LATCH 0x20 -#define TIMER2_SPEAKER 0x02 -#define TIMER2_GATE 0x01 - -void -grub_pit_wait (grub_uint16_t tics) -{ - /* Disable timer2 gate and speaker. */ - grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE), - TIMER2_REG_LATCH); - - /* Set tics. */ - grub_outb (TIMER2_SELECT | TIMER_ENABLE_LSB | TIMER_ENABLE_MSB, TIMER_REG_COMMAND); - grub_outb (tics & 0xff, TIMER2_REG_CONTROL); - grub_outb (tics >> 8, TIMER2_REG_CONTROL); - - /* Enable timer2 gate, keep speaker disabled. */ - grub_outb ((grub_inb (TIMER2_REG_LATCH) & ~ TIMER2_SPEAKER) | TIMER2_GATE, - TIMER2_REG_LATCH); - - /* Wait. */ - while ((grub_inb (TIMER2_REG_LATCH) & TIMER2_LATCH) == 0x00); - - /* Disable timer2 gate and speaker. */ - grub_outb (grub_inb (TIMER2_REG_LATCH) & ~ (TIMER2_SPEAKER | TIMER2_GATE), - TIMER2_REG_LATCH); -} diff --git a/grub-core/kern/i386/qemu/init.c b/grub-core/kern/i386/qemu/init.c new file mode 100644 index 000000000..08f81d25e --- /dev/null +++ b/grub-core/kern/i386/qemu/init.c @@ -0,0 +1,276 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern grub_uint8_t _start[]; +extern grub_uint8_t _end[]; +extern grub_uint8_t _edata[]; + +void __attribute__ ((noreturn)) +grub_exit (void) +{ + /* We can't use grub_fatal() in this function. This would create an infinite + loop, since grub_fatal() calls grub_abort() which in turn calls grub_exit(). */ + while (1) + grub_cpu_idle (); +} + +grub_addr_t grub_modbase; + +/* Helper for grub_machine_init. */ +static int +heap_init (grub_uint64_t addr, grub_uint64_t size, grub_memory_type_t type, + void *data __attribute__ ((unused))) +{ + grub_uint64_t begin = addr, end = addr + size; + +#if GRUB_CPU_SIZEOF_VOID_P == 4 + /* Restrict ourselves to 32-bit memory space. */ + if (begin > GRUB_ULONG_MAX) + return 0; + if (end > GRUB_ULONG_MAX) + end = GRUB_ULONG_MAX; +#endif + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + /* Avoid the lower memory. */ + if (begin < GRUB_MEMORY_MACHINE_LOWER_SIZE) + begin = GRUB_MEMORY_MACHINE_LOWER_SIZE; + + if (end <= begin) + return 0; + + grub_mm_init_region ((void *) (grub_addr_t) begin, (grub_size_t) (end - begin)); + + return 0; +} + +struct resource +{ + grub_pci_device_t dev; + grub_size_t size; + unsigned type:4; + unsigned bar:3; +}; + +struct iterator_ctx +{ + struct resource *resources; + grub_size_t nresources; +}; + +/* We don't support bridges, so can't have more than 32 devices. */ +#define MAX_DEVICES 32 + +static int +find_resources (grub_pci_device_t dev, + grub_pci_id_t pciid __attribute__ ((unused)), + void *data) +{ + struct iterator_ctx *ctx = data; + int bar; + + if (ctx->nresources >= MAX_DEVICES * 6) + return 1; + + for (bar = 0; bar < 6; bar++) + { + grub_pci_address_t addr; + grub_uint32_t ones, zeros, mask; + struct resource *res; + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0 + + 4 * bar); + grub_pci_write (addr, 0xffffffff); + grub_pci_read (addr); + ones = grub_pci_read (addr); + grub_pci_write (addr, 0); + grub_pci_read (addr); + zeros = grub_pci_read (addr); + if (ones == zeros) + continue; + res = &ctx->resources[ctx->nresources++]; + if ((zeros & GRUB_PCI_ADDR_SPACE_MASK) == GRUB_PCI_ADDR_SPACE_IO) + mask = GRUB_PCI_ADDR_SPACE_MASK; + else + mask = (GRUB_PCI_ADDR_MEM_TYPE_MASK | GRUB_PCI_ADDR_SPACE_MASK | GRUB_PCI_ADDR_MEM_PREFETCH); + + res->type = ones & mask; + res->dev = dev; + res->bar = bar; + res->size = (~((zeros ^ ones)) | mask) + 1; + if ((zeros & (GRUB_PCI_ADDR_MEM_TYPE_MASK | GRUB_PCI_ADDR_SPACE_MASK)) + == (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_64)) + bar++; + } + return 0; +} + +static int +enable_cards (grub_pci_device_t dev, + grub_pci_id_t pciid __attribute__ ((unused)), + void *data __attribute__ ((unused))) +{ + grub_uint16_t cmd = 0; + grub_pci_address_t addr; + grub_uint32_t class; + int bar; + + for (bar = 0; bar < 6; bar++) + { + grub_uint32_t val; + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0 + + 4 * bar); + val = grub_pci_read (addr); + if (!val) + continue; + if ((val & GRUB_PCI_ADDR_SPACE_MASK) == GRUB_PCI_ADDR_SPACE_IO) + cmd |= GRUB_PCI_COMMAND_IO_ENABLED; + else + cmd |= GRUB_PCI_COMMAND_MEM_ENABLED; + } + + class = (grub_pci_read (addr) >> 16) & 0xffff; + + if (class == GRUB_PCI_CLASS_DISPLAY_VGA) + cmd |= GRUB_PCI_COMMAND_IO_ENABLED + | GRUB_PCI_COMMAND_MEM_ENABLED; + + if (class == GRUB_PCI_CLASS_SERIAL_USB) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write (addr, cmd); + + return 0; +} + +static void +grub_pci_assign_addresses (void) +{ + struct iterator_ctx ctx; + + { + struct resource resources[MAX_DEVICES * 6]; + int done; + unsigned i; + ctx.nresources = 0; + ctx.resources = resources; + grub_uint32_t memptr = 0xf0000000; + grub_uint16_t ioptr = 0x1000; + + grub_pci_iterate (find_resources, &ctx); + /* FIXME: do we need a better sort here? */ + do + { + done = 0; + for (i = 0; i + 1 < ctx.nresources; i++) + if (resources[i].size < resources[i+1].size) + { + struct resource t; + t = resources[i]; + resources[i] = resources[i+1]; + resources[i+1] = t; + done = 1; + } + } + while (done); + + for (i = 0; i < ctx.nresources; i++) + { + grub_pci_address_t addr; + addr = grub_pci_make_address (resources[i].dev, + GRUB_PCI_REG_ADDRESS_REG0 + + 4 * resources[i].bar); + if ((resources[i].type & GRUB_PCI_ADDR_SPACE_MASK) + == GRUB_PCI_ADDR_SPACE_IO) + { + grub_pci_write (addr, ioptr | resources[i].type); + ioptr += resources[i].size; + } + else + { + grub_pci_write (addr, memptr | resources[i].type); + memptr += resources[i].size; + if ((resources[i].type & (GRUB_PCI_ADDR_MEM_TYPE_MASK + | GRUB_PCI_ADDR_SPACE_MASK)) + == (GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_64)) + { + addr = grub_pci_make_address (resources[i].dev, + GRUB_PCI_REG_ADDRESS_REG0 + + 4 * resources[i].bar + 4); + grub_pci_write (addr, 0); + } + } + } + grub_pci_iterate (enable_cards, NULL); + } +} + +void +grub_machine_init (void) +{ + grub_modbase = grub_core_entry_addr + (_edata - _start); + + grub_pci_assign_addresses (); + + grub_qemu_init_cirrus (); + + grub_vga_text_init (); + + grub_machine_mmap_init (); + grub_machine_mmap_iterate (heap_init, NULL); + + + grub_tsc_init (); +} + +void +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) +{ +} + +void +grub_machine_fini (int flags) +{ + if (flags & GRUB_LOADER_FLAG_NORETURN) + grub_vga_text_fini (); + grub_stop_floppy (); +} diff --git a/grub-core/kern/i386/qemu/mmap.c b/grub-core/kern/i386/qemu/mmap.c index ffb61a47a..f449637ef 100644 --- a/grub-core/kern/i386/qemu/mmap.c +++ b/grub-core/kern/i386/qemu/mmap.c @@ -69,38 +69,38 @@ grub_machine_mmap_init (void) } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { if (hook (0x0, (grub_addr_t) _start, - GRUB_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE, hook_data)) return 1; if (hook ((grub_addr_t) _end, 0xa0000 - (grub_addr_t) _end, - GRUB_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE, hook_data)) return 1; if (hook (GRUB_MEMORY_MACHINE_UPPER, 0x100000 - GRUB_MEMORY_MACHINE_UPPER, - GRUB_MEMORY_RESERVED)) + GRUB_MEMORY_RESERVED, hook_data)) return 1; /* Everything else is free. */ if (hook (0x100000, min (mem_size, (grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE) - 0x100000, - GRUB_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE, hook_data)) return 1; /* Protect boot.img, which contains the gdt. It is mapped at the top of memory (it is also mapped below 0x100000, but we already reserved that area). */ if (hook ((grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE, GRUB_BOOT_MACHINE_SIZE, - GRUB_MEMORY_RESERVED)) + GRUB_MEMORY_RESERVED, hook_data)) return 1; if (above_4g != 0 && hook (0x100000000ULL, above_4g, - GRUB_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE, hook_data)) return 1; return 0; diff --git a/grub-core/kern/i386/qemu/startup.S b/grub-core/kern/i386/qemu/startup.S index 0761807ed..0d89858d9 100644 --- a/grub-core/kern/i386/qemu/startup.S +++ b/grub-core/kern/i386/qemu/startup.S @@ -19,7 +19,6 @@ #include #include -#include #include #include @@ -29,7 +28,7 @@ _start: jmp codestart - . = _start + GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR + .org GRUB_KERNEL_I386_QEMU_CORE_ENTRY_ADDR VARIABLE(grub_core_entry_addr) .long 0 @@ -74,5 +73,3 @@ codestart: 1: hlt jmp 1b - -#include "../realmode.S" diff --git a/grub-core/kern/i386/realmode.S b/grub-core/kern/i386/realmode.S index 6403b9699..265cdcb9d 100644 --- a/grub-core/kern/i386/realmode.S +++ b/grub-core/kern/i386/realmode.S @@ -16,7 +16,7 @@ * along with GRUB. If not, see . */ -#include +#include /* * Note: These functions defined in this file may be called from C. @@ -54,7 +54,7 @@ protstack: .endm .macro REAL_TO_PROT - DATA32 call real_to_prot + calll real_to_prot .endm /* @@ -77,7 +77,7 @@ protstack: * description. */ - .p2align 5 /* force 4-byte alignment */ + .p2align 5 /* force 32-byte alignment */ gdt: .word 0, 0 .byte 0, 0, 0, 0 @@ -137,7 +137,22 @@ real_to_prot: /* load the GDT register */ xorw %ax, %ax movw %ax, %ds - DATA32 ADDR32 lgdt gdtdesc +#ifdef GRUB_MACHINE_QEMU + /* + qemu is special: gdtdesc is in ROM. + %cs = 0xf000 + _start + GRUB_BOOT_MACHINE_SIZE = 0x100000 + So + _start + GRUB_BOOT_MACHINE_SIZE - 0x10000 points to the same point + as %cs. + gdtdesc - (_start + GRUB_BOOT_MACHINE_SIZE - 0x10000) + = gdtdesc - _start - GRUB_BOOT_MACHINE_SIZE + 0x10000 + but the later can be computed by assembly. + */ + lgdtl %cs:(gdtdesc - _start - GRUB_BOOT_MACHINE_SIZE + 0x10000) +#else + lgdtl gdtdesc +#endif /* turn on protected mode */ movl %cr0, %eax @@ -145,7 +160,7 @@ real_to_prot: movl %eax, %cr0 /* jump to relocation, flush prefetch queue, and reload %cs */ - DATA32 ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg + ljmpl $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $protcseg .code32 protcseg: @@ -178,6 +193,9 @@ protcseg: /* return on the old (or initialized) stack! */ ret + /* prot_to_real assumes that this code is under 64K which is not + true for qemu. */ +#ifndef GRUB_MACHINE_QEMU /* * GRUB -- GRand Unified Bootloader * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2009,2010 Free Software Foundation, Inc. @@ -196,8 +214,6 @@ protcseg: * along with GRUB. If not, see . */ -#include - prot_to_real: /* just in case, set GDT */ lgdt gdtdesc @@ -239,7 +255,7 @@ tmpcseg: movl %eax, %cr0 /* flush prefetch queue, reload %cs */ - DATA32 ljmp $0, $realcseg + ljmpl $0, $realcseg realcseg: /* we are in real mode now @@ -260,6 +276,6 @@ realcseg: #endif /* return on new stack! */ - DATA32 ret - + retl +#endif .code32 diff --git a/grub-core/kern/i386/tsc.c b/grub-core/kern/i386/tsc.c index c4645f043..9293b161d 100644 --- a/grub-core/kern/i386/tsc.c +++ b/grub-core/kern/i386/tsc.c @@ -1,7 +1,6 @@ /* kern/i386/tsc.c - x86 TSC time source implementation * Requires Pentium or better x86 CPU that supports the RDTSC instruction. - * This module uses the RTC (via grub_get_rtc()) to calibrate the TSC to - * real time. + * This module calibrates the TSC to real time. * * GRUB -- GRand Unified Bootloader * Copyright (C) 2008 Free Software Foundation, Inc. @@ -24,55 +23,56 @@ #include #include #include -#include +#include /* This defines the value TSC had at the epoch (that is, when we calibrated it). */ static grub_uint64_t tsc_boot_time; -/* Calibrated TSC rate. (In TSC ticks per millisecond.) */ -static grub_uint64_t tsc_ticks_per_ms; +/* Calibrated TSC rate. (In ms per 2^32 ticks) */ +/* We assume that the tick is less than 1 ms and hence this value fits + in 32-bit. */ +grub_uint32_t grub_tsc_rate; - -grub_uint64_t +static grub_uint64_t grub_tsc_get_time_ms (void) { - return tsc_boot_time + grub_divmod64 (grub_get_tsc (), tsc_ticks_per_ms, 0); + grub_uint64_t a = grub_get_tsc () - tsc_boot_time; + grub_uint64_t ah = a >> 32; + grub_uint64_t al = a & 0xffffffff; + + return ((al * grub_tsc_rate) >> 32) + ah * grub_tsc_rate; } - -/* How many RTC ticks to use for calibration loop. (>= 1) */ -#define CALIBRATION_TICKS 2 - -/* Calibrate the TSC based on the RTC. */ -static void -calibrate_tsc (void) +static int +calibrate_tsc_hardcode (void) { - /* First calibrate the TSC rate (relative, not absolute time). */ - grub_uint64_t start_tsc; - grub_uint64_t end_tsc; - - start_tsc = grub_get_tsc (); - grub_pit_wait (0xffff); - end_tsc = grub_get_tsc (); - - tsc_ticks_per_ms = grub_divmod64 (end_tsc - start_tsc, 55, 0); + grub_tsc_rate = 5368;/* 800 MHz */ + return 1; } void grub_tsc_init (void) { - if (grub_cpu_is_tsc_supported ()) - { - tsc_boot_time = grub_get_tsc (); - calibrate_tsc (); - grub_install_get_time_ms (grub_tsc_get_time_ms); - } - else + if (!grub_cpu_is_tsc_supported ()) { #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_IEEE1275) grub_install_get_time_ms (grub_rtc_get_time_ms); #else grub_fatal ("no TSC found"); #endif + return; } + + tsc_boot_time = grub_get_tsc (); + +#if defined (GRUB_MACHINE_XEN) || defined (GRUB_MACHINE_XEN_PVH) + (void) (grub_tsc_calibrate_from_xen () || calibrate_tsc_hardcode()); +#elif defined (GRUB_MACHINE_EFI) + (void) (grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_pit () || grub_tsc_calibrate_from_efi() || calibrate_tsc_hardcode()); +#elif defined (GRUB_MACHINE_COREBOOT) + (void) (grub_tsc_calibrate_from_pmtimer () || grub_tsc_calibrate_from_pit () || calibrate_tsc_hardcode()); +#else + (void) (grub_tsc_calibrate_from_pit () || calibrate_tsc_hardcode()); +#endif + grub_install_get_time_ms (grub_tsc_get_time_ms); } diff --git a/grub-core/kern/i386/tsc_pit.c b/grub-core/kern/i386/tsc_pit.c new file mode 100644 index 000000000..67990bfa6 --- /dev/null +++ b/grub-core/kern/i386/tsc_pit.c @@ -0,0 +1,84 @@ +/* kern/i386/tsc.c - x86 TSC time source implementation + * Requires Pentium or better x86 CPU that supports the RDTSC instruction. + * This module uses the PIT to calibrate the TSC to + * real time. + * + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +static int +grub_pit_wait (void) +{ + int ret = 0; + + /* Disable timer2 gate and speaker. */ + grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT) + & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2), + GRUB_PIT_SPEAKER_PORT); + + /* Set tics. */ + grub_outb (GRUB_PIT_CTRL_SELECT_2 | GRUB_PIT_CTRL_READLOAD_WORD, + GRUB_PIT_CTRL); + /* 0xffff ticks: 55ms. */ + grub_outb (0xff, GRUB_PIT_COUNTER_2); + grub_outb (0xff, GRUB_PIT_COUNTER_2); + + /* Enable timer2 gate, keep speaker disabled. */ + grub_outb ((grub_inb (GRUB_PIT_SPEAKER_PORT) & ~ GRUB_PIT_SPK_DATA) + | GRUB_PIT_SPK_TMR2, + GRUB_PIT_SPEAKER_PORT); + + if ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00) { + ret = 1; + /* Wait. */ + while ((grub_inb (GRUB_PIT_SPEAKER_PORT) & GRUB_PIT_SPK_TMR2_LATCH) == 0x00); + } + + /* Disable timer2 gate and speaker. */ + grub_outb (grub_inb (GRUB_PIT_SPEAKER_PORT) + & ~ (GRUB_PIT_SPK_DATA | GRUB_PIT_SPK_TMR2), + GRUB_PIT_SPEAKER_PORT); + + return ret; +} + +/* Calibrate the TSC based on the RTC. */ +int +grub_tsc_calibrate_from_pit (void) +{ + /* First calibrate the TSC rate (relative, not absolute time). */ + grub_uint64_t start_tsc, end_tsc; + + start_tsc = grub_get_tsc (); + if (!grub_pit_wait ()) + return 0; + end_tsc = grub_get_tsc (); + + grub_tsc_rate = 0; + if (end_tsc > start_tsc) + grub_tsc_rate = grub_divmod64 ((55ULL << 32), end_tsc - start_tsc, 0); + if (grub_tsc_rate == 0) + return 0; + return 1; +} diff --git a/grub-core/kern/i386/tsc_pmtimer.c b/grub-core/kern/i386/tsc_pmtimer.c new file mode 100644 index 000000000..dd044590d --- /dev/null +++ b/grub-core/kern/i386/tsc_pmtimer.c @@ -0,0 +1,157 @@ +/* kern/i386/tsc.c - x86 TSC time source implementation + * Requires Pentium or better x86 CPU that supports the RDTSC instruction. + * This module uses the PIT to calibrate the TSC to + * real time. + * + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +grub_uint64_t +grub_pmtimer_wait_count_tsc (grub_port_t pmtimer, + grub_uint16_t num_pm_ticks) +{ + grub_uint32_t start; + grub_uint64_t cur, end; + grub_uint64_t start_tsc; + grub_uint64_t end_tsc; + grub_uint32_t num_iter = 0; + int bad_reads = 0; + + /* + * Some timers are 24-bit and some are 32-bit, but it doesn't make much + * difference to us. Caring which one we have isn't really worth it since + * the low-order digits will give us enough data to calibrate TSC. So just + * mask the top-order byte off. + */ + cur = start = grub_inl (pmtimer) & 0x00ffffffUL; + end = start + num_pm_ticks; + start_tsc = grub_get_tsc (); + while (1) + { + cur &= 0xffffffffff000000ULL; + + /* Only take the low-order 24-bit for the reason explained above. */ + cur |= grub_inl (pmtimer) & 0x00ffffffUL; + + end_tsc = grub_get_tsc(); + + /* + * If we get 10 reads in a row that are obviously dead pins, there's no + * reason to do this thousands of times. + */ + if (cur == 0xffffffUL || cur == 0) + { + bad_reads++; + grub_dprintf ("pmtimer", + "pmtimer: 0x%"PRIxGRUB_UINT64_T" bad_reads: %d\n", + cur, bad_reads); + + if (bad_reads == 10) + { + grub_dprintf ("pmtimer", "timer is broken; giving up.\n"); + return 0; + } + } + + if (cur < start) + cur += 0x1000000; + + if (cur >= end) + { + grub_dprintf ("pmtimer", "pmtimer delta is 0x%"PRIxGRUB_UINT64_T"\n", + cur - start); + grub_dprintf ("pmtimer", "tsc delta is 0x%"PRIxGRUB_UINT64_T"\n", + end_tsc - start_tsc); + return end_tsc - start_tsc; + } + + /* + * Check for broken PM timer. 1ms at 10GHz should be 1E+7 TSCs; at + * 250MHz it should be 2.5E5. So if after 4E+7 TSCs on a 10GHz machine, + * we should have seen pmtimer show 4ms of change (i.e. cur =~ start + 14320); + * on a 250MHz machine that should be 160ms (start + 572800). If after + * this a time we still don't have 1ms on pmtimer, then pmtimer is broken. + * + * Likewise, if our code is perfectly efficient and introduces no delays + * whatsoever, on a 10GHz system we should see a TSC delta of 3580 in + * ~3580 iterations. On a 250MHz machine that should be ~900 iterations. + * + * With those factors in mind, there are two limits here. There's a hard + * limit here at 8x our desired pm timer delta. This limit was picked as + * an arbitrarily large value that's still not a lot of time to humans, + * because if we get that far this is either an implausibly fast machine + * or the pmtimer is not running. And there is another limit on a 4 ms TSC + * delta on a 10 GHz clock, without seeing cur converge on our target value. + */ + if ((++num_iter > (grub_uint32_t) num_pm_ticks << 3UL) || end_tsc - start_tsc > 40000000) + { + grub_dprintf ("pmtimer", + "pmtimer delta is 0x%"PRIxGRUB_UINT64_T" (%"PRIxGRUB_UINT32_T" iterations)\n", + cur - start, num_iter); + grub_dprintf ("pmtimer", + "tsc delta is implausible: 0x%"PRIxGRUB_UINT64_T"\n", + end_tsc - start_tsc); + return 0; + } + } +} + +int +grub_tsc_calibrate_from_pmtimer (void) +{ + struct grub_acpi_fadt *fadt; + grub_port_t pmtimer; + grub_uint64_t tsc_diff; + + fadt = grub_acpi_find_fadt (); + if (!fadt) + { + grub_dprintf ("pmtimer", "No FADT found; not using pmtimer.\n"); + return 0; + } + pmtimer = fadt->pmtimer; + if (!pmtimer) + { + grub_dprintf ("pmtimer", "FADT does not specify pmtimer; skipping.\n"); + return 0; + } + + /* It's 3.579545 MHz clock. Wait 1 ms. */ + tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer, 3580); + if (tsc_diff == 0) + return 0; + grub_tsc_rate = grub_divmod64 ((1ULL << 32), tsc_diff, 0); + /* + * Specifically, when the tsc_diff (end_tsc - start_tsc) is greater than (1ULL << 32), + * the result of grub_divmod64() becomes zero, causing grub_tsc_rate to always be zero. + * As a result, grub_tsc_get_time_ms() consistently returns zero, and the GRUB menu + * countdown gets stuck. To resolve this, we return 0 to proceed to the next calibration + * function when grub_tsc_rate is zero. + */ + if (grub_tsc_rate == 0) + return 0; + + return 1; +} diff --git a/grub-core/kern/i386/xen/hypercall.S b/grub-core/kern/i386/xen/hypercall.S new file mode 100644 index 000000000..09d75c3a5 --- /dev/null +++ b/grub-core/kern/i386/xen/hypercall.S @@ -0,0 +1,43 @@ +/* hypercall.S - wrappers for Xen hypercalls */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +FUNCTION(grub_xen_hypercall) + pushl %ebp + movl %esp, %ebp + pushl %esi + pushl %edi + pushl %ebx + + /* call number already in %eax. */ + /* %edx -> %ebx*/ + /* %ecx -> %ecx*/ + movl %edx, %ebx + movl 8(%ebp), %edx + movl 12(%ebp), %esi + movl 16(%ebp), %edi + movl 20(%ebp), %ebp + int $0x82 + popl %ebx + popl %edi + popl %esi + popl %ebp + ret diff --git a/grub-core/kern/i386/xen/pvh.c b/grub-core/kern/i386/xen/pvh.c new file mode 100644 index 000000000..91fbca859 --- /dev/null +++ b/grub-core/kern/i386/xen/pvh.c @@ -0,0 +1,369 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define XEN_MEMORY_MAP_SIZE 128 + +grub_uint64_t grub_rsdp_addr; + +static char hypercall_page[GRUB_XEN_PAGE_SIZE] + __attribute__ ((aligned (GRUB_XEN_PAGE_SIZE))); + +static grub_uint32_t xen_cpuid_base; +static struct start_info grub_xen_start_page; +static struct grub_e820_mmap_entry map[XEN_MEMORY_MAP_SIZE]; +static unsigned int nr_map_entries; + +static void +grub_xen_cons_msg (const char *msg) +{ + const char *c; + + for (c = msg; *c; c++) + grub_outb (*c, XEN_HVM_DEBUGCONS_IOPORT); +} + +static void +grub_xen_panic (const char *msg) +{ + grub_xen_cons_msg (msg); + grub_xen_cons_msg ("System halted!\n"); + + asm volatile ("cli"); + + while (1) + { + asm volatile ("hlt"); + } +} + +static void +grub_xen_cpuid_base (void) +{ + grub_uint32_t base, eax, signature[3]; + + for (base = 0x40000000; base < 0x40010000; base += 0x100) + { + grub_cpuid (base, eax, signature[0], signature[1], signature[2]); + if (!grub_memcmp ("XenVMMXenVMM", signature, 12) && (eax - base) >= 2) + { + xen_cpuid_base = base; + return; + } + } + + grub_xen_panic ("Found no Xen signature!\n"); +} + +static void +grub_xen_setup_hypercall_page (void) +{ + grub_uint32_t msr, addr, eax, ebx, ecx, edx; + + /* Get base address of Xen-specific MSRs. */ + grub_cpuid (xen_cpuid_base + 2, eax, ebx, ecx, edx); + msr = ebx; + addr = (grub_uint32_t) (&hypercall_page); + + /* Specify hypercall page address for Xen. */ + asm volatile ("wrmsr" : : "c" (msr), "a" (addr), "d" (0) : "memory"); +} + +int +grub_xen_hypercall (grub_uint32_t callno, grub_uint32_t a0, + grub_uint32_t a1, grub_uint32_t a2, + grub_uint32_t a3, grub_uint32_t a4, + grub_uint32_t a5 __attribute__ ((unused))) +{ + grub_uint32_t res; + + asm volatile ("call *%[callno]" + : "=a" (res), "+b" (a0), "+c" (a1), "+d" (a2), + "+S" (a3), "+D" (a4) + : [callno] "a" (&hypercall_page[callno * 32]) + : "memory"); + return res; +} + +static grub_uint32_t +grub_xen_get_param (int idx) +{ + struct xen_hvm_param xhv; + int r; + + xhv.domid = DOMID_SELF; + xhv.index = idx; + r = grub_xen_hypercall (__HYPERVISOR_hvm_op, HVMOP_get_param, + (grub_uint32_t) (&xhv), 0, 0, 0, 0); + if (r < 0) + grub_xen_panic ("Could not get parameter from Xen!\n"); + return xhv.value; +} + +static void * +grub_xen_add_physmap (unsigned int space, void *addr) +{ + struct xen_add_to_physmap xatp; + + xatp.domid = DOMID_SELF; + xatp.idx = 0; + xatp.space = space; + xatp.gpfn = (grub_addr_t) addr >> GRUB_XEN_LOG_PAGE_SIZE; + if (grub_xen_hypercall (__HYPERVISOR_memory_op, XENMEM_add_to_physmap, + (grub_uint32_t) (&xatp), 0, 0, 0, 0)) + grub_xen_panic ("Memory_op hypercall failed!\n"); + return addr; +} + +static void +grub_xen_sort_mmap (void) +{ + grub_uint64_t from, to; + unsigned int i; + struct grub_e820_mmap_entry tmp; + + /* Align map entries to page boundaries. */ + for (i = 0; i < nr_map_entries; i++) + { + from = map[i].addr; + to = from + map[i].len; + if (map[i].type == GRUB_MEMORY_AVAILABLE) + { + from = ALIGN_UP (from, GRUB_XEN_PAGE_SIZE); + to = ALIGN_DOWN (to, GRUB_XEN_PAGE_SIZE); + } + else + { + from = ALIGN_DOWN (from, GRUB_XEN_PAGE_SIZE); + to = ALIGN_UP (to, GRUB_XEN_PAGE_SIZE); + } + map[i].addr = from; + map[i].len = to - from; + } + + again: + /* Sort entries by start address. */ + for (i = 1; i < nr_map_entries; i++) + { + if (map[i].addr >= map[i - 1].addr) + continue; + tmp = map[i]; + map[i] = map[i - 1]; + map[i - 1] = tmp; + i = 0; + } + + /* Detect overlapping areas. */ + for (i = 1; i < nr_map_entries; i++) + { + if (map[i].addr >= map[i - 1].addr + map[i - 1].len) + continue; + tmp = map[i - 1]; + map[i - 1].len = map[i].addr - map[i - 1].addr; + if (map[i].addr + map[i].len >= tmp.addr + tmp.len) + continue; + if (nr_map_entries < ARRAY_SIZE (map)) + { + map[nr_map_entries].addr = map[i].addr + map[i].len; + map[nr_map_entries].len = tmp.addr + tmp.len - map[nr_map_entries].addr; + map[nr_map_entries].type = tmp.type; + nr_map_entries++; + goto again; + } + } + + /* Merge adjacent entries. */ + for (i = 1; i < nr_map_entries; i++) + { + if (map[i].type == map[i - 1].type && + map[i].addr == map[i - 1].addr + map[i - 1].len) + { + map[i - 1].len += map[i].len; + map[i] = map[nr_map_entries - 1]; + nr_map_entries--; + goto again; + } + } +} + +static void +grub_xen_get_mmap (void) +{ + struct xen_memory_map memmap; + + memmap.nr_entries = ARRAY_SIZE (map); + set_xen_guest_handle (memmap.buffer, map); + if (grub_xen_hypercall (__HYPERVISOR_memory_op, XENMEM_memory_map, + (grub_uint32_t) (&memmap), 0, 0, 0, 0)) + grub_xen_panic ("Could not get memory map from Xen!\n"); + nr_map_entries = memmap.nr_entries; + + grub_xen_sort_mmap (); +} + +static void +grub_xen_set_mmap (void) +{ + struct xen_foreign_memory_map memmap; + + memmap.domid = DOMID_SELF; + memmap.map.nr_entries = nr_map_entries; + set_xen_guest_handle (memmap.map.buffer, map); + grub_xen_hypercall (__HYPERVISOR_memory_op, XENMEM_set_memory_map, + (grub_uint32_t) (&memmap), 0, 0, 0, 0); +} + +static void +grub_xen_mm_init_regions (void) +{ + grub_uint64_t modend, from, to; + unsigned int i; + + modend = grub_modules_get_end (); + + for (i = 0; i < nr_map_entries; i++) + { + if (map[i].type != GRUB_MEMORY_AVAILABLE) + continue; + from = map[i].addr; + to = from + map[i].len; + if (from < modend) + from = modend; + if (from >= to || from >= (1ULL << 32)) + continue; + if (to > (1ULL << 32)) + to = 1ULL << 32; + grub_mm_init_region ((void *) (grub_addr_t) from, to - from); + } +} + +static grub_uint64_t +grub_xen_find_page (grub_uint64_t start) +{ + unsigned int i, j; + grub_uint64_t last = start; + + /* + * Try to find a e820 map hole below 4G. + * Relies on page-aligned entries (addr and len) and input (start). + */ + + for (i = 0; i < nr_map_entries; i++) + { + if (last > map[i].addr + map[i].len) + continue; + if (last < map[i].addr) + return last; + if ((map[i].addr >> 32) || ((map[i].addr + map[i].len) >> 32)) + break; + last = map[i].addr + map[i].len; + } + if (i == nr_map_entries) + return last; + + /* No hole found, use the highest RAM page below 4G and reserve it. */ + if (nr_map_entries == ARRAY_SIZE (map)) + grub_xen_panic ("Memory map size limit reached!\n"); + for (i = 0, j = 0; i < nr_map_entries; i++) + { + if (map[i].type != GRUB_MEMORY_AVAILABLE) + continue; + if (map[i].addr >> 32) + break; + j = i; + if ((map[i].addr + map[i].len) >> 32) + break; + } + if (map[j].type != GRUB_MEMORY_AVAILABLE) + grub_xen_panic ("No free memory page found!\n"); + if ((map[j].addr + map[j].len) >> 32) + last = (1ULL << 32) - GRUB_XEN_PAGE_SIZE; + else + last = map[j].addr + map[j].len - GRUB_XEN_PAGE_SIZE; + map[nr_map_entries].addr = last; + map[nr_map_entries].len = GRUB_XEN_PAGE_SIZE; + map[nr_map_entries].type = GRUB_MEMORY_RESERVED; + nr_map_entries++; + grub_xen_sort_mmap (); + + return last; +} + +void +grub_xen_setup_pvh (void) +{ + grub_addr_t par; + + grub_xen_cpuid_base (); + grub_xen_setup_hypercall_page (); + grub_xen_get_mmap (); + + /* Setup Xen data. */ + grub_xen_start_page_addr = &grub_xen_start_page; + + par = grub_xen_get_param (HVM_PARAM_CONSOLE_PFN); + grub_xen_start_page_addr->console.domU.mfn = par; + grub_xen_xcons = (void *) (grub_addr_t) (par << GRUB_XEN_LOG_PAGE_SIZE); + par = grub_xen_get_param (HVM_PARAM_CONSOLE_EVTCHN); + grub_xen_start_page_addr->console.domU.evtchn = par; + + par = grub_xen_get_param (HVM_PARAM_STORE_PFN); + grub_xen_start_page_addr->store_mfn = par; + grub_xen_xenstore = (void *) (grub_addr_t) (par << GRUB_XEN_LOG_PAGE_SIZE); + par = grub_xen_get_param (HVM_PARAM_STORE_EVTCHN); + grub_xen_start_page_addr->store_evtchn = par; + + par = grub_xen_find_page (0); + grub_xen_grant_table = grub_xen_add_physmap (XENMAPSPACE_grant_table, + (void *) par); + par = grub_xen_find_page (par + GRUB_XEN_PAGE_SIZE); + grub_xen_shared_info = grub_xen_add_physmap (XENMAPSPACE_shared_info, + (void *) par); + grub_xen_set_mmap (); + + grub_xen_mm_init_regions (); + + grub_rsdp_addr = pvh_start_info->rsdp_paddr; +} + +grub_err_t +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) +{ + unsigned int i; + + for (i = 0; i < nr_map_entries; i++) + { + if (map[i].len && hook (map[i].addr, map[i].len, map[i].type, hook_data)) + break; + } + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/i386/xen/startup.S b/grub-core/kern/i386/xen/startup.S new file mode 100644 index 000000000..fbe8300a7 --- /dev/null +++ b/grub-core/kern/i386/xen/startup.S @@ -0,0 +1,38 @@ +/* startup.S - bootstrap GRUB itself */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + + .file "startup.S" + .text + .globl start, _start + .code32 + +start: +_start: + leal LOCAL(stack_end), %esp + movl %esi, EXT_C(grub_xen_start_page_addr) + + call EXT_C(grub_main) + /* Doesn't return. */ + + .bss + .space (1 << 22) +LOCAL(stack_end): diff --git a/grub-core/kern/i386/xen/startup_pvh.S b/grub-core/kern/i386/xen/startup_pvh.S new file mode 100644 index 000000000..363c31858 --- /dev/null +++ b/grub-core/kern/i386/xen/startup_pvh.S @@ -0,0 +1,81 @@ +/* startup.S - bootstrap GRUB itself */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include + + .file "startup_pvh.S" + .text + .globl start, _start + .code32 + +start: +_start: + cld + lgdt gdtdesc + ljmp $GRUB_MEMORY_MACHINE_PROT_MODE_CSEG, $1f +1: + movl $GRUB_MEMORY_MACHINE_PROT_MODE_DSEG, %eax + mov %eax, %ds + mov %eax, %es + mov %eax, %fs + mov %eax, %gs + mov %eax, %ss + leal LOCAL(stack_end), %esp + + /* Save address of start info structure. */ + mov %ebx, pvh_start_info + call EXT_C(grub_main) + /* Doesn't return. */ + + .p2align 3 +gdt: + .word 0, 0 + .byte 0, 0, 0, 0 + + /* -- code segment -- + * base = 0x00000000, limit = 0xFFFFF (4 KiB Granularity), present + * type = 32bit code execute/read, DPL = 0 + */ + .word 0xFFFF, 0 + .byte 0, 0x9A, 0xCF, 0 + + /* -- data segment -- + * base = 0x00000000, limit 0xFFFFF (4 KiB Granularity), present + * type = 32 bit data read/write, DPL = 0 + */ + .word 0xFFFF, 0 + .byte 0, 0x92, 0xCF, 0 + + .p2align 3 +/* this is the GDT descriptor */ +gdtdesc: + .word 0x17 /* limit */ + .long gdt /* addr */ + + .p2align 2 +/* Saved pointer to start info structure. */ + .globl pvh_start_info +pvh_start_info: + .long 0 + + .bss + .space GRUB_MEMORY_MACHINE_PROT_STACK_SIZE +LOCAL(stack_end): diff --git a/grub-core/kern/i386/xen/tsc.c b/grub-core/kern/i386/xen/tsc.c new file mode 100644 index 000000000..8792b308d --- /dev/null +++ b/grub-core/kern/i386/xen/tsc.c @@ -0,0 +1,40 @@ +/* kern/i386/tsc.c - x86 TSC time source implementation + * Requires Pentium or better x86 CPU that supports the RDTSC instruction. + * This module uses the PIT to calibrate the TSC to + * real time. + * + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +int +grub_tsc_calibrate_from_xen (void) +{ + grub_uint64_t t; + t = grub_xen_shared_info->vcpu_info[0].time.tsc_to_system_mul; + if (grub_xen_shared_info->vcpu_info[0].time.tsc_shift > 0) + t <<= grub_xen_shared_info->vcpu_info[0].time.tsc_shift; + else + t >>= -grub_xen_shared_info->vcpu_info[0].time.tsc_shift; + grub_tsc_rate = grub_divmod64 (t, 1000000, 0); + return 1; +} diff --git a/grub-core/kern/ia64/cache.c b/grub-core/kern/ia64/cache.c new file mode 100644 index 000000000..13efd308f --- /dev/null +++ b/grub-core/kern/ia64/cache.c @@ -0,0 +1,35 @@ +/* init.c - initialize an ia64-based EFI system */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ + /* Cache line length is at least 32. */ + len += (grub_uint64_t)address & 0x1f; + grub_uint64_t a = (grub_uint64_t)address & ~0x1f; + + /* Flush data. */ + for (len = (len + 31) & ~0x1f; len > 0; len -= 0x20, a += 0x20) + asm volatile ("fc.i %0" : : "r" (a)); + /* Sync and serialize. Maybe extra. */ + asm volatile (";; sync.i;; srlz.i;;"); +} diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 7c22b0b06..db59300fe 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -23,6 +23,10 @@ #include #include #include +#include + +#define MASK19 ((1 << 19) - 1) +#define MASK20 ((1 << 20) - 1) /* Check if EHDR is a valid ELF header. */ grub_err_t @@ -41,239 +45,106 @@ grub_arch_dl_check_header (void *ehdr) #pragma GCC diagnostic ignored "-Wcast-align" -#define MASK20 ((1 << 20) - 1) -#define MASK19 ((1 << 19) - 1) - -struct unaligned_uint32 -{ - grub_uint32_t val; -} __attribute__ ((packed)); - -static void -add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value) -{ - struct unaligned_uint32 *p; - switch (addr & 3) - { - case 0: - p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2); - p->val = ((((((p->val >> 2) & MASK20) + value) & MASK20) << 2) - | (p->val & ~(MASK20 << 2))); - break; - case 1: - p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7); - p->val = ((((((p->val >> 3) & MASK20) + value) & MASK20) << 3) - | (p->val & ~(MASK20 << 3))); - break; - case 2: - p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12); - p->val = ((((((p->val >> 4) & MASK20) + value) & MASK20) << 4) - | (p->val & ~(MASK20 << 4))); - break; - } -} - -#define MASKF21 ( ((1 << 23) - 1) & ~((1 << 7) | (1 << 8)) ) - -static grub_uint32_t -add_value_to_slot_21_real (grub_uint32_t a, grub_uint32_t value) -{ - grub_uint32_t high, mid, low, c; - low = (a & 0x00007f); - mid = (a & 0x7fc000) >> 7; - high = (a & 0x003e00) << 7; - c = (low | mid | high) + value; - return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 7) & 0x0003e00); //0x003e00 -} - -static void -add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value) -{ - struct unaligned_uint32 *p; - switch (addr & 3) - { - case 0: - p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2); - p->val = ((add_value_to_slot_21_real (((p->val >> 2) & MASKF21), value) & MASKF21) << 2) | (p->val & ~(MASKF21 << 2)); - break; - case 1: - p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 7); - p->val = ((add_value_to_slot_21_real (((p->val >> 3) & MASKF21), value) & MASKF21) << 3) | (p->val & ~(MASKF21 << 3)); - break; - case 2: - p = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & ~3ULL) + 12); - p->val = ((add_value_to_slot_21_real (((p->val >> 4) & MASKF21), value) & MASKF21) << 4) | (p->val & ~(MASKF21 << 4)); - break; - } -} - -static const grub_uint8_t nopm[5] = - { - /* [MLX] nop.m 0x0 */ - 0x05, 0x00, 0x00, 0x00, 0x01 - }; - -static const grub_uint8_t jump[0x20] = - { - /* ld8 r16=[r15],8 */ - 0x02, 0x80, 0x20, 0x1e, 0x18, 0x14, - /* mov r14=r1;; */ - 0xe0, 0x00, 0x04, 0x00, 0x42, 0x00, - /* nop.i 0x0 */ - 0x00, 0x00, 0x04, 0x00, - /* ld8 r1=[r15] */ - 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, - /* mov b6=r16 */ - 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, - /* br.few b6;; */ - 0x60, 0x00, 0x80, 0x00 - }; - -struct ia64_trampoline -{ - /* nop.m */ - grub_uint8_t nop[5]; - /* movl r15 = addr*/ - grub_uint8_t addr_hi[6]; - grub_uint8_t e0; - grub_uint8_t addr_lo[4]; - grub_uint8_t jump[0x20]; -}; - -static void -make_trampoline (struct ia64_trampoline *tr, grub_uint64_t addr) -{ - COMPILE_TIME_ASSERT (sizeof (struct ia64_trampoline) - == GRUB_IA64_DL_TRAMP_SIZE); - grub_memcpy (tr->nop, nopm, sizeof (tr->nop)); - tr->addr_hi[0] = ((addr & 0xc00000) >> 16); - tr->addr_hi[1] = (addr >> 24) & 0xff; - tr->addr_hi[2] = (addr >> 32) & 0xff; - tr->addr_hi[3] = (addr >> 40) & 0xff; - tr->addr_hi[4] = (addr >> 48) & 0xff; - tr->addr_hi[5] = (addr >> 56) & 0xff; - tr->e0 = 0xe0; - tr->addr_lo[0] = ((addr & 0x000f) << 4) | 0x01; - tr->addr_lo[1] = (((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11) - | ((addr & 0x200000) >> 17)); - tr->addr_lo[2] = ((addr & 0x1f80) >> 5) | ((addr & 0x180000) >> 19); - tr->addr_lo[3] = ((addr & 0xe000) >> 13) | 0x60; - grub_memcpy (tr->jump, jump, sizeof (tr->jump)); -} - /* Relocate symbols. */ grub_err_t -grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg) { - Elf_Ehdr *e = ehdr; - Elf_Shdr *s; - Elf_Word entsize; - unsigned i; - grub_uint64_t *gp, *gpptr; - struct ia64_trampoline *tr; + Elf_Rela *rel, *max; - gp = (grub_uint64_t *) mod->base; - gpptr = (grub_uint64_t *) mod->got; - tr = mod->tramp; + for (rel = (Elf_Rela *) ((char *) ehdr + s->sh_offset), + max = (Elf_Rela *) ((char *) rel + s->sh_size); + rel < max; + rel = (Elf_Rela *) ((char *) rel + s->sh_entsize)) + { + grub_addr_t addr; + Elf_Sym *sym; + grub_uint64_t value; - /* Find a symbol table. */ - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_SYMTAB) - break; + if (seg->size < (rel->r_offset & ~3)) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); - if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); + addr = (grub_addr_t) seg->addr + rel->r_offset; + sym = (Elf_Sym *) ((char *) mod->symtab + + mod->symsize * ELF_R_SYM (rel->r_info)); - entsize = s->sh_entsize; + /* On the PPC the value does not have an explicit + addend, add it. */ + value = sym->st_value + rel->r_addend; - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_RELA) - { - grub_dl_segment_t seg; - - /* Find the target segment. */ - for (seg = mod->segment; seg; seg = seg->next) - if (seg->section == s->sh_info) - break; - - if (seg) + switch (ELF_R_TYPE (rel->r_info)) + { + case R_IA64_PCREL21B: { - Elf_Rela *rel, *max; - - for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), - max = rel + s->sh_size / s->sh_entsize; - rel < max; - rel++) + grub_int64_t noff; + if (ELF_ST_TYPE (sym->st_info) == STT_FUNC) { - grub_addr_t addr; - Elf_Sym *sym; - grub_uint64_t value; - - if (seg->size < (rel->r_offset & ~3)) - return grub_error (GRUB_ERR_BAD_MODULE, - "reloc offset is out of the segment"); - - addr = (grub_addr_t) seg->addr + rel->r_offset; - sym = (Elf_Sym *) ((char *) mod->symtab - + entsize * ELF_R_SYM (rel->r_info)); - - /* On the PPC the value does not have an explicit - addend, add it. */ - value = sym->st_value + rel->r_addend; - - switch (ELF_R_TYPE (rel->r_info)) - { - case R_IA64_PCREL21B: - { - grub_uint64_t noff; - make_trampoline (tr, value); - noff = ((char *) tr - (char *) (addr & ~3)) >> 4; - tr++; - if (noff & ~MASK19) - return grub_error (GRUB_ERR_BAD_OS, - "trampoline offset too big (%lx)", noff); - add_value_to_slot_20b (addr, noff); - } - break; - case R_IA64_SEGREL64LSB: - *(grub_uint64_t *) addr += value - (grub_addr_t) seg->addr; - break; - case R_IA64_FPTR64LSB: - case R_IA64_DIR64LSB: - *(grub_uint64_t *) addr += value; - break; - case R_IA64_PCREL64LSB: - *(grub_uint64_t *) addr += value - addr; - break; - case R_IA64_GPREL22: - add_value_to_slot_21 (addr, value - (grub_addr_t) gp); - break; - - case R_IA64_LTOFF22X: - case R_IA64_LTOFF22: - if (ELF_ST_TYPE (sym->st_info) == STT_FUNC) - value = *(grub_uint64_t *) sym->st_value + rel->r_addend; - case R_IA64_LTOFF_FPTR22: - *gpptr = value; - add_value_to_slot_21 (addr, (grub_addr_t) gpptr - (grub_addr_t) gp); - gpptr++; - break; - - /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */ - case R_IA64_LDXMOV: - break; - default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("relocation 0x%x is not implemented yet"), - ELF_R_TYPE (rel->r_info)); - } + struct grub_ia64_trampoline *tr = mod->trampptr; + grub_ia64_make_trampoline (tr, value); + noff = ((char *) tr - (char *) (addr & ~3)) >> 4; + mod->trampptr = tr + 1; } - } - } + else + noff = ((char *) value - (char *) (addr & ~3)) >> 4; + if ((noff & ~MASK19) && ((-noff) & ~MASK19)) + return grub_error (GRUB_ERR_BAD_MODULE, + "jump offset too big (%lx)", noff); + grub_ia64_add_value_to_slot_20b (addr, noff); + } + break; + case R_IA64_SEGREL64LSB: + *(grub_uint64_t *) addr += value - (grub_addr_t) seg->addr; + break; + case R_IA64_FPTR64LSB: + case R_IA64_DIR64LSB: + *(grub_uint64_t *) addr += value; + break; + case R_IA64_PCREL64LSB: + *(grub_uint64_t *) addr += value - addr; + break; + case R_IA64_GPREL64I: + grub_ia64_set_immu64 (addr, value - (grub_addr_t) mod->base); + break; + case R_IA64_GPREL22: + if ((value - (grub_addr_t) mod->base) & ~MASK20) + return grub_error (GRUB_ERR_BAD_MODULE, + "gprel offset too big (%lx)", + value - (grub_addr_t) mod->base); + grub_ia64_add_value_to_slot_21 (addr, value - (grub_addr_t) mod->base); + break; + + case R_IA64_LTOFF22X: + case R_IA64_LTOFF22: + if (ELF_ST_TYPE (sym->st_info) == STT_FUNC) + value = *(grub_uint64_t *) sym->st_value + rel->r_addend; + /* Fallthrough. */ + case R_IA64_LTOFF_FPTR22: + { + grub_uint64_t *gpptr = mod->gotptr; + *gpptr = value; + if (((grub_addr_t) gpptr - (grub_addr_t) mod->base) & ~MASK20) + return grub_error (GRUB_ERR_BAD_MODULE, + "gprel offset too big (%lx)", + (grub_addr_t) gpptr - (grub_addr_t) mod->base); + grub_ia64_add_value_to_slot_21 (addr, (grub_addr_t) gpptr - (grub_addr_t) mod->base); + mod->gotptr = gpptr + 1; + break; + } + /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */ + case R_IA64_LDXMOV: + break; + default: + { + char rel_info[17]; /* log16(2^64) = 16, plus NUL. */ + + grub_snprintf (rel_info, sizeof (rel_info) - 1, "%" PRIxGRUB_UINT64_T, + ELF_R_TYPE (rel->r_info)); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%s is not implemented yet"), rel_info); + } + } + } return GRUB_ERR_NONE; } diff --git a/grub-core/kern/ia64/dl_helper.c b/grub-core/kern/ia64/dl_helper.c index 9394e32e2..05a0a68db 100644 --- a/grub-core/kern/ia64/dl_helper.c +++ b/grub-core/kern/ia64/dl_helper.c @@ -22,39 +22,206 @@ #include #include #include +#include +#include #pragma GCC diagnostic ignored "-Wcast-align" +#define MASK20 ((1 << 20) - 1) +#define MASK3 (~(grub_addr_t) 3) + void +grub_ia64_set_immu64 (grub_addr_t addr, grub_uint64_t val) +{ + /* Copied from binutils. */ + grub_uint64_t *ptr = ((grub_uint64_t *) (addr & MASK3)); + grub_uint64_t t0, t1; + + t0 = grub_le_to_cpu64 (ptr[0]); + t1 = grub_le_to_cpu64 (ptr[1]); + + /* tmpl/s: bits 0.. 5 in t0 + slot 0: bits 5..45 in t0 + slot 1: bits 46..63 in t0, bits 0..22 in t1 + slot 2: bits 23..63 in t1 */ + + /* First, clear the bits that form the 64 bit constant. */ + t0 &= ~(0x3ffffLL << 46); + t1 &= ~(0x7fffffLL + | (( (0x07fLL << 13) | (0x1ffLL << 27) + | (0x01fLL << 22) | (0x001LL << 21) + | (0x001LL << 36)) << 23)); + + t0 |= ((val >> 22) & 0x03ffffLL) << 46; /* 18 lsbs of imm41 */ + t1 |= ((val >> 40) & 0x7fffffLL) << 0; /* 23 msbs of imm41 */ + t1 |= ( (((val >> 0) & 0x07f) << 13) /* imm7b */ + | (((val >> 7) & 0x1ff) << 27) /* imm9d */ + | (((val >> 16) & 0x01f) << 22) /* imm5c */ + | (((val >> 21) & 0x001) << 21) /* ic */ + | (((val >> 63) & 0x001) << 36)) << 23; /* i */ + + ptr[0] = t0; + ptr[1] = t1; +} + +void +grub_ia64_add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value) +{ + grub_uint32_t val; + switch (addr & 3) + { + case 0: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 2))); + val = (((((val & MASK20) + value) & MASK20) << 2) + | (val & ~(MASK20 << 2))); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 2), + grub_cpu_to_le32 (val)); + break; + case 1: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 7))); + val = ((((((val >> 3) & MASK20) + value) & MASK20) << 3) + | (val & ~(MASK20 << 3))); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 7), + grub_cpu_to_le32 (val)); + break; + case 2: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 12))); + val = ((((((val >> 4) & MASK20) + value) & MASK20) << 4) + | (val & ~(MASK20 << 4))); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 12), + grub_cpu_to_le32 (val)); + break; + } +} + +#define MASKF21 ( ((1 << 23) - 1) & ~((1 << 7) | (1 << 8)) ) + +static grub_uint32_t +add_value_to_slot_21_real (grub_uint32_t a, grub_uint32_t value) +{ + grub_uint32_t high, mid, low, c; + low = (a & 0x00007f); + mid = (a & 0x7fc000) >> 7; + high = (a & 0x003e00) << 7; + c = (low | mid | high) + value; + return (c & 0x7f) | ((c << 7) & 0x7fc000) | ((c >> 7) & 0x0003e00); //0x003e00 +} + +void +grub_ia64_add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value) +{ + grub_uint32_t val; + switch (addr & 3) + { + case 0: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 2))); + val = ((add_value_to_slot_21_real (((val >> 2) & MASKF21), value) + & MASKF21) << 2) | (val & ~(MASKF21 << 2)); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 2), + grub_cpu_to_le32 (val)); + break; + case 1: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 7))); + val = ((add_value_to_slot_21_real (((val >> 3) & MASKF21), value) + & MASKF21) << 3) | (val & ~(MASKF21 << 3)); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 7), + grub_cpu_to_le32 (val)); + break; + case 2: + val = grub_le_to_cpu32 (grub_get_unaligned32 (((grub_uint8_t *) + (addr & MASK3) + 12))); + val = ((add_value_to_slot_21_real (((val >> 4) & MASKF21), value) + & MASKF21) << 4) | (val & ~(MASKF21 << 4)); + grub_set_unaligned32 (((grub_uint8_t *) (addr & MASK3) + 12), + grub_cpu_to_le32 (val)); + break; + } +} + +static const grub_uint8_t nopm[5] = + { + /* [MLX] nop.m 0x0 */ + 0x05, 0x00, 0x00, 0x00, 0x01 + }; + +#ifdef GRUB_UTIL +static grub_uint8_t jump[0x20] = + { + /* [MMI] add r15=r15,r1;; */ + 0x0b, 0x78, 0x3c, 0x02, 0x00, 0x20, + /* ld8 r16=[r15],8 */ + 0x00, 0x41, 0x3c, 0x30, 0x28, 0xc0, + /* mov r14=r1;; */ + 0x01, 0x08, 0x00, 0x84, + /* [MIB] ld8 r1=[r15] */ + 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, + /* mov b6=r16 */ + 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, + /* br.few b6;; */ + 0x60, 0x00, 0x80, 0x00 + }; +#else +static const grub_uint8_t jump[0x20] = + { + /* ld8 r16=[r15],8 */ + 0x02, 0x80, 0x20, 0x1e, 0x18, 0x14, + /* mov r14=r1;; */ + 0xe0, 0x00, 0x04, 0x00, 0x42, 0x00, + /* nop.i 0x0 */ + 0x00, 0x00, 0x04, 0x00, + /* ld8 r1=[r15] */ + 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, + /* mov b6=r16 */ + 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, + /* br.few b6;; */ + 0x60, 0x00, 0x80, 0x00 + }; +#endif + +void +grub_ia64_make_trampoline (struct grub_ia64_trampoline *tr, grub_uint64_t addr) +{ + grub_memcpy (tr->nop, nopm, sizeof (tr->nop)); + tr->addr_hi[0] = ((addr & 0xc00000) >> 16); + tr->addr_hi[1] = (addr >> 24) & 0xff; + tr->addr_hi[2] = (addr >> 32) & 0xff; + tr->addr_hi[3] = (addr >> 40) & 0xff; + tr->addr_hi[4] = (addr >> 48) & 0xff; + tr->addr_hi[5] = (addr >> 56) & 0xff; + tr->e0 = 0xe0; + tr->addr_lo[0] = ((addr & 0x000f) << 4) | 0x01; + tr->addr_lo[1] = (((addr & 0x0070) >> 4) | ((addr & 0x070000) >> 11) + | ((addr & 0x200000) >> 17)); + tr->addr_lo[2] = ((addr & 0x1f80) >> 5) | ((addr & 0x180000) >> 19); + tr->addr_lo[3] = ((addr & 0xe000) >> 13) | 0x60; + grub_memcpy (tr->jump, jump, sizeof (tr->jump)); +} + +grub_err_t grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got) { const Elf64_Ehdr *e = ehdr; - grub_size_t cntt = 0, cntg = 0;; + grub_size_t cntt = 0, cntg = 0; const Elf64_Shdr *s; unsigned i; - /* Find a symbol table. */ - for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); + for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu64 (e->e_shoff)); i < grub_le_to_cpu16 (e->e_shnum); i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) - if (grub_le_to_cpu32 (s->sh_type) == SHT_SYMTAB) - break; - - if (i == grub_le_to_cpu16 (e->e_shnum)) - return; - - for (i = 0, s = (Elf64_Shdr *) ((char *) e + grub_le_to_cpu32 (e->e_shoff)); - i < grub_le_to_cpu16 (e->e_shnum); - i++, s = (Elf64_Shdr *) ((char *) s + grub_le_to_cpu16 (e->e_shentsize))) - if (grub_le_to_cpu32 (s->sh_type) == SHT_RELA) + if (s->sh_type == grub_cpu_to_le32_compile_time (SHT_RELA)) { - Elf64_Rela *rel, *max; + const Elf64_Rela *rel, *max; - for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu32 (s->sh_offset)), - max = rel + grub_le_to_cpu32 (s->sh_size) / grub_le_to_cpu16 (s->sh_entsize); - rel < max; rel++) - switch (ELF64_R_TYPE (grub_le_to_cpu32 (rel->r_info))) + for (rel = (Elf64_Rela *) ((char *) e + grub_le_to_cpu64 (s->sh_offset)), + max = (const Elf64_Rela *) ((char *) rel + grub_le_to_cpu64 (s->sh_size)); + rel < max; rel = (const Elf64_Rela *) ((char *) rel + grub_le_to_cpu64 (s->sh_entsize))) + switch (ELF64_R_TYPE (grub_le_to_cpu64 (rel->r_info))) { case R_IA64_PCREL21B: cntt++; @@ -66,7 +233,9 @@ grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, break; } } - *tramp = cntt; - *got = cntg; + *tramp = cntt * sizeof (struct grub_ia64_trampoline); + *got = cntg * sizeof (grub_uint64_t); + + return GRUB_ERR_NONE; } diff --git a/grub-core/kern/ia64/efi/init.c b/grub-core/kern/ia64/efi/init.c index 7fa6fbf71..f8de85398 100644 --- a/grub-core/kern/ia64/efi/init.c +++ b/grub-core/kern/ia64/efi/init.c @@ -23,9 +23,9 @@ #include #include #include -#include #include #include +#include static grub_uint64_t divisor = 1; @@ -51,16 +51,16 @@ grub_machine_init (void) grub_efi_uintn_t idx; grub_efi_init (); - efi_call_5 (grub_efi_system_table->boot_services->create_event, - GRUB_EFI_EVT_TIMER, GRUB_EFI_TPL_CALLBACK, 0, 0, &event); + grub_efi_system_table->boot_services->create_event (GRUB_EFI_EVT_TIMER, + GRUB_EFI_TPL_CALLBACK, + 0, 0, &event); before = get_itc (); - efi_call_3 (grub_efi_system_table->boot_services->set_timer, event, - GRUB_EFI_TIMER_RELATIVE, 200000); - efi_call_3 (grub_efi_system_table->boot_services->wait_for_event, 1, - &event, &idx); + grub_efi_system_table->boot_services->set_timer (event, GRUB_EFI_TIMER_RELATIVE, + 200000); + grub_efi_system_table->boot_services->wait_for_event (1, &event, &idx); after = get_itc (); - efi_call_1 (grub_efi_system_table->boot_services->close_event, event); + grub_efi_system_table->boot_services->close_event (event); divisor = (after - before + 5) / 20; if (divisor == 0) divisor = 800000; @@ -68,20 +68,13 @@ grub_machine_init (void) } void -grub_machine_fini (void) +grub_machine_fini (int flags) { + if (!(flags & GRUB_LOADER_FLAG_NORETURN)) + return; + grub_efi_fini (); -} -void -grub_arch_sync_caches (void *address, grub_size_t len) -{ - /* Cache line length is at least 32. */ - grub_uint64_t a = (grub_uint64_t)address & ~0x1f; - - /* Flush data. */ - for (len = (len + 31) & ~0x1f; len > 0; len -= 0x20, a += 0x20) - asm volatile ("fc.i %0" : : "r" (a)); - /* Sync and serialize. Maybe extra. */ - asm volatile (";; sync.i;; srlz.i;;"); + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY)) + grub_efi_memory_fini (); } diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c index dd04d3976..e74de3248 100644 --- a/grub-core/kern/ieee1275/cmain.c +++ b/grub-core/kern/ieee1275/cmain.c @@ -22,7 +22,7 @@ #include #include -int (*grub_ieee1275_entry_fn) (void *); +int (*grub_ieee1275_entry_fn) (void *) GRUB_IEEE1275_ENTRY_FN_ATTRIBUTE; grub_ieee1275_phandle_t grub_ieee1275_chosen; grub_ieee1275_ihandle_t grub_ieee1275_mmu; @@ -43,16 +43,12 @@ grub_ieee1275_set_flag (enum grub_ieee1275_flag flag) grub_ieee1275_flags |= (1 << flag); } -#define SF "SmartFirmware(tm)" -#define OHW "PPC Open Hack'Ware" - static void grub_ieee1275_find_options (void) { grub_ieee1275_phandle_t root; grub_ieee1275_phandle_t options; grub_ieee1275_phandle_t openprom; - grub_ieee1275_phandle_t bootrom; int rc; grub_uint32_t realmode = 0; char tmp[256]; @@ -76,7 +72,8 @@ grub_ieee1275_find_options (void) rc = grub_ieee1275_get_property (openprom, "CodeGen-copyright", tmp, sizeof (tmp), 0); - if (rc >= 0 && !grub_strncmp (tmp, SF, sizeof (SF) - 1)) + if (rc >= 0 && !grub_strncmp (tmp, "SmartFirmware(tm)", + sizeof ("SmartFirmware(tm)") - 1)) is_smartfirmware = 1; rc = grub_ieee1275_get_property (root, "architecture", @@ -86,8 +83,10 @@ grub_ieee1275_find_options (void) rc = grub_ieee1275_get_property (root, "model", tmp, sizeof (tmp), 0); - if (rc >= 0 && !grub_strcmp (tmp, "Emulated PC")) + if (rc >= 0 && (!grub_strcmp (tmp, "Emulated PC") + || !grub_strcmp (tmp, "IBM pSeries (emulated by qemu)"))) { is_qemu = 1; + } if (rc >= 0 && grub_strncmp (tmp, "IBM", 3) == 0) grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_TREE_SCANNING_FOR_DISKS); @@ -108,6 +107,9 @@ grub_ieee1275_find_options (void) if (rc >= 0) { char *ptr; + + if (grub_strncmp (tmp, "sun4v", 5) == 0) + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_RAW_DEVNAMES); for (ptr = tmp; ptr - tmp < actual; ptr += grub_strlen (ptr) + 1) { if (grub_memcmp (ptr, "MacRISC", sizeof ("MacRISC") - 1) == 0 @@ -117,9 +119,18 @@ grub_ieee1275_find_options (void) grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS); grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_OFNET_SUFFIX); grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_VIRT_TO_REAL_BROKEN); + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CURSORONOFF_ANSI_BROKEN); break; } } + +#if defined(__powerpc__) + if (grub_strncmp (tmp, "IBM,", 4) == 0) + { + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY); + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_POWER_VM); + } +#endif } if (is_smartfirmware) @@ -185,25 +196,12 @@ grub_ieee1275_find_options (void) grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM); grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF); - } - - if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom)) - { - rc = grub_ieee1275_get_property (bootrom, "model", tmp, sizeof (tmp), 0); - if (rc >= 0 && !grub_strncmp (tmp, OHW, sizeof (OHW) - 1)) - { - grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_BROKEN_OUTPUT); - grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS); - grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET); - grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM); - grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_ANSI); - } +#if defined(__powerpc__) + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_POWER_KVM); +#endif } } -#undef SF -#undef OHW - void grub_ieee1275_init (void) { diff --git a/grub-core/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c index 98217029f..36ca2dbfc 100644 --- a/grub-core/kern/ieee1275/ieee1275.c +++ b/grub-core/kern/ieee1275/ieee1275.c @@ -19,6 +19,7 @@ #include #include +#include #define IEEE1275_PHANDLE_INVALID ((grub_ieee1275_cell_t) -1) #define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_cell_t) 0) @@ -305,7 +306,7 @@ grub_ieee1275_seek (grub_ieee1275_ihandle_t ihandle, grub_disk_addr_t pos, args.pos_lo = pos; #else args.pos_hi = (grub_ieee1275_cell_t) (pos >> (8 * GRUB_IEEE1275_CELL_SIZEOF)); - args.pos_lo = (grub_ieee1275_cell_t) + args.pos_lo = (grub_ieee1275_cell_t) (pos & ((1ULL << (8 * GRUB_IEEE1275_CELL_SIZEOF)) - 1)); #endif @@ -397,9 +398,6 @@ grub_ieee1275_interpret (const char *command, grub_ieee1275_cell_t *catch) } args; - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET)) - return -1; - INIT_IEEE1275_COMMON (&args.common, "interpret", 1, 1); args.command = (grub_ieee1275_cell_t) command; @@ -482,6 +480,91 @@ grub_ieee1275_close (grub_ieee1275_ihandle_t ihandle) return 0; } +int +grub_ieee1275_decode_unit4 (grub_ieee1275_ihandle_t ihandle, + void *addr, grub_size_t size, + grub_uint32_t *phy_lo, grub_uint32_t *phy_hi, + grub_uint32_t *lun_lo, grub_uint32_t *lun_hi) +{ + struct decode_args + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t size; + grub_ieee1275_cell_t addr; + grub_ieee1275_cell_t catch_result; + grub_ieee1275_cell_t tgt_h; + grub_ieee1275_cell_t tgt_l; + grub_ieee1275_cell_t lun_h; + grub_ieee1275_cell_t lun_l; + } + args; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 5); + args.method = (grub_ieee1275_cell_t) "decode-unit"; + args.ihandle = ihandle; + args.size = size; + args.addr = (grub_ieee1275_cell_t) addr; + args.catch_result = 1; + + if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "decode-unit failed\n"); + return -1; + } + + *phy_lo = args.tgt_l; + *phy_hi = args.tgt_h; + *lun_lo = args.lun_l; + *lun_hi = args.lun_h; + return 0; +} + +char * +grub_ieee1275_encode_uint4 (grub_ieee1275_ihandle_t ihandle, + grub_uint32_t phy_lo, grub_uint32_t phy_hi, + grub_uint32_t lun_lo, grub_uint32_t lun_hi, + grub_size_t *size) +{ + char *addr; + struct encode_args + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t tgt_h; + grub_ieee1275_cell_t tgt_l; + grub_ieee1275_cell_t lun_h; + grub_ieee1275_cell_t lun_l; + grub_ieee1275_cell_t catch_result; + grub_ieee1275_cell_t size; + grub_ieee1275_cell_t addr; + } + args; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 3); + args.method = (grub_ieee1275_cell_t) "encode-unit"; + args.ihandle = ihandle; + + args.tgt_l = phy_lo; + args.tgt_h = phy_hi; + args.lun_l = lun_lo; + args.lun_h = lun_hi; + args.catch_result = 1; + + if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "encode-unit failed\n"); + return 0; + } + + addr = (void *)args.addr; + *size = args.size; + addr = grub_strdup ((char *)args.addr); + return addr; +} + int grub_ieee1275_claim (grub_addr_t addr, grub_size_t size, unsigned int align, grub_addr_t *result) @@ -507,6 +590,9 @@ grub_ieee1275_claim (grub_addr_t addr, grub_size_t size, unsigned int align, *result = args.base; if (args.base == IEEE1275_CELL_INVALID) return -1; + grub_dprintf ("mmap", "CLAIMED: 0x%" PRIxGRUB_IEEE1275_CELL_T " (%" + PRIuGRUB_IEEE1275_CELL_T " MiB) size: %" PRIuGRUB_SIZE " MiB\n", + args.base, args.base >> 20, ALIGN_UP (size, 1 << 20) >> 20); return 0; } @@ -607,3 +693,117 @@ grub_ieee1275_milliseconds (grub_uint32_t *msecs) *msecs = args.msecs; return 0; } + +int +grub_ieee1275_set_address (grub_ieee1275_ihandle_t ihandle, + grub_uint32_t target, grub_uint32_t lun) +{ + struct set_address + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t tgt; + grub_ieee1275_cell_t lun; + grub_ieee1275_cell_t catch_result; + } + args; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 1); + + /* + * IEEE 1275-1994 Standard for Boot (Initialization Configuration) + * Firmware: Core Requirements and Practices + * E.3.2.2 Bus-specific methods for bus nodes + * + * A package implementing the scsi-2 device type shall implement the + * following bus-specific method: + * + * set-address ( unit# target# -- ) + * Sets the SCSI target number (0x0..0xf) and unit number (0..7) to which + * subsequent commands apply. + */ + args.method = (grub_ieee1275_cell_t) "set-address"; + args.ihandle = ihandle; + args.tgt = target; + args.lun = lun; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return -1; + + return args.catch_result; +} + +int +grub_ieee1275_no_data_command (grub_ieee1275_ihandle_t ihandle, + const void *cmd_addr, grub_ssize_t *result) +{ + struct set_address + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t cmd_addr; + grub_ieee1275_cell_t error; + grub_ieee1275_cell_t catch_result; + } + args; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); + + /* + * IEEE 1275-1994 Standard for Boot (Initialization Configuration) + * Firmware: Core Requirements and Practices + * + * E.3.2.2 Bus-specific methods for bus nodes + * + * A package implementing the scsi-2 device type shall implement the + * following bus-specific method: + * + * no-data-command ( cmd-addr -- error? ) + * Executes a simple SCSI command, automatically retrying under + * certain conditions. cmd-addr is the address of a 6-byte command buffer + * containing an SCSI command that does not have a data transfer phase. + * Executes the command, retrying indefinitely with the same retry criteria + * as retry-command. + * + * error? is nonzero if an error occurred, zero otherwise. + * NOTE no-data-command is a convenience function. It provides + * no capabilities that are not present in retry-command, but for + * those commands that meet its restrictions, it is easier to use. + */ + args.method = (grub_ieee1275_cell_t) "no-data-command"; + args.ihandle = ihandle; + args.cmd_addr = (grub_ieee1275_cell_t) cmd_addr; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return -1; + + if (result) + *result = args.error; + + return args.catch_result; +} + +int +grub_ieee1275_get_block_size (grub_ieee1275_ihandle_t ihandle) +{ + struct size_args_ieee1275 + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t result; + grub_ieee1275_cell_t size; + } args; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 2); + args.method = (grub_ieee1275_cell_t) "block-size"; + args.ihandle = ihandle; + args.result = 1; + + if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result)) + return 0; + + return args.size; +} diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 7d03a8aac..a5586f85b 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -17,6 +17,8 @@ * along with GRUB. If not, see . */ +#include /* offsetof() */ + #include #include #include @@ -30,23 +32,43 @@ #include #include #include +#ifdef __sparc__ +#include +#endif #include #include #include #include +#include +#ifdef __i386__ +#include +#endif #ifdef __sparc__ #include #endif +#if defined(__powerpc__) || defined(__i386__) +#include +#endif -/* The minimal heap size we can live with. */ -#define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) - -/* The maximum heap size we're going to claim */ +/* The maximum heap size we're going to claim at boot. Not used by sparc. */ +#ifdef __i386__ +#define HEAP_MAX_SIZE (unsigned long) (64 * 1024 * 1024) +#else /* __powerpc__ */ #define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024) +#endif -/* If possible, we will avoid claiming heap above this address, because it - seems to cause relocation problems with OSes that link at 4 MiB */ -#define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024) +/* RMO max. address at 768 MB */ +#define RMO_ADDR_MAX (grub_uint64_t) (768 * 1024 * 1024) + +/* + * The amount of OF space we will not claim here so as to leave space for + * the loader and linux to service early allocations. + * + * In 2021, Daniel Axtens claims that we should leave at least 128MB to + * ensure we can load a stock kernel and initrd on a pseries guest with + * a 512MB real memory area under PowerVM. + */ +#define RUNTIME_MIN_SPACE (128UL * 1024 * 1024) extern char _start[]; extern char _end[]; @@ -55,6 +77,52 @@ extern char _end[]; grub_addr_t grub_ieee1275_original_stack; #endif +/* Options vector5 properties. */ + +#define LPAR 0x80 +#define SPLPAR 0x40 +#define DYN_RCON_MEM 0x20 +#define LARGE_PAGES 0x10 +#define DONATE_DCPU_CLS 0x02 +#define PCI_EXP 0x01 +#define BYTE2 (LPAR | SPLPAR | DYN_RCON_MEM | LARGE_PAGES | DONATE_DCPU_CLS | PCI_EXP) + +#define CMOC 0x80 +#define EXT_CMO 0x40 +#define CMO (CMOC | EXT_CMO) + +#define ASSOC_REF 0x80 +#define AFFINITY 0x40 +#define NUMA 0x20 +#define ASSOCIATIVITY (ASSOC_REF | AFFINITY | NUMA) + +#define HOTPLUG_INTRPT 0x04 +#define HPT_RESIZE 0x01 +#define BIN_OPTS (HOTPLUG_INTRPT | HPT_RESIZE) + +#define MAX_CPU 256 + +#define PFO_HWRNG 0x80000000 +#define PFO_HW_COMP 0x40000000 +#define PFO_ENCRYPT 0x20000000 +#define PLATFORM_FACILITIES (PFO_HWRNG | PFO_HW_COMP | PFO_ENCRYPT) + +#define SUB_PROCESSORS 1 + +#define DY_MEM_V2 0x80 +#define DRC_INFO 0x40 +#define BYTE22 (DY_MEM_V2 | DRC_INFO) + +/* For ibm,arch-vec-5-platform-support. */ +#define XIVE_INDEX 0x17 +#define MMU_INDEX 0x18 +#define RADIX_GTSE_INDEX 0x1a +#define RADIX_ENABLED 0x40 +#define XIVE_ENABLED 0x40 +#define HASH_ENABLED 0x00 +#define MAX_SUPPORTED 0xC0 +#define RADIX_GTSE_ENABLED 0x40 + void grub_exit (void) { @@ -76,23 +144,18 @@ grub_translate_ieee1275_path (char *filepath) } } -void (*grub_ieee1275_net_config) (const char *dev, - char **device, - char **path); +void (*grub_ieee1275_net_config) (const char *dev, char **device, char **path, + char *bootpath); void grub_machine_get_bootlocation (char **device, char **path) { - char bootpath[64]; /* XXX check length */ + char *bootpath; char *filename; char *type; - - if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath, - sizeof (bootpath), 0)) - { - /* Should never happen. */ - grub_printf ("/chosen/bootpath property missing!\n"); - return; - } + + bootpath = grub_ieee1275_get_boot_dev (); + if (! bootpath) + return; /* Transform an OF device path to a GRUB path. */ @@ -103,6 +166,8 @@ grub_machine_get_bootlocation (char **device, char **path) char *ptr; dev = grub_ieee1275_get_aliasdevname (bootpath); canon = grub_ieee1275_canonicalise_devname (dev); + if (! canon) + return; ptr = canon + grub_strlen (canon) - 1; while (ptr > canon && (*ptr == ',' || *ptr == ':')) ptr--; @@ -110,7 +175,7 @@ grub_machine_get_bootlocation (char **device, char **path) *ptr = 0; if (grub_ieee1275_net_config) - grub_ieee1275_net_config (canon, device, path); + grub_ieee1275_net_config (canon, device, path, bootpath); grub_free (dev); grub_free (canon); } @@ -132,85 +197,761 @@ grub_machine_get_bootlocation (char **device, char **path) *path = filename; } } + grub_free (bootpath); } /* Claim some available memory in the first /memory node. */ #ifdef __sparc__ -static void +static void grub_claim_heap (void) { grub_mm_init_region ((void *) (grub_modules_get_end () + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000); } #else -static void +/* Helpers for mm on powerpc. */ + +/* ibm,kernel-dump data structures */ +struct kd_section +{ + grub_uint32_t flags; + grub_uint16_t src_datatype; +#define KD_SRC_DATATYPE_REAL_MODE_REGION 0x0011 + grub_uint16_t error_flags; + grub_uint64_t src_address; + grub_uint64_t num_bytes; + grub_uint64_t act_bytes; + grub_uint64_t dst_address; +} GRUB_PACKED; + +#define MAX_KD_SECTIONS 10 + +struct kernel_dump +{ + grub_uint32_t format; + grub_uint16_t num_sections; + grub_uint16_t status_flags; + grub_uint32_t offset_1st_section; + grub_uint32_t num_blocks; + grub_uint64_t start_block; + grub_uint64_t num_blocks_avail; + grub_uint32_t offet_path_string; + grub_uint32_t max_time_allowed; + struct kd_section kds[MAX_KD_SECTIONS]; /* offset_1st_section should point to kds[0] */ +} GRUB_PACKED; + +/* + * Determine if a kernel dump exists and if it does, then determine the highest + * address that grub can use for memory allocations. + * The caller must have initialized *highest to rmo_top. *highest will not + * be modified if no kernel dump is found. + */ +static void +check_kernel_dump (grub_uint64_t *highest) +{ + struct kernel_dump kernel_dump; + grub_ssize_t kernel_dump_size; + grub_ieee1275_phandle_t rtas; + struct kd_section *kds; + grub_size_t i; + + /* If there's a kernel-dump it must have at least one section */ + if (grub_ieee1275_finddevice ("/rtas", &rtas) || + grub_ieee1275_get_property (rtas, "ibm,kernel-dump", &kernel_dump, + sizeof (kernel_dump), &kernel_dump_size) || + kernel_dump_size <= (grub_ssize_t) offsetof (struct kernel_dump, kds[1])) + return; + + kernel_dump_size = grub_min (kernel_dump_size, (grub_ssize_t) sizeof (kernel_dump)); + + if (grub_be_to_cpu32 (kernel_dump.format) != 1) + { + grub_printf (_("Error: ibm,kernel-dump has an unexpected format version '%u'\n"), + grub_be_to_cpu32 (kernel_dump.format)); + return; + } + + if (grub_be_to_cpu16 (kernel_dump.num_sections) > MAX_KD_SECTIONS) + { + grub_printf (_("Error: Too many kernel dump sections: %d\n"), + grub_be_to_cpu32 (kernel_dump.num_sections)); + return; + } + + for (i = 0; i < grub_be_to_cpu16 (kernel_dump.num_sections); i++) + { + kds = (struct kd_section *) ((grub_addr_t) &kernel_dump + + grub_be_to_cpu32 (kernel_dump.offset_1st_section) + + i * sizeof (struct kd_section)); + /* sanity check the address is within the 'kernel_dump' struct */ + if ((grub_addr_t) kds > (grub_addr_t) &kernel_dump + kernel_dump_size + sizeof (*kds)) + { + grub_printf (_("Error: 'kds' address beyond last available section\n")); + return; + } + + if ((grub_be_to_cpu16 (kds->src_datatype) == KD_SRC_DATATYPE_REAL_MODE_REGION) && + (grub_be_to_cpu64 (kds->src_address) == 0)) + { + *highest = grub_min (*highest, grub_be_to_cpu64 (kds->num_bytes)); + break; + } + } + + return; +} + +/* + * How much memory does OF believe exists in total? + * + * This isn't necessarily the true total. It can be the total memory + * accessible in real mode for a pseries guest, for example. + */ +static grub_uint64_t rmo_top; + +static int +count_free (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + void *data) +{ + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + /* Do not consider memory beyond 4GB */ + if (addr > 0xffffffffULL) + return 0; + + if (addr + len > 0xffffffffULL) + len = 0xffffffffULL - addr; + + *(grub_uint32_t *) data += len; + + return 0; +} + +int +grub_regions_claim (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type, void *data) +{ + struct regions_claim_request *rcr = data; + grub_uint64_t linux_rmo_save; + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + /* Do not consider memory beyond 4GB */ + if (addr > 0xffffffffULL) + return 0; + + if (addr + len > 0xffffffffULL) + len = 0xffffffffULL - addr; + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) + { + if (addr + len <= 0x180000) + return 0; + + if (addr < 0x180000) + { + len = addr + len - 0x180000; + addr = 0x180000; + } + } + + /* In theory, firmware should already prevent this from happening by not + listing our own image in /memory/available. The check below is intended + as a safeguard in case that doesn't happen. However, it doesn't protect + us from corrupting our module area, which extends up to a + yet-undetermined region above _end. */ + if ((addr < (grub_addr_t) _end) && ((addr + len) > (grub_addr_t) _start)) + { + grub_printf ("Warning: attempt to claim over our own code!\n"); + len = 0; + } + + /* + * Linux likes to claim memory at min(RMO top, 768MB) and works down + * without reference to /memory/available. (See prom_init.c::alloc_down) + * + * If this block contains min(RMO top, 768MB), do not claim below that for + * at least a few MB (this is where RTAS, SML and potentially TCEs live). + * + * We also need to leave enough space for the DT in the RMA. (See + * prom_init.c::alloc_up) + * + * Finally, we also want to make sure that when grub loads the kernel, + * it isn't going to use up all the memory we're trying to reserve! So + * enforce our entire RUNTIME_MIN_SPACE here (no fadump): + * + * | Top of memory == upper_mem_limit -| + * | | + * | available | + * | | + * |---------- 768 MB ----------| + * | | + * | reserved | + * | | + * |--- 768 MB - runtime min space ---| + * | | + * | available | + * | | + * |---------- 0 MB ----------| + * + * In case fadump is used, we allow the following: + * + * |---------- Top of memory ----------| + * | | + * | unavailable | + * | (kernel dump area) | + * | | + * |--------- upper_mem_limit ---------| + * | | + * | available | + * | | + * |---------- 768 MB ----------| + * | | + * | reserved | + * | | + * |--- 768 MB - runtime min space ---| + * | | + * | available | + * | | + * |---------- 0 MB ----------| + * + * Edge cases: + * + * - Total memory less than RUNTIME_MIN_SPACE: only claim up to HEAP_MAX_SIZE. + * (enforced elsewhere) + * + * - Total memory between RUNTIME_MIN_SPACE and 768MB: + * + * |---------- Top of memory ----------| + * | | + * | reserved | + * | | + * |---- top - runtime min space ----| + * | | + * | available | + * | | + * |---------- 0 MB ----------| + * + * This by itself would not leave us with RUNTIME_MIN_SPACE of free bytes: if + * rmo_top < 768MB, we will almost certainly have FW claims in the reserved + * region. We try to address that elsewhere: grub_ieee1275_mm_add_region will + * not call us if the resulting free space would be less than RUNTIME_MIN_SPACE. + */ + linux_rmo_save = grub_min (RMO_ADDR_MAX, rmo_top) - RUNTIME_MIN_SPACE; + if (rmo_top > RUNTIME_MIN_SPACE) + { + if (rmo_top <= RMO_ADDR_MAX) + { + if (addr > linux_rmo_save) + { + grub_dprintf ("ieee1275", "rejecting region in RUNTIME_MIN_SPACE reservation (%llx)\n", + addr); + return 0; + } + else if (addr + len > linux_rmo_save) + { + grub_dprintf ("ieee1275", "capping region: (%llx -> %llx) -> (%llx -> %llx)\n", + addr, addr + len, addr, rmo_top - RUNTIME_MIN_SPACE); + len = linux_rmo_save - addr; + } + } + else + { + grub_uint64_t upper_mem_limit = rmo_top; + grub_uint64_t orig_addr = addr; + + check_kernel_dump (&upper_mem_limit); + + grub_dprintf ("ieee1275", "upper_mem_limit is at %llx (%lld MiB)\n", + upper_mem_limit, upper_mem_limit >> 20); + + /* + * we order these cases to prefer higher addresses and avoid some + * splitting issues + * The following shows the order of variables: + * no kernel dump: linux_rmo_save < RMO_ADDR_MAX <= upper_mem_limit == rmo_top + * with kernel dump: liuxx_rmo_save < RMO_ADDR_MAX <= upper_mem_limit <= rmo_top + */ + if (addr < RMO_ADDR_MAX && (addr + len) > RMO_ADDR_MAX && upper_mem_limit >= RMO_ADDR_MAX) + { + grub_dprintf ("ieee1275", + "adjusting region for RUNTIME_MIN_SPACE: (%llx -> %llx) -> (%llx -> %llx)\n", + addr, addr + len, RMO_ADDR_MAX, addr + len); + len = (addr + len) - RMO_ADDR_MAX; + addr = RMO_ADDR_MAX; + + /* We must not exceed the upper_mem_limit (assuming it's >= RMO_ADDR_MAX) */ + if (addr + len > upper_mem_limit) + { + /* Take the bigger chunk from either below linux_rmo_save or above RMO_ADDR_MAX. */ + len = upper_mem_limit - addr; + if (orig_addr < linux_rmo_save && linux_rmo_save - orig_addr > len) + { + /* lower part is bigger */ + addr = orig_addr; + len = linux_rmo_save - addr; + } + + grub_dprintf ("ieee1275", "re-adjusted region to: (%llx -> %llx)\n", + addr, addr + len); + + if (len == 0) + return 0; + } + } + else if ((addr < linux_rmo_save) && ((addr + len) > linux_rmo_save)) + { + grub_dprintf ("ieee1275", "capping region: (%llx -> %llx) -> (%llx -> %llx)\n", + addr, addr + len, addr, linux_rmo_save); + len = linux_rmo_save - addr; + } + else if (addr >= linux_rmo_save && (addr + len) <= RMO_ADDR_MAX) + { + grub_dprintf ("ieee1275", "rejecting region in RUNTIME_MIN_SPACE reservation (%llx)\n", + addr); + return 0; + } + } + } + + /* Honor alignment restrictions on candidate addr */ + if (rcr->align) + { + grub_uint64_t align_addr = ALIGN_UP (addr, rcr->align); + grub_uint64_t d = align_addr - addr; + + if (d > len) + return 0; + + len -= d; + addr = align_addr; + } + + if (rcr->flags & GRUB_MM_ADD_REGION_CONSECUTIVE && len < rcr->total) + return 0; + + if (len > rcr->total) + len = rcr->total; + + if (len) + { + grub_err_t err; + /* Claim and use it. */ + err = grub_claimmap (addr, len); + if (err) + return err; + if (rcr->init_region) + grub_mm_init_region ((void *) (grub_addr_t) addr, len); + rcr->total -= len; + + rcr->addr = addr; + } + + *(grub_uint32_t *) data = rcr->total; + + if (rcr->total == 0) + return 1; + + return 0; +} + +static int +heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + void *data) +{ + struct regions_claim_request rcr = { + .flags = GRUB_MM_ADD_REGION_NONE, + .total = *(grub_uint32_t *) data, + .init_region = true, + }; + int ret; + + ret = grub_regions_claim (addr, len, type, &rcr); + + *(grub_uint32_t *) data = rcr.total; + + return ret; +} + +static int +region_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type, + void *data) +{ + struct regions_claim_request rcr = { + .flags = GRUB_MM_ADD_REGION_CONSECUTIVE, + .total = *(grub_uint32_t *) data, + .init_region = true, + }; + int ret; + + ret = grub_regions_claim (addr, len, type, &rcr); + + *(grub_uint32_t *) data = rcr.total; + + return ret; +} + +static grub_err_t +grub_ieee1275_mm_add_region (grub_size_t size, unsigned int flags) +{ + grub_uint32_t free_memory = 0; + grub_uint32_t avail = 0; + grub_uint32_t total; + + grub_dprintf ("ieee1275", "mm requested region of size %x, flags %x\n", + size, flags); + + /* + * Update free memory each time, which is a bit inefficient but guards us + * against a situation where some OF driver goes out to firmware for + * memory and we don't realise. + */ + grub_machine_mmap_iterate (count_free, &free_memory); + + /* Ensure we leave enough space to boot. */ + if (free_memory <= RUNTIME_MIN_SPACE + size) + { + grub_dprintf ("ieee1275", "Cannot satisfy allocation and retain minimum runtime space\n"); + return GRUB_ERR_OUT_OF_MEMORY; + } + + if (free_memory > RUNTIME_MIN_SPACE) + avail = free_memory - RUNTIME_MIN_SPACE; + + grub_dprintf ("ieee1275", "free = 0x%x available = 0x%x\n", free_memory, avail); + + if (flags & GRUB_MM_ADD_REGION_CONSECUTIVE) + { + /* first try rounding up hard for the sake of speed */ + total = grub_max (ALIGN_UP (size, 1024 * 1024) + 1024 * 1024, 32 * 1024 * 1024); + total = grub_min (avail, total); + + grub_dprintf ("ieee1275", "looking for %x bytes of memory (%x requested)\n", total, size); + + grub_machine_mmap_iterate (region_claim, &total); + grub_dprintf ("ieee1275", "get memory from fw %s\n", total == 0 ? "succeeded" : "failed"); + + if (total != 0) + { + total = grub_min (avail, size); + + grub_dprintf ("ieee1275", "fallback for %x bytes of memory (%x requested)\n", total, size); + + grub_machine_mmap_iterate (region_claim, &total); + grub_dprintf ("ieee1275", "fallback from fw %s\n", total == 0 ? "succeeded" : "failed"); + } + } + else + { + /* provide padding for a grub_mm_header_t and region */ + total = grub_min (avail, size); + grub_machine_mmap_iterate (heap_init, &total); + grub_dprintf ("ieee1275", "get noncontig memory from fw %s\n", total == 0 ? "succeeded" : "failed"); + } + + if (total == 0) + return GRUB_ERR_NONE; + else + return GRUB_ERR_OUT_OF_MEMORY; +} + +/* + * How much memory does OF believe it has? (regardless of whether + * it's accessible or not) + */ +static grub_err_t +grub_ieee1275_total_mem (grub_uint64_t *total) +{ + grub_ieee1275_phandle_t root; + grub_ieee1275_phandle_t memory; + grub_uint32_t reg[4]; + grub_ssize_t reg_size; + grub_uint32_t address_cells = 1; + grub_uint32_t size_cells = 1; + grub_uint64_t size; + + /* If we fail to get to the end, report 0. */ + *total = 0; + + /* Determine the format of each entry in `reg'. */ + if (grub_ieee1275_finddevice ("/", &root)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find / node"); + if (grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells, + sizeof (address_cells), 0)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine #address-cells"); + if (grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells, + sizeof (size_cells), 0)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine #size-cells"); + + if (size_cells > address_cells) + address_cells = size_cells; + + /* Load `/memory/reg'. */ + if (grub_ieee1275_finddevice ("/memory", &memory)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find /memory node"); + if (grub_ieee1275_get_integer_property (memory, "reg", reg, + sizeof (reg), ®_size)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine /memory/reg property"); + if (reg_size < 0 || (grub_size_t) reg_size > sizeof (reg)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "/memory response buffer exceeded"); + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS)) + { + address_cells = 1; + size_cells = 1; + } + + /* Decode only the size */ + size = reg[address_cells]; + if (size_cells == 2) + size = (size << 32) | reg[address_cells + 1]; + + *total = size; + + return grub_errno; +} + +#if defined(__powerpc__) + +/* See PAPR or arch/powerpc/kernel/prom_init.c */ +struct option_vector2 +{ + grub_uint8_t byte1; + grub_uint16_t reserved; + grub_uint32_t real_base; + grub_uint32_t real_size; + grub_uint32_t virt_base; + grub_uint32_t virt_size; + grub_uint32_t load_base; + grub_uint32_t min_rma; + grub_uint32_t min_load; + grub_uint8_t min_rma_percent; + grub_uint8_t max_pft_size; +} GRUB_PACKED; + +struct option_vector5 +{ + grub_uint8_t byte1; + grub_uint8_t byte2; + grub_uint8_t byte3; + grub_uint8_t cmo; + grub_uint8_t associativity; + grub_uint8_t bin_opts; + grub_uint8_t micro_checkpoint; + grub_uint8_t reserved0; + grub_uint32_t max_cpus; + grub_uint16_t base_papr; + grub_uint16_t mem_reference; + grub_uint32_t platform_facilities; + grub_uint8_t sub_processors; + grub_uint8_t byte22; + grub_uint8_t xive; + grub_uint8_t mmu; + grub_uint8_t hpt_ext; + grub_uint8_t radix_gtse; +} GRUB_PACKED; + +struct pvr_entry +{ + grub_uint32_t mask; + grub_uint32_t entry; +}; + +struct cas_vector +{ + struct + { + struct pvr_entry terminal; + } pvr_list; + grub_uint8_t num_vecs; + grub_uint8_t vec1_size; + grub_uint8_t vec1; + grub_uint8_t vec2_size; + struct option_vector2 vec2; + grub_uint8_t vec3_size; + grub_uint16_t vec3; + grub_uint8_t vec4_size; + grub_uint16_t vec4; + grub_uint8_t vec5_size; + struct option_vector5 vec5; +} GRUB_PACKED; + +/* + * Call ibm,client-architecture-support to try to get more RMA. + * We ask for 768MB which should be enough to verify a distro kernel. + * We ignore most errors: if we don't succeed we'll proceed with whatever + * memory we have. + */ +static void +grub_ieee1275_ibm_cas (void) +{ + int rc; + grub_ieee1275_ihandle_t root; + grub_uint8_t ibm_arch_platform_support[8]; + grub_ssize_t actual; + grub_uint8_t xive_support = 0; + grub_uint8_t mmu_support = 0; + grub_uint8_t radix_gtse_support = 0; + int i = 0; + int prop_len = 8; + struct cas_args + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_ihandle_t ihandle; + grub_ieee1275_cell_t cas_addr; + grub_ieee1275_cell_t result; + } args; + + grub_ieee1275_get_integer_property (grub_ieee1275_chosen, + "ibm,arch-vec-5-platform-support", + (grub_uint32_t *) ibm_arch_platform_support, + sizeof (ibm_arch_platform_support), + &actual); + + for (i = 0; i < prop_len; i++) + { + switch (ibm_arch_platform_support[i]) + { + case XIVE_INDEX: + if (ibm_arch_platform_support[i + 1] & MAX_SUPPORTED) + xive_support = XIVE_ENABLED; + else + xive_support = 0; + break; + + case MMU_INDEX: + if (ibm_arch_platform_support[i + 1] & MAX_SUPPORTED) + mmu_support = RADIX_ENABLED; + else + mmu_support = HASH_ENABLED; + break; + + case RADIX_GTSE_INDEX: + if (mmu_support == RADIX_ENABLED) + radix_gtse_support = ibm_arch_platform_support[i + 1] & RADIX_GTSE_ENABLED; + else + radix_gtse_support = 0; + break; + + default: + /* Ignoring the other indexes of ibm,arch-vec-5-platform-support. */ + break; + } + /* Skipping the property value. */ + i++; + } + + struct cas_vector vector = + { + .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */ + .num_vecs = 5 - 1, + .vec1_size = 0, + .vec1 = 0x80, /* ignore */ + .vec2_size = 1 + sizeof (struct option_vector2) - 2, + .vec2 = { + 0, 0, -1, -1, -1, -1, -1, 768, -1, 0, 48 + }, + .vec3_size = 2 - 1, + .vec3 = 0x00e0, /* ask for FP + VMX + DFP but don't halt if unsatisfied */ + .vec4_size = 2 - 1, + .vec4 = 0x0001, /* set required minimum capacity % to the lowest value */ + .vec5_size = 1 + sizeof (struct option_vector5) - 2, + .vec5 = { + 0, BYTE2, 0, CMO, ASSOCIATIVITY, BIN_OPTS, 0, 0, MAX_CPU, 0, 0, PLATFORM_FACILITIES, SUB_PROCESSORS, BYTE22, xive_support, mmu_support, 0, radix_gtse_support + } + }; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2); + args.method = (grub_ieee1275_cell_t) "ibm,client-architecture-support"; + rc = grub_ieee1275_open ("/", &root); + if (rc) + { + grub_error (GRUB_ERR_IO, "could not open root when trying to call CAS"); + return; + } + args.ihandle = root; + args.cas_addr = (grub_ieee1275_cell_t) &vector; + + grub_printf ("Calling ibm,client-architecture-support from grub..."); + IEEE1275_CALL_ENTRY_FN (&args); + grub_printf ("done\n"); + + grub_ieee1275_close (root); +} + +#endif /* __powerpc__ */ + +static void grub_claim_heap (void) { - unsigned long total = 0; + grub_err_t err; + grub_uint32_t total = HEAP_MAX_SIZE; +#if defined(__powerpc__) + grub_uint32_t ibm_ca_support_reboot = 0; + grub_ssize_t actual; +#endif - auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, - grub_memory_type_t type); - int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, - grub_memory_type_t type) - { - if (type != 1) - return 0; + err = grub_ieee1275_total_mem (&rmo_top); - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) - { - if (addr + len <= 0x180000) - return 0; + /* + * If we cannot size the available memory, we can't be sure we're leaving + * space for the kernel, initrd and things Linux loads early in boot. So only + * allow further allocations from firmware on success + */ + if (err == GRUB_ERR_NONE) + grub_mm_add_region_fn = grub_ieee1275_mm_add_region; - if (addr < 0x180000) - { - len = addr + len - 0x180000; - addr = 0x180000; - } - } - len -= 1; /* Required for some firmware. */ +#if defined(__powerpc__) + /* Check if it's a CAS reboot with below property. If so, we will skip CAS call. */ + if (grub_ieee1275_get_integer_property (grub_ieee1275_chosen, + "ibm,client-architecture-support-reboot", + &ibm_ca_support_reboot, + sizeof (ibm_ca_support_reboot), + &actual) >= 0) + grub_dprintf ("ieee1275", "ibm,client-architecture-support-reboot: %" PRIuGRUB_UINT32_T "\n", + ibm_ca_support_reboot); - /* Never exceed HEAP_MAX_SIZE */ - if (total + len > HEAP_MAX_SIZE) - len = HEAP_MAX_SIZE - total; + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY)) + { + /* + * If we have an error don't call CAS. Just hope for the best. + * Along with the above, if the rmo_top is 512 MB or above. We + * will skip the CAS call. However, if we call CAS, the rmo_top + * will be set to 768 MB via CAS Vector2. But we need to call + * CAS with rmo_top < 512 MB to avoid the issue on the older + * Linux kernel, which still uses rmo_top as 512 MB. If we call + * CAS with a condition rmo_top < 768 MB, it will result in an + * issue due to the IBM CAS reboot feature and we won't be able + * to boot the newer kernel. Whenever a reboot is detected as + * the CAS reboot by GRUB it will boot the machine with the + * last booted kernel by reading the variable boot-last-label + * which has the info related to the last boot and it's specific + * to IBM PowerPC. Due to this, the machine will boot with the + * last booted kernel which has rmo_top as 512 MB. Also, if the + * reboot is detected as a CAS reboot, the GRUB will skip the CAS + * call. As the CAS has already been called earlier, so it is + * not required to call CAS even if the other conditions are met. + * This condition will also prevent a scenario where the machine + * get stuck in the CAS reboot loop while booting a machine with + * an older kernel, having option_vector2 MIN_RMA as 512 MB in + * Linux prom_init.c and GRUB uses rmo_top < 768 MB condition + * for calling CAS. Due to their respective conditions, Linux + * CAS and GRUB CAS will keep doing the CAS calls and change + * the MIN_RMA from 768, changed by GRUB, to 512, changed by Linux, + * to 768, changed by GRUB, to 512, changed by Linux, and so on. + * The machine will stuck in this CAS reboot loop forever. + * + * IBM PAPR: https://openpower.foundation/specifications/linuxonpower/ + */ + if (!ibm_ca_support_reboot && err == GRUB_ERR_NONE && rmo_top < (512 * 1024 * 1024)) + grub_ieee1275_ibm_cas (); + } +#endif - /* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */ - if ((addr < HEAP_MAX_ADDR) && /* if it's too late, don't bother */ - (addr + len > HEAP_MAX_ADDR) && /* if it wasn't available anyway, don't bother */ - (total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE)) /* only limit ourselves when we can afford to */ - len = HEAP_MAX_ADDR - addr; - - /* In theory, firmware should already prevent this from happening by not - listing our own image in /memory/available. The check below is intended - as a safeguard in case that doesn't happen. However, it doesn't protect - us from corrupting our module area, which extends up to a - yet-undetermined region above _end. */ - if ((addr < (grub_addr_t) _end) && ((addr + len) > (grub_addr_t) _start)) - { - grub_printf ("Warning: attempt to claim over our own code!\n"); - len = 0; - } - - if (len) - { - grub_err_t err; - /* Claim and use it. */ - err = grub_claimmap (addr, len); - if (err) - return err; - grub_mm_init_region ((void *) (grub_addr_t) addr, len); - } - - total += len; - if (total >= HEAP_MAX_SIZE) - return 1; - - return 0; - } - - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET)) - heap_init (HEAP_MAX_ADDR - HEAP_MIN_SIZE, HEAP_MIN_SIZE, 1); - else - grub_machine_mmap_iterate (heap_init); + grub_machine_mmap_iterate (heap_init, &total); } #endif @@ -254,14 +995,12 @@ grub_parse_cmdline (void) } } -static grub_uint64_t ieee1275_get_time_ms (void); - grub_addr_t grub_modbase; void grub_machine_init (void) { - grub_modbase = ALIGN_UP((grub_addr_t) _end + grub_modbase = ALIGN_UP((grub_addr_t) _end + GRUB_KERNEL_MACHINE_MOD_GAP, GRUB_KERNEL_MACHINE_MOD_ALIGN); grub_ieee1275_init (); @@ -269,22 +1008,36 @@ grub_machine_init (void) grub_console_init_early (); grub_claim_heap (); grub_console_init_lately (); +#ifdef __sparc__ + grub_obdisk_init (); +#else grub_ofdisk_init (); - +#endif grub_parse_cmdline (); - grub_install_get_time_ms (ieee1275_get_time_ms); +#ifdef __i386__ + grub_tsc_init (); +#else + grub_install_get_time_ms (grub_rtc_get_time_ms); +#endif } void -grub_machine_fini (void) +grub_machine_fini (int flags) { - grub_ofdisk_fini (); - grub_console_fini (); + if (flags & GRUB_LOADER_FLAG_NORETURN) + { +#ifdef __sparc__ + grub_obdisk_fini (); +#else + grub_ofdisk_fini (); +#endif + grub_console_fini (); + } } -static grub_uint64_t -ieee1275_get_time_ms (void) +grub_uint64_t +grub_rtc_get_time_ms (void) { grub_uint32_t msecs = 0; diff --git a/grub-core/kern/ieee1275/mmap.c b/grub-core/kern/ieee1275/mmap.c index 2e4e085bb..bf325eadf 100644 --- a/grub-core/kern/ieee1275/mmap.c +++ b/grub-core/kern/ieee1275/mmap.c @@ -21,11 +21,11 @@ #include grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { grub_ieee1275_phandle_t root; grub_ieee1275_phandle_t memory; - grub_uint32_t available[32]; + grub_uint32_t available[128]; grub_ssize_t available_size; grub_uint32_t address_cells = 1; grub_uint32_t size_cells = 1; @@ -49,6 +49,9 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) sizeof available, &available_size)) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine /memory/available property"); + if (available_size < 0 || (grub_size_t) available_size > sizeof (available)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "/memory response buffer exceeded"); if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS)) { @@ -72,7 +75,7 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) if (size_cells == 2) size = (size << 32) | available[i++]; - if (hook (address, size, GRUB_MEMORY_AVAILABLE)) + if (hook (address, size, GRUB_MEMORY_AVAILABLE, hook_data)) break; } diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 40abaa373..11b2beb2f 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -32,184 +32,231 @@ enum grub_ieee1275_parse_type GRUB_PARSE_DEVICE_TYPE }; -/* Walk children of 'devpath', calling hook for each. */ -int -grub_children_iterate (const char *devpath, - int (*hook) (struct grub_ieee1275_devalias *alias)) +static int +fill_alias (struct grub_ieee1275_devalias *alias) +{ + grub_ssize_t actual; + + if (grub_ieee1275_get_property (alias->phandle, "device_type", alias->type, + IEEE1275_MAX_PROP_LEN, &actual)) + alias->type[0] = 0; + + if (alias->parent_dev == alias->phandle) + return 0; + + if (grub_ieee1275_package_to_path (alias->phandle, alias->path, + IEEE1275_MAX_PATH_LEN, &actual)) + return 0; + + if (grub_strcmp (alias->parent_path, alias->path) == 0) + return 0; + + if (grub_ieee1275_get_property (alias->phandle, "name", alias->name, + IEEE1275_MAX_PROP_LEN, &actual)) + return 0; + grub_dprintf ("devalias", "device path=%s\n", alias->path); + return 1; +} + +void +grub_ieee1275_devalias_free (struct grub_ieee1275_devalias *alias) +{ + grub_free (alias->name); + grub_free (alias->type); + grub_free (alias->path); + grub_free (alias->parent_path); + alias->name = 0; + alias->type = 0; + alias->path = 0; + alias->parent_path = 0; + alias->phandle = GRUB_IEEE1275_PHANDLE_INVALID; +} + +void +grub_ieee1275_children_peer (struct grub_ieee1275_devalias *alias) +{ + while (grub_ieee1275_peer (alias->phandle, &alias->phandle) != -1) + if (fill_alias (alias)) + return; + grub_ieee1275_devalias_free (alias); +} + +void +grub_ieee1275_children_first (const char *devpath, + struct grub_ieee1275_devalias *alias) { grub_ieee1275_phandle_t dev; - grub_ieee1275_phandle_t child; - char *childtype, *childpath; - char *childname; - int ret = 0; + + grub_dprintf ("devalias", "iterating children of %s\n", + devpath); + + alias->name = 0; + alias->path = 0; + alias->parent_path = 0; + alias->type = 0; if (grub_ieee1275_finddevice (devpath, &dev)) - return 0; + return; - if (grub_ieee1275_child (dev, &child)) - return 0; + if (grub_ieee1275_child (dev, &alias->phandle)) + return; - childtype = grub_malloc (IEEE1275_MAX_PROP_LEN); - if (!childtype) - return 0; - childpath = grub_malloc (IEEE1275_MAX_PATH_LEN); - if (!childpath) + alias->type = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!alias->type) + return; + alias->path = grub_malloc (IEEE1275_MAX_PATH_LEN); + if (!alias->path) { - grub_free (childtype); - return 0; + grub_free (alias->type); + return; } - childname = grub_malloc (IEEE1275_MAX_PROP_LEN); - if (!childname) + alias->parent_path = grub_strdup (devpath); + if (!alias->parent_path) { - grub_free (childpath); - grub_free (childtype); - return 0; + grub_free (alias->path); + grub_free (alias->type); + return; } - do + alias->name = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!alias->name) { - struct grub_ieee1275_devalias alias; - grub_ssize_t actual; + grub_free (alias->path); + grub_free (alias->type); + grub_free (alias->parent_path); + return; + } + if (!fill_alias (alias)) + grub_ieee1275_children_peer (alias); +} - if (grub_ieee1275_get_property (child, "device_type", childtype, - IEEE1275_MAX_PROP_LEN, &actual)) - childtype[0] = 0; +static int +iterate_recursively (const char *path, + int (*hook) (struct grub_ieee1275_devalias *alias)) +{ + struct grub_ieee1275_devalias alias; + int ret = 0; - if (dev == child) - continue; - - if (grub_ieee1275_package_to_path (child, childpath, - IEEE1275_MAX_PATH_LEN, &actual)) - continue; - - if (grub_strcmp (devpath, childpath) == 0) - continue; - - if (grub_ieee1275_get_property (child, "name", childname, - IEEE1275_MAX_PROP_LEN, &actual)) - continue; - - alias.type = childtype; - alias.path = childpath; - alias.name = childname; + FOR_IEEE1275_DEVCHILDREN(path, alias) + { ret = hook (&alias); if (ret) break; + ret = iterate_recursively (alias.path, hook); + if (ret) + break; } - while (grub_ieee1275_peer (child, &child) != -1); - - grub_free (childname); - grub_free (childpath); - grub_free (childtype); - + grub_ieee1275_devalias_free (&alias); return ret; } int grub_ieee1275_devices_iterate (int (*hook) (struct grub_ieee1275_devalias *alias)) { - auto int it_through (struct grub_ieee1275_devalias *alias); - int it_through (struct grub_ieee1275_devalias *alias) - { - if (hook (alias)) - return 1; - return grub_children_iterate (alias->path, it_through); - } - - return grub_children_iterate ("/", it_through); + return iterate_recursively ("/", hook); } -/* Iterate through all device aliases. This function can be used to - find a device of a specific type. */ -int -grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias)) +void +grub_ieee1275_devalias_init_iterator (struct grub_ieee1275_devalias *alias) { - grub_ieee1275_phandle_t aliases; - char *aliasname, *devtype; - grub_ssize_t actual; - struct grub_ieee1275_devalias alias; - int ret = 0; + alias->name = 0; + alias->path = 0; + alias->parent_path = 0; + alias->type = 0; - if (grub_ieee1275_finddevice ("/aliases", &aliases)) - return 0; + grub_dprintf ("devalias", "iterating aliases\n"); - aliasname = grub_malloc (IEEE1275_MAX_PROP_LEN); - if (!aliasname) - return 0; - devtype = grub_malloc (IEEE1275_MAX_PROP_LEN); - if (!devtype) + if (grub_ieee1275_finddevice ("/aliases", &alias->parent_dev)) + return; + + alias->name = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!alias->name) + return; + + alias->type = grub_malloc (IEEE1275_MAX_PROP_LEN); + if (!alias->type) { - grub_free (aliasname); - return 0; + grub_free (alias->name); + alias->name = 0; + return; } - /* Find the first property. */ - aliasname[0] = '\0'; + alias->name[0] = '\0'; +} - while (grub_ieee1275_next_property (aliases, aliasname, aliasname) > 0) +int +grub_ieee1275_devalias_next (struct grub_ieee1275_devalias *alias) +{ + if (!alias->name) + return 0; + while (1) { - grub_ieee1275_phandle_t dev; grub_ssize_t pathlen; - char *devpath; + grub_ssize_t actual; + char *tmp; - grub_dprintf ("devalias", "devalias name = %s\n", aliasname); + if (alias->path) + { + grub_free (alias->path); + alias->path = 0; + } + tmp = grub_strdup (alias->name); + if (grub_ieee1275_next_property (alias->parent_dev, tmp, + alias->name) <= 0) + { + grub_free (tmp); + grub_ieee1275_devalias_free (alias); + return 0; + } + grub_free (tmp); - grub_ieee1275_get_property_length (aliases, aliasname, &pathlen); + grub_dprintf ("devalias", "devalias name = %s\n", alias->name); + + grub_ieee1275_get_property_length (alias->parent_dev, alias->name, &pathlen); /* The property `name' is a special case we should skip. */ - if (!grub_strcmp (aliasname, "name")) + if (grub_strcmp (alias->name, "name") == 0) continue; /* Sun's OpenBoot often doesn't zero terminate the device alias strings, so we will add a NULL byte at the end explicitly. */ pathlen += 1; - devpath = grub_malloc (pathlen + 1); - if (! devpath) + alias->path = grub_malloc (pathlen + 1); + if (! alias->path) { - grub_free (devtype); - grub_free (aliasname); + grub_ieee1275_devalias_free (alias); return 0; } - if (grub_ieee1275_get_property (aliases, aliasname, devpath, pathlen, - &actual) || actual < 0) + if (grub_ieee1275_get_property (alias->parent_dev, alias->name, alias->path, + pathlen, &actual) || actual < 0) { - grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname); - goto nextprop; + grub_dprintf ("devalias", "get_property (%s) failed\n", alias->name); + grub_free (alias->path); + continue; } if (actual > pathlen) actual = pathlen; - devpath[actual] = '\0'; - devpath[pathlen] = '\0'; + alias->path[actual] = '\0'; + alias->path[pathlen] = '\0'; - if (grub_ieee1275_finddevice (devpath, &dev)) + if (grub_ieee1275_finddevice (alias->path, &alias->phandle)) { - grub_dprintf ("devalias", "finddevice (%s) failed\n", devpath); - goto nextprop; + grub_dprintf ("devalias", "finddevice (%s) failed\n", alias->path); + grub_free (alias->path); + alias->path = 0; + continue; } - if (grub_ieee1275_get_property (dev, "device_type", devtype, + if (grub_ieee1275_get_property (alias->phandle, "device_type", alias->type, IEEE1275_MAX_PROP_LEN, &actual)) { /* NAND device don't have device_type property. */ - devtype[0] = 0; + alias->type[0] = 0; } - - alias.name = aliasname; - alias.path = devpath; - alias.type = devtype; - ret = hook (&alias); - -nextprop: - grub_free (devpath); - if (ret) - break; + return 1; } - - grub_free (devtype); - grub_free (aliasname); - return ret; } /* Call the "map" method of /chosen/mmu. */ @@ -224,7 +271,7 @@ grub_ieee1275_map (grub_addr_t phys, grub_addr_t virt, grub_size_t size, grub_ieee1275_cell_t mode; grub_ieee1275_cell_t size; grub_ieee1275_cell_t virt; -#ifdef GRUB_MACHINE_SPARC64 +#ifdef __sparc__ grub_ieee1275_cell_t phys_high; #endif grub_ieee1275_cell_t phys_low; @@ -232,7 +279,7 @@ grub_ieee1275_map (grub_addr_t phys, grub_addr_t virt, grub_size_t size, } args; INIT_IEEE1275_COMMON (&args.common, "call-method", -#ifdef GRUB_MACHINE_SPARC64 +#ifdef __sparc__ 7, #else 6, @@ -240,7 +287,7 @@ grub_ieee1275_map (grub_addr_t phys, grub_addr_t virt, grub_size_t size, 1); args.method = (grub_ieee1275_cell_t) "map"; args.ihandle = grub_ieee1275_mmu; -#ifdef GRUB_MACHINE_SPARC64 +#ifdef __sparc__ args.phys_high = 0; #endif args.phys_low = phys; @@ -286,37 +333,28 @@ grub_ieee1275_get_devargs (const char *path) } /* Get the device path of the Open Firmware node name `path'. */ -static char * +char * grub_ieee1275_get_devname (const char *path) { char *colon = grub_strchr (path, ':'); - char *newpath = 0; int pathlen = grub_strlen (path); - auto int match_alias (struct grub_ieee1275_devalias *alias); - - int match_alias (struct grub_ieee1275_devalias *curalias) - { - /* briQ firmware can change capitalization in /chosen/bootpath. */ - if (grub_strncasecmp (curalias->path, path, pathlen) == 0 - && curalias->path[pathlen] == 0) - { - newpath = grub_strdup (curalias->name); - return 1; - } - - return 0; - } - + struct grub_ieee1275_devalias curalias; if (colon) pathlen = (int)(colon - path); /* Try to find an alias for this device. */ - grub_devalias_iterate (match_alias); + FOR_IEEE1275_DEVALIASES (curalias) + /* briQ firmware can change capitalization in /chosen/bootpath. */ + if (grub_strncasecmp (curalias.path, path, pathlen) == 0 + && curalias.path[pathlen] == 0) + { + char *newpath; + newpath = grub_strdup (curalias.name); + grub_ieee1275_devalias_free (&curalias); + return newpath; + } - if (! newpath) - newpath = grub_strndup (path, pathlen); - - return newpath; + return grub_strndup (path, pathlen); } static char * @@ -366,7 +404,7 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) if (comma) { char *filepath = comma + 1; - + /* Make sure filepath has leading backslash. */ if (filepath[0] != '\\') ret = grub_xasprintf ("\\%s", filepath); @@ -441,6 +479,9 @@ grub_ieee1275_encode_devname (const char *path) char *optr; const char *iptr; + if (! device) + return 0; + encoding = grub_malloc (sizeof ("ieee1275/") + 2 * grub_strlen (device) + sizeof (",XXXXXXXXXXXX")); if (!encoding) @@ -523,3 +564,30 @@ grub_ieee1275_canonicalise_devname (const char *path) return NULL; } +char * +grub_ieee1275_get_boot_dev (void) +{ + char *bootpath; + grub_ssize_t bootpath_size; + + if (grub_ieee1275_get_property_length (grub_ieee1275_chosen, "bootpath", + &bootpath_size) + || bootpath_size <= 0) + { + /* Should never happen. */ + grub_printf ("/chosen/bootpath property missing!\n"); + return NULL; + } + + bootpath = (char *) grub_malloc ((grub_size_t) bootpath_size + 64); + if (! bootpath) + { + grub_print_error (); + return NULL; + } + grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", bootpath, + (grub_size_t) bootpath_size + 1, 0); + bootpath[bootpath_size] = '\0'; + + return bootpath; +} diff --git a/grub-core/kern/lockdown.c b/grub-core/kern/lockdown.c new file mode 100644 index 000000000..af6d493cd --- /dev/null +++ b/grub-core/kern/lockdown.c @@ -0,0 +1,85 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2020 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + * + */ + +#include +#include +#include +#include +#include + +static int lockdown = GRUB_LOCKDOWN_DISABLED; + +static grub_err_t +lockdown_verifier_init (grub_file_t io __attribute__ ((unused)), + enum grub_file_type type, + void **context __attribute__ ((unused)), + enum grub_verify_flags *flags) +{ + *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION; + + switch (type & GRUB_FILE_TYPE_MASK) + { + case GRUB_FILE_TYPE_GRUB_MODULE: + case GRUB_FILE_TYPE_LINUX_KERNEL: + case GRUB_FILE_TYPE_MULTIBOOT_KERNEL: + case GRUB_FILE_TYPE_XEN_HYPERVISOR: + case GRUB_FILE_TYPE_BSD_KERNEL: + case GRUB_FILE_TYPE_XNU_KERNEL: + case GRUB_FILE_TYPE_PLAN9_KERNEL: + case GRUB_FILE_TYPE_NTLDR: + case GRUB_FILE_TYPE_TRUECRYPT: + case GRUB_FILE_TYPE_FREEDOS: + case GRUB_FILE_TYPE_PXECHAINLOADER: + case GRUB_FILE_TYPE_PCCHAINLOADER: + case GRUB_FILE_TYPE_COREBOOT_CHAINLOADER: + case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE: + case GRUB_FILE_TYPE_ACPI_TABLE: + case GRUB_FILE_TYPE_DEVICE_TREE_IMAGE: + case GRUB_FILE_TYPE_FONT: + *flags = GRUB_VERIFY_FLAGS_DEFER_AUTH; + + /* Fall through. */ + + default: + return GRUB_ERR_NONE; + } +} + +struct grub_file_verifier lockdown_verifier = + { + .name = "lockdown_verifier", + .init = lockdown_verifier_init, + }; + +void +grub_lockdown (void) +{ + lockdown = GRUB_LOCKDOWN_ENABLED; + + grub_verifier_register (&lockdown_verifier); + + grub_env_set ("lockdown", "y"); + grub_env_export ("lockdown"); +} + +int +grub_is_lockdown (void) +{ + return lockdown; +} diff --git a/grub-core/kern/loongarch64/cache.c b/grub-core/kern/loongarch64/cache.c new file mode 100644 index 000000000..ff834dca4 --- /dev/null +++ b/grub-core/kern/loongarch64/cache.c @@ -0,0 +1,39 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2023 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +/* Prototypes for asm functions. */ +void grub_arch_clean_dcache_range (void); +void grub_arch_invalidate_icache_range (void); + +void +grub_arch_sync_caches (void *address __attribute__((unused)), + grub_size_t len __attribute__((unused))) +{ + grub_arch_clean_dcache_range (); + grub_arch_invalidate_icache_range (); +} + +void +grub_arch_sync_dma_caches (volatile void *address __attribute__((unused)), + grub_size_t len __attribute__((unused))) +{ + /* DMA non-coherent devices not supported yet */ +} diff --git a/grub-core/kern/loongarch64/cache_flush.S b/grub-core/kern/loongarch64/cache_flush.S new file mode 100644 index 000000000..a587ed58f --- /dev/null +++ b/grub-core/kern/loongarch64/cache_flush.S @@ -0,0 +1,33 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2023 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include + + .file "cache_flush.S" + .text +/* + * No further work to do because cache consistency is maintained by hardware on + * LoongArch. + */ +FUNCTION(grub_arch_clean_dcache_range) + dbar 0 + jr $ra + +FUNCTION(grub_arch_invalidate_icache_range) + ibar 0 + jr $ra diff --git a/grub-core/kern/loongarch64/dl.c b/grub-core/kern/loongarch64/dl.c new file mode 100644 index 000000000..7f923b415 --- /dev/null +++ b/grub-core/kern/loongarch64/dl.c @@ -0,0 +1,150 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2023 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Check if EHDR is a valid ELF header. */ +grub_err_t +grub_arch_dl_check_header (void *ehdr) +{ + Elf_Ehdr *e = ehdr; + + /* Check the magic numbers. */ + if (e->e_ident[EI_CLASS] != ELFCLASS64 + || e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_LOONGARCH) + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic")); + + return GRUB_ERR_NONE; +} + +#pragma GCC diagnostic ignored "-Wcast-align" + +/* + * Unified function for both REL and RELA. + */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg) +{ + Elf_Rel *rel, *max; + struct grub_loongarch64_stack stack; + grub_loongarch64_stack_init (&stack); + + for (rel = (Elf_Rel *) ((char *) ehdr + s->sh_offset), + max = (Elf_Rel *) ((char *) rel + s->sh_size); + rel < max; + rel = (Elf_Rel *) ((char *) rel + s->sh_entsize)) + { + Elf_Sym *sym; + void *place; + grub_uint64_t sym_addr; + + if (rel->r_offset >= seg->size) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is outside the segment"); + + sym = (Elf_Sym *) ((char*) mod->symtab + + mod->symsize * ELF_R_SYM (rel->r_info)); + + sym_addr = sym->st_value; + if (s->sh_type == SHT_RELA) + sym_addr += ((Elf_Rela *) rel)->r_addend; + + place = (void *) ((grub_addr_t) seg->addr + rel->r_offset); + + switch (ELF_R_TYPE (rel->r_info)) + { + case R_LARCH_64: + { + grub_uint64_t *abs_place = place; + + grub_dprintf ("dl", "reloc_abs64 %p => 0x%016llx, %p\n", + place, (unsigned long long) sym_addr, abs_place); + + *abs_place += (grub_uint64_t) sym_addr; + } + break; + case R_LARCH_MARK_LA: + break; + case R_LARCH_SOP_PUSH_PCREL: + case R_LARCH_SOP_PUSH_PLT_PCREL: + grub_loongarch64_sop_push (&stack, sym_addr - (grub_uint64_t)place); + break; + case R_LARCH_B26: + { + grub_uint32_t *abs_place = place; + grub_ssize_t off = sym_addr - (grub_addr_t) place; + + grub_loongarch64_b26 (abs_place, off); + } + break; + case R_LARCH_ABS_HI20: + { + grub_uint32_t *abs_place = place; + grub_loongarch64_xxx_hi20 (abs_place, sym_addr); + } + break; + case R_LARCH_ABS64_LO20: + { + grub_uint32_t *abs_place = place; + grub_loongarch64_abs64_lo20 (abs_place, sym_addr); + } + break; + case R_LARCH_ABS64_HI12: + { + grub_uint32_t *abs_place = place; + grub_loongarch64_abs64_hi12 (abs_place, sym_addr); + } + break; + case R_LARCH_PCALA_HI20: + { + grub_uint32_t *abs_place = place; + grub_int32_t off = (((sym_addr + 0x800) & ~0xfffULL) - ((grub_addr_t)place & ~0xfffULL)); + + grub_loongarch64_xxx_hi20 (abs_place, off); + } + break; + case R_LARCH_ABS_LO12: + case R_LARCH_PCALA_LO12: + { + grub_uint32_t *abs_place = place; + grub_loongarch64_xxx_lo12 (abs_place, sym_addr); + } + break; + GRUB_LOONGARCH64_RELOCATION (&stack, place, sym_addr) + default: + { + char rel_info[17]; /* log16(2^64) = 16, plus NUL. */ + + grub_snprintf (rel_info, sizeof (rel_info) - 1, "%" PRIxGRUB_UINT64_T, + (grub_uint64_t) ELF_R_TYPE (rel->r_info)); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%s is not implemented yet"), rel_info); + } + break; + } + } + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/loongarch64/dl_helper.c b/grub-core/kern/loongarch64/dl_helper.c new file mode 100644 index 000000000..006e8500e --- /dev/null +++ b/grub-core/kern/loongarch64/dl_helper.c @@ -0,0 +1,285 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2023 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * LoongArch relocations documentation: + * https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#relocations + */ +static void grub_loongarch64_stack_push (grub_loongarch64_stack_t stack, grub_uint64_t x); +static grub_uint64_t grub_loongarch64_stack_pop (grub_loongarch64_stack_t stack); + +void +grub_loongarch64_stack_init (grub_loongarch64_stack_t stack) +{ + stack->top = -1; + stack->count = LOONGARCH64_STACK_MAX; +} + +static void +grub_loongarch64_stack_push (grub_loongarch64_stack_t stack, grub_uint64_t x) +{ + if (stack->top == stack->count) + return; + stack->data[++stack->top] = x; +} + +static grub_uint64_t +grub_loongarch64_stack_pop (grub_loongarch64_stack_t stack) +{ + if (stack->top == -1) + return 0; + return stack->data[stack->top--]; +} + +void +grub_loongarch64_sop_push (grub_loongarch64_stack_t stack, grub_int64_t offset) +{ + grub_loongarch64_stack_push (stack, offset); +} + +/* opr2 = pop (), opr1 = pop (), push (opr1 - opr2) */ +void +grub_loongarch64_sop_sub (grub_loongarch64_stack_t stack) +{ + grub_uint64_t a, b; + b = grub_loongarch64_stack_pop (stack); + a = grub_loongarch64_stack_pop (stack); + grub_loongarch64_stack_push (stack, a - b); +} + +/* opr2 = pop (), opr1 = pop (), push (opr1 << opr2) */ +void +grub_loongarch64_sop_sl (grub_loongarch64_stack_t stack) +{ + grub_uint64_t a, b; + b = grub_loongarch64_stack_pop (stack); + a = grub_loongarch64_stack_pop (stack); + grub_loongarch64_stack_push (stack, a << b); +} + +/* opr2 = pop (), opr1 = pop (), push (opr1 >> opr2) */ +void +grub_loongarch64_sop_sr (grub_loongarch64_stack_t stack) +{ + grub_uint64_t a, b; + b = grub_loongarch64_stack_pop (stack); + a = grub_loongarch64_stack_pop (stack); + grub_loongarch64_stack_push (stack, a >> b); +} + +/* opr2 = pop (), opr1 = pop (), push (opr1 + opr2) */ +void +grub_loongarch64_sop_add (grub_loongarch64_stack_t stack) +{ + grub_uint64_t a, b; + b = grub_loongarch64_stack_pop (stack); + a = grub_loongarch64_stack_pop (stack); + grub_loongarch64_stack_push (stack, a + b); +} + +/* opr2 = pop (), opr1 = pop (), push (opr1 & opr2) */ +void +grub_loongarch64_sop_and (grub_loongarch64_stack_t stack) +{ + grub_uint64_t a, b; + b = grub_loongarch64_stack_pop (stack); + a = grub_loongarch64_stack_pop (stack); + grub_loongarch64_stack_push (stack, a & b); +} + +/* opr3 = pop (), opr2 = pop (), opr1 = pop (), push (opr1 ? opr2 : opr3) */ +void +grub_loongarch64_sop_if_else (grub_loongarch64_stack_t stack) +{ + grub_uint64_t a, b, c; + c = grub_loongarch64_stack_pop (stack); + b = grub_loongarch64_stack_pop (stack); + a = grub_loongarch64_stack_pop (stack); + + if (a) { + grub_loongarch64_stack_push (stack, b); + } else { + grub_loongarch64_stack_push (stack, c); + } +} + +/* opr1 = pop (), (*(uint32_t *) PC) [14 ... 10] = opr1 [4 ... 0] */ +void +grub_loongarch64_sop_32_s_10_5 (grub_loongarch64_stack_t stack, + grub_uint64_t *place) +{ + grub_uint64_t a = grub_loongarch64_stack_pop (stack); + *place |= ((a & 0x1f) << 10); +} + +/* opr1 = pop (), (*(uint32_t *) PC) [21 ... 10] = opr1 [11 ... 0] */ +void +grub_loongarch64_sop_32_u_10_12 (grub_loongarch64_stack_t stack, + grub_uint64_t *place) +{ + grub_uint64_t a = grub_loongarch64_stack_pop (stack); + *place = *place | ((a & 0xfff) << 10); +} + +/* opr1 = pop (), (*(uint32_t *) PC) [21 ... 10] = opr1 [11 ... 0] */ +void +grub_loongarch64_sop_32_s_10_12 (grub_loongarch64_stack_t stack, + grub_uint64_t *place) +{ + grub_uint64_t a = grub_loongarch64_stack_pop (stack); + *place = (*place) | ((a & 0xfff) << 10); +} + +/* opr1 = pop (), (*(uint32_t *) PC) [25 ... 10] = opr1 [15 ... 0] */ +void +grub_loongarch64_sop_32_s_10_16 (grub_loongarch64_stack_t stack, + grub_uint64_t *place) +{ + grub_uint64_t a = grub_loongarch64_stack_pop (stack); + *place = (*place) | ((a & 0xffff) << 10); +} + +/* opr1 = pop (), (*(uint32_t *) PC) [25 ... 10] = opr1 [17 ... 2] */ +void +grub_loongarch64_sop_32_s_10_16_s2 (grub_loongarch64_stack_t stack, + grub_uint64_t *place) +{ + grub_uint64_t a = grub_loongarch64_stack_pop (stack); + *place = (*place) | (((a >> 2) & 0xffff) << 10); +} + +/* opr1 = pop (), (*(uint32_t *) PC) [24 ... 5] = opr1 [19 ... 0] */ +void +grub_loongarch64_sop_32_s_5_20 (grub_loongarch64_stack_t stack, grub_uint64_t *place) +{ + grub_uint64_t a = grub_loongarch64_stack_pop (stack); + *place = (*place) | ((a & 0xfffff)<<5); +} + +/* opr1 = pop (), (*(uint32_t *) PC) [4 ... 0] = opr1 [22 ... 18] */ +void +grub_loongarch64_sop_32_s_0_5_10_16_s2 (grub_loongarch64_stack_t stack, + grub_uint64_t *place) +{ + grub_uint64_t a = grub_loongarch64_stack_pop (stack); + + *place =(*place) | (((a >> 2) & 0xffff) << 10); + *place =(*place) | ((a >> 18) & 0x1f); +} + +/* + * opr1 = pop () + * (*(uint32_t *) PC) [9 ... 0] = opr1 [27 ... 18], + * (*(uint32_t *) PC) [25 ... 10] = opr1 [17 ... 2] + */ +void +grub_loongarch64_sop_32_s_0_10_10_16_s2 (grub_loongarch64_stack_t stack, + grub_uint64_t *place) +{ + grub_uint64_t a = grub_loongarch64_stack_pop (stack); + *place =(*place) | (((a >> 2) & 0xffff) << 10); + *place =(*place) | ((a >> 18) & 0x3ff); +} + +/* + * B26 relocation for the 28-bit PC-relative jump + * (*(uint32_t *) PC) [9 ... 0] = (S + A - PC) [27 ... 18] + * (*(uint32_t *) PC) [25 ... 10] = (S + A - PC) [17 ... 2] + */ +void grub_loongarch64_b26 (grub_uint32_t *place, grub_int64_t offset) +{ + grub_uint32_t val; + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfc000000); + + grub_dprintf ("dl", " reloc_b26 %p %c= 0x%" PRIxGRUB_INT64_T "\n", + place, offset > 0 ? '+' : '-', + offset < 0 ? -offset : offset); + + val = ((offset >> 18) & 0x3ff) | (((offset >> 2) & 0xffff) << 10); + + *place &= insmask; + *place |= grub_cpu_to_le32 (val) & ~insmask; +} + +/* + * ABS_HI20/PCALA_HI20 relocations for 32/64-bit absolute address/PC-relative offset + * (*(uint32_t *) PC) [24 ... 5] = (S + A) [31 ... 12] + */ +void grub_loongarch64_xxx_hi20 (grub_uint32_t *place, grub_int64_t offset) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfe00001f); + grub_uint32_t val; + + offset >>= 12; + val = ((offset & 0xfffff) << 5); + + *place &= insmask; + *place |= grub_cpu_to_le32 (val) & ~insmask; +} + +/* + * ABS_LO12/PCALA_LO12 relocations for 32/64-bit absolute address + * (*(uint32_t *) PC) [21 ... 10] = (S + A) [11 ... 0] + */ +void grub_loongarch64_xxx_lo12 (grub_uint32_t *place, grub_int64_t offset) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff); + + *place &= insmask; + *place |= grub_cpu_to_le32 (offset << 10) & ~insmask; +} + +/* + * ABS64_HI12 relocation for the 64-bit absolute address + * (*(uint32_t *) PC) [21 ... 10] = (S + A) [63 ... 52] + */ +void grub_loongarch64_abs64_hi12 (grub_uint32_t *place, grub_int64_t offset) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff); + grub_uint32_t val; + + offset >>= 52; + val = ((offset & 0xfff) << 10); + + *place &= insmask; + *place |= grub_cpu_to_le32 (val) & ~insmask; +} + +/* + * ABS64_LO20 relocation for the 64-bit absolute address + * (*(uint32_t *) PC) [24 ... 5] = (S + A) [51 ... 32] + */ +void grub_loongarch64_abs64_lo20 (grub_uint32_t *place, grub_int64_t offset) +{ + const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfe00001f); + grub_uint32_t val; + + offset >>= 32; + val = ((offset & 0xfffff) << 5); + + *place &= insmask; + *place |= grub_cpu_to_le32 (val) & ~insmask; +} diff --git a/grub-core/kern/loongarch64/efi/init.c b/grub-core/kern/loongarch64/efi/init.c new file mode 100644 index 000000000..924b0e87d --- /dev/null +++ b/grub-core/kern/loongarch64/efi/init.c @@ -0,0 +1,77 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2023 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#define EFI_TIMER_PERIOD_MILLISECONDS(ms) ((grub_uint64_t)(ms * 10000)) + +static grub_uint64_t tmr; +static grub_efi_event_t tmr_evt; + +static grub_uint64_t +grub_efi_get_time_ms (void) +{ + return tmr; +} + +static void +grub_loongson_increment_timer (grub_efi_event_t event __attribute__ ((unused)), + void *context __attribute__ ((unused))) +{ + tmr += 10; +} + +void +grub_machine_init (void) +{ + grub_efi_boot_services_t *b; + + grub_efi_init (); + + b = grub_efi_system_table->boot_services; + b->create_event (GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL, + GRUB_EFI_TPL_CALLBACK, grub_loongson_increment_timer, NULL, &tmr_evt); + b->set_timer (tmr_evt, GRUB_EFI_TIMER_PERIODIC, EFI_TIMER_PERIOD_MILLISECONDS(10)); + + grub_install_get_time_ms (grub_efi_get_time_ms); +} + +void +grub_machine_fini (int flags) +{ + grub_efi_boot_services_t *b; + + if (!(flags & GRUB_LOADER_FLAG_NORETURN)) + return; + + b = grub_efi_system_table->boot_services; + + b->set_timer (tmr_evt, GRUB_EFI_TIMER_CANCEL, 0); + b->close_event (tmr_evt); + + grub_efi_fini (); + + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY)) + grub_efi_memory_fini (); +} diff --git a/grub-core/kern/loongarch64/efi/startup.S b/grub-core/kern/loongarch64/efi/startup.S new file mode 100644 index 000000000..87cfb23ea --- /dev/null +++ b/grub-core/kern/loongarch64/efi/startup.S @@ -0,0 +1,34 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2023 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include + + .file "startup.S" + .text + +FUNCTION(_start) + /* + * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in $a1/$a0. + */ + + la $a2, EXT_C(grub_efi_image_handle) + st.d $a0, $a2, 0 + la $a2, EXT_C(grub_efi_system_table) + st.d $a1, $a2, 0 + + b EXT_C(grub_main) diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index 326244419..143a232b8 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -29,9 +30,16 @@ #include #include #include +#include +#include + +#ifdef GRUB_MACHINE_PCBIOS +#include +#endif + +static bool cli_disabled = false; +static bool cli_need_auth = false; -/* This is actualy platform-independant but used only on loongson and sparc. */ -#if defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS) || defined (GRUB_MACHINE_SPARC64) grub_addr_t grub_modules_get_end (void) { @@ -45,7 +53,6 @@ grub_modules_get_end (void) return grub_modbase + modinfo->size; } -#endif /* Load all modules in core. */ static void @@ -67,6 +74,8 @@ grub_load_modules (void) } } +static char *load_config; + static void grub_load_config (void) { @@ -76,9 +85,17 @@ grub_load_config (void) /* Not an embedded config, skip. */ if (header->type != OBJ_TYPE_CONFIG) continue; - - grub_parser_execute ((char *) header + - sizeof (struct grub_module_header)); + + load_config = grub_malloc (header->size - sizeof (struct grub_module_header) + 1); + if (!load_config) + { + grub_print_error (); + break; + } + grub_memcpy (load_config, (char *) header + + sizeof (struct grub_module_header), + header->size - sizeof (struct grub_module_header)); + load_config[header->size - sizeof (struct grub_module_header)] = 0; break; } } @@ -114,6 +131,21 @@ grub_set_prefix_and_root (void) grub_register_variable_hook ("root", 0, grub_env_write_root); + grub_machine_get_bootlocation (&fwdevice, &fwpath); + + if (fwdevice) + { + char *cmdpath; + + cmdpath = grub_xasprintf ("(%s)%s", fwdevice, fwpath ? : ""); + if (cmdpath) + { + grub_env_set ("cmdpath", cmdpath); + grub_env_export ("cmdpath"); + grub_free (cmdpath); + } + } + if (prefix) { char *pptr = NULL; @@ -131,8 +163,6 @@ grub_set_prefix_and_root (void) if (pptr[0]) path = grub_strdup (pptr); } - if ((!device || device[0] == ',' || !device[0]) || !path) - grub_machine_get_bootlocation (&fwdevice, &fwpath); if (!device && fwdevice) device = fwdevice; @@ -168,13 +198,22 @@ grub_set_prefix_and_root (void) else grub_free (fwdevice); if (fwpath && !path) - path = fwpath; + { + grub_size_t len = grub_strlen (fwpath); + while (len > 1 && fwpath[len - 1] == '/') + fwpath[--len] = 0; + if (len >= sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1 + && grub_memcmp (fwpath + len - (sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1), GRUB_TARGET_CPU "-" GRUB_PLATFORM, + sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1) == 0) + fwpath[len - (sizeof (GRUB_TARGET_CPU "-" GRUB_PLATFORM) - 1)] = 0; + path = fwpath; + } else grub_free (fwpath); if (device) { char *prefix_set; - + prefix_set = grub_xasprintf ("(%s)%s", device, path ? : ""); if (prefix_set) { @@ -203,34 +242,129 @@ grub_load_normal_mode (void) grub_command_execute ("normal", 0, 0); } +bool +grub_is_cli_disabled (void) +{ + return cli_disabled; +} + +bool +grub_is_cli_need_auth (void) +{ + return cli_need_auth; +} + +void grub_cli_set_auth_needed (void) +{ + cli_need_auth = true; +} + +static void +check_is_cli_disabled (void) +{ + struct grub_module_header *header; + header = 0; + + FOR_MODULES (header) + { + if (header->type == OBJ_TYPE_DISABLE_CLI) + { + cli_disabled = true; + return; + } + } +} + +static void +reclaim_module_space (void) +{ + grub_addr_t modstart, modend; + + if (!grub_modbase) + return; + +#ifdef GRUB_MACHINE_PCBIOS + modstart = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR; +#else + modstart = grub_modbase; +#endif + modend = grub_modules_get_end (); + grub_modbase = 0; + +#if GRUB_KERNEL_PRELOAD_SPACE_REUSABLE + grub_mm_init_region ((void *) modstart, modend - modstart); +#else + (void) modstart; + (void) modend; +#endif +} + /* The main routine. */ void __attribute__ ((noreturn)) grub_main (void) { +#ifdef GRUB_STACK_PROTECTOR + /* + * This call should only be made from a function that does not return because + * functions that return will get instrumented to check that the stack cookie + * does not change and this call will change the stack cookie. Thus a stack + * guard failure will be triggered. + */ + grub_update_stack_guard (); +#endif + /* First of all, initialize the machine. */ grub_machine_init (); + grub_boot_time ("After machine init."); + + /* This breaks flicker-free boot on EFI systems, so disable it there. */ +#ifndef GRUB_MACHINE_EFI /* Hello. */ grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); grub_printf ("Welcome to GRUB!\n\n"); grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); +#endif + + /* Init verifiers API. */ + grub_verifiers_init (); + + grub_load_config (); + + grub_boot_time ("Before loading embedded modules."); /* Load pre-loaded modules and free the space. */ grub_register_exported_symbols (); #ifdef GRUB_LINKER_HAVE_INIT grub_arch_dl_init_linker (); -#endif +#endif grub_load_modules (); + grub_boot_time ("After loading embedded modules."); + + /* Check if the CLI should be disabled */ + check_is_cli_disabled (); + /* It is better to set the root device as soon as possible, for convenience. */ grub_set_prefix_and_root (); grub_env_export ("root"); grub_env_export ("prefix"); + /* Reclaim space used for modules. */ + reclaim_module_space (); + + grub_boot_time ("After reclaiming module space."); + grub_register_core_commands (); - grub_load_config (); + grub_boot_time ("Before execution of embedded config."); + + if (load_config) + grub_parser_execute (load_config); + + grub_boot_time ("After execution of embedded config. Attempt to go to normal mode"); + grub_load_normal_mode (); grub_rescue_run (); } diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c index 44b417147..2ed3ff319 100644 --- a/grub-core/kern/mips/arc/init.c +++ b/grub-core/kern/mips/arc/init.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include const char *type_names[] = { #ifdef GRUB_CPU_WORDS_BIGENDIAN @@ -43,13 +45,16 @@ const char *type_names[] = { "eisa", "tc", "scsi", "dti", "multi", "disk", "tape", "cdrom", "worm", "serial", "net", "video", "par", "point", "key", "audio", "other", "rdisk", "fdisk", "tape", "modem", "monitor", "print", "pointer", - "keyboard", "term", "other", "line", "network", NULL + "keyboard", "term", +#ifndef GRUB_CPU_WORDS_BIGENDIAN + "other", +#endif + "line", "network", NULL }; static int iterate_rec (const char *prefix, const struct grub_arc_component *parent, - int (*hook) (const char *name, - const struct grub_arc_component *comp), + grub_arc_iterate_devs_hook_t hook, void *hook_data, int alt_names) { const struct grub_arc_component *comp; @@ -67,12 +72,13 @@ iterate_rec (const char *prefix, const struct grub_arc_component *parent, name = grub_xasprintf ("%s%s(%lu)", prefix, cname, comp->key); if (!name) return 1; - if (hook (name, comp)) + if (hook (name, comp, hook_data)) { grub_free (name); return 1; } - if (iterate_rec ((parent ? name : prefix), comp, hook, alt_names)) + if (iterate_rec ((parent ? name : prefix), comp, hook, hook_data, + alt_names)) { grub_free (name); return 1; @@ -83,15 +89,15 @@ iterate_rec (const char *prefix, const struct grub_arc_component *parent, } int -grub_arc_iterate_devs (int (*hook) (const char *name, - const struct grub_arc_component *comp), +grub_arc_iterate_devs (grub_arc_iterate_devs_hook_t hook, void *hook_data, int alt_names) { - return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, alt_names); + return iterate_rec ((alt_names ? "arc" : ""), NULL, hook, hook_data, + alt_names); } grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { struct grub_arc_memory_descriptor *cur = NULL; while (1) @@ -120,20 +126,105 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) break; } if (hook (((grub_uint64_t) cur->start_page) << 12, - ((grub_uint64_t) cur->num_pages) << 12, type)) + ((grub_uint64_t) cur->num_pages) << 12, type, hook_data)) return GRUB_ERR_NONE; } } +char * +grub_arc_alt_name_to_norm (const char *name, const char *suffix) +{ + char *optr; + const char *iptr; + char * ret = grub_malloc (2 * grub_strlen (name) + grub_strlen (suffix)); + int state = 0; + + if (!ret) + return NULL; + optr = ret; + for (iptr = name + 4; *iptr; iptr++) + if (state == 0) + { + if (!grub_isdigit (*iptr)) + *optr++ = *iptr; + else + { + *optr++ = '('; + *optr++ = *iptr; + state = 1; + } + } + else + { + if (grub_isdigit (*iptr)) + *optr++ = *iptr; + else + { + *optr++ = ')'; + state = 0; + } + } + if (state) + *optr++ = ')'; + grub_strcpy (optr, suffix); + return ret; +} + +static char * +norm_name_to_alt (const char *name) +{ + char *optr; + const char *iptr; + int state = 0; + char * ret = grub_malloc (grub_strlen (name) + sizeof ("arc/")); + + if (!ret) + return NULL; + optr = grub_stpcpy (ret, "arc/"); + for (iptr = name; *iptr; iptr++) + { + if (state == 3) + { + *optr++ = '/'; + state = 0; + } + if (*iptr == '(') + { + state = 1; + continue; + } + if (*iptr == ')') + { + if (state == 1) + *optr++ = '0'; + state = 3; + continue; + } + *optr++ = *iptr; + if (state == 1) + state = 2; + } + *optr = '\0'; + return ret; +} + extern grub_uint32_t grub_total_modules_size __attribute__ ((section(".text"))); grub_addr_t grub_modbase; +extern char _end[]; +static char boot_location[256]; + void grub_machine_init (void) { struct grub_arc_memory_descriptor *cur = NULL; + grub_addr_t modend; - grub_modbase = GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size; + grub_memcpy (boot_location, + (char *) (GRUB_DECOMPRESSOR_LINK_ADDR - 256), 256); + + grub_modbase = ALIGN_UP ((grub_addr_t) _end, GRUB_KERNEL_MACHINE_MOD_ALIGN); + modend = grub_modbase + grub_total_modules_size; grub_console_init_early (); /* FIXME: measure this. */ @@ -153,10 +244,10 @@ grub_machine_init (void) start = ((grub_uint64_t) cur->start_page) << 12; end = ((grub_uint64_t) cur->num_pages) << 12; end += start; - if ((grub_uint64_t) end > ((GRUB_KERNEL_MIPS_ARC_LINK_ADDR - - grub_total_modules_size) & 0x1fffffff)) - end = ((GRUB_KERNEL_MIPS_ARC_LINK_ADDR - grub_total_modules_size) - & 0x1fffffff); + if ((grub_uint64_t) start < (modend & 0x1fffffff)) + start = (modend & 0x1fffffff); + if ((grub_uint64_t) end > 0x20000000) + end = 0x20000000; if (end > start) grub_mm_init_region ((void *) (grub_addr_t) (start | 0x80000000), end - start); @@ -168,7 +259,7 @@ grub_machine_init (void) } void -grub_machine_fini (void) +grub_machine_fini (int flags __attribute__ ((unused))) { } @@ -196,3 +287,177 @@ grub_exit (void) while (1); } +static char * +get_part (char *dev) +{ + char *ptr; + if (!*dev) + return 0; + ptr = dev + grub_strlen (dev) - 1; + if (ptr == dev || *ptr != ')') + return 0; + ptr--; + while (grub_isdigit (*ptr) && ptr > dev) + ptr--; + if (*ptr != '(' || ptr == dev) + return 0; + ptr--; + if (ptr - dev < (int) sizeof ("partition") - 2) + return 0; + ptr -= sizeof ("partition") - 2; + if (grub_memcmp (ptr, "partition", sizeof ("partition") - 1) != 0) + return 0; + return ptr; +} + +static grub_disk_addr_t +get_partition_offset (char *part, grub_disk_addr_t *en) +{ + grub_arc_fileno_t handle; + grub_disk_addr_t ret = -1; + struct grub_arc_fileinfo info; + grub_arc_err_t r; + + if (GRUB_ARC_FIRMWARE_VECTOR->open (part, GRUB_ARC_FILE_ACCESS_OPEN_RO, + &handle)) + return -1; + + r = GRUB_ARC_FIRMWARE_VECTOR->getfileinformation (handle, &info); + if (!r) + { + ret = (info.start >> 9); + *en = (info.end >> 9); + } + GRUB_ARC_FIRMWARE_VECTOR->close (handle); + return ret; +} + +struct get_device_name_ctx +{ + char *partition_name; + grub_disk_addr_t poff, pend; +}; + +static int +get_device_name_iter (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t part, void *data) +{ + struct get_device_name_ctx *ctx = data; + + if (grub_partition_get_start (part) == ctx->poff + && grub_partition_get_len (part) == ctx->pend) + { + ctx->partition_name = grub_partition_get_name (part); + return 1; + } + + return 0; +} + +void +grub_machine_get_bootlocation (char **device, char **path) +{ + char *loaddev = boot_location; + char *pptr, *partptr; + char *dname; + grub_disk_addr_t poff = -1, pend = -1; + struct get_device_name_ctx ctx; + grub_disk_t parent = 0; + unsigned i; + + for (i = 0; i < ARRAY_SIZE (type_names); i++) + if (type_names[i] + && grub_memcmp (loaddev, type_names[i], grub_strlen (type_names[i])) == 0 + && loaddev[grub_strlen (type_names[i])] == '(') + break; + if (i == ARRAY_SIZE (type_names)) + pptr = loaddev; + else + for (pptr = loaddev; *pptr && *pptr != '/' && *pptr != '\\'; pptr++); + if (*pptr) + { + char *iptr, *optr; + char sep = *pptr; + *path = grub_malloc (grub_strlen (pptr) + 1); + if (!*path) + return; + for (iptr = pptr, optr = *path; *iptr; iptr++, optr++) + if (*iptr == sep) + *optr = '/'; + else + *optr = *iptr; + *optr = '\0'; + *path = grub_strdup (pptr); + *pptr = '\0'; + } + + if (*loaddev == '\0') + { + const char *syspart = 0; + + if (GRUB_ARC_SYSTEM_PARAMETER_BLOCK->firmware_vector_length + >= (unsigned) ((char *) (&GRUB_ARC_FIRMWARE_VECTOR->getenvironmentvariable + 1) + - (char *) GRUB_ARC_FIRMWARE_VECTOR) + && GRUB_ARC_FIRMWARE_VECTOR->getenvironmentvariable) + syspart = GRUB_ARC_FIRMWARE_VECTOR->getenvironmentvariable ("SystemPartition"); + if (!syspart) + return; + loaddev = grub_strdup (syspart); + } + + partptr = get_part (loaddev); + if (partptr) + { + poff = get_partition_offset (loaddev, &pend); + *partptr = '\0'; + } + dname = norm_name_to_alt (loaddev); + if (poff == (grub_addr_t) -1) + { + *device = dname; + if (loaddev != boot_location) + grub_free (loaddev); + return; + } + + parent = grub_disk_open (dname); + if (!parent) + { + *device = dname; + if (loaddev != boot_location) + grub_free (loaddev); + return; + } + + if (poff == 0 + && pend == grub_disk_native_sectors (parent)) + { + grub_disk_close (parent); + *device = dname; + if (loaddev != boot_location) + grub_free (loaddev); + return; + } + + ctx.partition_name = NULL; + ctx.poff = poff; + ctx.pend = pend; + + grub_partition_iterate (parent, get_device_name_iter, &ctx); + grub_disk_close (parent); + + if (! ctx.partition_name) + { + *device = dname; + if (loaddev != boot_location) + grub_free (loaddev); + return; + } + + *device = grub_xasprintf ("%s,%s", dname, + ctx.partition_name); + grub_free (ctx.partition_name); + grub_free (dname); + if (loaddev != boot_location) + grub_free (loaddev); +} diff --git a/grub-core/kern/mips/cache.S b/grub-core/kern/mips/cache.S index 141c030e9..fa331eca1 100644 --- a/grub-core/kern/mips/cache.S +++ b/grub-core/kern/mips/cache.S @@ -4,10 +4,10 @@ .set noreorder .set nomacro -FUNCTION (grub_cpu_flush_cache) FUNCTION (grub_arch_sync_caches) #include "cache_flush.S" j $ra + nop FUNCTION (grub_arch_sync_dma_caches) move $t2, $a0 @@ -20,11 +20,11 @@ FUNCTION (grub_arch_sync_dma_caches) move $t0, $t2 subu $t1, $t3, $t2 1: - cache 1, 0($t0) + cache_op 1, 0($t0) #ifdef GRUB_MACHINE_MIPS_LOONGSON - cache 1, 1($t0) - cache 1, 2($t0) - cache 1, 3($t0) + cache_op 1, 1($t0) + cache_op 1, 2($t0) + cache_op 1, 3($t0) addiu $t1, $t1, -0x20 bne $t1, $zero, 1b @@ -34,36 +34,37 @@ FUNCTION (grub_arch_sync_dma_caches) bne $t1, $zero, 1b addiu $t0, $t0, 0x4 #endif - sync + sync_op move $t0, $t2 subu $t1, $t3, $t2 2: #ifdef GRUB_MACHINE_MIPS_LOONGSON - cache 0, 0($t0) + cache_op 0, 0($t0) addiu $t1, $t1, -0x20 bne $t1, $zero, 2b addiu $t0, $t0, 0x20 #else - cache 0, 0($t0) + cache_op 0, 0($t0) addiu $t1, $t1, -4 bne $t1, $zero, 2b addiu $t0, $t0, 0x4 #endif - sync + sync_op move $t0, $t2 subu $t1, $t3, $t2 2: #ifdef GRUB_MACHINE_MIPS_LOONGSON - cache 23, 0($t0) + cache_op 23, 0($t0) addiu $t1, $t1, -0x20 bne $t1, $zero, 2b addiu $t0, $t0, 0x20 #else - cache 23, 0($t0) + cache_op 23, 0($t0) addiu $t1, $t1, -0x4 bne $t1, $zero, 2b addiu $t0, $t0, 0x4 #endif - sync + sync_op - jr $ra \ No newline at end of file + jr $ra + nop diff --git a/grub-core/kern/mips/cache_flush.S b/grub-core/kern/mips/cache_flush.S index a5435cf51..89961a0f7 100644 --- a/grub-core/kern/mips/cache_flush.S +++ b/grub-core/kern/mips/cache_flush.S @@ -1,3 +1,17 @@ +#ifndef CACHE_OP_DEFINED +#define CACHE_OP_DEFINED 1 + .macro cache_op op addr + .set mips3 + cache \op, \addr + .set mips1 + .endm + .macro sync_op + .set mips3 + sync + .set mips1 + .endm +#endif + move $t2, $a0 addu $t3, $a0, $a1 srl $t2, $t2, 5 @@ -8,12 +22,12 @@ move $t0, $t2 subu $t1, $t3, $t2 1: - cache 1, 0($t0) + cache_op 1, 0($t0) /* All four ways. */ #ifdef GRUB_MACHINE_MIPS_LOONGSON - cache 1, 1($t0) - cache 1, 2($t0) - cache 1, 3($t0) + cache_op 1, 1($t0) + cache_op 1, 2($t0) + cache_op 1, 3($t0) addiu $t1, $t1, -0x20 bne $t1, $zero, 1b addiu $t0, $t0, 0x20 @@ -23,11 +37,11 @@ bne $t1, $zero, 1b addiu $t0, $t0, 0x4 #endif - sync + sync_op move $t0, $t2 subu $t1, $t3, $t2 2: - cache 0, 0($t0) + cache_op 0, 0($t0) #ifdef GRUB_MACHINE_MIPS_LOONGSON addiu $t1, $t1, -0x20 bne $t1, $zero, 2b @@ -37,4 +51,4 @@ bne $t1, $zero, 2b addiu $t0, $t0, 0x4 #endif - sync + sync_op diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c index ee65c9d18..5b02f97fc 100644 --- a/grub-core/kern/mips/dl.c +++ b/grub-core/kern/mips/dl.c @@ -27,6 +27,7 @@ /* Dummy __gnu_local_gp. Resolved by linker. */ static char __gnu_local_gp_dummy; +static char _gp_disp_dummy; /* Check if EHDR is a valid ELF header. */ grub_err_t @@ -51,206 +52,223 @@ grub_arch_dl_check_header (void *ehdr) #pragma GCC diagnostic ignored "-Wcast-align" -/* Relocate symbols. */ grub_err_t -grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got) { - Elf_Ehdr *e = ehdr; - Elf_Shdr *s; - Elf_Word entsize; - unsigned i; - grub_size_t gp_size = 0; + const Elf_Ehdr *e = ehdr; + const Elf_Shdr *s; /* FIXME: suboptimal. */ - grub_uint32_t *gp, *gpptr; - grub_uint32_t gp0; + grub_size_t gp_size = 0; + unsigned i; - /* Find a symbol table. */ - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + *tramp = 0; + *got = 0; + + for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff); i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_SYMTAB) - break; - - if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); - - entsize = s->sh_entsize; - - /* Find reginfo. */ - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_MIPS_REGINFO) - break; - - if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, "no reginfo found"); - - gp0 = ((grub_uint32_t *)((char *) e + s->sh_offset))[5]; - - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize)) if (s->sh_type == SHT_REL) { - grub_dl_segment_t seg; + const Elf_Rel *rel, *max; - /* Find the target segment. */ - for (seg = mod->segment; seg; seg = seg->next) - if (seg->section == s->sh_info) - break; - - if (seg) - { - Elf_Rel *rel, *max; - - for (rel = (Elf_Rel *) ((char *) e + s->sh_offset), - max = rel + s->sh_size / s->sh_entsize; - rel < max; - rel++) - switch (ELF_R_TYPE (rel->r_info)) - { - case R_MIPS_GOT16: - case R_MIPS_CALL16: - case R_MIPS_GPREL32: - gp_size += 4; - break; - } - } + for (rel = (const Elf_Rel *) ((const char *) e + s->sh_offset), + max = rel + s->sh_size / s->sh_entsize; + rel < max; + rel++) + switch (ELF_R_TYPE (rel->r_info)) + { + case R_MIPS_GOT16: + case R_MIPS_CALL16: + case R_MIPS_GPREL32: + gp_size += 4; + break; + } } if (gp_size > 0x08000) return grub_error (GRUB_ERR_OUT_OF_RANGE, "__gnu_local_gp is too big\n"); - gpptr = gp = grub_malloc (gp_size); - if (!gp) - return grub_errno; - - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_REL) - { - grub_dl_segment_t seg; - - /* Find the target segment. */ - for (seg = mod->segment; seg; seg = seg->next) - if (seg->section == s->sh_info) - break; - - if (seg) - { - Elf_Rel *rel, *max; - - for (rel = (Elf_Rel *) ((char *) e + s->sh_offset), - max = rel + s->sh_size / s->sh_entsize; - rel < max; - rel++) - { - grub_uint8_t *addr; - Elf_Sym *sym; - - if (seg->size < rel->r_offset) - return grub_error (GRUB_ERR_BAD_MODULE, - "reloc offset is out of the segment"); - - addr = (grub_uint8_t *) ((char *) seg->addr + rel->r_offset); - sym = (Elf_Sym *) ((char *) mod->symtab - + entsize * ELF_R_SYM (rel->r_info)); - if (sym->st_value == (grub_addr_t) &__gnu_local_gp_dummy) - sym->st_value = (grub_addr_t) gp; - - switch (ELF_R_TYPE (rel->r_info)) - { - case R_MIPS_HI16: - { - grub_uint32_t value; - Elf_Rel *rel2; - -#ifdef GRUB_CPU_WORDS_BIGENDIAN - addr += 2; -#endif - - /* Handle partner lo16 relocation. Lower part is - treated as signed. Hence add 0x8000 to compensate. - */ - value = (*(grub_uint16_t *) addr << 16) - + sym->st_value + 0x8000; - for (rel2 = rel + 1; rel2 < max; rel2++) - if (ELF_R_SYM (rel2->r_info) - == ELF_R_SYM (rel->r_info) - && ELF_R_TYPE (rel2->r_info) == R_MIPS_LO16) - { - value += *(grub_int16_t *) - ((char *) seg->addr + rel2->r_offset -#ifdef GRUB_CPU_WORDS_BIGENDIAN - + 2 -#endif - ); - break; - } - *(grub_uint16_t *) addr = (value >> 16) & 0xffff; - } - break; - case R_MIPS_LO16: -#ifdef GRUB_CPU_WORDS_BIGENDIAN - addr += 2; -#endif - *(grub_uint16_t *) addr += (sym->st_value) & 0xffff; - break; - case R_MIPS_32: - *(grub_uint32_t *) addr += sym->st_value; - break; - case R_MIPS_GPREL32: - *(grub_uint32_t *) addr = sym->st_value - + *(grub_uint32_t *) addr + gp0 - (grub_uint32_t)gp; - break; - - case R_MIPS_26: - { - grub_uint32_t value; - grub_uint32_t raw; - raw = (*(grub_uint32_t *) addr) & 0x3ffffff; - value = raw << 2; - value += sym->st_value; - raw = (value >> 2) & 0x3ffffff; - - *(grub_uint32_t *) addr = - raw | ((*(grub_uint32_t *) addr) & 0xfc000000); - } - break; - case R_MIPS_GOT16: - case R_MIPS_CALL16: - /* FIXME: reuse*/ -#ifdef GRUB_CPU_WORDS_BIGENDIAN - addr += 2; -#endif - *gpptr = sym->st_value + *(grub_uint16_t *) addr; - *(grub_uint16_t *) addr - = sizeof (grub_uint32_t) * (gpptr - gp); - gpptr++; - break; - case R_MIPS_JALR: - break; - default: - { - grub_free (gp); - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("relocation 0x%x is not implemented yet"), - ELF_R_TYPE (rel->r_info)); - } - break; - } - } - } - } + *got = gp_size; return GRUB_ERR_NONE; } -void +/* Relocate symbols. */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg) +{ + grub_uint32_t gp0; + Elf_Ehdr *e = ehdr; + + if (!mod->reginfo) + { + unsigned i; + Elf_Shdr *ri; + + /* Find reginfo. */ + for (i = 0, ri = (Elf_Shdr *) ((char *) ehdr + e->e_shoff); + i < e->e_shnum; + i++, ri = (Elf_Shdr *) ((char *) ri + e->e_shentsize)) + if (ri->sh_type == SHT_MIPS_REGINFO) + break; + if (i == e->e_shnum) + return grub_error (GRUB_ERR_BAD_MODULE, "no reginfo found"); + mod->reginfo = (grub_uint32_t *)((char *) ehdr + ri->sh_offset); + } + + gp0 = mod->reginfo[5]; + Elf_Rel *rel, *max; + + for (rel = (Elf_Rel *) ((char *) e + s->sh_offset), + max = (Elf_Rel *) ((char *) rel + s->sh_size); + rel < max; + rel = (Elf_Rel *) ((char *) rel + s->sh_entsize)) + { + grub_uint8_t *addr; + Elf_Sym *sym; + grub_uint32_t sym_value; + + if (seg->size < rel->r_offset) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + + addr = (grub_uint8_t *) ((char *) seg->addr + rel->r_offset); + sym = (Elf_Sym *) ((char *) mod->symtab + + mod->symsize * ELF_R_SYM (rel->r_info)); + sym_value = sym->st_value; + if (s->sh_type == SHT_RELA) + { + sym_value += ((Elf_Rela *) rel)->r_addend; + } + if (sym_value == (grub_addr_t) &__gnu_local_gp_dummy) + sym_value = (grub_addr_t) mod->got; + else if (sym_value == (grub_addr_t) &_gp_disp_dummy) + { + sym_value = (grub_addr_t) mod->got - (grub_addr_t) addr; + if (ELF_R_TYPE (rel->r_info) == R_MIPS_LO16) + /* ABI mandates +4 even if partner lui doesn't + immediately precede addiu. */ + sym_value += 4; + } + switch (ELF_R_TYPE (rel->r_info)) + { + case R_MIPS_HI16: + { + grub_uint32_t value; + Elf_Rel *rel2; + +#ifdef GRUB_CPU_WORDS_BIGENDIAN + addr += 2; +#endif + + /* Handle partner lo16 relocation. Lower part is + treated as signed. Hence add 0x8000 to compensate. + */ + value = (*(grub_uint16_t *) addr << 16) + + sym_value + 0x8000; + for (rel2 = rel + 1; rel2 < max; rel2++) + if (ELF_R_SYM (rel2->r_info) + == ELF_R_SYM (rel->r_info) + && ELF_R_TYPE (rel2->r_info) == R_MIPS_LO16) + { + value += *(grub_int16_t *) + ((char *) seg->addr + rel2->r_offset +#ifdef GRUB_CPU_WORDS_BIGENDIAN + + 2 +#endif + ); + break; + } + *(grub_uint16_t *) addr = (value >> 16) & 0xffff; + } + break; + case R_MIPS_LO16: +#ifdef GRUB_CPU_WORDS_BIGENDIAN + addr += 2; +#endif + *(grub_uint16_t *) addr += sym_value & 0xffff; + break; + case R_MIPS_32: + *(grub_uint32_t *) addr += sym_value; + break; + case R_MIPS_GPREL32: + *(grub_uint32_t *) addr = sym_value + + *(grub_uint32_t *) addr + gp0 - (grub_uint32_t)mod->got; + break; + + case R_MIPS_26: + { + grub_uint32_t value; + grub_uint32_t raw; + raw = (*(grub_uint32_t *) addr) & 0x3ffffff; + value = raw << 2; + value += sym_value; + raw = (value >> 2) & 0x3ffffff; + + *(grub_uint32_t *) addr = + raw | ((*(grub_uint32_t *) addr) & 0xfc000000); + } + break; + case R_MIPS_GOT16: + if (ELF_ST_BIND (sym->st_info) == STB_LOCAL) + { + Elf_Rel *rel2; + /* Handle partner lo16 relocation. Lower part is + treated as signed. Hence add 0x8000 to compensate. + */ + sym_value += (*(grub_uint16_t *) addr << 16) + + 0x8000; + for (rel2 = rel + 1; rel2 < max; rel2++) + if (ELF_R_SYM (rel2->r_info) + == ELF_R_SYM (rel->r_info) + && ELF_R_TYPE (rel2->r_info) == R_MIPS_LO16) + { + sym_value += *(grub_int16_t *) + ((char *) seg->addr + rel2->r_offset +#ifdef GRUB_CPU_WORDS_BIGENDIAN + + 2 +#endif + ); + break; + } + sym_value &= 0xffff0000; + *(grub_uint16_t *) addr = 0; + } + /* Fallthrough. */ + case R_MIPS_CALL16: + { + grub_uint32_t *gpptr = mod->gotptr; + /* FIXME: reuse*/ +#ifdef GRUB_CPU_WORDS_BIGENDIAN + addr += 2; +#endif + *gpptr = sym_value + *(grub_uint16_t *) addr; + *(grub_uint16_t *) addr + = sizeof (grub_uint32_t) * (gpptr - (grub_uint32_t *) mod->got); + mod->gotptr = gpptr + 1; + break; + } + case R_MIPS_JALR: + break; + default: + { + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%x is not implemented yet"), + ELF_R_TYPE (rel->r_info)); + } + break; + } + } + + return GRUB_ERR_NONE; +} + +void grub_arch_dl_init_linker (void) { grub_dl_register_symbol ("__gnu_local_gp", &__gnu_local_gp_dummy, 0, 0); + grub_dl_register_symbol ("_gp_disp", &_gp_disp_dummy, 0, 0); } diff --git a/grub-core/kern/mips/init.c b/grub-core/kern/mips/init.c index 353f679e6..14b8752ec 100644 --- a/grub-core/kern/mips/init.c +++ b/grub-core/kern/mips/init.c @@ -36,9 +36,3 @@ grub_get_rtc (void) return (((grub_uint64_t) high) << 32) | low; } - -void -grub_machine_get_bootlocation (char **device __attribute__ ((unused)), - char **path __attribute__ ((unused))) -{ -} diff --git a/grub-core/kern/mips/loongson/init.c b/grub-core/kern/mips/loongson/init.c index 19f2d639b..5bd721260 100644 --- a/grub-core/kern/mips/loongson/init.c +++ b/grub-core/kern/mips/loongson/init.c @@ -40,54 +40,57 @@ #include grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { hook (GRUB_ARCH_LOWMEMPSTART, grub_arch_memsize << 20, - GRUB_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE, hook_data); hook (GRUB_ARCH_HIGHMEMPSTART, grub_arch_highmemsize << 20, - GRUB_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE, hook_data); return GRUB_ERR_NONE; } +/* Helper for init_pci. */ +static int +set_card (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + grub_pci_address_t addr; + /* We could use grub_pci_assign_addresses for this but we prefer to + have exactly same memory map as on pmon. */ + switch (pciid) + { + case GRUB_LOONGSON_OHCI_PCIID: + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, 0x5025000); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE + | GRUB_PCI_COMMAND_PARITY_ERROR + | GRUB_PCI_COMMAND_BUS_MASTER + | GRUB_PCI_COMMAND_MEM_ENABLED); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); + grub_pci_write_word (addr, 0x0200 | GRUB_PCI_STATUS_CAPABILITIES); + break; + case GRUB_LOONGSON_EHCI_PCIID: + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, 0x5026000); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE + | GRUB_PCI_COMMAND_PARITY_ERROR + | GRUB_PCI_COMMAND_BUS_MASTER + | GRUB_PCI_COMMAND_MEM_ENABLED); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); + grub_pci_write_word (addr, (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) + | GRUB_PCI_STATUS_CAPABILITIES); + break; + } + return 0; +} + static void init_pci (void) { - auto int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid); - int NESTED_FUNC_ATTR set_card (grub_pci_device_t dev, grub_pci_id_t pciid) - { - grub_pci_address_t addr; - /* FIXME: autoscan for BARs and devices. */ - switch (pciid) - { - case GRUB_LOONGSON_OHCI_PCIID: - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - grub_pci_write (addr, 0x5025000); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE - | GRUB_PCI_COMMAND_PARITY_ERROR - | GRUB_PCI_COMMAND_BUS_MASTER - | GRUB_PCI_COMMAND_MEM_ENABLED); - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); - grub_pci_write_word (addr, 0x0200 | GRUB_PCI_STATUS_CAPABILITIES); - break; - case GRUB_LOONGSON_EHCI_PCIID: - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - grub_pci_write (addr, 0x5026000); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write_word (addr, GRUB_PCI_COMMAND_SERR_ENABLE - | GRUB_PCI_COMMAND_PARITY_ERROR - | GRUB_PCI_COMMAND_BUS_MASTER - | GRUB_PCI_COMMAND_MEM_ENABLED); - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_STATUS); - grub_pci_write_word (addr, (1 << GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT) - | GRUB_PCI_STATUS_CAPABILITIES); - break; - } - return 0; - } - *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_LO) = 0x8000000c; *((volatile grub_uint32_t *) GRUB_CPU_LOONGSON_PCI_HIT1_SEL_HI) = 0xffffffff; @@ -104,13 +107,13 @@ init_pci (void) *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + GRUB_PCI_REG_CACHELINE)) = 0xff; - *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + GRUB_PCI_REG_ADDRESS_REG0)) = 0x80000000 | GRUB_PCI_ADDR_MEM_TYPE_64 | GRUB_PCI_ADDR_MEM_PREFETCH; - *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + *((volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONTROLLER_HEADER + GRUB_PCI_REG_ADDRESS_REG1)) = 0; - grub_pci_iterate (set_card); + grub_pci_iterate (set_card, NULL); } void @@ -126,12 +129,19 @@ grub_machine_init (void) /* Loongson 2E. */ case 0x6302: grub_arch_machine = GRUB_ARCH_MACHINE_FULOONG2E; + grub_bonito_type = GRUB_BONITO_2F; break; /* Loongson 2F. */ case 0x6303: if (grub_arch_machine != GRUB_ARCH_MACHINE_FULOONG2F && grub_arch_machine != GRUB_ARCH_MACHINE_YEELOONG) grub_arch_machine = GRUB_ARCH_MACHINE_YEELOONG; + grub_bonito_type = GRUB_BONITO_2F; + break; + /* Loongson 3A. */ + case 0x6305: + grub_arch_machine = GRUB_ARCH_MACHINE_YEELOONG_3A; + grub_bonito_type = GRUB_BONITO_3A; break; } @@ -173,7 +183,7 @@ grub_machine_init (void) else totalmem = ((spd.ddr2.num_of_ranks & GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_MASK) + 1) << (i + 2); - + if (totalmem >= 256) { grub_arch_memsize = 256; @@ -200,11 +210,13 @@ grub_machine_init (void) grub_video_sm712_init (); grub_video_sis315pro_init (); grub_video_radeon_fuloong2e_init (); + grub_video_radeon_yeeloong3a_init (); grub_font_init (); grub_gfxterm_init (); grub_keylayouts_init (); - if (grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG) + if (grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG + || grub_arch_machine == GRUB_ARCH_MACHINE_YEELOONG_3A) grub_at_keyboard_init (); grub_terminfo_init (); @@ -214,16 +226,49 @@ grub_machine_init (void) } void -grub_machine_fini (void) +grub_machine_fini (int flags __attribute__ ((unused))) { } +static int +halt_via (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + grub_uint16_t pm; + grub_pci_address_t addr; + + if (pciid != 0x30571106) + return 0; + + addr = grub_pci_make_address (dev, 0x40); + pm = grub_pci_read (addr) & ~1; + + if (pm == 0) + { + grub_pci_write (addr, 0x1801); + pm = 0x1800; + } + + addr = grub_pci_make_address (dev, 0x80); + grub_pci_write_byte (addr, 0xff); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write_word (addr, grub_pci_read_word (addr) | GRUB_PCI_COMMAND_IO_ENABLED); + + /* FIXME: This one is derived from qemu. Check on real hardware. */ + grub_outw (0x2000, pm + 4 + GRUB_MACHINE_PCI_IO_BASE); + grub_millisleep (5000); + + return 0; +} + void grub_halt (void) { switch (grub_arch_machine) { case GRUB_ARCH_MACHINE_FULOONG2E: + grub_pci_iterate (halt_via, NULL); break; case GRUB_ARCH_MACHINE_FULOONG2F: { @@ -244,6 +289,13 @@ grub_halt (void) & ~GRUB_CPU_YEELOONG_SHUTDOWN_GPIO, GRUB_CPU_LOONGSON_GPIOCFG); grub_millisleep (1500); break; + case GRUB_ARCH_MACHINE_YEELOONG_3A: + grub_millisleep (1); + grub_outb (0x4e, GRUB_MACHINE_PCI_IO_BASE_3A | 0x66); + grub_millisleep (1); + grub_outb (2, GRUB_MACHINE_PCI_IO_BASE_3A | 0x62); + grub_millisleep (5000); + break; } grub_puts_ (N_("Shutdown failed")); @@ -257,6 +309,12 @@ grub_exit (void) grub_halt (); } +void +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) +{ +} + extern char _end[]; grub_addr_t grub_modbase = (grub_addr_t) _end; diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index 782f17fbf..b5477b87f 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -41,7 +41,7 @@ grub_machine_init (void) if (grub_arch_memsize == 0) { int i; - + for (i = 27; i >= 0; i--) if (probe_mem (grub_arch_memsize | (1 << i))) grub_arch_memsize |= (1 << i); @@ -49,7 +49,7 @@ grub_machine_init (void) } /* FIXME: measure this. */ - grub_arch_cpuclock = 64000000; + grub_arch_cpuclock = 200000000; modend = grub_modules_get_end (); grub_mm_init_region ((void *) modend, grub_arch_memsize @@ -57,8 +57,6 @@ grub_machine_init (void) grub_install_get_time_ms (grub_rtc_get_time_ms); - grub_font_init (); - grub_keylayouts_init (); grub_at_keyboard_init (); @@ -69,12 +67,10 @@ grub_machine_init (void) grub_serial_init (); grub_boot_init (); - - grub_gfxterm_init (); } void -grub_machine_fini (void) +grub_machine_fini (int flags __attribute__ ((unused))) { } @@ -91,13 +87,19 @@ grub_halt (void) while (1); } -grub_err_t -grub_machine_mmap_iterate (grub_memory_hook_t hook) +grub_err_t +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) { - hook (0, grub_arch_memsize, GRUB_MEMORY_AVAILABLE); + hook (0, grub_arch_memsize, GRUB_MEMORY_AVAILABLE, hook_data); return GRUB_ERR_NONE; } +void +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) +{ +} + extern char _end[]; grub_addr_t grub_modbase = (grub_addr_t) _end; diff --git a/grub-core/kern/mips/startup.S b/grub-core/kern/mips/startup.S index 2476038bc..1fdb58aca 100644 --- a/grub-core/kern/mips/startup.S +++ b/grub-core/kern/mips/startup.S @@ -22,6 +22,7 @@ #include #include #include +#include #define BASE_ADDR 8 @@ -36,7 +37,7 @@ start: bal cont nop - . = _start + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE + .org GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE VARIABLE(grub_total_modules_size) .long 0 @@ -73,7 +74,6 @@ cont: #endif /* Move the modules out of BSS. */ -#ifndef GRUB_MACHINE_ARC lui $t2, %hi(__bss_start) addiu $t2, %lo(__bss_start) @@ -96,14 +96,13 @@ cont: modulesmovcont: beq $t3, $0, modulesmovdone nop - lb $t4, 0($t2) - sb $t4, 0($t1) + lb GRUB_ASM_T4, 0($t2) + sb GRUB_ASM_T4, 0($t1) addiu $t2, $t2, -1 addiu $t1, $t1, -1 b modulesmovcont addiu $t3, $t3, -1 modulesmovdone: -#endif /* Clean BSS. */ @@ -118,10 +117,10 @@ bsscont: bne $t3, $0, bsscont nop - lui $t1, %hi(grub_main) - addiu $t1, %lo(grub_main) + lui $t9, %hi(grub_main) + addiu $t9, %lo(grub_main) lui $sp, %hi(GRUB_MACHINE_MEMORY_STACK_HIGH) - jr $t1 + jr $t9 addiu $sp, $sp, %lo(GRUB_MACHINE_MEMORY_STACK_HIGH) diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index 95d46245e..2b7922393 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -24,9 +24,44 @@ #include #include #include +#include +#include +union printf_arg +{ + /* Yes, type is also part of union as the moment we fill the value + we don't need to store its type anymore (when we'll need it, we'll + have format spec again. So save some space. */ + enum + { + INT, LONG, LONGLONG, + UNSIGNED_INT = 3, UNSIGNED_LONG, UNSIGNED_LONGLONG, + STRING, + GUID + } type; + long long ll; +}; + +struct printf_args +{ + union printf_arg prealloc[32]; + union printf_arg *ptr; + grub_size_t count; +}; + +static void +parse_printf_args (const char *fmt0, struct printf_args *args, + va_list args_in); static int -grub_vsnprintf_real (char *str, grub_size_t n, const char *fmt, va_list args); +grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, + struct printf_args *args); + +static void +free_printf_args (struct printf_args *args) +{ + if (args->ptr != args->prealloc) + grub_free (args->ptr); +} static int grub_iswordseparator (int c) @@ -64,25 +99,6 @@ grub_memmove (void *dest, const void *src, grub_size_t n) return dest; } -#ifndef __APPLE__ -void *memmove (void *dest, const void *src, grub_size_t n) - __attribute__ ((alias ("grub_memmove"))); -/* GCC emits references to memcpy() for struct copies etc. */ -void *memcpy (void *dest, const void *src, grub_size_t n) - __attribute__ ((alias ("grub_memmove"))); -#else -void * __attribute__ ((regparm(0))) -memcpy (void *dest, const void *src, grub_size_t n) -{ - return grub_memmove (dest, src, n); -} -void * __attribute__ ((regparm(0))) -memmove (void *dest, const void *src, grub_size_t n) -{ - return grub_memmove (dest, src, n); -} -#endif - char * grub_strcpy (char *dest, const char *src) { @@ -94,27 +110,36 @@ grub_strcpy (char *dest, const char *src) return dest; } -char * -grub_strncpy (char *dest, const char *src, int c) -{ - char *p = dest; - - while ((*p++ = *src++) != '\0' && --c) - ; - - return dest; -} - int grub_printf (const char *fmt, ...) { va_list ap; int ret; +#if defined(MM_DEBUG) && !defined(GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) + /* + * To prevent infinite recursion when grub_mm_debug is on, disable it + * when calling grub_vprintf(). One such call loop is: + * grub_vprintf() -> parse_printf_args() -> parse_printf_arg_fmt() -> + * grub_debug_calloc() -> grub_printf() -> grub_vprintf(). + */ + int grub_mm_debug_save = 0; + + if (grub_mm_debug) + { + grub_mm_debug_save = grub_mm_debug; + grub_mm_debug = 0; + } +#endif + va_start (ap, fmt); ret = grub_vprintf (fmt, ap); va_end (ap); +#if defined(MM_DEBUG) && !defined(GRUB_UTIL) && !defined (GRUB_MACHINE_EMU) + grub_mm_debug = grub_mm_debug_save; +#endif + return ret; } @@ -157,19 +182,63 @@ int grub_err_printf (const char *fmt, ...) __attribute__ ((alias("grub_printf"))); #endif +int +grub_debug_enabled (const char * condition) +{ + const char *debug, *found; + grub_size_t clen; + int ret = 0; + + debug = grub_env_get ("debug"); + if (!debug) + return 0; + + if (grub_strword (debug, "all")) + { + if (debug[3] == '\0') + return 1; + ret = 1; + } + + clen = grub_strlen (condition); + found = debug-1; + while(1) + { + found = grub_strstr (found+1, condition); + + if (found == NULL) + break; + + /* Found condition is not a whole word, so ignore it. */ + if (*(found + clen) != '\0' && *(found + clen) != ',' + && !grub_isspace (*(found + clen))) + continue; + + /* + * If found condition is at the start of debug or the start is on a word + * boundary, then enable debug. Else if found condition is prefixed with + * '-' and the start is on a word boundary, then disable debug. If none + * of these cases, ignore. + */ + if (found == debug || *(found - 1) == ',' || grub_isspace (*(found - 1))) + ret = 1; + else if (*(found - 1) == '-' && ((found == debug + 1) || (*(found - 2) == ',' + || grub_isspace (*(found - 2))))) + ret = 0; + } + + return ret; +} + void grub_real_dprintf (const char *file, const int line, const char *condition, const char *fmt, ...) { va_list args; - const char *debug = grub_env_get ("debug"); - if (! debug) - return; - - if (grub_strword (debug, "all") || grub_strword (debug, condition)) + if (grub_debug_enabled (condition)) { - grub_printf ("%s:%d: ", file, line); + grub_printf ("%s:%d:%s: ", file, line, condition); va_start (args, fmt); grub_vprintf (fmt, args); va_end (args); @@ -180,15 +249,16 @@ grub_real_dprintf (const char *file, const int line, const char *condition, #define PREALLOC_SIZE 255 int -grub_vprintf (const char *fmt, va_list args) +grub_vprintf (const char *fmt, va_list ap) { grub_size_t s; static char buf[PREALLOC_SIZE + 1]; char *curbuf = buf; - va_list ap2; - va_copy (ap2, args); + struct printf_args args; - s = grub_vsnprintf_real (buf, PREALLOC_SIZE, fmt, args); + parse_printf_args (fmt, &args, ap); + + s = grub_vsnprintf_real (buf, PREALLOC_SIZE, fmt, &args); if (s > PREALLOC_SIZE) { curbuf = grub_malloc (s + 1); @@ -202,16 +272,16 @@ grub_vprintf (const char *fmt, va_list args) curbuf = buf; } else - s = grub_vsnprintf_real (curbuf, s, fmt, ap2); + s = grub_vsnprintf_real (curbuf, s, fmt, &args); } - va_end (ap2); + free_printf_args (&args); grub_xputs (curbuf); if (curbuf != buf) grub_free (curbuf); - + return s; } @@ -232,16 +302,6 @@ grub_memcmp (const void *s1, const void *s2, grub_size_t n) return 0; } -#ifndef __APPLE__ -int memcmp (const void *s1, const void *s2, grub_size_t n) - __attribute__ ((alias ("grub_memcmp"))); -#else -int __attribute__ ((regparm(0))) -memcmp (const void *s1, const void *s2, grub_size_t n) -{ - return grub_memcmp (s1, s2, n); -} -#endif int grub_strcmp (const char *s1, const char *s2) @@ -347,15 +407,9 @@ grub_isspace (int c) return (c == '\n' || c == '\r' || c == ' ' || c == '\t'); } -int -grub_isprint (int c) -{ - return (c >= ' ' && c <= '~'); -} - - unsigned long -grub_strtoul (const char *str, char **end, int base) +grub_strtoul (const char * restrict str, const char ** const restrict end, + int base) { unsigned long long num; @@ -372,13 +426,15 @@ grub_strtoul (const char *str, char **end, int base) } unsigned long long -grub_strtoull (const char *str, char **end, int base) +grub_strtoull (const char * restrict str, const char ** const restrict end, + int base) { unsigned long long num = 0; int found = 0; /* Skip white spaces. */ - while (*str && grub_isspace (*str)) + /* grub_isspace checks that *str != '\0'. */ + while (grub_isspace (*str)) str++; /* Guess the base, if not specified. The prefix `0x' means 16, and @@ -405,12 +461,13 @@ grub_strtoull (const char *str, char **end, int base) unsigned long digit; digit = grub_tolower (*str) - '0'; - if (digit > 9) - { - digit += '0' - 'a' + 10; - if (digit >= (unsigned long) base) - break; - } + if (digit >= 'a' - '0') + digit += '0' - 'a' + 10; + else if (digit > 9) + break; + + if (digit >= (unsigned long) base) + break; found = 1; @@ -419,6 +476,10 @@ grub_strtoull (const char *str, char **end, int base) { grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + + if (end) + *end = (char *) str; + return ~0ULL; } @@ -430,6 +491,10 @@ grub_strtoull (const char *str, char **end, int base) { grub_error (GRUB_ERR_BAD_NUMBER, N_("unrecognized number")); + + if (end) + *end = (char *) str; + return 0; } @@ -471,6 +536,15 @@ grub_strndup (const char *s, grub_size_t n) return p; } +/* clang detects that we're implementing here a memset so it decides to + optimise and calls memset resulting in infinite recursion. With volatile + we make it not optimise in this way. */ +#ifdef __clang__ +#define VOLATILE_CLANG volatile +#else +#define VOLATILE_CLANG +#endif + void * grub_memset (void *s, int c, grub_size_t len) { @@ -487,13 +561,13 @@ grub_memset (void *s, int c, grub_size_t len) while (len > 0 && (((grub_addr_t) p) & (sizeof (unsigned long) - 1))) { - *(grub_uint8_t *) p = pattern8; + *(VOLATILE_CLANG grub_uint8_t *) p = pattern8; p = (grub_uint8_t *) p + 1; len--; } while (len >= sizeof (unsigned long)) { - *(unsigned long *) p = patternl; + *(VOLATILE_CLANG unsigned long *) p = patternl; p = (unsigned long *) p + 1; len -= sizeof (unsigned long); } @@ -501,23 +575,13 @@ grub_memset (void *s, int c, grub_size_t len) while (len > 0) { - *(grub_uint8_t *) p = pattern8; + *(VOLATILE_CLANG grub_uint8_t *) p = pattern8; p = (grub_uint8_t *) p + 1; len--; } return s; } -#ifndef __APPLE__ -void *memset (void *s, int c, grub_size_t n) - __attribute__ ((alias ("grub_memset"))); -#else -void * __attribute__ ((regparm(0))) -memset (void *s, int c, grub_size_t n) -{ - return grub_memset (s, c, n); -} -#endif grub_size_t grub_strlen (const char *s) @@ -559,6 +623,11 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) grub_uint64_t q = 0; grub_uint64_t m = 0; + /* ARM and IA64 don't have a fast 32-bit division. + Using that code would just make us use software division routines, calling + ourselves indirectly and hence getting infinite recursion. + */ +#if !GRUB_DIVISION_IN_SOFTWARE /* Skip the slow computation if 32-bit arithmetic is possible. */ if (n < 0xffffffff && d < 0xffffffff) { @@ -567,6 +636,7 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) return ((grub_uint32_t) n) / (grub_uint32_t) d; } +#endif while (bits--) { @@ -593,10 +663,10 @@ grub_divmod64 (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r) /* Convert a long long value to a string. This function avoids 64-bit modular arithmetic or divisions. */ -static char * +static inline char * grub_lltoa (char *str, int c, unsigned long long n) { - unsigned base = (c == 'x') ? 16 : 10; + unsigned base = ((c == 'x') || (c == 'X')) ? 16 : ((c == 'o') ? 8 : 10); char *p; if ((long long) n < 0 && c == 'd') @@ -611,9 +681,15 @@ grub_lltoa (char *str, int c, unsigned long long n) do { unsigned d = (unsigned) (n & 0xf); - *p++ = (d > 9) ? d + 'a' - 10 : d + '0'; + *p++ = (d > 9) ? (d + ((c == 'x') ? 'a' : 'A') - 10) : d + '0'; } while (n >>= 4); + else if (base == 8) + do + { + *p++ = ((unsigned) (n & 0x7)) + '0'; + } + while (n >>= 3); else /* BASE == 10 */ do @@ -631,38 +707,38 @@ grub_lltoa (char *str, int c, unsigned long long n) return p; } -static int -grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list args_in) +/* + * Parse printf() fmt0 string into args arguments. + * + * The parsed arguments are either used by a printf() function to format the fmt0 + * string or they are used to compare a format string from an untrusted source + * against a format string with expected arguments. + * + * When the fmt_check is set to !0, e.g. 1, then this function is executed in + * printf() format check mode. This enforces stricter rules for parsing the + * fmt0 to limit exposure to possible errors in printf() handling. It also + * disables positional parameters, "$", because some formats, e.g "%s%1$d", + * cannot be validated with the current implementation. + * + * The max_args allows to set a maximum number of accepted arguments. If the fmt0 + * string defines more arguments than the max_args then the parse_printf_arg_fmt() + * function returns an error. This is currently used for format check only. + */ +static grub_err_t +parse_printf_arg_fmt (const char *fmt0, struct printf_args *args, + int fmt_check, grub_size_t max_args) { + const char *fmt; char c; grub_size_t n = 0; - grub_size_t count = 0; - grub_size_t count_args = 0; - const char *fmt; - auto void write_char (unsigned char ch); - auto void write_str (const char *s); - auto void write_fill (const char ch, int n); - void write_char (unsigned char ch) - { - if (count < max_len) - *str++ = ch; + args->count = 0; - count++; - } - - void write_str (const char *s) - { - while (*s) - write_char (*s++); - } - - void write_fill (const char ch, int count_fill) - { - int i; - for (i = 0; i < count_fill; i++) - write_char (ch); - } + COMPILE_TIME_ASSERT (sizeof (int) == sizeof (grub_uint32_t)); + COMPILE_TIME_ASSERT (sizeof (int) <= sizeof (long long)); + COMPILE_TIME_ASSERT (sizeof (long) <= sizeof (long long)); + COMPILE_TIME_ASSERT (sizeof (long long) == sizeof (void *) + || sizeof (int) == sizeof (void *)); fmt = fmt0; while ((c = *fmt++) != 0) @@ -670,67 +746,91 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a if (c != '%') continue; - if (*fmt && *fmt =='-') + if (*fmt =='-') fmt++; - while (*fmt && grub_isdigit (*fmt)) + while (grub_isdigit (*fmt)) fmt++; - if (*fmt && *fmt == '$') + if (*fmt == '$') + { + if (fmt_check) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "positional arguments are not supported"); + fmt++; + } + + if (*fmt =='-') fmt++; - if (*fmt && *fmt =='-') + while (grub_isdigit (*fmt)) fmt++; - while (*fmt && grub_isdigit (*fmt)) + if (*fmt =='.') fmt++; - if (*fmt && *fmt =='.') - fmt++; - - while (*fmt && grub_isdigit (*fmt)) + while (grub_isdigit (*fmt)) fmt++; c = *fmt++; if (c == 'l') - { - c = *fmt++; - if (c == 'l') - c = *fmt++; - } + c = *fmt++; + if (c == 'l') + c = *fmt++; + switch (c) { case 'p': + if (*(fmt) == 'G') + ++fmt; + /* Fall through. */ case 'x': + case 'X': case 'u': case 'd': + case 'o': case 'c': case 'C': case 's': - count_args++; + args->count++; + break; + case '%': + /* "%%" is the escape sequence to output "%". */ + break; + default: + if (fmt_check) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unexpected format"); break; } } - enum { INT, WCHAR, LONG, LONGLONG, POINTER } types[count_args]; - union - { - int i; - grub_uint32_t w; - long l; - long long ll; - void *p; - } args[count_args]; + if (fmt_check && args->count > max_args) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "too many arguments"); - grub_memset (types, 0, sizeof (types)); + if (args->count <= ARRAY_SIZE (args->prealloc)) + args->ptr = args->prealloc; + else + { + args->ptr = grub_calloc (args->count, sizeof (args->ptr[0])); + if (!args->ptr) + { + if (fmt_check) + return grub_errno; + + grub_errno = GRUB_ERR_NONE; + args->ptr = args->prealloc; + args->count = ARRAY_SIZE (args->prealloc); + } + } + + grub_memset (args->ptr, 0, args->count * sizeof (args->ptr[0])); fmt = fmt0; n = 0; while ((c = *fmt++) != 0) { int longfmt = 0; - int longlongfmt = 0; - grub_size_t curn; + unsigned long curn; const char *p; if (c != '%') @@ -738,106 +838,176 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a curn = n++; - if (*fmt && *fmt =='-') - fmt++; - - while (*fmt && grub_isdigit (*fmt)) - fmt++; - - if (*fmt && *fmt =='.') - fmt++; - - while (*fmt && grub_isdigit (*fmt)) + if (*fmt =='-') fmt++; p = fmt; - if (*fmt && *fmt == '$') + while (grub_isdigit (*fmt)) + fmt++; + + if (*fmt == '$') { - curn = grub_strtoull (p, 0, 10) - 1; + curn = grub_strtoul (p, 0, 10); + if (curn == 0) + continue; + curn--; fmt++; } - while (*fmt && grub_isdigit (*fmt)) + if (*fmt =='-') + fmt++; + + while (grub_isdigit (*fmt)) + fmt++; + + if (*fmt =='.') + fmt++; + + while (grub_isdigit (*fmt)) fmt++; c = *fmt++; + if (c == '%') + { + n--; + continue; + } + if (c == 'l') { c = *fmt++; longfmt = 1; - if (c == 'l') - { - c = *fmt++; - longlongfmt = 1; - } } - if (curn >= count_args) + if (c == 'l') + { + c = *fmt++; + longfmt = 2; + } + if (curn >= args->count) continue; switch (c) { case 'x': + case 'X': + case 'o': case 'u': + args->ptr[curn].type = UNSIGNED_INT + longfmt; + break; case 'd': - if (longlongfmt) - types[curn] = LONGLONG; - else if (longfmt) - types[curn] = LONG; - else - types[curn] = INT; + args->ptr[curn].type = INT + longfmt; break; case 'p': - case 's': - types[curn] = POINTER; + if (sizeof (void *) == sizeof (long long)) + args->ptr[curn].type = UNSIGNED_LONGLONG; + else + args->ptr[curn].type = UNSIGNED_INT; + if (*(fmt) == 'G') { + args->ptr[curn].type = GUID; + ++fmt; + } break; - case 'c': - types[curn] = INT; + case 's': + args->ptr[curn].type = STRING; break; case 'C': - types[curn] = WCHAR; + case 'c': + args->ptr[curn].type = INT; break; } } - for (n = 0; n < count_args; n++) - switch (types[n]) + return GRUB_ERR_NONE; +} + +static void +parse_printf_args (const char *fmt0, struct printf_args *args, va_list args_in) +{ + grub_size_t n; + + parse_printf_arg_fmt (fmt0, args, 0, 0); + + for (n = 0; n < args->count; n++) + switch (args->ptr[n].type) { - case WCHAR: - args[n].w = va_arg (args_in, grub_uint32_t); - break; - case POINTER: - args[n].p = va_arg (args_in, void *); - break; case INT: - args[n].i = va_arg (args_in, int); + args->ptr[n].ll = va_arg (args_in, int); break; case LONG: - args[n].l = va_arg (args_in, long); + args->ptr[n].ll = va_arg (args_in, long); + break; + case UNSIGNED_INT: + args->ptr[n].ll = va_arg (args_in, unsigned int); + break; + case UNSIGNED_LONG: + args->ptr[n].ll = va_arg (args_in, unsigned long); break; case LONGLONG: - args[n].ll = va_arg (args_in, long long); + case UNSIGNED_LONGLONG: + args->ptr[n].ll = va_arg (args_in, long long); + break; + case STRING: + case GUID: + if (sizeof (void *) == sizeof (long long)) + args->ptr[n].ll = va_arg (args_in, long long); + else + args->ptr[n].ll = va_arg (args_in, unsigned int); break; } +} + +static inline void __attribute__ ((always_inline)) +write_char (char *str, grub_size_t *count, grub_size_t max_len, unsigned char ch) +{ + if (*count < max_len) + str[*count] = ch; + + (*count)++; +} + +static void +write_number (char *str, grub_size_t *count, grub_size_t max_len, grub_size_t format1, + char rightfill, char zerofill, char c, long long value) +{ + char tmp[32]; + const char *p = tmp; + grub_size_t len; + grub_size_t fill; + + len = grub_lltoa (tmp, c, value) - tmp; + fill = len < format1 ? format1 - len : 0; + if (! rightfill) + while (fill--) + write_char (str, count, max_len, zerofill); + while (*p) + write_char (str, count, max_len, *p++); + if (rightfill) + while (fill--) + write_char (str, count, max_len, zerofill); +} + +static int +grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, + struct printf_args *args) +{ + char c; + grub_size_t n = 0; + grub_size_t count = 0; + const char *fmt; fmt = fmt0; - n = 0; while ((c = *fmt++) != 0) { - char tmp[32]; - char *p; unsigned int format1 = 0; unsigned int format2 = ~ 0U; char zerofill = ' '; - int rightfill = 0; - int longfmt = 0; - int longlongfmt = 0; - int unsig = 0; + char rightfill = 0; grub_size_t curn; - + if (c != '%') { - write_char (c); + write_char (str, &count, max_len, c); continue; } @@ -845,46 +1015,30 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a rescan:; - if (*fmt && *fmt =='-') + if (*fmt =='-') { rightfill = 1; fmt++; } - p = (char *) fmt; /* Read formatting parameters. */ - while (*p && grub_isdigit (*p)) - p++; - - if (p > fmt) + if (grub_isdigit (*fmt)) { - char s[p - fmt + 1]; - grub_strncpy (s, fmt, p - fmt); - s[p - fmt] = 0; - if (s[0] == '0') + if (fmt[0] == '0') zerofill = '0'; - format1 = grub_strtoul (s, 0, 10); - fmt = p; + format1 = grub_strtoul (fmt, &fmt, 10); } - if (*p && *p == '.') - { - p++; - fmt++; - while (*p && grub_isdigit (*p)) - p++; + if (*fmt == '.') + fmt++; + + if (grub_isdigit (*fmt)) + format2 = grub_strtoul (fmt, &fmt, 10); - if (p > fmt) - { - char fstr[p - fmt + 1]; - grub_strncpy (fstr, fmt, p - fmt); - fstr[p - fmt] = 0; - format2 = grub_strtoul (fstr, 0, 10); - fmt = p; - } - } if (*fmt == '$') { + if (format1 == 0) + continue; curn = format1 - 1; fmt++; format1 = 0; @@ -897,55 +1051,68 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a c = *fmt++; if (c == 'l') + c = *fmt++; + if (c == 'l') + c = *fmt++; + + if (c == '%') { - longfmt = 1; - c = *fmt++; - if (c == 'l') - { - longlongfmt = 1; - c = *fmt++; - } + write_char (str, &count, max_len, c); + n--; + continue; } - if (curn >= count_args) + if (curn >= args->count) continue; + long long curarg = args->ptr[curn].ll; + switch (c) { case 'p': - write_str ("0x"); - c = 'x'; - longlongfmt |= (sizeof (void *) == sizeof (long long)); + if (*(fmt) == 'G') + { + ++fmt; + grub_packed_guid_t *guid = (grub_packed_guid_t *)(grub_addr_t) curarg; + write_number (str, &count, max_len, 8, 0, '0', 'x', guid->data1); + write_char (str, &count, max_len, '-'); + write_number (str, &count, max_len, 4, 0, '0', 'x', guid->data2); + write_char (str, &count, max_len, '-'); + write_number (str, &count, max_len, 4, 0, '0', 'x', guid->data3); + write_char (str, &count, max_len, '-'); + write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[0]); + write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[1]); + write_char (str, &count, max_len, '-'); + write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[2]); + write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[3]); + write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[4]); + write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[5]); + write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[6]); + write_number (str, &count, max_len, 2, 0, '0', 'x', guid->data4[7]); + break; + } + else + { + write_char (str, &count, max_len, '0'); + write_char (str, &count, max_len, 'x'); + c = 'x'; + } /* Fall through. */ case 'x': + case 'X': case 'u': - unsig = 1; - /* Fall through. */ case 'd': - if (longlongfmt) - grub_lltoa (tmp, c, args[curn].ll); - else if (longfmt && unsig) - grub_lltoa (tmp, c, (unsigned long) args[curn].l); - else if (longfmt) - grub_lltoa (tmp, c, args[curn].l); - else if (unsig) - grub_lltoa (tmp, c, (unsigned) args[curn].i); - else - grub_lltoa (tmp, c, args[curn].i); - if (! rightfill && grub_strlen (tmp) < format1) - write_fill (zerofill, format1 - grub_strlen (tmp)); - write_str (tmp); - if (rightfill && grub_strlen (tmp) < format1) - write_fill (zerofill, format1 - grub_strlen (tmp)); + case 'o': + write_number (str, &count, max_len, format1, rightfill, zerofill, c, curarg); break; case 'c': - write_char (args[curn].i & 0xff); + write_char (str, &count, max_len, curarg & 0xff); break; case 'C': { - grub_uint32_t code = args[curn].w; + grub_uint32_t code = curarg; int shift; unsigned mask; @@ -964,21 +1131,11 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a shift = 12; mask = 0xe0; } - else if (code <= 0x1fffff) + else if (code <= 0x10ffff) { shift = 18; mask = 0xf0; } - else if (code <= 0x3ffffff) - { - shift = 24; - mask = 0xf8; - } - else if (code <= 0x7fffffff) - { - shift = 30; - mask = 0xfc; - } else { code = '?'; @@ -986,44 +1143,49 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a mask = 0; } - write_char (mask | (code >> shift)); + write_char (str, &count, max_len, mask | (code >> shift)); for (shift -= 6; shift >= 0; shift -= 6) - write_char (0x80 | (0x3f & (code >> shift))); + write_char (str, &count, max_len, 0x80 | (0x3f & (code >> shift))); } break; case 's': - p = args[curn].p; - if (p) - { - grub_size_t len = 0; - while (len < format2 && p[len]) - len++; + { + grub_size_t len = 0; + grub_size_t fill; + const char *p = ((char *) (grub_addr_t) curarg) ? : "(null)"; + grub_size_t i; - if (!rightfill && len < format1) - write_fill (zerofill, format1 - len); + while (len < format2 && p[len]) + len++; - grub_size_t i; - for (i = 0; i < len; i++) - write_char (*p++); + fill = len < format1 ? format1 - len : 0; - if (rightfill && len < format1) - write_fill (zerofill, format1 - len); - } - else - write_str ("(null)"); + if (!rightfill) + while (fill--) + write_char (str, &count, max_len, zerofill); + + for (i = 0; i < len; i++) + write_char (str, &count, max_len, *p++); + + if (rightfill) + while (fill--) + write_char (str, &count, max_len, zerofill); + } break; default: - write_char (c); + write_char (str, &count, max_len, c); break; } } - *str = '\0'; - + if (count < max_len) + str[count] = '\0'; + else + str[max_len] = '\0'; return count; } @@ -1031,15 +1193,20 @@ int grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list ap) { grub_size_t ret; + struct printf_args args; if (!n) return 0; n--; - ret = grub_vsnprintf_real (str, n, fmt, ap); + parse_printf_args (fmt, &args, ap); - return ret < n ? ret : n; + ret = grub_vsnprintf_real (str, n, fmt, &args); + + free_printf_args (&args); + + return ret; } int @@ -1060,22 +1227,26 @@ grub_xvasprintf (const char *fmt, va_list ap) { grub_size_t s, as = PREALLOC_SIZE; char *ret; + struct printf_args args; + + parse_printf_args (fmt, &args, ap); while (1) { - va_list ap2; ret = grub_malloc (as + 1); if (!ret) - return NULL; + { + free_printf_args (&args); + return NULL; + } - va_copy (ap2, ap); - - s = grub_vsnprintf_real (ret, as, fmt, ap2); - - va_end (ap2); + s = grub_vsnprintf_real (ret, as, fmt, &args); if (s <= as) - return ret; + { + free_printf_args (&args); + return ret; + } grub_free (ret); as = s; @@ -1095,12 +1266,48 @@ grub_xasprintf (const char *fmt, ...) return ret; } +grub_err_t +grub_printf_fmt_check (const char *fmt, const char *fmt_expected) +{ + struct printf_args args_expected, args_fmt; + grub_err_t ret; + grub_size_t n; + + if (fmt == NULL || fmt_expected == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid format"); + + ret = parse_printf_arg_fmt (fmt_expected, &args_expected, 1, GRUB_SIZE_MAX); + if (ret != GRUB_ERR_NONE) + return ret; + + /* Limit parsing to the number of expected arguments. */ + ret = parse_printf_arg_fmt (fmt, &args_fmt, 1, args_expected.count); + if (ret != GRUB_ERR_NONE) + { + free_printf_args (&args_expected); + return ret; + } + + for (n = 0; n < args_fmt.count; n++) + if (args_fmt.ptr[n].type != args_expected.ptr[n].type) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments types do not match"); + break; + } + + free_printf_args (&args_expected); + free_printf_args (&args_fmt); + + return ret; +} + + /* Abort GRUB. This function does not return. */ -void +void __attribute__ ((noreturn)) grub_abort (void) { grub_printf ("\nAborted."); - + #ifndef GRUB_UTIL if (grub_term_inputs) #endif @@ -1112,26 +1319,87 @@ grub_abort (void) grub_exit (); } -#if ! defined (__APPLE__) && !defined (GRUB_UTIL) -/* GCC emits references to abort(). */ -void abort (void) __attribute__ ((alias ("grub_abort"))); -#endif - -#if NEED_ENABLE_EXECUTE_STACK && !defined(GRUB_UTIL) && !defined(GRUB_MACHINE_EMU) -/* Some gcc versions generate a call to this function - in trampolines for nested functions. */ -void __enable_execute_stack (void *addr __attribute__ ((unused))) +void +grub_fatal (const char *fmt, ...) { -} -#endif + va_list ap; -#if NEED_REGISTER_FRAME_INFO && !defined(GRUB_UTIL) -void __register_frame_info (void) -{ + va_start (ap, fmt); + grub_vprintf (_(fmt), ap); + va_end (ap); + + grub_refresh (); + + grub_abort (); } -void __deregister_frame_info (void) +grub_ssize_t +grub_utf8_to_utf16_alloc (const char *str8, grub_uint16_t **utf16_msg, grub_uint16_t **last_position) { + grub_size_t len; + grub_size_t len16; + + len = grub_strlen (str8); + + /* Check for integer overflow */ + if (len > GRUB_SSIZE_MAX / GRUB_MAX_UTF16_PER_UTF8 - 1) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("string too long")); + *utf16_msg = NULL; + return -1; + } + + len16 = len * GRUB_MAX_UTF16_PER_UTF8; + + *utf16_msg = grub_calloc (len16 + 1, sizeof (*utf16_msg[0])); + if (*utf16_msg == NULL) + return -1; + + len16 = grub_utf8_to_utf16 (*utf16_msg, len16, (grub_uint8_t *) str8, len, NULL); + + if (last_position != NULL) + *last_position = *utf16_msg + len16; + + return len16; +} + + +#if BOOT_TIME_STATS + +#include + +struct grub_boot_time *grub_boot_time_head; +static struct grub_boot_time **boot_time_last = &grub_boot_time_head; + +void +grub_real_boot_time (const char *file, + const int line, + const char *fmt, ...) +{ + struct grub_boot_time *n; + va_list args; + + grub_error_push (); + n = grub_malloc (sizeof (*n)); + if (!n) + { + grub_errno = 0; + grub_error_pop (); + return; + } + n->file = file; + n->line = line; + n->tp = grub_get_time_ms (); + n->next = 0; + + va_start (args, fmt); + n->msg = grub_xvasprintf (fmt, args); + va_end (args); + + *boot_time_last = n; + boot_time_last = &n->next; + + grub_errno = 0; + grub_error_pop (); } #endif - diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c index 9f08e05bf..027a25cd1 100644 --- a/grub-core/kern/mm.c +++ b/grub-core/kern/mm.c @@ -28,6 +28,9 @@ - multiple regions may be used as free space. They may not be contiguous. + - if existing regions are insufficient to satisfy an allocation, a new + region can be requested from firmware. + Regions are managed by a singly linked list, and the meta information is stored in the beginning of each region. Space after the meta information is used to allocate memory. @@ -67,8 +70,10 @@ #include #include #include +#include #ifdef MM_DEBUG +# undef grub_calloc # undef grub_malloc # undef grub_zalloc # undef grub_realloc @@ -78,7 +83,51 @@ +/* + * GRUB_MM_MGMT_OVERHEAD is an upper bound of management overhead of + * each region, with any possible padding taken into account. + * + * The value must be large enough to make sure grub_memalign(align, size) + * always succeeds after a successful call to + * grub_mm_init_region(addr, size + align + GRUB_MM_MGMT_OVERHEAD), + * for any given addr, align and size (assuming no interger overflow). + * + * The worst case which has maximum overhead is shown in the figure below: + * + * +-- addr + * v |<- size + align ->| + * +---------+----------------+----------------+------------------+---------+ + * | padding | grub_mm_region | grub_mm_header | usable bytes | padding | + * +---------+----------------+----------------+------------------+---------+ + * |<- a ->|<- b ->|<- c ->|<- d ->|<- e ->| + * ^ + * b == sizeof (struct grub_mm_region) | / Assuming no other suitable + * c == sizeof (struct grub_mm_header) | | block is available, then: + * d == size + align +-| If align == 0, this will be + * | the pointer returned by next + * Assuming addr % GRUB_MM_ALIGN == 1, then: | grub_memalign(align, size). + * a == GRUB_MM_ALIGN - 1 | If align > 0, this chunk may + * | need to be split to fulfill + * Assuming d % GRUB_MM_ALIGN == 1, then: | alignment requirements, and + * e == GRUB_MM_ALIGN - 1 | the returned pointer may be + * \ inside these usable bytes. + * Therefore, the maximum overhead is: + * a + b + c + e == (GRUB_MM_ALIGN - 1) + sizeof (struct grub_mm_region) + * + sizeof (struct grub_mm_header) + (GRUB_MM_ALIGN - 1) + */ +#define GRUB_MM_MGMT_OVERHEAD ((GRUB_MM_ALIGN - 1) \ + + sizeof (struct grub_mm_region) \ + + sizeof (struct grub_mm_header) \ + + (GRUB_MM_ALIGN - 1)) + +/* The size passed to grub_mm_add_region_fn() is aligned up by this value. */ +#define GRUB_MM_HEAP_GROW_ALIGN 4096 + +/* Minimal heap growth granularity when existing heap space is exhausted. */ +#define GRUB_MM_HEAP_GROW_EXTRA 0x100000 + grub_mm_region_t grub_mm_base; +grub_mm_add_region_func_t grub_mm_add_region_fn; /* Get a header from the pointer PTR, and set *P and *R to a pointer to the header and a pointer to its region, respectively. PTR must @@ -113,18 +162,131 @@ grub_mm_init_region (void *addr, grub_size_t size) grub_mm_header_t h; grub_mm_region_t r, *p, q; -#if 0 - grub_printf ("Using memory for heap: start=%p, end=%p\n", addr, addr + (unsigned int) size); -#endif + grub_dprintf ("regions", "Using memory for heap: start=%p, end=%p\n", + addr, (char *) addr + (unsigned int) size); + + /* Exclude last 4K to avoid overflows. */ + /* If addr + 0x1000 overflows then whole region is in excluded zone. */ + if ((grub_addr_t) addr > ~((grub_addr_t) 0x1000)) + return; + + /* If addr + 0x1000 + size overflows then decrease size. */ + if (((grub_addr_t) addr + 0x1000) > ~(grub_addr_t) size) + size = ((grub_addr_t) -0x1000) - (grub_addr_t) addr; + + /* Attempt to merge this region with every existing region */ + for (p = &grub_mm_base, q = *p; q; p = &(q->next), q = *p) + { + /* + * Is the new region immediately below an existing region? That + * is, is the address of the memory we're adding now (addr) + size + * of the memory we're adding (size) + the bytes we couldn't use + * at the start of the region we're considering (q->pre_size) + * equal to the address of q? In other words, does the memory + * looks like this? + * + * addr q + * |----size-----|-q->pre_size-|| + */ + grub_dprintf ("regions", "Can we extend into region above?" + " %p + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n", + (grub_uint8_t *) addr, size, q->pre_size, (grub_uint8_t *) q); + if ((grub_uint8_t *) addr + size + q->pre_size == (grub_uint8_t *) q) + { + grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n", + q, (grub_uint8_t *) q + sizeof (*q) + q->size, + addr, (grub_uint8_t *) q + sizeof (*q) + q->size); + /* + * Yes, we can merge the memory starting at addr into the + * existing region from below. Align up addr to GRUB_MM_ALIGN + * so that our new region has proper alignment. + */ + r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); + /* Copy the region data across */ + *r = *q; + /* Consider all the new size as pre-size */ + r->pre_size += size; + + /* + * If we have enough pre-size to create a block, create a + * block with it. Mark it as allocated and pass it to + * grub_free (), which will sort out getting it into the free + * list. + */ + if (r->pre_size >> GRUB_MM_ALIGN_LOG2) + { + h = (grub_mm_header_t) (r + 1); + /* block size is pre-size converted to cells */ + h->size = (r->pre_size >> GRUB_MM_ALIGN_LOG2); + h->magic = GRUB_MM_ALLOC_MAGIC; + /* region size grows by block size converted back to bytes */ + r->size += h->size << GRUB_MM_ALIGN_LOG2; + /* adjust pre_size to be accurate */ + r->pre_size &= (GRUB_MM_ALIGN - 1); + *p = r; + grub_free (h + 1); + } + /* Replace the old region with the new region */ + *p = r; + return; + } + + /* + * Is the new region immediately above an existing region? That + * is: + * q addr + * ||-q->post_size-|----size-----| + */ + grub_dprintf ("regions", "Can we extend into region below?" + " %p + %x + %" PRIxGRUB_SIZE " + %" PRIxGRUB_SIZE " ?=? %p\n", + (grub_uint8_t *) q, (int) sizeof (*q), q->size, q->post_size, (grub_uint8_t *) addr); + if ((grub_uint8_t *) q + sizeof (*q) + q->size + q->post_size == + (grub_uint8_t *) addr) + { + grub_dprintf ("regions", "Yes: extending a region: (%p -> %p) -> (%p -> %p)\n", + q, (grub_uint8_t *) q + sizeof (*q) + q->size, + q, (grub_uint8_t *) addr + size); + /* + * Yes! Follow a similar pattern to above, but simpler. + * Our header starts at address - post_size, which should align us + * to a cell boundary. + * + * Cast to (void *) first to avoid the following build error: + * kern/mm.c: In function ‘grub_mm_init_region’: + * kern/mm.c:211:15: error: cast increases required alignment of target type [-Werror=cast-align] + * 211 | h = (grub_mm_header_t) ((grub_uint8_t *) addr - q->post_size); + * | ^ + * It is safe to do that because proper alignment is enforced in grub_mm_size_sanity_check(). + */ + h = (grub_mm_header_t)(void *) ((grub_uint8_t *) addr - q->post_size); + /* our size is the allocated size plus post_size, in cells */ + h->size = (size + q->post_size) >> GRUB_MM_ALIGN_LOG2; + h->magic = GRUB_MM_ALLOC_MAGIC; + /* region size grows by block size converted back to bytes */ + q->size += h->size << GRUB_MM_ALIGN_LOG2; + /* adjust new post_size to be accurate */ + q->post_size = (q->post_size + size) & (GRUB_MM_ALIGN - 1); + grub_free (h + 1); + return; + } + } + + grub_dprintf ("regions", "No: considering a new region at %p of size %" PRIxGRUB_SIZE "\n", + addr, size); + /* + * If you want to modify the code below, please also take a look at + * GRUB_MM_MGMT_OVERHEAD and make sure it is synchronized with the code. + */ /* Allocate a region from the head. */ r = (grub_mm_region_t) ALIGN_UP ((grub_addr_t) addr, GRUB_MM_ALIGN); - size -= (char *) r - (char *) addr + sizeof (*r); /* If this region is too small, ignore it. */ - if (size < GRUB_MM_ALIGN) + if (size < GRUB_MM_ALIGN + (char *) r - (char *) addr + sizeof (*r)) return; + size -= (char *) r - (char *) addr + sizeof (*r); + h = (grub_mm_header_t) (r + 1); h->next = h; h->magic = GRUB_MM_FREE_MAGIC; @@ -133,6 +295,7 @@ grub_mm_init_region (void *addr, grub_size_t size) r->first = h; r->pre_size = (grub_addr_t) r - (grub_addr_t) addr; r->size = (h->size << GRUB_MM_ALIGN_LOG2); + r->post_size = size - r->size; /* Find where to insert this region. Put a smaller one before bigger ones, to prevent fragmentation. */ @@ -145,13 +308,20 @@ grub_mm_init_region (void *addr, grub_size_t size) } /* Allocate the number of units N with the alignment ALIGN from the ring - buffer starting from *FIRST. ALIGN must be a power of two. Both N and - ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful, - otherwise return NULL. */ + * buffer given in *FIRST. ALIGN must be a power of two. Both N and + * ALIGN are in units of GRUB_MM_ALIGN. Return a non-NULL if successful, + * otherwise return NULL. + * + * Note: because in certain circumstances we need to adjust the ->next + * pointer of the previous block, we iterate over the singly linked + * list with the pair (prev, cur). *FIRST is our initial previous, and + * *FIRST->next is our initial current pointer. So we will actually + * allocate from *FIRST->next first and *FIRST itself last. + */ static void * grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) { - grub_mm_header_t p, q; + grub_mm_header_t cur, prev; /* When everything is allocated side effect is that *first will have alloc magic marked, meaning that there is no room in this region. */ @@ -159,24 +329,24 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) return 0; /* Try to search free slot for allocation in this memory region. */ - for (q = *first, p = q->next; ; q = p, p = p->next) + for (prev = *first, cur = prev->next; ; prev = cur, cur = cur->next) { grub_off_t extra; - extra = ((grub_addr_t) (p + 1) >> GRUB_MM_ALIGN_LOG2) % align; + extra = ((grub_addr_t) (cur + 1) >> GRUB_MM_ALIGN_LOG2) & (align - 1); if (extra) extra = align - extra; - if (! p) + if (! cur) grub_fatal ("null in the ring"); - if (p->magic != GRUB_MM_FREE_MAGIC) - grub_fatal ("free magic is broken at %p: 0x%x", p, p->magic); + if (cur->magic != GRUB_MM_FREE_MAGIC) + grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic); - if (p->size >= n + extra) + if (cur->size >= n + extra) { - extra += (p->size - extra - n) & (~(align - 1)); - if (extra == 0 && p->size == n) + extra += (cur->size - extra - n) & (~(align - 1)); + if (extra == 0 && cur->size == n) { /* There is no special alignment requirement and memory block is complete match. @@ -189,9 +359,9 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) | alloc, size=n | | +---------------+ v */ - q->next = p->next; + prev->next = cur->next; } - else if (align == 1 || p->size == n + extra) + else if (align == 1 || cur->size == n + extra) { /* There might be alignment requirement, when taking it into account memory block fits in. @@ -208,23 +378,22 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) | alloc, size=n | | +---------------+ v */ - - p->size -= n; - p += p->size; + cur->size -= n; + cur += cur->size; } else if (extra == 0) { grub_mm_header_t r; - - r = p + extra + n; - r->magic = GRUB_MM_FREE_MAGIC; - r->size = p->size - extra - n; - r->next = p->next; - q->next = r; - if (q == p) + r = cur + extra + n; + r->magic = GRUB_MM_FREE_MAGIC; + r->size = cur->size - extra - n; + r->next = cur->next; + prev->next = r; + + if (prev == cur) { - q = r; + prev = r; r->next = r; } } @@ -251,29 +420,32 @@ grub_real_malloc (grub_mm_header_t *first, grub_size_t n, grub_size_t align) */ grub_mm_header_t r; - r = p + extra + n; + r = cur + extra + n; r->magic = GRUB_MM_FREE_MAGIC; - r->size = p->size - extra - n; - r->next = p; + r->size = cur->size - extra - n; + r->next = cur; - p->size = extra; - q->next = r; - p += extra; + cur->size = extra; + prev->next = r; + cur += extra; } - p->magic = GRUB_MM_ALLOC_MAGIC; - p->size = n; + cur->magic = GRUB_MM_ALLOC_MAGIC; + cur->size = n; /* Mark find as a start marker for next allocation to fasten it. This will have side effect of fragmenting memory as small pieces before this will be un-used. */ - *first = q; + /* So do it only for chunks under 32K. */ + if (n < (0x8000 >> GRUB_MM_ALIGN_LOG2) + || *first == cur) + *first = prev; - return p + 1; + return cur + 1; } /* Search was completed without result. */ - if (p == *first) + if (cur == *first) break; } @@ -286,11 +458,23 @@ grub_memalign (grub_size_t align, grub_size_t size) { grub_mm_region_t r; grub_size_t n = ((size + GRUB_MM_ALIGN - 1) >> GRUB_MM_ALIGN_LOG2) + 1; + grub_size_t grow; int count = 0; if (!grub_mm_base) goto fail; + if (size > ~(grub_size_t) align) + goto fail; + + grow = size + align; + + /* We currently assume at least a 32-bit grub_size_t, + so limiting allocations to - 1MiB + in name of sanity is beneficial. */ + if (grow > ~(grub_size_t) 0x100000) + goto fail; + align = (align >> GRUB_MM_ALIGN_LOG2); if (align == 0) align = 1; @@ -310,19 +494,56 @@ grub_memalign (grub_size_t align, grub_size_t size) switch (count) { case 0: + /* Request additional pages, contiguous */ + count++; + + /* + * Calculate the necessary size of heap growth (if applicable), + * with region management overhead taken into account. + */ + if (grub_add (grow, GRUB_MM_MGMT_OVERHEAD, &grow)) + goto fail; + + /* Preallocate some extra space if heap growth is small. */ + grow = grub_max (grow, GRUB_MM_HEAP_GROW_EXTRA); + + /* Align up heap growth to make it friendly to CPU/MMU. */ + if (grow > ~(grub_size_t) (GRUB_MM_HEAP_GROW_ALIGN - 1)) + goto fail; + grow = ALIGN_UP (grow, GRUB_MM_HEAP_GROW_ALIGN); + + /* Do the same sanity check again. */ + if (grow > ~(grub_size_t) 0x100000) + goto fail; + + if (grub_mm_add_region_fn != NULL && + grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_CONSECUTIVE) == GRUB_ERR_NONE) + goto again; + + /* fallthrough */ + + case 1: + /* Request additional pages, anything at all */ + count++; + + if (grub_mm_add_region_fn != NULL) + { + /* + * Try again even if this fails, in case it was able to partially + * satisfy the request + */ + grub_mm_add_region_fn (grow, GRUB_MM_ADD_REGION_NONE); + goto again; + } + + /* fallthrough */ + + case 2: /* Invalidate disk caches. */ grub_disk_cache_invalidate_all (); count++; goto again; -#if 0 - case 1: - /* Unload unneeded modules. */ - grub_dl_unload_unneeded (); - count++; - goto again; -#endif - default: break; } @@ -332,6 +553,30 @@ grub_memalign (grub_size_t align, grub_size_t size) return 0; } +/* + * Allocate NMEMB instances of SIZE bytes and return the pointer, or error on + * integer overflow. + */ +void * +grub_calloc (grub_size_t nmemb, grub_size_t size) +{ + void *ret; + grub_size_t sz = 0; + + if (grub_mul (nmemb, size, &sz)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + return NULL; + } + + ret = grub_memalign (0, sz); + if (!ret) + return NULL; + + grub_memset (ret, 0, sz); + return ret; +} + /* Allocate SIZE bytes and return the pointer. */ void * grub_malloc (grub_size_t size) @@ -371,54 +616,73 @@ grub_free (void *ptr) } else { - grub_mm_header_t q, s; + grub_mm_header_t cur, prev; #if 0 - q = r->first; + cur = r->first; do { grub_printf ("%s:%d: q=%p, q->size=0x%x, q->magic=0x%x\n", - GRUB_FILE, __LINE__, q, q->size, q->magic); - q = q->next; + GRUB_FILE, __LINE__, cur, cur->size, cur->magic); + cur = cur->next; } - while (q != r->first); + while (cur != r->first); #endif - - for (s = r->first, q = s->next; q <= p || q->next >= p; s = q, q = s->next) + /* Iterate over all blocks in the free ring. + * + * The free ring is arranged from high addresses to low + * addresses, modulo wraparound. + * + * We are looking for a block with a higher address than p or + * whose next address is lower than p. + */ + for (prev = r->first, cur = prev->next; cur <= p || cur->next >= p; + prev = cur, cur = prev->next) { - if (q->magic != GRUB_MM_FREE_MAGIC) - grub_fatal ("free magic is broken at %p: 0x%x", q, q->magic); + if (cur->magic != GRUB_MM_FREE_MAGIC) + grub_fatal ("free magic is broken at %p: 0x%x", cur, cur->magic); - if (q <= q->next && (q > p || q->next < p)) + /* Deal with wrap-around */ + if (cur <= cur->next && (cur > p || cur->next < p)) break; } + /* mark p as free and insert it between cur and cur->next */ p->magic = GRUB_MM_FREE_MAGIC; - p->next = q->next; - q->next = p; + p->next = cur->next; + cur->next = p; + /* + * If the block we are freeing can be merged with the next + * free block, do that. + */ if (p->next + p->next->size == p) { p->magic = 0; p->next->size += p->size; - q->next = p->next; + cur->next = p->next; p = p->next; } - r->first = q; + r->first = cur; - if (q == p + p->size) + /* Likewise if can be merged with the preceeding free block */ + if (cur == p + p->size) { - q->magic = 0; - p->size += q->size; - if (q == s) - s = p; - s->next = p; - q = s; + cur->magic = 0; + p->size += cur->size; + if (cur == prev) + prev = p; + prev->next = p; + cur = prev; } - r->first = q; + /* + * Set r->first such that the just free()d block is tried first. + * (An allocation is tried from *first->next, and cur->next == p.) + */ + r->first = cur; } } @@ -452,7 +716,8 @@ grub_realloc (void *ptr, grub_size_t size) if (! q) return q; - grub_memcpy (q, ptr, size); + /* We've already checked that p->size < n. */ + grub_memcpy (q, ptr, p->size << GRUB_MM_ALIGN_LOG2); grub_free (ptr); return q; } @@ -469,6 +734,8 @@ grub_mm_dump_free (void) { grub_mm_header_t p; + grub_printf ("Region %p (size %" PRIuGRUB_SIZE ")\n\n", r, r->size); + /* Follow the free list. */ p = r->first; do @@ -496,6 +763,8 @@ grub_mm_dump (unsigned lineno) { grub_mm_header_t p; + grub_printf ("Region %p (size %" PRIuGRUB_SIZE ")\n\n", r, r->size); + for (p = (grub_mm_header_t) ALIGN_UP ((grub_addr_t) (r + 1), GRUB_MM_ALIGN); (grub_addr_t) p < (grub_addr_t) (r+1) + r->size; @@ -517,6 +786,20 @@ grub_mm_dump (unsigned lineno) grub_printf ("\n"); } +void * +grub_debug_calloc (const char *file, int line, grub_size_t nmemb, grub_size_t size) +{ + void *ptr; + + if (grub_mm_debug) + grub_printf ("%s:%d: calloc (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE ") = ", + file, line, nmemb, size); + ptr = grub_calloc (nmemb, size); + if (grub_mm_debug) + grub_printf ("%p\n", ptr); + return ptr; +} + void * grub_debug_malloc (const char *file, int line, grub_size_t size) { @@ -569,7 +852,7 @@ grub_debug_memalign (const char *file, int line, grub_size_t align, void *ptr; if (grub_mm_debug) - grub_printf ("%s:%d: memalign (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE + grub_printf ("%s:%d: memalign (0x%" PRIxGRUB_SIZE ", 0x%" PRIxGRUB_SIZE ") = ", file, line, align, size); ptr = grub_memalign (align, size); if (grub_mm_debug) diff --git a/grub-core/kern/parser.c b/grub-core/kern/parser.c index 9213caa76..9b7b31a51 100644 --- a/grub-core/kern/parser.c +++ b/grub-core/kern/parser.c @@ -1,7 +1,7 @@ /* parser.c - the part of the parser that can return partial tokens */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2007,2009 Free Software Foundation, Inc. + * Copyright (C) 2005,2007,2009,2021 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -96,60 +97,132 @@ grub_parser_cmdline_state (grub_parser_state_t state, char c, char *result) } +/* Helper for grub_parser_split_cmdline. */ +static inline int +check_varstate (grub_parser_state_t s) +{ + return (s == GRUB_PARSER_STATE_VARNAME + || s == GRUB_PARSER_STATE_VARNAME2 + || s == GRUB_PARSER_STATE_QVARNAME + || s == GRUB_PARSER_STATE_QVARNAME2); +} + + +static grub_err_t +add_var (grub_buffer_t varname, grub_buffer_t buf, + grub_parser_state_t state, grub_parser_state_t newstate) +{ + const char *val; + + /* Check if a variable was being read in and the end of the name + was reached. */ + if (!(check_varstate (state) && !check_varstate (newstate))) + return GRUB_ERR_NONE; + + if (grub_buffer_append_char (varname, '\0') != GRUB_ERR_NONE) + return grub_errno; + + val = grub_env_get ((const char *) grub_buffer_peek_data (varname)); + grub_buffer_reset (varname); + if (!val) + return GRUB_ERR_NONE; + + /* Insert the contents of the variable in the buffer. */ + return grub_buffer_append_data (buf, val, grub_strlen (val)); +} + +static grub_err_t +terminate_arg (grub_buffer_t buffer, int *argc) +{ + grub_size_t unread = grub_buffer_get_unread_bytes (buffer); + + if (unread == 0) + return GRUB_ERR_NONE; + + if (*(const char *) grub_buffer_peek_data_at (buffer, unread - 1) == '\0') + return GRUB_ERR_NONE; + + if (grub_buffer_append_char (buffer, '\0') != GRUB_ERR_NONE) + return grub_errno; + + (*argc)++; + + return GRUB_ERR_NONE; +} + +static grub_err_t +process_char (char c, grub_buffer_t buffer, grub_buffer_t varname, + grub_parser_state_t state, int *argc, + grub_parser_state_t *newstate) +{ + char use; + + *newstate = grub_parser_cmdline_state (state, c, &use); + + /* + * If a variable was being processed and this character does + * not describe the variable anymore, write the variable to + * the buffer. + */ + if (add_var (varname, buffer, state, *newstate) != GRUB_ERR_NONE) + return grub_errno; + + if (check_varstate (*newstate)) + { + if (use) + return grub_buffer_append_char (varname, use); + } + else if (*newstate == GRUB_PARSER_STATE_TEXT && + state != GRUB_PARSER_STATE_ESC && grub_isspace (use)) + { + /* + * Don't add more than one argument if multiple + * spaces are used. + */ + return terminate_arg (buffer, argc); + } + else if (use) + return grub_buffer_append_char (buffer, use); + + return GRUB_ERR_NONE; +} + grub_err_t -grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, +grub_parser_split_cmdline (const char *cmdline, + grub_reader_getline_t getline, void *getline_data, int *argc, char ***argv) { grub_parser_state_t state = GRUB_PARSER_STATE_TEXT; - /* XXX: Fixed size buffer, perhaps this buffer should be dynamically - allocated. */ - char buffer[1024]; - char *bp = buffer; + grub_buffer_t buffer, varname; char *rd = (char *) cmdline; - char varname[200]; - char *vp = varname; - char *args; + char *rp = rd; int i; - auto int check_varstate (grub_parser_state_t s); - - int check_varstate (grub_parser_state_t s) - { - return (s == GRUB_PARSER_STATE_VARNAME - || s == GRUB_PARSER_STATE_VARNAME2 - || s == GRUB_PARSER_STATE_QVARNAME - || s == GRUB_PARSER_STATE_QVARNAME2); - } - - auto void add_var (grub_parser_state_t newstate); - - void add_var (grub_parser_state_t newstate) - { - const char *val; - - /* Check if a variable was being read in and the end of the name - was reached. */ - if (!(check_varstate (state) && !check_varstate (newstate))) - return; - - *(vp++) = '\0'; - val = grub_env_get (varname); - vp = varname; - if (!val) - return; - - /* Insert the contents of the variable in the buffer. */ - for (; *val; val++) - *(bp++) = *val; - } - *argc = 0; + *argv = NULL; + + buffer = grub_buffer_new (1024); + if (buffer == NULL) + return grub_errno; + + varname = grub_buffer_new (200); + if (varname == NULL) + goto fail; + do { - if (!rd || !*rd) + if (rp == NULL || *rp == '\0') { + if (rd != cmdline) + { + grub_free (rd); + rd = rp = NULL; + } if (getline) - getline (&rd, 1); + { + getline (&rd, 1, getline_data); + rp = rd; + } else break; } @@ -157,39 +230,14 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, if (!rd) break; - for (; *rd; rd++) + for (; *rp != '\0'; rp++) { grub_parser_state_t newstate; - char use; - newstate = grub_parser_cmdline_state (state, *rd, &use); + if (process_char (*rp, buffer, varname, state, argc, + &newstate) != GRUB_ERR_NONE) + goto fail; - /* If a variable was being processed and this character does - not describe the variable anymore, write the variable to - the buffer. */ - add_var (newstate); - - if (check_varstate (newstate)) - { - if (use) - *(vp++) = use; - } - else - { - if (newstate == GRUB_PARSER_STATE_TEXT - && state != GRUB_PARSER_STATE_ESC && grub_isspace (use)) - { - /* Don't add more than one argument if multiple - spaces are used. */ - if (bp != buffer && *(bp - 1)) - { - *(bp++) = '\0'; - (*argc)++; - } - } - else if (use) - *(bp++) = use; - } state = newstate; } } @@ -197,72 +245,99 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, /* A special case for when the last character was part of a variable. */ - add_var (GRUB_PARSER_STATE_TEXT); + if (add_var (varname, buffer, state, GRUB_PARSER_STATE_TEXT) != GRUB_ERR_NONE) + goto fail; - if (bp != buffer && *(bp - 1)) + /* Ensure that the last argument is terminated. */ + if (terminate_arg (buffer, argc) != GRUB_ERR_NONE) + goto fail; + + /* If there are no args, then we're done. */ + if (!*argc) { - *(bp++) = '\0'; - (*argc)++; + grub_errno = GRUB_ERR_NONE; + goto out; } - /* Reserve memory for the return values. */ - args = grub_malloc (bp - buffer); - if (!args) - return grub_errno; - grub_memcpy (args, buffer, bp - buffer); - - *argv = grub_malloc (sizeof (char *) * (*argc + 1)); + *argv = grub_calloc (*argc + 1, sizeof (char *)); if (!*argv) - { - grub_free (args); - return grub_errno; - } + goto fail; /* The arguments are separated with 0's, setup argv so it points to the right values. */ - bp = args; for (i = 0; i < *argc; i++) { - (*argv)[i] = bp; - while (*bp) - bp++; - bp++; + char *arg; + + if (i > 0) + { + if (grub_buffer_advance_read_pos (buffer, 1) != GRUB_ERR_NONE) + goto fail; + } + + arg = (char *) grub_buffer_peek_data (buffer); + if (arg == NULL || + grub_buffer_advance_read_pos (buffer, grub_strlen (arg)) != GRUB_ERR_NONE) + goto fail; + + (*argv)[i] = arg; } + /* Keep memory for the return values. */ + grub_buffer_take_data (buffer); + + grub_errno = GRUB_ERR_NONE; + + out: + if (rd != cmdline) + grub_free (rd); + grub_buffer_free (buffer); + grub_buffer_free (varname); + + return grub_errno; + + fail: + grub_free (*argv); + *argv = NULL; + *argc = 0; + goto out; +} + +/* Helper for grub_parser_execute. */ +static grub_err_t +grub_parser_execute_getline (char **line, int cont __attribute__ ((unused)), + void *data) +{ + char **source = data; + char *p; + + if (!*source) + { + *line = 0; + return 0; + } + + p = grub_strchr (*source, '\n'); + + if (p) + *line = grub_strndup (*source, p - *source); + else + *line = grub_strdup (*source); + *source = p ? p + 1 : 0; return 0; } grub_err_t grub_parser_execute (char *source) { - auto grub_err_t getline (char **line, int cont); - grub_err_t getline (char **line, int cont __attribute__ ((unused))) - { - char *p; - - if (!source) - { - *line = 0; - return 0; - } - - p = grub_strchr (source, '\n'); - - if (p) - *line = grub_strndup (source, p - source); - else - *line = grub_strdup (source); - source = p ? p + 1 : 0; - return 0; - } - while (source) { char *line; - getline (&line, 0); - grub_rescue_parse_line (line, getline); + grub_parser_execute_getline (&line, 0, &source); + grub_rescue_parse_line (line, grub_parser_execute_getline, &source); grub_free (line); + grub_print_error (); } return grub_errno; diff --git a/grub-core/kern/partition.c b/grub-core/kern/partition.c index 82ae9c8c2..3b128e6d2 100644 --- a/grub-core/kern/partition.c +++ b/grub-core/kern/partition.c @@ -28,6 +28,9 @@ grub_partition_map_t grub_partition_map_list; +#define MAX_RECURSION_DEPTH 32 +static unsigned int recursion_depth = 0; + /* * Checks that disk->partition contains part. This function assumes that the * start of part is relative to the start of disk->partition. Returns 1 if @@ -59,63 +62,85 @@ grub_partition_check_containment (const grub_disk_t disk, return 1; } +/* Context for grub_partition_map_probe. */ +struct grub_partition_map_probe_ctx +{ + int partnum; + grub_partition_t p; +}; + +/* Helper for grub_partition_map_probe. */ +static int +probe_iter (grub_disk_t dsk, const grub_partition_t partition, void *data) +{ + struct grub_partition_map_probe_ctx *ctx = data; + + if (ctx->partnum != partition->number) + return 0; + + if (!(grub_partition_check_containment (dsk, partition))) + return 0; + + ctx->p = (grub_partition_t) grub_malloc (sizeof (*ctx->p)); + if (! ctx->p) + return 1; + + grub_memcpy (ctx->p, partition, sizeof (*ctx->p)); + return 1; +} + static grub_partition_t grub_partition_map_probe (const grub_partition_map_t partmap, grub_disk_t disk, int partnum) { - grub_partition_t p = 0; + struct grub_partition_map_probe_ctx ctx = { + .partnum = partnum, + .p = 0 + }; - auto int find_func (grub_disk_t d, const grub_partition_t partition); - - int find_func (grub_disk_t dsk, - const grub_partition_t partition) - { - if (partnum != partition->number) - return 0; - - if (!(grub_partition_check_containment (dsk, partition))) - return 0; - - p = (grub_partition_t) grub_malloc (sizeof (*p)); - if (! p) - return 1; - - grub_memcpy (p, partition, sizeof (*p)); - return 1; - } - - partmap->iterate (disk, find_func); + partmap->iterate (disk, probe_iter, &ctx); if (grub_errno) goto fail; - return p; + return ctx.p; fail: - grub_free (p); + grub_free (ctx.p); return 0; } grub_partition_t grub_partition_probe (struct grub_disk *disk, const char *str) { - grub_partition_t part = 0; + grub_partition_t part; grub_partition_t curpart = 0; grub_partition_t tail; const char *ptr; + if (str == NULL) + return 0; + part = tail = disk->partition; for (ptr = str; *ptr;) { grub_partition_map_t partmap; - int num; + unsigned long num; const char *partname, *partname_end; partname = ptr; while (*ptr && grub_isalpha (*ptr)) ptr++; - partname_end = ptr; - num = grub_strtoul (ptr, (char **) &ptr, 0) - 1; + partname_end = ptr; + + num = grub_strtoul (ptr, &ptr, 0); + if (num == 0 || num > GRUB_INT_MAX) + { + grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid partition number")); + return 0; + } + + num -= 1; curpart = 0; /* Use the first partition map type found. */ @@ -162,62 +187,76 @@ grub_partition_probe (struct grub_disk *disk, const char *str) return part; } +/* Context for grub_partition_iterate. */ +struct grub_partition_iterate_ctx +{ + int ret; + grub_partition_iterate_hook_t hook; + void *hook_data; +}; + +/* Helper for grub_partition_iterate. */ +static int +part_iterate (grub_disk_t dsk, const grub_partition_t partition, void *data) +{ + struct grub_partition_iterate_ctx *ctx = data; + struct grub_partition p = *partition; + + if (!(grub_partition_check_containment (dsk, partition))) + return 0; + + p.parent = dsk->partition; + dsk->partition = 0; + if (ctx->hook (dsk, &p, ctx->hook_data)) + { + ctx->ret = 1; + return 1; + } + if (p.start != 0) + { + const struct grub_partition_map *partmap; + dsk->partition = &p; + FOR_PARTITION_MAPS(partmap) + { + grub_err_t err; + recursion_depth++; + if (recursion_depth <= MAX_RECURSION_DEPTH) + err = partmap->iterate (dsk, part_iterate, ctx); + else + err = grub_error (GRUB_ERR_RECURSION_DEPTH, "maximum recursion depth exceeded"); + recursion_depth--; + if (err) + grub_errno = GRUB_ERR_NONE; + if (ctx->ret) + break; + } + } + dsk->partition = p.parent; + return ctx->ret; +} + int grub_partition_iterate (struct grub_disk *disk, - int (*hook) (grub_disk_t disk, - const grub_partition_t partition)) + grub_partition_iterate_hook_t hook, void *hook_data) { - int ret = 0; - - auto int part_iterate (grub_disk_t dsk, const grub_partition_t p); - - int part_iterate (grub_disk_t dsk, - const grub_partition_t partition) - { - struct grub_partition p = *partition; - - if (!(grub_partition_check_containment (dsk, partition))) - return 0; - - p.parent = dsk->partition; - dsk->partition = 0; - if (hook (dsk, &p)) - { - ret = 1; - return 1; - } - if (p.start != 0) - { - const struct grub_partition_map *partmap; - dsk->partition = &p; - FOR_PARTITION_MAPS(partmap) - { - grub_err_t err; - err = partmap->iterate (dsk, part_iterate); - if (err) - grub_errno = GRUB_ERR_NONE; - if (ret) - break; - } - } - dsk->partition = p.parent; - return ret; - } + struct grub_partition_iterate_ctx ctx = { + .ret = 0, + .hook = hook, + .hook_data = hook_data + }; + const struct grub_partition_map *partmap; + FOR_PARTITION_MAPS(partmap) { - const struct grub_partition_map *partmap; - FOR_PARTITION_MAPS(partmap) - { - grub_err_t err; - err = partmap->iterate (disk, part_iterate); - if (err) - grub_errno = GRUB_ERR_NONE; - if (ret) - break; - } + grub_err_t err; + err = partmap->iterate (disk, part_iterate, &ctx); + if (err) + grub_errno = GRUB_ERR_NONE; + if (ctx.ret) + break; } - return ret; + return ctx.ret; } char * diff --git a/grub-core/kern/powerpc/compiler-rt.S b/grub-core/kern/powerpc/compiler-rt.S new file mode 100644 index 000000000..b3b912db6 --- /dev/null +++ b/grub-core/kern/powerpc/compiler-rt.S @@ -0,0 +1,130 @@ +/* + * Special support for eabi and SVR4 + * + * Copyright (C) 1995-2014 Free Software Foundation, Inc. + * Written By Michael Meissner + * 64-bit support written by David Edelsohn + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 3, or (at your option) any + * later version. + * + * This file 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. + * + * Under Section 7 of GPL version 3, you are granted additional + * permissions described in the GCC Runtime Library Exception, version + * 3.1, as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License and + * a copy of the GCC Runtime Library Exception along with this program; + * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + * . + */ + +/* Do any initializations needed for the eabi environment */ + +#include +#include + + .section ".text" + +#define CFI_RESTORE(reg) .cfi_restore reg +#define CFI_OFFSET(reg, off) .cfi_offset reg, off +#define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg +#define CFI_STARTPROC .cfi_startproc +#define CFI_ENDPROC .cfi_endproc + +/* Routines for restoring integer registers, called by the compiler. */ +/* Called with r11 pointing to the stack header word of the caller of the */ +/* function, just beyond the end of the integer restore area. */ + +CFI_STARTPROC +CFI_DEF_CFA_REGISTER (11) +CFI_OFFSET (65, 4) +CFI_OFFSET (14, -72) +CFI_OFFSET (15, -68) +CFI_OFFSET (16, -64) +CFI_OFFSET (17, -60) +CFI_OFFSET (18, -56) +CFI_OFFSET (19, -52) +CFI_OFFSET (20, -48) +CFI_OFFSET (21, -44) +CFI_OFFSET (22, -40) +CFI_OFFSET (23, -36) +CFI_OFFSET (24, -32) +CFI_OFFSET (25, -28) +CFI_OFFSET (26, -24) +CFI_OFFSET (27, -20) +CFI_OFFSET (28, -16) +CFI_OFFSET (29, -12) +CFI_OFFSET (30, -8) +CFI_OFFSET (31, -4) +FUNCTION(_restgpr_14_x) lwz 14,-72(11) /* restore gp registers */ +CFI_RESTORE (14) +FUNCTION(_restgpr_15_x) lwz 15,-68(11) +CFI_RESTORE (15) +FUNCTION(_restgpr_16_x) lwz 16,-64(11) +CFI_RESTORE (16) +FUNCTION(_restgpr_17_x) lwz 17,-60(11) +CFI_RESTORE (17) +FUNCTION(_restgpr_18_x) lwz 18,-56(11) +CFI_RESTORE (18) +FUNCTION(_restgpr_19_x) lwz 19,-52(11) +CFI_RESTORE (19) +FUNCTION(_restgpr_20_x) lwz 20,-48(11) +CFI_RESTORE (20) +FUNCTION(_restgpr_21_x) lwz 21,-44(11) +CFI_RESTORE (21) +FUNCTION(_restgpr_22_x) lwz 22,-40(11) +CFI_RESTORE (22) +FUNCTION(_restgpr_23_x) lwz 23,-36(11) +CFI_RESTORE (23) +FUNCTION(_restgpr_24_x) lwz 24,-32(11) +CFI_RESTORE (24) +FUNCTION(_restgpr_25_x) lwz 25,-28(11) +CFI_RESTORE (25) +FUNCTION(_restgpr_26_x) lwz 26,-24(11) +CFI_RESTORE (26) +FUNCTION(_restgpr_27_x) lwz 27,-20(11) +CFI_RESTORE (27) +FUNCTION(_restgpr_28_x) lwz 28,-16(11) +CFI_RESTORE (28) +FUNCTION(_restgpr_29_x) lwz 29,-12(11) +CFI_RESTORE (29) +FUNCTION(_restgpr_30_x) lwz 30,-8(11) +CFI_RESTORE (30) +FUNCTION(_restgpr_31_x) lwz 0,4(11) + lwz 31,-4(11) +CFI_RESTORE (31) + mtlr 0 +CFI_RESTORE (65) + mr 1,11 +CFI_DEF_CFA_REGISTER (1) + blr +CFI_ENDPROC + +CFI_STARTPROC +FUNCTION(_savegpr_14) stw 14,-72(11) /* save gp registers */ +FUNCTION(_savegpr_15) stw 15,-68(11) +FUNCTION(_savegpr_16) stw 16,-64(11) +FUNCTION(_savegpr_17) stw 17,-60(11) +FUNCTION(_savegpr_18) stw 18,-56(11) +FUNCTION(_savegpr_19) stw 19,-52(11) +FUNCTION(_savegpr_20) stw 20,-48(11) +FUNCTION(_savegpr_21) stw 21,-44(11) +FUNCTION(_savegpr_22) stw 22,-40(11) +FUNCTION(_savegpr_23) stw 23,-36(11) +FUNCTION(_savegpr_24) stw 24,-32(11) +FUNCTION(_savegpr_25) stw 25,-28(11) +FUNCTION(_savegpr_26) stw 26,-24(11) +FUNCTION(_savegpr_27) stw 27,-20(11) +FUNCTION(_savegpr_28) stw 28,-16(11) +FUNCTION(_savegpr_29) stw 29,-12(11) +FUNCTION(_savegpr_30) stw 30,-8(11) +FUNCTION(_savegpr_31) stw 31,-4(11) + blr +CFI_ENDPROC diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c index 4057fee5a..7b6418eab 100644 --- a/grub-core/kern/powerpc/dl.c +++ b/grub-core/kern/powerpc/dl.c @@ -38,7 +38,26 @@ grub_arch_dl_check_header (void *ehdr) return GRUB_ERR_NONE; } -void +/* For low-endian reverse lis and addr_high as well as ori and addr_low. */ +struct trampoline +{ + grub_uint32_t lis; + grub_uint32_t ori; + grub_uint32_t mtctr; + grub_uint32_t bctr; +}; + +static const struct trampoline trampoline_template = + { + 0x3d800000, + 0x618c0000, + 0x7d8903a6, + 0x4e800420, + }; + +#pragma GCC diagnostic ignored "-Wcast-align" + +grub_err_t grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got) { @@ -49,159 +68,102 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, *tramp = 0; *got = 0; - /* Find a symbol table. */ - for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize)) - if (s->sh_type == SHT_SYMTAB) - break; - - if (i == e->e_shnum) - return; - for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff); i < e->e_shnum; i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize)) if (s->sh_type == SHT_RELA) { const Elf_Rela *rel, *max; - + for (rel = (const Elf_Rela *) ((const char *) e + s->sh_offset), max = rel + s->sh_size / s->sh_entsize; rel < max; rel++) - if (ELF_R_TYPE (rel->r_info) == GRUB_ELF_R_PPC_REL24) + if (ELF_R_TYPE (rel->r_info) == GRUB_ELF_R_PPC_REL24 + || ELF_R_TYPE (rel->r_info) == GRUB_ELF_R_PPC_PLTREL24) (*tramp)++; - + } - return; -} - -/* For low-endian reverse lis and addr_high as well as ori and addr_low. */ -struct trampoline -{ - grub_uint32_t lis; - grub_uint32_t ori; - grub_uint32_t mtctr; - grub_uint32_t bctr; -}; - -static const struct trampoline trampoline_template = - { - 0x3d800000, - 0x618c0000, - 0x7d8903a6, - 0x4e800420, - }; - -/* Relocate symbols. */ -grub_err_t -grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) -{ - Elf_Ehdr *e = ehdr; - Elf_Shdr *s; - Elf_Word entsize; - unsigned i; - struct trampoline *tptr = mod->tramp; - - /* Find a symbol table. */ - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_SYMTAB) - break; - - if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); - - entsize = s->sh_entsize; - - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_RELA) - { - grub_dl_segment_t seg; - - /* Find the target segment. */ - for (seg = mod->segment; seg; seg = seg->next) - if (seg->section == s->sh_info) - break; - - if (seg) - { - Elf_Rela *rel, *max; - - for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), - max = rel + s->sh_size / s->sh_entsize; - rel < max; - rel++) - { - Elf_Word *addr; - Elf_Sym *sym; - grub_uint32_t value; - - if (seg->size < rel->r_offset) - return grub_error (GRUB_ERR_BAD_MODULE, - "reloc offset is out of the segment"); - - addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset); - sym = (Elf_Sym *) ((char *) mod->symtab - + entsize * ELF_R_SYM (rel->r_info)); - - /* On the PPC the value does not have an explicit - addend, add it. */ - value = sym->st_value + rel->r_addend; - switch (ELF_R_TYPE (rel->r_info)) - { - case GRUB_ELF_R_PPC_ADDR16_LO: - *(Elf_Half *) addr = value; - break; - - case GRUB_ELF_R_PPC_REL24: - { - Elf_Sword delta = value - (Elf_Word) addr; - - if (delta << 6 >> 6 != delta) - { - COMPILE_TIME_ASSERT (sizeof (struct trampoline) - == GRUB_ARCH_DL_TRAMP_SIZE); - grub_memcpy (tptr, &trampoline_template, - sizeof (*tptr)); - delta = (grub_uint8_t *) tptr - (grub_uint8_t *) addr; - tptr->lis |= (((value) >> 16) & 0xffff); - tptr->ori |= ((value) & 0xffff); - tptr++; - } - - if (delta << 6 >> 6 != delta) - return grub_error (GRUB_ERR_BAD_MODULE, - "relocation overflow"); - *addr = (*addr & 0xfc000003) | (delta & 0x3fffffc); - break; - } - - case GRUB_ELF_R_PPC_ADDR16_HA: - *(Elf_Half *) addr = (value + 0x8000) >> 16; - break; - - case GRUB_ELF_R_PPC_ADDR32: - *addr = value; - break; - - case GRUB_ELF_R_PPC_REL32: - *addr = value - (Elf_Word) addr; - break; - - default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("relocation 0x%x is not implemented yet"), - ELF_R_TYPE (rel->r_info)); - } - } - } - } + *tramp *= sizeof (struct trampoline); + + return GRUB_ERR_NONE; +} + +/* Relocate symbols. */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg) +{ + Elf_Rela *rel, *max; + + for (rel = (Elf_Rela *) ((char *) ehdr + s->sh_offset), + max = (Elf_Rela *) ((char *) rel + s->sh_size); + rel < max; + rel = (Elf_Rela *) ((char *) rel + s->sh_entsize)) + { + Elf_Word *addr; + Elf_Sym *sym; + grub_uint32_t value; + + if (seg->size < rel->r_offset) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + + addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset); + sym = (Elf_Sym *) ((char *) mod->symtab + + mod->symsize * ELF_R_SYM (rel->r_info)); + + /* On the PPC the value does not have an explicit + addend, add it. */ + value = sym->st_value + rel->r_addend; + switch (ELF_R_TYPE (rel->r_info)) + { + case GRUB_ELF_R_PPC_ADDR16_LO: + *(Elf_Half *) addr = value; + break; + + case GRUB_ELF_R_PPC_PLTREL24: + case GRUB_ELF_R_PPC_REL24: + { + Elf_Sword delta = value - (Elf_Word) addr; + + if (delta << 6 >> 6 != delta) + { + struct trampoline *tptr = mod->trampptr; + grub_memcpy (tptr, &trampoline_template, + sizeof (*tptr)); + delta = (grub_uint8_t *) tptr - (grub_uint8_t *) addr; + tptr->lis |= (((value) >> 16) & 0xffff); + tptr->ori |= ((value) & 0xffff); + mod->trampptr = tptr + 1; + } + + if (delta << 6 >> 6 != delta) + return grub_error (GRUB_ERR_BAD_MODULE, + "relocation overflow"); + *addr = (*addr & 0xfc000003) | (delta & 0x3fffffc); + break; + } + + case GRUB_ELF_R_PPC_ADDR16_HA: + *(Elf_Half *) addr = (value + 0x8000) >> 16; + break; + + case GRUB_ELF_R_PPC_ADDR32: + *addr = value; + break; + + case GRUB_ELF_R_PPC_REL32: + *addr = value - (Elf_Word) addr; + break; + + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%x is not implemented yet"), + ELF_R_TYPE (rel->r_info)); + } + } return GRUB_ERR_NONE; } diff --git a/grub-core/kern/powerpc/ieee1275/startup.S b/grub-core/kern/powerpc/ieee1275/startup.S index b26c47edb..21c884b43 100644 --- a/grub-core/kern/powerpc/ieee1275/startup.S +++ b/grub-core/kern/powerpc/ieee1275/startup.S @@ -34,14 +34,31 @@ _start: /* Stage1 won't zero BSS for us. In other cases, why not do it again? */ lis 6, (__bss_start - 4)@h ori 6, 6, (__bss_start - 4)@l + +2: stb 2, 4(6) + addi 6, 6, 1 + andi. 7, 6, 3 + cmpi 0, 1, 7, 0 + bne 2b + lis 7, (_end - 4)@h ori 7, 7, (_end - 4)@l subf 7, 6, 7 + subi 8, 7, 1 + andi. 8, 8, 3 + addi 8, 8, 1 + sub 7, 7, 8 + srwi 7, 7, 2 /* We store 4 bytes at a time. */ mtctr 7 2: stwu 2, 4(6) /* We know r2 is already 0 from above. */ bdnz 2b + mtctr 8 +2: stb 2, 4(6) /* We know r2 is already 0 from above. */ + addi 6, 6, 1 + bdnz 2b + /* Store r5 in grub_ieee1275_entry_fn. */ lis 9, grub_ieee1275_entry_fn@ha stw 5, grub_ieee1275_entry_fn@l(9) diff --git a/grub-core/kern/rescue_parser.c b/grub-core/kern/rescue_parser.c index 656342d27..799641a03 100644 --- a/grub-core/kern/rescue_parser.c +++ b/grub-core/kern/rescue_parser.c @@ -26,28 +26,40 @@ #include grub_err_t -grub_rescue_parse_line (char *line, grub_reader_getline_t getline) +grub_rescue_parse_line (char *line, + grub_reader_getline_t getline, void *getline_data) { char *name; int n; grub_command_t cmd; char **args; - if (grub_parser_split_cmdline (line, getline, &n, &args) || n < 0) - return grub_errno; + if (grub_parser_split_cmdline (line, getline, getline_data, &n, &args) + || n < 0) + { + grub_free(args); + return grub_errno; + } if (n == 0) - return GRUB_ERR_NONE; + { + grub_free(args); + return GRUB_ERR_NONE; + } /* In case of an assignment set the environment accordingly instead of calling a function. */ - if (n == 1 && grub_strchr (line, '=')) + if (n == 1) { char *val = grub_strchr (args[0], '='); - val[0] = 0; - grub_env_set (args[0], val + 1); - val[0] = '='; - goto quit; + + if (val) + { + val[0] = 0; + grub_env_set (args[0], val + 1); + val[0] = '='; + goto quit; + } } /* Get the command name. */ @@ -70,6 +82,7 @@ grub_rescue_parse_line (char *line, grub_reader_getline_t getline) } quit: + /* Arguments are returned in single memory chunk separated by zeroes */ grub_free (args[0]); grub_free (args); diff --git a/grub-core/kern/rescue_reader.c b/grub-core/kern/rescue_reader.c index 4587b944f..a71ada8fb 100644 --- a/grub-core/kern/rescue_reader.c +++ b/grub-core/kern/rescue_reader.c @@ -30,7 +30,8 @@ static char linebuf[GRUB_RESCUE_BUF_SIZE]; /* Prompt to input a command and read the line. */ static grub_err_t -grub_rescue_read_line (char **line, int cont) +grub_rescue_read_line (char **line, int cont, + void *data __attribute__ ((unused))) { int c; int pos = 0; @@ -77,6 +78,19 @@ grub_rescue_read_line (char **line, int cont) void __attribute__ ((noreturn)) grub_rescue_run (void) { + /* Stall if the CLI has been disabled */ + if (grub_is_cli_disabled () || grub_is_cli_need_auth ()) + { + grub_printf ("Rescue mode has been disabled...\n"); + + do + { + /* Do not optimize out the loop. */ + asm volatile (""); + } + while (1); + } + grub_printf ("Entering rescue mode...\n"); while (1) @@ -87,11 +101,11 @@ grub_rescue_run (void) grub_print_error (); grub_errno = GRUB_ERR_NONE; - grub_rescue_read_line (&line, 0); + grub_rescue_read_line (&line, 0, NULL); if (! line || line[0] == '\0') continue; - grub_rescue_parse_line (line, grub_rescue_read_line); + grub_rescue_parse_line (line, grub_rescue_read_line, NULL); grub_free (line); } } diff --git a/grub-core/kern/riscv/cache.c b/grub-core/kern/riscv/cache.c new file mode 100644 index 000000000..47777a033 --- /dev/null +++ b/grub-core/kern/riscv/cache.c @@ -0,0 +1,63 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +static grub_int64_t dlinesz; +static grub_int64_t ilinesz; + +/* Prototypes for asm functions. */ +void grub_arch_clean_dcache_range (grub_addr_t beg, grub_addr_t end, + grub_size_t line_size); +void grub_arch_invalidate_icache_range (grub_addr_t beg, grub_addr_t end, + grub_size_t line_size); + +static void +probe_caches (void) +{ + /* TODO */ + dlinesz = 32; + ilinesz = 32; +} + +void +grub_arch_sync_caches (void *address, grub_size_t len) +{ + grub_size_t start, end, max_align; + + if (dlinesz == 0) + probe_caches(); + if (dlinesz == 0) + grub_fatal ("Unknown cache line size!"); + + max_align = dlinesz > ilinesz ? dlinesz : ilinesz; + + start = ALIGN_DOWN ((grub_size_t) address, max_align); + end = ALIGN_UP ((grub_size_t) address + len, max_align); + + grub_arch_clean_dcache_range (start, end, dlinesz); + grub_arch_invalidate_icache_range (start, end, ilinesz); +} + +void +grub_arch_sync_dma_caches (volatile void *address __attribute__((unused)), + grub_size_t len __attribute__((unused))) +{ + /* DMA incoherent devices not supported yet */ +} diff --git a/grub-core/kern/riscv/cache_flush.S b/grub-core/kern/riscv/cache_flush.S new file mode 100644 index 000000000..41de6e411 --- /dev/null +++ b/grub-core/kern/riscv/cache_flush.S @@ -0,0 +1,44 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include + + .file "cache_flush.S" + .text + +/* + * Simple cache maintenance functions + */ + +/* + * a0 - *beg (inclusive) + * a1 - *end (exclusive) + * a2 - line size +*/ +FUNCTION(grub_arch_clean_dcache_range) + /* TODO */ + ret + +/* + * a0 - *beg (inclusive) + * a1 - *end (exclusive) + * a2 - line size + */ +FUNCTION(grub_arch_invalidate_icache_range) + fence.i + ret diff --git a/grub-core/kern/riscv/dl.c b/grub-core/kern/riscv/dl.c new file mode 100644 index 000000000..896653bb4 --- /dev/null +++ b/grub-core/kern/riscv/dl.c @@ -0,0 +1,346 @@ +/* dl.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +/* + * Instructions and instruction encoding are documented in the RISC-V + * specification. This file is based on version 2.2: + * + * https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf + */ +#define LDR 0x58000050 +#define BR 0xd61f0200 + +/* + * Check if EHDR is a valid ELF header. + */ +grub_err_t +grub_arch_dl_check_header (void *ehdr) +{ + Elf_Ehdr *e = ehdr; + + /* Check the magic numbers. */ + if (e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_RISCV) + return grub_error (GRUB_ERR_BAD_OS, + N_("invalid arch-dependent ELF magic")); + + return GRUB_ERR_NONE; +} + +#pragma GCC diagnostic ignored "-Wcast-align" + +/* Relocate symbols. */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg) +{ + Elf_Rel *rel, *max; + + for (rel = (Elf_Rel *) ((char *) ehdr + s->sh_offset), + max = (Elf_Rel *) ((char *) rel + s->sh_size); + rel < max; + rel = (Elf_Rel *) ((char *) rel + s->sh_entsize)) + { + Elf_Sym *sym; + void *place; + grub_size_t sym_addr; + + if (rel->r_offset >= seg->size) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + + sym = (Elf_Sym *) ((char *) mod->symtab + + mod->symsize * ELF_R_SYM (rel->r_info)); + + sym_addr = sym->st_value; + if (s->sh_type == SHT_RELA) + sym_addr += ((Elf_Rela *) rel)->r_addend; + + place = (void *) ((grub_addr_t) seg->addr + rel->r_offset); + + switch (ELF_R_TYPE (rel->r_info)) + { + case R_RISCV_32: + { + grub_uint32_t *abs_place = place; + + grub_dprintf ("dl", " reloc_abs32 %p => 0x%016llx\n", + place, (unsigned long long) sym_addr); + + *abs_place = (grub_uint32_t) sym_addr; + } + break; + case R_RISCV_64: + { + grub_size_t *abs_place = place; + + grub_dprintf ("dl", " reloc_abs64 %p => 0x%016llx\n", + place, (unsigned long long) sym_addr); + + *abs_place = (grub_size_t) sym_addr; + } + break; + + case R_RISCV_ADD8: + { + grub_uint8_t *abs_place = place; + + *abs_place += (grub_uint8_t) sym_addr; + } + break; + case R_RISCV_ADD16: + { + grub_uint16_t *abs_place = place; + + *abs_place += (grub_uint16_t) sym_addr; + } + break; + case R_RISCV_ADD32: + { + grub_uint32_t *abs_place = place; + + *abs_place += (grub_uint32_t) sym_addr; + } + break; + case R_RISCV_ADD64: + { + grub_size_t *abs_place = place; + + *abs_place += (grub_size_t) sym_addr; + } + break; + + case R_RISCV_SUB8: + { + grub_uint8_t *abs_place = place; + + *abs_place -= (grub_uint8_t) sym_addr; + } + break; + case R_RISCV_SUB16: + { + grub_uint16_t *abs_place = place; + + *abs_place -= (grub_uint16_t) sym_addr; + } + break; + case R_RISCV_SUB32: + { + grub_uint32_t *abs_place = place; + + *abs_place -= (grub_uint32_t) sym_addr; + } + break; + case R_RISCV_SUB64: + { + grub_size_t *abs_place = place; + + *abs_place -= (grub_size_t) sym_addr; + } + break; + + case R_RISCV_BRANCH: + { + grub_uint32_t *abs_place = place; + grub_ssize_t off = sym_addr - (grub_addr_t) place; + grub_uint32_t imm12 = (off & 0x1000) << (31 - 12); + grub_uint32_t imm11 = (off & 0x800) >> (11 - 7); + grub_uint32_t imm10_5 = (off & 0x7e0) << (30 - 10); + grub_uint32_t imm4_1 = (off & 0x1e) << (11 - 4); + *abs_place = (*abs_place & 0x1fff07f) + | imm12 | imm11 | imm10_5 | imm4_1; + } + break; + + case R_RISCV_JAL: + { + grub_uint32_t *abs_place = place; + grub_ssize_t off = sym_addr - (grub_addr_t) place; + grub_uint32_t imm20 = (off & 0x100000) << (31 - 20); + grub_uint32_t imm19_12 = (off & 0xff000); + grub_uint32_t imm11 = (off & 0x800) << (20 - 11); + grub_uint32_t imm10_1 = (off & 0x7fe) << (30 - 10); + *abs_place = (*abs_place & 0xfff) + | imm20 | imm19_12 | imm11 | imm10_1; + } + break; + + case R_RISCV_CALL: + case R_RISCV_CALL_PLT: + { + grub_uint32_t *abs_place = place; + grub_ssize_t off = sym_addr - (grub_addr_t) place; + grub_uint32_t hi20, lo12; + + if (off != (grub_int32_t) off) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation overflow"); + + hi20 = (off + 0x800) & 0xfffff000; + lo12 = (off - hi20) & 0xfff; + abs_place[0] = (abs_place[0] & 0xfff) | hi20; + abs_place[1] = (abs_place[1] & 0xfffff) | (lo12 << 20); + } + break; + + case R_RISCV_RVC_BRANCH: + { + grub_uint16_t *abs_place = place; + grub_ssize_t off = sym_addr - (grub_addr_t) place; + grub_uint16_t imm8 = (off & 0x100) << (12 - 8); + grub_uint16_t imm7_6 = (off & 0xc0) >> (6 - 5); + grub_uint16_t imm5 = (off & 0x20) >> (5 - 2); + grub_uint16_t imm4_3 = (off & 0x18) << (12 - 5); + grub_uint16_t imm2_1 = (off & 0x6) << (12 - 10); + *abs_place = (*abs_place & 0xe383) + | imm8 | imm7_6 | imm5 | imm4_3 | imm2_1; + } + break; + + case R_RISCV_RVC_JUMP: + { + grub_uint16_t *abs_place = place; + grub_ssize_t off = sym_addr - (grub_addr_t) place; + grub_uint16_t imm11 = (off & 0x800) << (12 - 11); + grub_uint16_t imm10 = (off & 0x400) >> (10 - 8); + grub_uint16_t imm9_8 = (off & 0x300) << (12 - 11); + grub_uint16_t imm7 = (off & 0x80) >> (7 - 6); + grub_uint16_t imm6 = (off & 0x40) << (12 - 11); + grub_uint16_t imm5 = (off & 0x20) >> (5 - 2); + grub_uint16_t imm4 = (off & 0x10) << (12 - 5); + grub_uint16_t imm3_1 = (off & 0xe) << (12 - 10); + *abs_place = ((*abs_place & 0xe003) + | imm11 | imm10 | imm9_8 | imm7 | imm6 + | imm5 | imm4 | imm3_1); + } + break; + + case R_RISCV_PCREL_HI20: + { + grub_uint32_t *abs_place = place; + grub_ssize_t off = sym_addr - (grub_addr_t) place; + grub_int32_t hi20; + + if (off != (grub_int32_t)off) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation overflow"); + + hi20 = (off + 0x800) & 0xfffff000; + *abs_place = (*abs_place & 0xfff) | hi20; + } + break; + + case R_RISCV_PCREL_LO12_I: + case R_RISCV_PCREL_LO12_S: + { + grub_uint32_t *t32 = place; + Elf_Rela *rel2; + /* Search backwards for matching HI20 reloc. */ + for (rel2 = (Elf_Rela *) ((char *) rel - s->sh_entsize); + (unsigned long)rel2 >= ((unsigned long)ehdr + s->sh_offset); + rel2 = (Elf_Rela *) ((char *) rel2 - s->sh_entsize)) + { + Elf_Addr rel2_info; + Elf_Addr rel2_offset; + Elf_Addr rel2_sym_addr; + Elf_Addr rel2_loc; + grub_ssize_t rel2_off; + grub_ssize_t off; + Elf_Sym *sym2; + + rel2_offset = rel2->r_offset; + rel2_info = rel2->r_info; + rel2_loc = (grub_addr_t) seg->addr + rel2_offset; + + if (ELF_R_TYPE (rel2_info) == R_RISCV_PCREL_HI20 + && rel2_loc == sym_addr) + { + sym2 = (Elf_Sym *) ((char *) mod->symtab + + mod->symsize * ELF_R_SYM (rel2->r_info)); + rel2_sym_addr = sym2->st_value; + if (s->sh_type == SHT_RELA) + rel2_sym_addr += ((Elf_Rela *) rel2)->r_addend; + + rel2_off = rel2_sym_addr - rel2_loc; + off = rel2_off - ((rel2_off + 0x800) & 0xfffff000); + + if (ELF_R_TYPE (rel->r_info) == R_RISCV_PCREL_LO12_I) + *t32 = (*t32 & 0xfffff) | (off & 0xfff) << 20; + else + { + grub_uint32_t imm11_5 = (off & 0xfe0) << (31 - 11); + grub_uint32_t imm4_0 = (off & 0x1f) << (11 - 4); + *t32 = (*t32 & 0x1fff07f) | imm11_5 | imm4_0; + } + break; + } + } + if ((unsigned long)rel2 < ((unsigned long)ehdr + s->sh_offset)) + return grub_error (GRUB_ERR_BAD_MODULE, "cannot find matching HI20 relocation"); + } + break; + + case R_RISCV_HI20: + { + grub_uint32_t *abs_place = place; + *abs_place = (*abs_place & 0xfff) | + (((grub_int32_t) sym_addr + 0x800) & 0xfffff000); + } + break; + + case R_RISCV_LO12_I: + { + grub_uint32_t *abs_place = place; + grub_int32_t lo12 = (grub_int32_t) sym_addr - + (((grub_int32_t) sym_addr + 0x800) & 0xfffff000); + *abs_place = (*abs_place & 0xfffff) | ((lo12 & 0xfff) << 20); + } + break; + + case R_RISCV_LO12_S: + { + grub_uint32_t *abs_place = place; + grub_int32_t lo12 = (grub_int32_t) sym_addr - + (((grub_int32_t) sym_addr + 0x800) & 0xfffff000); + grub_uint32_t imm11_5 = (lo12 & 0xfe0) << (31 - 11); + grub_uint32_t imm4_0 = (lo12 & 0x1f) << (11 - 4); + *abs_place = (*abs_place & 0x1fff07f) | imm11_5 | imm4_0; + } + break; + + case R_RISCV_RELAX: + break; + default: + { + char rel_info[17]; /* log16(2^64) = 16, plus NUL. */ + + grub_snprintf (rel_info, sizeof (rel_info) - 1, "%" PRIxGRUB_UINT64_T, + (grub_uint64_t) ELF_R_TYPE (rel->r_info)); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%s is not implemented yet"), rel_info); + } + } + } + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/riscv/efi/init.c b/grub-core/kern/riscv/efi/init.c new file mode 100644 index 000000000..0d7de4f54 --- /dev/null +++ b/grub-core/kern/riscv/efi/init.c @@ -0,0 +1,78 @@ +/* init.c - initialize a riscv-based EFI system */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +static grub_uint64_t timer_frequency_in_khz; + +static grub_uint64_t +grub_efi_get_time_ms (void) +{ + grub_uint64_t tmr; + +#if __riscv_xlen == 64 + asm volatile ("rdtime %0" : "=r"(tmr)); +#else + grub_uint32_t lo, hi, tmp; + asm volatile ("1:\n" + "rdtimeh %0\n" + "rdtime %1\n" + "rdtimeh %2\n" + "bne %0, %2, 1b" + : "=&r" (hi), "=&r" (lo), "=&r" (tmp)); + tmr = ((grub_uint64_t)hi << 32) | lo; +#endif + + return tmr / timer_frequency_in_khz; +} + +void +grub_machine_init (void) +{ + grub_uint64_t time_before, time_after; + + grub_efi_init (); + + /* Calculate timer frequency */ + timer_frequency_in_khz = 1; + time_before = grub_efi_get_time_ms(); + grub_efi_stall(1000); + time_after = grub_efi_get_time_ms(); + timer_frequency_in_khz = time_after - time_before; + + grub_install_get_time_ms (grub_efi_get_time_ms); +} + +void +grub_machine_fini (int flags) +{ + if (!(flags & GRUB_LOADER_FLAG_NORETURN)) + return; + + grub_efi_fini (); + + if (!(flags & GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY)) + grub_efi_memory_fini (); +} diff --git a/grub-core/kern/riscv/efi/startup.S b/grub-core/kern/riscv/efi/startup.S new file mode 100644 index 000000000..f2a7b2b1e --- /dev/null +++ b/grub-core/kern/riscv/efi/startup.S @@ -0,0 +1,48 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include + +#if __riscv_xlen == 64 +#define sl sd +#define ll ld +#else +#define sl sw +#define ll lw +#endif + + + .file "startup.S" + .text +FUNCTION(_start) + /* + * EFI_SYSTEM_TABLE and EFI_HANDLE are passed in a1/a0. + */ + + ll a2, efi_image_handle_val + sl a0, 0(a2) + ll a2, efi_system_table_val + sl a1, 0(a2) + ll a2, grub_main_val + jr a2 +grub_main_val: + .quad EXT_C(grub_main) +efi_system_table_val: + .quad EXT_C(grub_efi_system_table) +efi_image_handle_val: + .quad EXT_C(grub_efi_image_handle) diff --git a/grub-core/kern/sparc64/dl.c b/grub-core/kern/sparc64/dl.c index d188c4f23..f3d960186 100644 --- a/grub-core/kern/sparc64/dl.c +++ b/grub-core/kern/sparc64/dl.c @@ -40,108 +40,152 @@ grub_arch_dl_check_header (void *ehdr) #pragma GCC diagnostic ignored "-Wcast-align" -/* Relocate symbols. */ -grub_err_t -grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +struct trampoline { - Elf_Ehdr *e = ehdr; - Elf_Shdr *s; - Elf_Word entsize; + grub_uint8_t code[0x28]; + grub_uint64_t addr; +}; + +static const grub_uint8_t trampoline_code[0x28] = +{ + /* 0: */ 0x82, 0x10, 0x00, 0x0f, /* mov %o7, %g1 */ + /* 4: */ 0x40, 0x00, 0x00, 0x02, /* call 0xc */ + /* 8: */ 0x01, 0x00, 0x00, 0x00, /* nop */ + /* c: */ 0x9e, 0x1b, 0xc0, 0x01, /* xor %o7, %g1, %o7 */ + /* 10: */ 0x82, 0x18, 0x40, 0x0f, /* xor %g1, %o7, %g1 */ + /* 14: */ 0x9e, 0x1b, 0xc0, 0x01, /* xor %o7, %g1, %o7 */ + /* 18: */ 0xc2, 0x58, 0x60, 0x24, /* ldx [ %g1 + 0x24 ], %g1 */ + /* 1c: */ 0x81, 0xc0, 0x40, 0x00, /* jmp %g1 */ + /* 20: */ 0x01, 0x00, 0x00, 0x00, /* nop */ + /* 24: */ 0x01, 0x00, 0x00, 0x00, /* nop */ +}; + +grub_err_t +grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, + grub_size_t *got) +{ + const Elf_Ehdr *e = ehdr; + const Elf_Shdr *s; unsigned i; - /* Find a symbol table. */ - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + *tramp = 0; + *got = 0; + + for (i = 0, s = (const Elf_Shdr *) ((grub_addr_t) e + e->e_shoff); i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_SYMTAB) - break; - - if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); - - entsize = s->sh_entsize; - - for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_RELA) + i++, s = (const Elf_Shdr *) ((grub_addr_t) s + e->e_shentsize)) + if (s->sh_type == SHT_REL || s->sh_type == SHT_RELA) { - grub_dl_segment_t seg; + const Elf_Rel *rel, *max; - /* Find the target segment. */ - for (seg = mod->segment; seg; seg = seg->next) - if (seg->section == s->sh_info) - break; - - if (seg) - { - Elf_Rela *rel, *max; - - for (rel = (Elf_Rela *) ((char *) e + s->sh_offset), - max = rel + s->sh_size / s->sh_entsize; - rel < max; - rel++) + for (rel = (const Elf_Rel *) ((grub_addr_t) e + s->sh_offset), + max = rel + s->sh_size / s->sh_entsize; + rel < max; + rel = (const Elf_Rel *) ((grub_addr_t) rel + s->sh_entsize)) + switch (ELF_R_TYPE (rel->r_info)) + { + case R_SPARC_WDISP30: { - Elf_Word *addr; - Elf_Sym *sym; - Elf_Addr value; - - if (seg->size < rel->r_offset) - return grub_error (GRUB_ERR_BAD_MODULE, - "reloc offset is out of the segment"); - - addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset); - sym = (Elf_Sym *) ((char *) mod->symtab - + entsize * ELF_R_SYM (rel->r_info)); - - value = sym->st_value + rel->r_addend; - switch (ELF_R_TYPE (rel->r_info) & 0xff) - { - case R_SPARC_32: /* 3 V-word32 */ - if (value & 0xFFFFFFFF00000000) - return grub_error (GRUB_ERR_BAD_MODULE, - "address out of 32 bits range"); - *addr = value; - break; - case R_SPARC_WDISP30: /* 7 V-disp30 */ - if (((value - (Elf_Addr) addr) & 0xFFFFFFFF00000000) && - (((value - (Elf_Addr) addr) & 0xFFFFFFFF00000000) - != 0xFFFFFFFF00000000)) - return grub_error (GRUB_ERR_BAD_MODULE, - "displacement out of 30 bits range"); - *addr = (*addr & 0xC0000000) | - (((grub_int32_t) ((value - (Elf_Addr) addr) >> 2)) & - 0x3FFFFFFF); - break; - case R_SPARC_HH22: /* 9 V-imm22 */ - *addr = (*addr & 0xFFC00000) | ((value >> 42) & 0x3FFFFF); - break; - case R_SPARC_HM10: /* 12 T-simm13 */ - *addr = (*addr & 0xFFFFFC00) | ((value >> 32) & 0x3FF); - break; - case R_SPARC_HI22: /* 9 V-imm22 */ - *addr = (*addr & 0xFFC00000) | ((value >> 10) & 0x3FFFFF); - break; - case R_SPARC_LO10: /* 12 T-simm13 */ - *addr = (*addr & 0xFFFFFC00) | (value & 0x3FF); - break; - case R_SPARC_64: /* 32 V-xwords64 */ - *(Elf_Xword *) addr = value; - break; - case R_SPARC_OLO10: - *addr = (*addr & ~0x1fff) - | (((value & 0x3ff) + - (ELF_R_TYPE (rel->r_info) >> 8)) - & 0x1fff); - break; - default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("relocation 0x%x is not implemented yet"), - ELF_R_TYPE (rel->r_info)); - } + *tramp += sizeof (struct trampoline); + break; } - } + } } return GRUB_ERR_NONE; } + +/* Relocate symbols. */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg) +{ + Elf_Rela *rel, *max; + + for (rel = (Elf_Rela *) ((char *) ehdr + s->sh_offset), + max = (Elf_Rela *) ((char *) rel + s->sh_size); + rel < max; + rel = (Elf_Rela *) ((char *) rel + s->sh_entsize)) + { + Elf_Word *addr; + Elf_Sym *sym; + Elf_Addr value; + + if (seg->size < rel->r_offset) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + + addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset); + sym = (Elf_Sym *) ((char *) mod->symtab + + mod->symsize * ELF_R_SYM (rel->r_info)); + + value = sym->st_value + rel->r_addend; + switch (ELF_R_TYPE (rel->r_info) & 0xff) + { + case R_SPARC_32: /* 3 V-word32 */ + if (value & 0xFFFFFFFF00000000) + return grub_error (GRUB_ERR_BAD_MODULE, + "address out of 32 bits range"); + *addr = value; + break; + case R_SPARC_WDISP30: /* 7 V-disp30 */ + if (((value - (Elf_Addr) addr) & 0xFFFFFFFF00000000) && + (((value - (Elf_Addr) addr) & 0xFFFFFFFF00000000) + != 0xFFFFFFFF00000000)) + { + struct trampoline *tp = mod->trampptr; + mod->trampptr = tp + 1; + grub_memcpy (tp->code, trampoline_code, sizeof (tp->code)); + tp->addr = value; + value = (Elf_Addr) tp; + } + + if (((value - (Elf_Addr) addr) & 0xFFFFFFFF00000000) && + (((value - (Elf_Addr) addr) & 0xFFFFFFFF00000000) + != 0xFFFFFFFF00000000)) + return grub_error (GRUB_ERR_BAD_MODULE, + "displacement out of 30 bits range"); + *addr = (*addr & 0xC0000000) | + (((grub_int32_t) ((value - (Elf_Addr) addr) >> 2)) & + 0x3FFFFFFF); + break; + case R_SPARC_HH22: /* 9 V-imm22 */ + *addr = (*addr & 0xFFC00000) | ((value >> 42) & 0x3FFFFF); + break; + case R_SPARC_HM10: /* 12 T-simm13 */ + *addr = (*addr & 0xFFFFFC00) | ((value >> 32) & 0x3FF); + break; + case R_SPARC_HI22: /* 9 V-imm22 */ + if (value >> 32) + return grub_error (GRUB_ERR_BAD_MODULE, + "address out of 32 bits range"); + /* Fallthrough. */ + case R_SPARC_LM22: + *addr = (*addr & 0xFFC00000) | ((value >> 10) & 0x3FFFFF); + break; + case R_SPARC_LO10: /* 12 T-simm13 */ + *addr = (*addr & 0xFFFFFC00) | (value & 0x3FF); + break; + case R_SPARC_64: /* 32 V-xwords64 */ + *(Elf_Xword *) addr = value; + break; + case R_SPARC_OLO10: + *addr = (*addr & ~0x1fff) + | (((value & 0x3ff) + + (ELF_R_TYPE (rel->r_info) >> 8)) + & 0x1fff); + break; + default: + { + char rel_info[17]; /* log16(2^64) = 16, plus NUL. */ + + grub_snprintf (rel_info, sizeof (rel_info) - 1, "%" PRIxGRUB_UINT64_T, + ELF_R_TYPE (rel->r_info)); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%s is not implemented yet"), rel_info); + } + } + } + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S index 9d91fba48..03b916f05 100644 --- a/grub-core/kern/sparc64/ieee1275/crt0.S +++ b/grub-core/kern/sparc64/ieee1275/crt0.S @@ -27,7 +27,7 @@ _start: ba codestart mov %o4, %o0 - . = EXT_C(_start) + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE + .org GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE VARIABLE(grub_total_module_size) .word 0 @@ -36,10 +36,14 @@ codestart: /* Copy the modules past the end of the kernel image. * They are currently sitting in the BSS. */ - sethi %hi(__bss_start), %o2 - or %o2, %lo(__bss_start), %o2 - sethi %hi(_end), %o3 - or %o3, %lo(_end), %o3 + sethi %hi(__bss_start + GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN - 1), %o2 + or %o2, %lo(__bss_start + GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN - 1), %o2 + srl %o2, GRUB_KERNEL_SPARC64_IEEE1275_LOG_MOD_ALIGN, %o2 + sll %o2, GRUB_KERNEL_SPARC64_IEEE1275_LOG_MOD_ALIGN, %o2 + sethi %hi(_end + GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN - 1), %o3 + or %o3, %lo(_end + GRUB_KERNEL_SPARC64_IEEE1275_MOD_ALIGN - 1), %o3 + srl %o3, GRUB_KERNEL_SPARC64_IEEE1275_LOG_MOD_ALIGN, %o3 + sll %o3, GRUB_KERNEL_SPARC64_IEEE1275_LOG_MOD_ALIGN, %o3 sethi %hi(grub_total_module_size), %o4 lduw [%o4 + %lo(grub_total_module_size)], %o4 @@ -67,16 +71,34 @@ codestart: /* Now it's safe to clear out the BSS. */ sethi %hi(__bss_start), %o2 or %o2, %lo(__bss_start), %o2 - sethi %hi(_end), %o3 - or %o3, %lo(_end), %o3 +1: stb %g0, [%o2] + add %o2, 1, %o2 + and %o2, 7, %o3 + brnz %o3, 1b + nop + + sethi %hi(_end - 1), %o3 + or %o3, %lo(_end - 1), %o3 + srl %o3, 3, %o3 + sll %o3, 3, %o3 1: stx %g0, [%o2] add %o2, 8, %o2 cmp %o2, %o3 blt,pt %xcc, 1b nop + + sethi %hi(_end), %o3 + or %o3, %lo(_end), %o3 +1: stb %g0, [%o2] + add %o2, 1, %o2 + cmp %o2, %o3 + blt,pt %xcc, 1b + nop + sethi %hi(grub_ieee1275_original_stack), %o2 stx %o1, [%o2 + %lo(grub_ieee1275_original_stack)] sethi %hi(grub_ieee1275_entry_fn), %o2 call grub_main stx %o0, [%o2 + %lo(grub_ieee1275_entry_fn)] 1: ba,a 1b + nop diff --git a/grub-core/kern/sparc64/ieee1275/ieee1275.c b/grub-core/kern/sparc64/ieee1275/ieee1275.c index 53be692c3..5a59aaf06 100644 --- a/grub-core/kern/sparc64/ieee1275/ieee1275.c +++ b/grub-core/kern/sparc64/ieee1275/ieee1275.c @@ -89,3 +89,59 @@ grub_ieee1275_alloc_physmem (grub_addr_t *paddr, grub_size_t size, return args.catch_result; } + +grub_uint64_t +grub_ieee1275_num_blocks (grub_ieee1275_ihandle_t ihandle) +{ + struct nblocks_args_ieee1275 + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t catch_result; + grub_ieee1275_cell_t blocks; + } + args; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 2); + args.method = (grub_ieee1275_cell_t) "#blocks"; + args.ihandle = ihandle; + args.catch_result = 1; + + if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result != 0)) + return -1; + + /* + * If the number of blocks exceeds the range of an unsigned number, + * return 0 to alert the caller to try the #blocks64 command. + */ + if (args.blocks >= 0xffffffffULL) + return 0; + + return args.blocks; +} + +grub_uint64_t +grub_ieee1275_num_blocks64 (grub_ieee1275_ihandle_t ihandle) +{ + struct nblocks_args_ieee1275 + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t catch_result; + grub_ieee1275_cell_t hi_blocks; + grub_ieee1275_cell_t lo_blocks; + } + args; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 3); + args.method = (grub_ieee1275_cell_t) "#blocks64"; + args.ihandle = ihandle; + args.catch_result = 1; + + if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.catch_result != 0)) + return -1; + + return ((args.hi_blocks << 32) | (args.lo_blocks)); +} diff --git a/grub-core/kern/term.c b/grub-core/kern/term.c index 5014caf62..14d596498 100644 --- a/grub-core/kern/term.c +++ b/grub-core/kern/term.c @@ -28,7 +28,11 @@ struct grub_term_input *grub_term_inputs_disabled; struct grub_term_output *grub_term_outputs; struct grub_term_input *grub_term_inputs; -void (*grub_term_poll_usb) (void) = NULL; +/* Current color state. */ +grub_uint8_t grub_term_normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR; +grub_uint8_t grub_term_highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR; + +void (*grub_term_poll_usb) (int wait_for_completion) = NULL; void (*grub_net_poll_cards_idle) (void) = NULL; /* Put a Unicode character. */ @@ -42,7 +46,6 @@ grub_putcode_dumb (grub_uint32_t code, .variant = 0, .attributes = 0, .ncomb = 0, - .combining = 0, .estimated_width = 1 }; @@ -50,7 +53,7 @@ grub_putcode_dumb (grub_uint32_t code, { int n; - n = GRUB_TERM_TAB_WIDTH - ((term->getxy (term) >> 8) + n = GRUB_TERM_TAB_WIDTH - ((term->getxy (term).x) % GRUB_TERM_TAB_WIDTH); while (n--) grub_putcode_dumb (' ', term); @@ -86,7 +89,7 @@ grub_getkey_noblock (void) grub_term_input_t term; if (grub_term_poll_usb) - grub_term_poll_usb (); + grub_term_poll_usb (0); if (grub_net_poll_cards_idle) grub_net_poll_cards_idle (); @@ -117,6 +120,45 @@ grub_getkey (void) } } +int +grub_getkeystatus (void) +{ + int status = 0; + grub_term_input_t term; + + if (grub_term_poll_usb) + grub_term_poll_usb (0); + + FOR_ACTIVE_TERM_INPUTS(term) + { + if (term->getkeystatus) + status |= term->getkeystatus (term); + } + + return status; +} + +int +grub_key_is_interrupt (int key) +{ + /* + * ESC sometimes is the BIOS setup hotkey and may be hard to discover, also + * check F4, which was chosen because is not used as a hotkey to enter the + * BIOS setup by any vendor. + */ + if (key == GRUB_TERM_ESC || key == GRUB_TERM_KEY_F4) + return 1; + + /* + * Pressing keys at the right time during boot is hard to time, also allow + * interrupting sleeps / the menu countdown by keeping shift pressed. + */ + if (grub_getkeystatus() & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) + return 1; + + return 0; +} + void grub_refresh (void) { diff --git a/grub-core/kern/uboot/hw.c b/grub-core/kern/uboot/hw.c new file mode 100644 index 000000000..272b83bd7 --- /dev/null +++ b/grub-core/kern/uboot/hw.c @@ -0,0 +1,112 @@ +/* hw.c - U-Boot hardware discovery */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +grub_addr_t start_of_ram; + +/* + * grub_uboot_probe_memory(): + * Queries U-Boot for available memory regions. + * + * Sets up heap near the image in memory and sets up "start_of_ram". + */ +void +grub_uboot_mm_init (void) +{ + struct sys_info *si = grub_uboot_get_sys_info (); + + grub_mm_init_region ((void *) grub_modules_get_end (), + GRUB_KERNEL_MACHINE_HEAP_SIZE); + + if (si && (si->mr_no != 0)) + { + int i; + start_of_ram = GRUB_UINT_MAX; + + for (i = 0; i < si->mr_no; i++) + if ((si->mr[i].flags & MR_ATTR_MASK) == MR_ATTR_DRAM) + if (si->mr[i].start < start_of_ram) + start_of_ram = si->mr[i].start; + } +} + +/* + * grub_uboot_probe_hardware(): + */ +grub_err_t +grub_uboot_probe_hardware (void) +{ + int devcount, i; + + devcount = grub_uboot_dev_enum (); + grub_dprintf ("init", "%d devices found\n", devcount); + + for (i = 0; i < devcount; i++) + { + struct device_info *devinfo = grub_uboot_dev_get (i); + + grub_dprintf ("init", "device handle: %d\n", i); + grub_dprintf ("init", " cookie\t= 0x%08x\n", + (grub_uint32_t) devinfo->cookie); + + if (devinfo->type & DEV_TYP_STOR) + { + grub_dprintf ("init", " type\t\t= DISK\n"); + grub_ubootdisk_register (devinfo); + } + else if (devinfo->type & DEV_TYP_NET) + { + /* Dealt with in ubootnet module. */ + grub_dprintf ("init", " type\t\t= NET (not supported yet)\n"); + } + else + { + grub_dprintf ("init", "%s: unknown device type", __FUNCTION__); + } + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) +{ + int i; + struct sys_info *si = grub_uboot_get_sys_info (); + + if (!si || (si->mr_no < 1)) + return GRUB_ERR_BUG; + + /* Iterate and call `hook'. */ + for (i = 0; i < si->mr_no; i++) + if ((si->mr[i].flags & MR_ATTR_MASK) == MR_ATTR_DRAM) + hook (si->mr[i].start, si->mr[i].size, GRUB_MEMORY_AVAILABLE, + hook_data); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/kern/uboot/init.c b/grub-core/kern/uboot/init.c new file mode 100644 index 000000000..3e338645c --- /dev/null +++ b/grub-core/kern/uboot/init.c @@ -0,0 +1,172 @@ +/* init.c - generic U-Boot initialization and finalization */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char __bss_start[]; +extern char _end[]; +extern grub_size_t grub_total_module_size; +static unsigned long timer_start; + +void +grub_exit (void) +{ + grub_uboot_return (0); +} + +static grub_uint64_t +uboot_timer_ms (void) +{ + static grub_uint32_t last = 0, high = 0; + grub_uint32_t cur = grub_uboot_get_timer (timer_start); + if (cur < last) + high++; + last = cur; + return (((grub_uint64_t) high) << 32) | cur; +} + +#ifdef __arm__ +static grub_uint64_t +rpi_timer_ms (void) +{ + static grub_uint32_t last = 0, high = 0; + grub_uint32_t cur = *(volatile grub_uint32_t *) 0x20003004; + if (cur < last) + high++; + last = cur; + return grub_divmod64 ((((grub_uint64_t) high) << 32) | cur, 1000, 0); +} +#endif + +void +grub_machine_init (void) +{ + int ver; + + /* First of all - establish connection with U-Boot */ + ver = grub_uboot_api_init (); + if (!ver) + { + /* Don't even have a console to log errors to... */ + grub_exit (); + } + else if (ver > API_SIG_VERSION) + { + /* Try to print an error message */ + grub_uboot_puts ("invalid U-Boot API version\n"); + } + + /* Initialize the console so that GRUB can display messages. */ + grub_console_init_early (); + + /* Enumerate memory and initialize the memory management system. */ + grub_uboot_mm_init (); + + /* Should be earlier but it needs memalign. */ +#ifdef __arm__ + grub_arm_enable_caches_mmu (); +#endif + + grub_dprintf ("init", "__bss_start: %p\n", __bss_start); + grub_dprintf ("init", "_end: %p\n", _end); + grub_dprintf ("init", "grub_modbase: %p\n", (void *) grub_modbase); + grub_dprintf ("init", "grub_modules_get_end(): %p\n", + (void *) grub_modules_get_end ()); + + /* Initialise full terminfo support */ + grub_console_init_lately (); + + /* Enumerate uboot devices */ + grub_uboot_probe_hardware (); + + /* Initialise timer */ +#ifdef __arm__ + if (grub_uboot_get_machine_type () == GRUB_ARM_MACHINE_TYPE_RASPBERRY_PI) + { + grub_install_get_time_ms (rpi_timer_ms); + } + else +#endif + { + timer_start = grub_uboot_get_timer (0); + grub_install_get_time_ms (uboot_timer_ms); + } + + /* Initialize */ + grub_ubootdisk_init (); +} + + +void +grub_machine_fini (int flags __attribute__ ((unused))) +{ +} + +/* + * grub_machine_get_bootlocation(): + * Called from kern/main.c, which expects a device name (minus parentheses) + * and a filesystem path back, if any are known. + * Any returned values must be pointers to dynamically allocated strings. + */ +void +grub_machine_get_bootlocation (char **device, char **path) +{ + char *tmp; + + tmp = grub_uboot_env_get ("grub_bootdev"); + if (tmp) + { + *device = grub_strdup (tmp); + if (*device == NULL) + return; + } + else + *device = NULL; + + tmp = grub_uboot_env_get ("grub_bootpath"); + if (tmp) + { + *path = grub_strdup (tmp); + if (*path == NULL) + return; + } + else + *path = NULL; +} + +void +grub_uboot_fini (void) +{ + grub_ubootdisk_fini (); + grub_console_fini (); +} diff --git a/grub-core/kern/uboot/uboot.c b/grub-core/kern/uboot/uboot.c new file mode 100644 index 000000000..aac8f9ae1 --- /dev/null +++ b/grub-core/kern/uboot/uboot.c @@ -0,0 +1,307 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include + +/* + * The main syscall entry point is not reentrant, only one call is + * serviced until finished. + * + * int syscall(int call, int *retval, ...) + * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t); + * + * call: syscall number + * + * retval: points to the return value placeholder, this is the place the + * syscall puts its return value, if NULL the caller does not + * expect a return value + * + * ... syscall arguments (variable number) + * + * returns: 0 if the call not found, 1 if serviced + */ + +extern int grub_uboot_syscall (int, int *, ...); + +static struct sys_info uboot_sys_info; +static struct mem_region uboot_mem_info[5]; +static struct device_info * devices; +static int num_devices; + + +/* + * All functions below are wrappers around the grub_uboot_syscall() function + */ + +int +grub_uboot_getc (void) +{ + int c; + if (!grub_uboot_syscall (API_GETC, NULL, &c)) + return -1; + + return c; +} + +int +grub_uboot_tstc (void) +{ + int c; + if (!grub_uboot_syscall (API_TSTC, NULL, &c)) + return -1; + + return c; +} + +void +grub_uboot_putc (int c) +{ + grub_uboot_syscall (API_PUTC, NULL, &c); +} + +void +grub_uboot_puts (const char *s) +{ + grub_uboot_syscall (API_PUTS, NULL, s); +} + +void +grub_uboot_reset (void) +{ + grub_uboot_syscall (API_RESET, NULL, 0); +} + +struct sys_info * +grub_uboot_get_sys_info (void) +{ + int retval; + + grub_memset (&uboot_sys_info, 0, sizeof (uboot_sys_info)); + grub_memset (&uboot_mem_info, 0, sizeof (uboot_mem_info)); + uboot_sys_info.mr = uboot_mem_info; + uboot_sys_info.mr_no = sizeof (uboot_mem_info) / sizeof (struct mem_region); + + if (grub_uboot_syscall (API_GET_SYS_INFO, &retval, &uboot_sys_info)) + if (retval == 0) + return &uboot_sys_info; + + return NULL; +} + +void +grub_uboot_udelay (grub_uint32_t usec) +{ + grub_uboot_syscall (API_UDELAY, NULL, &usec); +} + +grub_uint32_t +grub_uboot_get_timer (grub_uint32_t base) +{ + grub_uint32_t current; + + if (!grub_uboot_syscall (API_GET_TIMER, NULL, ¤t, &base)) + return 0; + + return current; +} + +int +grub_uboot_dev_enum (void) +{ + struct device_info * enum_devices; + int num_enum_devices, max_devices; + + if (num_devices) + return num_devices; + + max_devices = 2; + enum_devices = grub_calloc (max_devices, sizeof(struct device_info)); + if (!enum_devices) + return 0; + + /* + * The API_DEV_ENUM call starts a fresh enumeration when passed a + * struct device_info with a NULL cookie, and then depends on having + * the previously enumerated device cookie "seeded" into the target + * structure. + */ + + enum_devices[0].cookie = NULL; + num_enum_devices = 0; + + if (grub_uboot_syscall (API_DEV_ENUM, NULL, + &enum_devices[num_enum_devices]) == 0) + goto error; + + num_enum_devices++; + + while (enum_devices[num_enum_devices - 1].cookie != NULL) + { + if (num_enum_devices == max_devices) + { + struct device_info *tmp; + int new_max; + new_max = max_devices * 2; + tmp = grub_realloc (enum_devices, + sizeof (struct device_info) * new_max); + if (!tmp) + { + /* Failed to realloc, so return what we have */ + break; + } + enum_devices = tmp; + max_devices = new_max; + } + + enum_devices[num_enum_devices].cookie = + enum_devices[num_enum_devices - 1].cookie; + if (grub_uboot_syscall (API_DEV_ENUM, NULL, + &enum_devices[num_enum_devices]) == 0) + goto error; + + if (enum_devices[num_enum_devices].cookie == NULL) + break; + + num_enum_devices++; + } + + devices = enum_devices; + return num_devices = num_enum_devices; + + error: + grub_free (enum_devices); + return 0; +} + +#define VALID_DEV(x) (((x) < num_devices) && ((x) >= 0)) +#define OPEN_DEV(x) ((x->state == DEV_STA_OPEN)) + +struct device_info * +grub_uboot_dev_get (int index) +{ + if (VALID_DEV (index)) + return &devices[index]; + + return NULL; +} + + +int +grub_uboot_dev_open (struct device_info *dev) +{ + int retval; + + if (!grub_uboot_syscall (API_DEV_OPEN, &retval, dev)) + return -1; + + return retval; +} + +int +grub_uboot_dev_close (struct device_info *dev) +{ + int retval; + + if (!grub_uboot_syscall (API_DEV_CLOSE, &retval, dev)) + return -1; + + return retval; +} + + +int +grub_uboot_dev_read (struct device_info *dev, void *buf, grub_size_t blocks, + grub_uint32_t start, grub_size_t * real_blocks) +{ + int retval; + + if (!OPEN_DEV (dev)) + return -1; + + if (!grub_uboot_syscall (API_DEV_READ, &retval, dev, buf, + &blocks, &start, real_blocks)) + return -1; + + return retval; +} + +int +grub_uboot_dev_write (struct device_info *dev, const void *buf, + grub_size_t blocks, grub_uint32_t start) +{ + int retval; + + if (!OPEN_DEV (dev)) + return -1; + + if (!grub_uboot_syscall (API_DEV_WRITE, &retval, dev, buf, + &blocks, &start)) + return -1; + + return retval; +} + +int +grub_uboot_dev_recv (struct device_info *dev, void *buf, + int size, int *real_size) +{ + int retval; + + if (!OPEN_DEV (dev)) + return -1; + + if (!grub_uboot_syscall (API_DEV_READ, &retval, dev, buf, &size, real_size)) + return -1; + + return retval; + +} + +int +grub_uboot_dev_send (struct device_info *dev, void *buf, int size) +{ + int retval; + + if (!OPEN_DEV (dev)) + return -1; + + if (!grub_uboot_syscall (API_DEV_WRITE, &retval, dev, buf, &size)) + return -1; + + return retval; +} + +char * +grub_uboot_env_get (const char *name) +{ + char *value; + + if (!grub_uboot_syscall (API_ENV_GET, NULL, name, &value)) + return NULL; + + return value; +} + +void +grub_uboot_env_set (const char *name, const char *value) +{ + grub_uboot_syscall (API_ENV_SET, NULL, name, value); +} diff --git a/grub-core/kern/verifiers.c b/grub-core/kern/verifiers.c new file mode 100644 index 000000000..75d7994cf --- /dev/null +++ b/grub-core/kern/verifiers.c @@ -0,0 +1,228 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2017 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + * + * Verifiers helper. + */ + +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +struct grub_file_verifier *grub_file_verifiers; + +struct grub_verified +{ + grub_file_t file; + void *buf; +}; +typedef struct grub_verified *grub_verified_t; + +static void +verified_free (grub_verified_t verified) +{ + if (verified) + { + grub_free (verified->buf); + grub_free (verified); + } +} + +static grub_ssize_t +verified_read (struct grub_file *file, char *buf, grub_size_t len) +{ + grub_verified_t verified = file->data; + + grub_memcpy (buf, (char *) verified->buf + file->offset, len); + return len; +} + +static grub_err_t +verified_close (struct grub_file *file) +{ + grub_verified_t verified = file->data; + + grub_file_close (verified->file); + verified_free (verified); + file->data = 0; + + /* Device and name are freed by parent. */ + file->device = 0; + file->name = 0; + + return grub_errno; +} + +struct grub_fs verified_fs = +{ + .name = "verified_read", + .fs_read = verified_read, + .fs_close = verified_close +}; + +static grub_file_t +grub_verifiers_open (grub_file_t io, enum grub_file_type type) +{ + grub_verified_t verified = NULL; + struct grub_file_verifier *ver; + void *context; + grub_file_t ret = 0; + grub_err_t err; + int defer = 0; + + grub_dprintf ("verify", "file: %s type: %d\n", io->name, type); + + if ((type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_SIGNATURE + || (type & GRUB_FILE_TYPE_MASK) == GRUB_FILE_TYPE_VERIFY_SIGNATURE + || (type & GRUB_FILE_TYPE_SKIP_SIGNATURE)) + return io; + + if (io->device->disk && + (io->device->disk->dev->id == GRUB_DISK_DEVICE_MEMDISK_ID + || io->device->disk->dev->id == GRUB_DISK_DEVICE_PROCFS_ID)) + return io; + + FOR_LIST_ELEMENTS(ver, grub_file_verifiers) + { + enum grub_verify_flags flags = 0; + err = ver->init (io, type, &context, &flags); + if (err) + goto fail_noclose; + if (flags & GRUB_VERIFY_FLAGS_DEFER_AUTH) + { + defer = 1; + continue; + } + if (!(flags & GRUB_VERIFY_FLAGS_SKIP_VERIFICATION)) + break; + } + + if (!ver) + { + if (defer) + { + grub_error (GRUB_ERR_ACCESS_DENIED, + N_("verification requested but nobody cares: %s"), io->name); + goto fail_noclose; + } + + /* No verifiers wanted to verify. Just return underlying file. */ + return io; + } + + ret = grub_malloc (sizeof (*ret)); + if (!ret) + { + goto fail; + } + *ret = *io; + + ret->fs = &verified_fs; + ret->not_easily_seekable = 0; + if (ret->size >> (sizeof (grub_size_t) * GRUB_CHAR_BIT - 1)) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("big file signature isn't implemented yet")); + goto fail; + } + verified = grub_malloc (sizeof (*verified)); + if (!verified) + { + goto fail; + } + verified->buf = grub_malloc (ret->size); + if (!verified->buf) + { + goto fail; + } + if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + io->name); + goto fail; + } + + err = ver->write (context, verified->buf, ret->size); + if (err) + goto fail; + + err = ver->fini ? ver->fini (context) : GRUB_ERR_NONE; + if (err) + goto fail; + + if (ver->close) + ver->close (context); + + FOR_LIST_ELEMENTS_NEXT(ver, grub_file_verifiers) + { + enum grub_verify_flags flags = 0; + err = ver->init (io, type, &context, &flags); + if (err) + goto fail_noclose; + if (flags & GRUB_VERIFY_FLAGS_SKIP_VERIFICATION || + /* Verification done earlier. So, we are happy here. */ + flags & GRUB_VERIFY_FLAGS_DEFER_AUTH) + continue; + err = ver->write (context, verified->buf, ret->size); + if (err) + goto fail; + + err = ver->fini ? ver->fini (context) : GRUB_ERR_NONE; + if (err) + goto fail; + + if (ver->close) + ver->close (context); + } + + verified->file = io; + ret->data = verified; + return ret; + + fail: + if (ver->close) + ver->close (context); + fail_noclose: + verified_free (verified); + grub_free (ret); + return NULL; +} + +grub_err_t +grub_verify_string (char *str, enum grub_verify_string_type type) +{ + struct grub_file_verifier *ver; + + grub_dprintf ("verify", "string: %s, type: %d\n", str, type); + + FOR_LIST_ELEMENTS(ver, grub_file_verifiers) + { + grub_err_t err; + err = ver->verify_string ? ver->verify_string (str, type) : GRUB_ERR_NONE; + if (err) + return err; + } + return GRUB_ERR_NONE; +} + +void +grub_verifiers_init (void) +{ + grub_file_filter_register (GRUB_FILE_FILTER_VERIFY, grub_verifiers_open); +} diff --git a/grub-core/kern/vga_init.c b/grub-core/kern/vga_init.c index 889d0128e..3fe2f16de 100644 --- a/grub-core/kern/vga_init.c +++ b/grub-core/kern/vga_init.c @@ -18,6 +18,7 @@ #ifndef __mips__ #include +#include #endif #include #include @@ -45,11 +46,7 @@ static struct {grub_uint8_t r, g, b, a; } colors[] = {0xFE, 0xFE, 0xFE, 0xFF} // 15 = white }; -#ifdef __mips__ -extern unsigned char ascii_bitmaps[]; -#else #include -#endif #ifdef __mips__ #define VGA_ADDR 0xb00a0000 @@ -90,37 +87,6 @@ load_palette (void) void grub_qemu_init_cirrus (void) { -#ifndef __mips__ - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid); - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))) - { - grub_pci_address_t addr; - grub_uint32_t class; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class = grub_pci_read (addr); - - if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA) - return 0; - - /* FIXME: chooose addresses dynamically. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - grub_pci_write (addr, 0xf0000000 | GRUB_PCI_ADDR_MEM_PREFETCH - | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32); - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); - grub_pci_write (addr, 0xf2000000 - | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32); - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); - grub_pci_write (addr, GRUB_PCI_COMMAND_MEM_ENABLED - | GRUB_PCI_COMMAND_IO_ENABLED); - - return 1; - } - - grub_pci_iterate (find_card); -#endif - grub_outb (GRUB_VGA_IO_MISC_COLOR, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_MISC_WRITE); diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c index 65f09ef53..e5a8bdcf4 100644 --- a/grub-core/kern/x86_64/dl.c +++ b/grub-core/kern/x86_64/dl.c @@ -40,83 +40,82 @@ grub_arch_dl_check_header (void *ehdr) /* Relocate symbols. */ grub_err_t -grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr, + Elf_Shdr *s, grub_dl_segment_t seg) { - Elf64_Ehdr *e = ehdr; - Elf64_Shdr *s; - Elf64_Word entsize; - unsigned i; + Elf64_Rela *rel, *max; - /* Find a symbol table. */ - for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf64_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_SYMTAB) - break; + for (rel = (Elf64_Rela *) ((char *) ehdr + s->sh_offset), + max = (Elf64_Rela *) ((char *) rel + s->sh_size); + rel < max; + rel = (Elf64_Rela *) ((char *) rel + s->sh_entsize)) + { + Elf64_Word *addr32; + Elf64_Xword *addr64; + Elf64_Sym *sym; - if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); + if (seg->size < rel->r_offset) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); - entsize = s->sh_entsize; + addr32 = (Elf64_Word *) ((char *) seg->addr + rel->r_offset); + addr64 = (Elf64_Xword *) addr32; + sym = (Elf64_Sym *) ((char *) mod->symtab + + mod->symsize * ELF_R_SYM (rel->r_info)); - for (i = 0, s = (Elf64_Shdr *) ((char *) e + e->e_shoff); - i < e->e_shnum; - i++, s = (Elf64_Shdr *) ((char *) s + e->e_shentsize)) - if (s->sh_type == SHT_RELA) - { - grub_dl_segment_t seg; + switch (ELF_R_TYPE (rel->r_info)) + { + case R_X86_64_64: + *addr64 += rel->r_addend + sym->st_value; + break; - /* Find the target segment. */ - for (seg = mod->segment; seg; seg = seg->next) - if (seg->section == s->sh_info) - break; - - if (seg) + case R_X86_64_PC32: + case R_X86_64_PLT32: { - Elf64_Rela *rel, *max; - - for (rel = (Elf64_Rela *) ((char *) e + s->sh_offset), - max = rel + s->sh_size / s->sh_entsize; - rel < max; - rel++) - { - Elf64_Word *addr32; - Elf64_Xword *addr64; - Elf64_Sym *sym; - - if (seg->size < rel->r_offset) - return grub_error (GRUB_ERR_BAD_MODULE, - "reloc offset is out of the segment"); - - addr32 = (Elf64_Word *) ((char *) seg->addr + rel->r_offset); - addr64 = (Elf64_Xword *) addr32; - sym = (Elf64_Sym *) ((char *) mod->symtab - + entsize * ELF_R_SYM (rel->r_info)); - - switch (ELF_R_TYPE (rel->r_info)) - { - case R_X86_64_64: - *addr64 += rel->r_addend + sym->st_value; - break; - - case R_X86_64_PC32: - *addr32 += rel->r_addend + sym->st_value - - (Elf64_Xword) seg->addr - rel->r_offset; - break; - - case R_X86_64_32: - case R_X86_64_32S: - *addr32 += rel->r_addend + sym->st_value; - break; - - default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - N_("relocation 0x%x is not implemented yet"), - ELF_R_TYPE (rel->r_info)); - } - } + grub_int64_t value; + value = ((grub_int32_t) *addr32) + rel->r_addend + sym->st_value - + (Elf64_Xword) (grub_addr_t) seg->addr - rel->r_offset; + if (value != (grub_int32_t) value) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); + *addr32 = value; } - } + break; + + case R_X86_64_PC64: + { + *addr64 += rel->r_addend + sym->st_value - + (Elf64_Xword) (grub_addr_t) seg->addr - rel->r_offset; + } + break; + + case R_X86_64_32: + { + grub_uint64_t value = *addr32 + rel->r_addend + sym->st_value; + if (value != (grub_uint32_t) value) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); + *addr32 = value; + } + break; + case R_X86_64_32S: + { + grub_int64_t value = ((grub_int32_t) *addr32) + rel->r_addend + sym->st_value; + if (value != (grub_int32_t) value) + return grub_error (GRUB_ERR_BAD_MODULE, "relocation out of range"); + *addr32 = value; + } + break; + + default: + { + char rel_info[17]; /* log16(2^64) = 16, plus NUL. */ + + grub_snprintf (rel_info, sizeof (rel_info) - 1, "%" PRIxGRUB_UINT64_T, + ELF_R_TYPE (rel->r_info)); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%s is not implemented yet"), rel_info); + } + } + } return GRUB_ERR_NONE; } diff --git a/grub-core/kern/x86_64/efi/callwrap.S b/grub-core/kern/x86_64/efi/callwrap.S deleted file mode 100644 index 2df95dda1..000000000 --- a/grub-core/kern/x86_64/efi/callwrap.S +++ /dev/null @@ -1,129 +0,0 @@ -/* callwrap.S - wrapper for x86_64 efi calls */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB 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 GRUB. If not, see . - */ - -#include -#include - -/* - * x86_64 uses registry to pass parameters. Unfortunately, gcc and efi use - * different call conversion, so we need to do some conversion. - * - * gcc: - * %rdi, %rsi, %rdx, %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ... - * - * efi: - * %rcx, %rdx, %r8, %r9, 32(%rsp), 40(%rsp), 48(%rsp), ... - * - */ - - .file "callwrap.S" - .text - -FUNCTION(efi_wrap_0) - subq $48, %rsp - call *%rdi - addq $48, %rsp - ret - -FUNCTION(efi_wrap_1) - subq $48, %rsp - mov %rsi, %rcx - call *%rdi - addq $48, %rsp - ret - -FUNCTION(efi_wrap_2) - subq $48, %rsp - mov %rsi, %rcx - call *%rdi - addq $48, %rsp - ret - -FUNCTION(efi_wrap_3) - subq $48, %rsp - mov %rcx, %r8 - mov %rsi, %rcx - call *%rdi - addq $48, %rsp - ret - -FUNCTION(efi_wrap_4) - subq $48, %rsp - mov %r8, %r9 - mov %rcx, %r8 - mov %rsi, %rcx - call *%rdi - addq $48, %rsp - ret - -FUNCTION(efi_wrap_5) - subq $48, %rsp - mov %r9, 32(%rsp) - mov %r8, %r9 - mov %rcx, %r8 - mov %rsi, %rcx - call *%rdi - addq $48, %rsp - ret - -FUNCTION(efi_wrap_6) - subq $64, %rsp - mov 64+8(%rsp), %rax - mov %rax, 40(%rsp) - mov %r9, 32(%rsp) - mov %r8, %r9 - mov %rcx, %r8 - mov %rsi, %rcx - call *%rdi - addq $64, %rsp - ret - -FUNCTION(efi_wrap_7) - subq $96, %rsp - mov 96+16(%rsp), %rax - mov %rax, 48(%rsp) - mov 96+8(%rsp), %rax - mov %rax, 40(%rsp) - mov %r9, 32(%rsp) - mov %r8, %r9 - mov %rcx, %r8 - mov %rsi, %rcx - call *%rdi - addq $96, %rsp - ret - -FUNCTION(efi_wrap_10) - subq $96, %rsp - mov 96+40(%rsp), %rax - mov %rax, 72(%rsp) - mov 96+32(%rsp), %rax - mov %rax, 64(%rsp) - mov 96+24(%rsp), %rax - mov %rax, 56(%rsp) - mov 96+16(%rsp), %rax - mov %rax, 48(%rsp) - mov 96+8(%rsp), %rax - mov %rax, 40(%rsp) - mov %r9, 32(%rsp) - mov %r8, %r9 - mov %rcx, %r8 - mov %rsi, %rcx - call *%rdi - addq $96, %rsp - ret diff --git a/grub-core/kern/x86_64/efi/startup.S b/grub-core/kern/x86_64/efi/startup.S index f86f01969..9357e5c5d 100644 --- a/grub-core/kern/x86_64/efi/startup.S +++ b/grub-core/kern/x86_64/efi/startup.S @@ -30,6 +30,6 @@ _start: movq %rcx, EXT_C(grub_efi_image_handle)(%rip) movq %rdx, EXT_C(grub_efi_system_table)(%rip) + andq $~0xf, %rsp call EXT_C(grub_main) - ret - + /* Doesn't return. */ diff --git a/grub-core/kern/x86_64/xen/hypercall.S b/grub-core/kern/x86_64/xen/hypercall.S new file mode 100644 index 000000000..9b04db6a0 --- /dev/null +++ b/grub-core/kern/x86_64/xen/hypercall.S @@ -0,0 +1,53 @@ +/* hypercall.S - wrappers for Xen hypercalls */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +FUNCTION(grub_xen_sched_op) + movq $__HYPERVISOR_sched_op, %rax + syscall + ret + +FUNCTION(grub_xen_event_channel_op) + movq $__HYPERVISOR_event_channel_op, %rax + syscall + ret + +FUNCTION(grub_xen_update_va_mapping) + movq $__HYPERVISOR_update_va_mapping, %rax + syscall + ret + +FUNCTION(grub_xen_mmuext_op) + movq %rcx, %r10 + movq $__HYPERVISOR_mmuext_op, %rax + syscall + ret + +FUNCTION(grub_xen_grant_table_op) + movq $__HYPERVISOR_grant_table_op, %rax + syscall + ret + +FUNCTION(grub_xen_mmu_update) + movq %rcx, %r10 + movq $__HYPERVISOR_mmu_update, %rax + syscall + ret diff --git a/grub-core/kern/x86_64/xen/startup.S b/grub-core/kern/x86_64/xen/startup.S new file mode 100644 index 000000000..21a139f40 --- /dev/null +++ b/grub-core/kern/x86_64/xen/startup.S @@ -0,0 +1,39 @@ +/* startup.S - bootstrap GRUB itself */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + + .file "startup.S" + .text + .globl start, _start + .code64 + +start: +_start: + leaq LOCAL(stack_end), %rsp + movq %rsi, EXT_C(grub_xen_start_page_addr)(%rip) + + andq $~0xf, %rsp + call EXT_C(grub_main) + /* Doesn't return. */ + + .bss + .space (1 << 22) +LOCAL(stack_end): diff --git a/grub-core/kern/xen/init.c b/grub-core/kern/xen/init.c new file mode 100644 index 000000000..782ca7295 --- /dev/null +++ b/grub-core/kern/xen/init.c @@ -0,0 +1,601 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +grub_addr_t grub_modbase; +struct start_info *grub_xen_start_page_addr; +volatile struct xencons_interface *grub_xen_xcons; +volatile struct shared_info *grub_xen_shared_info; +volatile struct xenstore_domain_interface *grub_xen_xenstore; +volatile grant_entry_v1_t *grub_xen_grant_table; +static const grub_size_t total_grants = + GRUB_XEN_PAGE_SIZE / sizeof (grub_xen_grant_table[0]); +grub_size_t grub_xen_n_allocated_shared_pages; + +static grub_xen_mfn_t +grub_xen_ptr2mfn (void *ptr) +{ +#ifdef GRUB_MACHINE_XEN + grub_xen_mfn_t *mfn_list = + (grub_xen_mfn_t *) grub_xen_start_page_addr->mfn_list; + return mfn_list[(grub_addr_t) ptr >> GRUB_XEN_LOG_PAGE_SIZE]; +#else + return (grub_addr_t) ptr >> GRUB_XEN_LOG_PAGE_SIZE; +#endif +} + +void * +grub_xen_alloc_shared_page (domid_t dom, grub_xen_grant_t * grnum) +{ + void *ret; + grub_xen_mfn_t mfn; + volatile grant_entry_v1_t *entry; + + /* Avoid 0. */ + for (entry = grub_xen_grant_table; + entry < grub_xen_grant_table + total_grants; entry++) + if (!entry->flags) + break; + + if (entry == grub_xen_grant_table + total_grants) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of grant entries"); + return NULL; + } + ret = grub_memalign (GRUB_XEN_PAGE_SIZE, GRUB_XEN_PAGE_SIZE); + if (!ret) + return NULL; + mfn = grub_xen_ptr2mfn (ret); + entry->frame = mfn; + entry->domid = dom; + mb (); + entry->flags = GTF_permit_access; + mb (); + *grnum = entry - grub_xen_grant_table; + grub_xen_n_allocated_shared_pages++; + return ret; +} + +void +grub_xen_free_shared_page (void *ptr) +{ + grub_xen_mfn_t mfn; + volatile grant_entry_v1_t *entry; + + mfn = grub_xen_ptr2mfn (ptr); + for (entry = grub_xen_grant_table + 1; + entry < grub_xen_grant_table + total_grants; entry++) + if (entry->flags && entry->frame == mfn) + { + mb (); + entry->flags = 0; + mb (); + entry->frame = 0; + mb (); + } + grub_xen_n_allocated_shared_pages--; +} + +void +grub_machine_get_bootlocation (char **device __attribute__ ((unused)), + char **path __attribute__ ((unused))) +{ +} + +void +grub_xen_store_send (const void *buf_, grub_size_t len) +{ + const grub_uint8_t *buf = buf_; + struct evtchn_send send; + int event_sent = 0; + while (len) + { + grub_size_t avail, inbuf; + grub_size_t prod, cons; + mb (); + prod = grub_xen_xenstore->req_prod; + cons = grub_xen_xenstore->req_cons; + if (prod >= cons + sizeof (grub_xen_xenstore->req)) + { + if (!event_sent) + { + send.port = grub_xen_start_page_addr->store_evtchn; + grub_xen_event_channel_op (EVTCHNOP_send, &send); + event_sent = 1; + } + grub_xen_sched_op (SCHEDOP_yield, 0); + continue; + } + event_sent = 0; + avail = cons + sizeof (grub_xen_xenstore->req) - prod; + inbuf = (~prod & (sizeof (grub_xen_xenstore->req) - 1)) + 1; + if (avail > inbuf) + avail = inbuf; + if (avail > len) + avail = len; + grub_memcpy ((void *) &grub_xen_xenstore->req[prod & (sizeof (grub_xen_xenstore->req) - 1)], + buf, avail); + buf += avail; + len -= avail; + mb (); + grub_xen_xenstore->req_prod += avail; + mb (); + if (!event_sent) + { + send.port = grub_xen_start_page_addr->store_evtchn; + grub_xen_event_channel_op (EVTCHNOP_send, &send); + event_sent = 1; + } + grub_xen_sched_op (SCHEDOP_yield, 0); + } +} + +void +grub_xen_store_recv (void *buf_, grub_size_t len) +{ + grub_uint8_t *buf = buf_; + struct evtchn_send send; + int event_sent = 0; + while (len) + { + grub_size_t avail, inbuf; + grub_size_t prod, cons; + mb (); + prod = grub_xen_xenstore->rsp_prod; + cons = grub_xen_xenstore->rsp_cons; + if (prod <= cons) + { + if (!event_sent) + { + send.port = grub_xen_start_page_addr->store_evtchn; + grub_xen_event_channel_op (EVTCHNOP_send, &send); + event_sent = 1; + } + grub_xen_sched_op (SCHEDOP_yield, 0); + continue; + } + event_sent = 0; + avail = prod - cons; + inbuf = (~cons & (sizeof (grub_xen_xenstore->req) - 1)) + 1; + if (avail > inbuf) + avail = inbuf; + if (avail > len) + avail = len; + grub_memcpy (buf, + (void *) &grub_xen_xenstore->rsp[cons & (sizeof (grub_xen_xenstore->rsp) - 1)], + avail); + buf += avail; + len -= avail; + mb (); + grub_xen_xenstore->rsp_cons += avail; + mb (); + if (!event_sent) + { + send.port = grub_xen_start_page_addr->store_evtchn; + grub_xen_event_channel_op(EVTCHNOP_send, &send); + event_sent = 1; + } + grub_xen_sched_op(SCHEDOP_yield, 0); + } +} + +void * +grub_xenstore_get_file (const char *dir, grub_size_t *len) +{ + struct xsd_sockmsg msg; + char *buf; + grub_size_t dirlen = grub_strlen (dir) + 1; + + if (len) + *len = 0; + + grub_memset (&msg, 0, sizeof (msg)); + msg.type = XS_READ; + msg.len = dirlen; + grub_xen_store_send (&msg, sizeof (msg)); + grub_xen_store_send (dir, dirlen); + grub_xen_store_recv (&msg, sizeof (msg)); + buf = grub_malloc (msg.len + 1); + if (!buf) + return NULL; + grub_dprintf ("xen", "msg type = %d, len = %d\n", msg.type, msg.len); + grub_xen_store_recv (buf, msg.len); + buf[msg.len] = '\0'; + if (msg.type == XS_ERROR) + { + grub_error (GRUB_ERR_IO, "couldn't read xenstorage `%s': %s", dir, buf); + grub_free (buf); + return NULL; + } + if (len) + *len = msg.len; + return buf; +} + +grub_err_t +grub_xenstore_write_file (const char *dir, const void *buf, grub_size_t len) +{ + struct xsd_sockmsg msg; + grub_size_t dirlen = grub_strlen (dir) + 1; + char *resp; + + grub_memset (&msg, 0, sizeof (msg)); + msg.type = XS_WRITE; + msg.len = dirlen + len; + grub_xen_store_send (&msg, sizeof (msg)); + grub_xen_store_send (dir, dirlen); + grub_xen_store_send (buf, len); + grub_xen_store_recv (&msg, sizeof (msg)); + resp = grub_malloc (msg.len + 1); + if (!resp) + return grub_errno; + grub_dprintf ("xen", "msg type = %d, len = %d\n", msg.type, msg.len); + grub_xen_store_recv (resp, msg.len); + resp[msg.len] = '\0'; + if (msg.type == XS_ERROR) + { + grub_dprintf ("xen", "error = %s\n", resp); + grub_error (GRUB_ERR_IO, "couldn't read xenstorage `%s': %s", + dir, resp); + grub_free (resp); + return grub_errno; + } + grub_free (resp); + return GRUB_ERR_NONE; +} + +/* FIXME: error handling. */ +grub_err_t +grub_xenstore_dir (const char *dir, + int (*hook) (const char *dir, void *hook_data), + void *hook_data) +{ + struct xsd_sockmsg msg; + char *buf; + char *ptr; + grub_size_t dirlen = grub_strlen (dir) + 1; + + grub_memset (&msg, 0, sizeof (msg)); + msg.type = XS_DIRECTORY; + msg.len = dirlen; + grub_xen_store_send (&msg, sizeof (msg)); + grub_xen_store_send (dir, dirlen); + grub_xen_store_recv (&msg, sizeof (msg)); + buf = grub_malloc (msg.len + 1); + if (!buf) + return grub_errno; + grub_dprintf ("xen", "msg type = %d, len = %d\n", msg.type, msg.len); + grub_xen_store_recv (buf, msg.len); + buf[msg.len] = '\0'; + if (msg.type == XS_ERROR) + { + grub_err_t err; + err = grub_error (GRUB_ERR_IO, "couldn't read xenstorage `%s': %s", + dir, buf); + grub_free (buf); + return err; + } + for (ptr = buf; ptr < buf + msg.len; ptr += grub_strlen (ptr) + 1) + if (hook (ptr, hook_data)) + break; + grub_free (buf); + return grub_errno; +} + +unsigned long gntframe = 0; + +static void +grub_xen_setup_gnttab (void) +{ + struct gnttab_set_version gnttab_setver; + struct gnttab_setup_table gnttab_setup; + + grub_memset (&gnttab_setver, 0, sizeof (gnttab_setver)); + + gnttab_setver.version = 1; + grub_xen_grant_table_op (GNTTABOP_set_version, &gnttab_setver, 1); + + grub_memset (&gnttab_setup, 0, sizeof (gnttab_setup)); + gnttab_setup.dom = DOMID_SELF; + gnttab_setup.nr_frames = 1; + gnttab_setup.frame_list.p = &gntframe; + + grub_xen_grant_table_op (GNTTABOP_setup_table, &gnttab_setup, 1); +} + +#ifdef GRUB_MACHINE_XEN +static grub_uint8_t window[GRUB_XEN_PAGE_SIZE] + __attribute__ ((aligned (GRUB_XEN_PAGE_SIZE))); + +#ifdef __x86_64__ +#define NUMBER_OF_LEVELS 4 +#else +#define NUMBER_OF_LEVELS 3 +#endif + +#define LOG_POINTERS_PER_PAGE 9 +#define POINTERS_PER_PAGE (1 << LOG_POINTERS_PER_PAGE) + +#define MAX_N_UNUSABLE_PAGES 4 + +static int +grub_xen_is_page_usable (grub_xen_mfn_t mfn) +{ + if (mfn == grub_xen_start_page_addr->console.domU.mfn) + return 0; + if (mfn == grub_xen_start_page_addr->shared_info) + return 0; + if (mfn == grub_xen_start_page_addr->store_mfn) + return 0; + if (mfn == gntframe) + return 0; + return 1; +} + +static grub_uint64_t +page2offset (grub_uint64_t page) +{ + return page << 12; +} + +#if defined (__x86_64__) && defined (__code_model_large__) +#define MAX_TOTAL_PAGES (1LL << (64 - 12)) +#elif defined (__x86_64__) +#define MAX_TOTAL_PAGES (1LL << (31 - 12)) +#else +#define MAX_TOTAL_PAGES (1LL << (32 - 12)) +#endif + +static void +map_all_pages (void) +{ + grub_uint64_t total_pages = grub_xen_start_page_addr->nr_pages; + grub_uint64_t i, j; + grub_xen_mfn_t *mfn_list = + (grub_xen_mfn_t *) grub_xen_start_page_addr->mfn_list; + grub_uint64_t *pg = (grub_uint64_t *) window; + grub_uint64_t oldpgstart, oldpgend; + grub_size_t n_unusable_pages = 0; + struct mmu_update m2p_updates[2 * MAX_N_UNUSABLE_PAGES]; + + if (total_pages > MAX_TOTAL_PAGES - 4) + total_pages = MAX_TOTAL_PAGES - 4; + + for (j = 0; j < total_pages - n_unusable_pages; j++) + while (!grub_xen_is_page_usable (mfn_list[j])) + { + grub_xen_mfn_t t; + if (n_unusable_pages >= MAX_N_UNUSABLE_PAGES) + { + struct sched_shutdown arg; + arg.reason = SHUTDOWN_crash; + grub_xen_sched_op (SCHEDOP_shutdown, &arg); + while (1); + } + t = mfn_list[j]; + mfn_list[j] = mfn_list[total_pages - n_unusable_pages - 1]; + mfn_list[total_pages - n_unusable_pages - 1] = t; + + m2p_updates[2 * n_unusable_pages].ptr + = page2offset (mfn_list[j]) | MMU_MACHPHYS_UPDATE; + m2p_updates[2 * n_unusable_pages].val = j; + m2p_updates[2 * n_unusable_pages + 1].ptr + = page2offset (mfn_list[total_pages - n_unusable_pages - 1]) + | MMU_MACHPHYS_UPDATE; + m2p_updates[2 * n_unusable_pages + 1].val = total_pages + - n_unusable_pages - 1; + + n_unusable_pages++; + } + + grub_xen_mmu_update (m2p_updates, 2 * n_unusable_pages, NULL, DOMID_SELF); + + total_pages += 4; + + grub_uint64_t lx[NUMBER_OF_LEVELS], nlx; + grub_uint64_t paging_start = total_pages - 4 - n_unusable_pages, curpage; + + for (nlx = total_pages, i = 0; i < (unsigned) NUMBER_OF_LEVELS; i++) + { + nlx = (nlx + POINTERS_PER_PAGE - 1) >> LOG_POINTERS_PER_PAGE; + /* PAE wants all 4 root directories present. */ +#ifdef __i386__ + if (i == 1) + nlx = 4; +#endif + lx[i] = nlx; + paging_start -= nlx; + } + + oldpgstart = grub_xen_start_page_addr->pt_base >> 12; + oldpgend = oldpgstart + grub_xen_start_page_addr->nr_pt_frames; + + curpage = paging_start; + + int l; + + for (l = NUMBER_OF_LEVELS - 1; l >= 1; l--) + { + for (i = 0; i < lx[l]; i++) + { + grub_xen_update_va_mapping (&window, + page2offset (mfn_list[curpage + i]) | 7, + UVMF_INVLPG); + grub_memset (&window, 0, sizeof (window)); + + for (j = i * POINTERS_PER_PAGE; + j < (i + 1) * POINTERS_PER_PAGE && j < lx[l - 1]; j++) + pg[j - i * POINTERS_PER_PAGE] = + page2offset (mfn_list[curpage + lx[l] + j]) +#ifdef __x86_64__ + | 4 +#endif + | 3; + } + curpage += lx[l]; + } + + for (i = 0; i < lx[0]; i++) + { + grub_xen_update_va_mapping (&window, + page2offset (mfn_list[curpage + i]) | 7, + UVMF_INVLPG); + grub_memset (&window, 0, sizeof (window)); + + for (j = i * POINTERS_PER_PAGE; + j < (i + 1) * POINTERS_PER_PAGE && j < total_pages; j++) + if (j < paging_start && !(j >= oldpgstart && j < oldpgend)) + pg[j - i * POINTERS_PER_PAGE] = page2offset (mfn_list[j]) | 0x7; + else if (j < grub_xen_start_page_addr->nr_pages) + pg[j - i * POINTERS_PER_PAGE] = page2offset (mfn_list[j]) | 5; + else if (j == grub_xen_start_page_addr->nr_pages) + { + pg[j - i * POINTERS_PER_PAGE] = + page2offset (grub_xen_start_page_addr->console.domU.mfn) | 7; + grub_xen_xcons = (void *) (grub_addr_t) page2offset (j); + } + else if (j == grub_xen_start_page_addr->nr_pages + 1) + { + pg[j - i * POINTERS_PER_PAGE] = + grub_xen_start_page_addr->shared_info | 7; + grub_xen_shared_info = (void *) (grub_addr_t) page2offset (j); + } + else if (j == grub_xen_start_page_addr->nr_pages + 2) + { + pg[j - i * POINTERS_PER_PAGE] = + page2offset (grub_xen_start_page_addr->store_mfn) | 7; + grub_xen_xenstore = (void *) (grub_addr_t) page2offset (j); + } + else if (j == grub_xen_start_page_addr->nr_pages + 3) + { + pg[j - i * POINTERS_PER_PAGE] = page2offset (gntframe) | 7; + grub_xen_grant_table = (void *) (grub_addr_t) page2offset (j); + } + } + + grub_xen_update_va_mapping (&window, 0, UVMF_INVLPG); + + mmuext_op_t op[3]; + + op[0].cmd = MMUEXT_PIN_L1_TABLE + (NUMBER_OF_LEVELS - 1); + op[0].arg1.mfn = mfn_list[paging_start]; + op[1].cmd = MMUEXT_NEW_BASEPTR; + op[1].arg1.mfn = mfn_list[paging_start]; + op[2].cmd = MMUEXT_UNPIN_TABLE; + op[2].arg1.mfn = mfn_list[oldpgstart]; + + grub_xen_mmuext_op (op, 3, NULL, DOMID_SELF); + + for (i = oldpgstart; i < oldpgend; i++) + grub_xen_update_va_mapping ((void *) (grub_addr_t) page2offset (i), + page2offset (mfn_list[i]) | 7, UVMF_INVLPG); + void *new_start_page, *new_mfn_list; + new_start_page = (void *) (grub_addr_t) page2offset (paging_start - 1); + grub_memcpy (new_start_page, grub_xen_start_page_addr, 4096); + grub_xen_start_page_addr = new_start_page; + new_mfn_list = (void *) (grub_addr_t) + page2offset (paging_start - 1 + - ((grub_xen_start_page_addr->nr_pages + * sizeof (grub_uint64_t) + 4095) / 4096)); + grub_memcpy (new_mfn_list, mfn_list, grub_xen_start_page_addr->nr_pages + * sizeof (grub_uint64_t)); + grub_xen_start_page_addr->pt_base = page2offset (paging_start); + grub_xen_start_page_addr->mfn_list = (grub_addr_t) new_mfn_list; + + grub_addr_t heap_start = grub_modules_get_end (); + grub_addr_t heap_end = (grub_addr_t) new_mfn_list; + + grub_mm_init_region ((void *) heap_start, heap_end - heap_start); +} + +grub_err_t +grub_machine_mmap_iterate (grub_memory_hook_t hook, void *hook_data) +{ + grub_uint64_t total_pages = grub_xen_start_page_addr->nr_pages; + grub_uint64_t usable_pages = grub_xen_start_page_addr->pt_base >> 12; + if (hook (0, page2offset (usable_pages), GRUB_MEMORY_AVAILABLE, hook_data)) + return GRUB_ERR_NONE; + + hook (page2offset (usable_pages), page2offset (total_pages - usable_pages), + GRUB_MEMORY_RESERVED, hook_data); + + return GRUB_ERR_NONE; +} +#endif + +extern char _end[]; + +void +grub_machine_init (void) +{ +#ifdef GRUB_MACHINE_XEN +#ifdef __i386__ + grub_xen_vm_assist (VMASST_CMD_enable, VMASST_TYPE_pae_extended_cr3); +#endif +#endif + + grub_modbase = ALIGN_UP ((grub_addr_t) _end + + GRUB_KERNEL_MACHINE_MOD_GAP, + GRUB_KERNEL_MACHINE_MOD_ALIGN); + +#ifdef GRUB_MACHINE_XEN_PVH + grub_xen_setup_pvh (); +#endif + + grub_xen_setup_gnttab (); + +#ifdef GRUB_MACHINE_XEN + map_all_pages (); +#endif + + grub_console_init (); + + grub_tsc_init (); + + grub_xendisk_init (); + + grub_boot_init (); +} + +void +grub_exit (void) +{ + struct sched_shutdown arg; + + arg.reason = SHUTDOWN_poweroff; + grub_xen_sched_op (SCHEDOP_shutdown, &arg); + while (1); +} + +void +grub_machine_fini (int flags __attribute__ ((unused))) +{ + grub_xendisk_fini (); + grub_boot_fini (); +} diff --git a/grub-core/lib/LzmaDec.c b/grub-core/lib/LzmaDec.c index 62ebee686..952edb346 100644 --- a/grub-core/lib/LzmaDec.c +++ b/grub-core/lib/LzmaDec.c @@ -26,7 +26,9 @@ #include -#include +#pragma GCC diagnostic ignored "-Wshadow" +#include +#define memcpy grub_memcpy #define kNumTopBits 24 #define kTopValue ((UInt32)1 << kNumTopBits) @@ -718,7 +720,7 @@ static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) p->needFlush = 0; } -void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) +static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) { p->needFlush = 1; p->remainLen = 0; diff --git a/grub-core/lib/LzmaEnc.c b/grub-core/lib/LzmaEnc.c index f2ec04a8c..52b331558 100644 --- a/grub-core/lib/LzmaEnc.c +++ b/grub-core/lib/LzmaEnc.c @@ -1359,7 +1359,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) startLen = lenTest + 1; /* if (_maxMode) */ - { + { UInt32 lenTest2 = lenTest + 1; UInt32 limit = lenTest2 + p->numFastBytes; UInt32 nextRepMatchPrice; @@ -1403,7 +1403,7 @@ static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) } } } - } + } } } /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */ @@ -1877,13 +1877,19 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize } else { - UInt32 posSlot; + UInt32 posSlot, lenToPosState; RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0); p->state = kMatchNextStates[p->state]; LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices); pos -= LZMA_NUM_REPS; GetPosSlot(pos, posSlot); - RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot); + lenToPosState = GetLenToPosState(len); + if (lenToPosState >= kNumLenToPosStates) + { + p->result = SZ_ERROR_DATA; + return CheckErrors(p); + } + RcTree_Encode(&p->rc, p->posSlotEncoder[lenToPosState], kNumPosSlotBits, posSlot); if (posSlot >= kStartPosModelIndex) { diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c index b34188528..c2bd6a452 100644 --- a/grub-core/lib/arg.c +++ b/grub-core/lib/arg.c @@ -23,6 +23,7 @@ #include #include #include +#include /* Built-in parser for default options. */ static const struct grub_arg_option help_options[] = @@ -34,36 +35,37 @@ static const struct grub_arg_option help_options[] = {0, 0, 0, 0, 0, 0} }; -static struct grub_arg_option * +/* Helper for find_short. */ +static const struct grub_arg_option * +fnd_short (const struct grub_arg_option *opt, char c) +{ + while (opt->doc) + { + if (opt->shortarg == c) + return opt; + opt++; + } + return 0; +} + +static const struct grub_arg_option * find_short (const struct grub_arg_option *options, char c) { - struct grub_arg_option *found = 0; - auto struct grub_arg_option *fnd_short (const struct grub_arg_option *opt); - - struct grub_arg_option *fnd_short (const struct grub_arg_option *opt) - { - while (opt->doc) - { - if (opt->shortarg == c) - return (struct grub_arg_option *) opt; - opt++; - } - return 0; - } + const struct grub_arg_option *found = 0; if (options) - found = fnd_short (options); + found = fnd_short (options, c); if (! found) { switch (c) { case 'h': - found = (struct grub_arg_option *) help_options; + found = help_options; break; case 'u': - found = (struct grub_arg_option *) (help_options + 1); + found = (help_options + 1); break; default: @@ -74,29 +76,30 @@ find_short (const struct grub_arg_option *options, char c) return found; } -static struct grub_arg_option * +/* Helper for find_long. */ +static const struct grub_arg_option * +fnd_long (const struct grub_arg_option *opt, const char *s, int len) +{ + while (opt->doc) + { + if (opt->longarg && ! grub_strncmp (opt->longarg, s, len) && + opt->longarg[len] == '\0') + return opt; + opt++; + } + return 0; +} + +static const struct grub_arg_option * find_long (const struct grub_arg_option *options, const char *s, int len) { - struct grub_arg_option *found = 0; - auto struct grub_arg_option *fnd_long (const struct grub_arg_option *opt); - - struct grub_arg_option *fnd_long (const struct grub_arg_option *opt) - { - while (opt->doc) - { - if (opt->longarg && ! grub_strncmp (opt->longarg, s, len) && - opt->longarg[len] == '\0') - return (struct grub_arg_option *) opt; - opt++; - } - return 0; - } + const struct grub_arg_option *found = 0; if (options) - found = fnd_long (options); + found = fnd_long (options, s, len); if (! found) - found = fnd_long (help_options); + found = fnd_long (help_options, s, len); return found; } @@ -107,69 +110,70 @@ show_usage (grub_extcmd_t cmd) grub_printf ("%s %s %s\n", _("Usage:"), cmd->cmd->name, _(cmd->cmd->summary)); } +static void +showargs (const struct grub_arg_option *opt, + int h_is_used, int u_is_used) +{ + for (; opt->doc; opt++) + { + int spacing = 20; + + if (opt->shortarg && grub_isgraph (opt->shortarg)) + grub_printf ("-%c%c ", opt->shortarg, opt->longarg ? ',':' '); + else if (opt == help_options && ! h_is_used) + grub_printf ("-h, "); + else if (opt == help_options + 1 && ! u_is_used) + grub_printf ("-u, "); + else + grub_printf (" "); + + if (opt->longarg) + { + grub_printf ("--%s", opt->longarg); + spacing -= grub_strlen (opt->longarg) + 2; + + if (opt->arg) + { + grub_printf ("=%s", opt->arg); + spacing -= grub_strlen (opt->arg) + 1; + } + } + + if (spacing <= 0) + spacing = 3; + + while (spacing--) + grub_xputs (" "); + + grub_printf ("%s\n", _(opt->doc)); + } +} + void grub_arg_show_help (grub_extcmd_t cmd) { - auto void showargs (const struct grub_arg_option *opt); int h_is_used = 0; int u_is_used = 0; - - auto void showargs (const struct grub_arg_option *opt) - { - for (; opt->doc; opt++) - { - int spacing = 20; - - if (opt->shortarg && grub_isgraph (opt->shortarg)) - grub_printf ("-%c%c ", opt->shortarg, opt->longarg ? ',':' '); - else if (opt == help_options && ! h_is_used) - grub_printf ("-h, "); - else if (opt == help_options + 1 && ! u_is_used) - grub_printf ("-u, "); - else - grub_printf (" "); - - if (opt->longarg) - { - grub_printf ("--%s", opt->longarg); - spacing -= grub_strlen (opt->longarg) + 2; - - if (opt->arg) - { - grub_printf ("=%s", opt->arg); - spacing -= grub_strlen (opt->arg) + 1; - } - } - - if (spacing < 0) - spacing = 3; - - while (spacing--) - grub_xputs (" "); - - grub_printf ("%s\n", _(opt->doc)); - - switch (opt->shortarg) - { - case 'h': - h_is_used = 1; - break; - - case 'u': - u_is_used = 1; - break; - - default: - break; - } - } - } + const struct grub_arg_option *opt; show_usage (cmd); grub_printf ("%s\n\n", _(cmd->cmd->description)); + + for (opt = cmd->options; opt && opt->doc; opt++) + switch (opt->shortarg) + { + case 'h': + h_is_used = 1; + break; + + case 'u': + u_is_used = 1; + break; + } + if (cmd->options) - showargs (cmd->options); - showargs (help_options); + showargs (cmd->options, h_is_used, u_is_used); + showargs (help_options, h_is_used, u_is_used); #if 0 grub_printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT); #endif @@ -209,6 +213,28 @@ parse_option (grub_extcmd_t cmd, const struct grub_arg_option *opt, return 0; } +static inline grub_err_t +add_arg (char ***argl, int *num, char *s) +{ + char **p = *argl; + grub_size_t sz; + + if (grub_add (++(*num), 1, &sz) || + grub_mul (sz, sizeof (char *), &sz)) + return grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + + *argl = grub_realloc (*argl, sz); + if (! *argl) + { + grub_free (p); + return grub_errno; + } + (*argl)[(*num) - 1] = s; + (*argl)[(*num)] = NULL; + return 0; +} + + int grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, struct grub_arg_list *usr, char ***args, int *argnum) @@ -217,34 +243,18 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, int arglen; char **argl = 0; int num = 0; - auto grub_err_t add_arg (char *s); - - grub_err_t add_arg (char *s) - { - char **p = argl; - argl = grub_realloc (argl, (++num + 1) * sizeof (char *)); - if (! argl) - { - grub_free (p); - return grub_errno; - } - argl[num - 1] = s; - argl[num] = NULL; - return 0; - } - for (curarg = 0; curarg < argc; curarg++) { char *arg = argv[curarg]; - struct grub_arg_option *opt; + const struct grub_arg_option *opt; char *option = 0; /* No option is used. */ if ((num && (cmd->cmd->flags & GRUB_COMMAND_OPTIONS_AT_START)) || arg[0] != '-' || grub_strlen (arg) == 1) { - if (add_arg (arg) != 0) + if (add_arg (&argl, &num, arg) != 0) goto fail; continue; @@ -260,10 +270,10 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, for (curshort = arg + 1; *curshort; curshort++) if (!find_short (cmd->options, *curshort)) break; - + if (*curshort) { - if (add_arg (arg) != 0) + if (add_arg (&argl, &num, arg) != 0) goto fail; continue; } @@ -289,6 +299,19 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, it can have an argument value. */ if (*curshort) { + /* + * Only permit further short opts if this one doesn't + * require a value. + */ + if (opt->type != ARG_TYPE_NONE && + !(opt->flags & GRUB_ARG_OPTION_OPTIONAL)) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("missing mandatory option for `%s'"), + opt->longarg); + goto fail; + } + if (parse_option (cmd, opt, 0, usr) || grub_errno) goto fail; } @@ -316,7 +339,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (grub_strlen (arg) == 2) { for (curarg++; curarg < argc; curarg++) - if (add_arg (argv[curarg]) != 0) + if (add_arg (&argl, &num, argv[curarg]) != 0) goto fail; break; } @@ -338,7 +361,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (!opt && (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH)) { - if (add_arg (arg) != 0) + if (add_arg (&argl, &num, arg) != 0) goto fail; continue; } @@ -372,7 +395,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, case ARG_TYPE_INT: { - char *tail; + const char * tail; grub_strtoull (option, &tail, 0); if (tail == 0 || tail == option || *tail != '\0' || grub_errno) @@ -425,9 +448,10 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, { int i; char **args; - unsigned argcnt; + grub_size_t argcnt; struct grub_arg_list *list; const struct grub_arg_option *options; + grub_size_t sz0, sz1; options = extcmd->options; if (! options) @@ -437,10 +461,18 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, for (i = 0; options[i].doc; i++) { if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE) - argcnt += (argc + 1) / 2 + 1; /* max possible for any option */ + argcnt += ((grub_size_t) argc + 1) / 2 + 1; /* max possible for any option */ } - list = grub_zalloc (sizeof (*list) * i + sizeof (char*) * argcnt); + if (grub_mul (sizeof (*list), i, &sz0) || + grub_mul (sizeof (char *), argcnt, &sz1) || + grub_add (sz0, sz1, &sz0)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); + return 0; + } + + list = grub_zalloc (sz0); if (! list) return 0; @@ -453,7 +485,7 @@ grub_arg_list_alloc(grub_extcmd_t extcmd, int argc, if (options[i].flags & GRUB_ARG_OPTION_REPEATABLE) { list[i].args = args; - args += argc / 2 + 1; + args += (grub_size_t) argc / 2 + 1; } } return list; diff --git a/grub-core/lib/arm/setjmp.S b/grub-core/lib/arm/setjmp.S new file mode 100644 index 000000000..a5373d3a9 --- /dev/null +++ b/grub-core/lib/arm/setjmp.S @@ -0,0 +1,53 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + + .file "setjmp.S" + +GRUB_MOD_LICENSE "GPLv3+" + + .syntax unified +#if !defined (__thumb2__) + .arm +#else + .thumb +#endif + + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + mov r12, sp + stm r0, { r4-r12, lr } + mov r0, #0 + bx lr + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + ldm r0, { r4-r12, lr } + mov sp, r12 + movs r0, r1 + it eq + moveq r0, #1 + bx lr diff --git a/grub-core/lib/arm64/setjmp.S b/grub-core/lib/arm64/setjmp.S new file mode 100644 index 000000000..ffcabf6e4 --- /dev/null +++ b/grub-core/lib/arm64/setjmp.S @@ -0,0 +1,56 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + + .file "setjmp.S" +GRUB_MOD_LICENSE "GPLv3+" + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + stp x19, x20, [x0], #16 + stp x21, x22, [x0], #16 + stp x23, x24, [x0], #16 + stp x25, x26, [x0], #16 + stp x27, x28, [x0], #16 + stp x29, x30, [x0], #16 + mov x1, sp + str x1, [x0] + mov x0, #0 + ret + +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + ldp x19, x20, [x0], #16 + ldp x21, x22, [x0], #16 + ldp x23, x24, [x0], #16 + ldp x25, x26, [x0], #16 + ldp x27, x28, [x0], #16 + ldp x29, x30, [x0], #16 + ldr x2, [x0] + mov sp, x2 + mov x0, #1 + cmp x1, #0 + csel x0, x1, x0, ne + ret diff --git a/grub-core/lib/backtrace.c b/grub-core/lib/backtrace.c index 32945d9f8..825a8800e 100644 --- a/grub-core/lib/backtrace.c +++ b/grub-core/lib/backtrace.c @@ -39,7 +39,7 @@ grub_backtrace_print_address (void *addr) + segment->size > (grub_uint8_t *) addr) { grub_printf ("%s.%x+%" PRIxGRUB_SIZE, mod->name, segment->section, - (grub_uint8_t *) addr - (grub_uint8_t *) segment->addr); + (grub_size_t) ((grub_uint8_t *) addr - (grub_uint8_t *) segment->addr)); return; } } diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c index a702e6487..ed0b149dc 100644 --- a/grub-core/lib/cmdline.c +++ b/grub-core/lib/cmdline.c @@ -56,15 +56,19 @@ unsigned int grub_loader_cmdline_size (int argc, char *argv[]) size++; /* Separator space or NULL. */ } + if (size == 0) + size = 1; + return size; } -int grub_create_loader_cmdline (int argc, char *argv[], char *buf, - grub_size_t size) +grub_err_t +grub_create_loader_cmdline (int argc, char *argv[], char *buf, + grub_size_t size, enum grub_verify_string_type type) { int i, space; unsigned int arg_size; - char *c; + char *c, *orig_buf = buf; for (i = 0; i < argc; i++) { @@ -101,5 +105,5 @@ int grub_create_loader_cmdline (int argc, char *argv[], char *buf, *buf = 0; - return i; + return grub_verify_string (orig_buf, type); } diff --git a/grub-core/lib/crc.c b/grub-core/lib/crc.c index ffc3ef3b5..bf97cc63a 100644 --- a/grub-core/lib/crc.c +++ b/grub-core/lib/crc.c @@ -22,25 +22,26 @@ static grub_uint32_t crc32c_table [256]; +/* Helper for init_crc32c_table. */ +static grub_uint32_t +reflect (grub_uint32_t ref, int len) +{ + grub_uint32_t result = 0; + int i; + + for (i = 1; i <= len; i++) + { + if (ref & 1) + result |= 1 << (len - i); + ref >>= 1; + } + + return result; +} + static void init_crc32c_table (void) { - auto grub_uint32_t reflect (grub_uint32_t ref, int len); - grub_uint32_t reflect (grub_uint32_t ref, int len) - { - grub_uint32_t result = 0; - int i; - - for (i = 1; i <= len; i++) - { - if (ref & 1) - result |= 1 << (len - i); - ref >>= 1; - } - - return result; - } - grub_uint32_t polynomial = 0x1edc6f41; int i, j; diff --git a/grub-core/lib/crc64.c b/grub-core/lib/crc64.c index 4b1c92cf0..4960f3f89 100644 --- a/grub-core/lib/crc64.c +++ b/grub-core/lib/crc64.c @@ -25,25 +25,26 @@ GRUB_MOD_LICENSE ("GPLv3+"); static grub_uint64_t crc64_table [256]; +/* Helper for init_crc64_table. */ +static grub_uint64_t +reflect (grub_uint64_t ref, int len) +{ + grub_uint64_t result = 0; + int i; + + for (i = 1; i <= len; i++) + { + if (ref & 1) + result |= 1ULL << (len - i); + ref >>= 1; + } + + return result; +} + static void init_crc64_table (void) { - auto grub_uint64_t reflect (grub_uint64_t ref, int len); - grub_uint64_t reflect (grub_uint64_t ref, int len) - { - grub_uint64_t result = 0; - int i; - - for (i = 1; i <= len; i++) - { - if (ref & 1) - result |= 1ULL << (len - i); - ref >>= 1; - } - - return result; - } - grub_uint64_t polynomial = 0x42f0e1eba9ea3693ULL; int i, j; diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index f4b13ed3d..396f76410 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -23,13 +23,7 @@ #include #include #include - -#ifdef GRUB_UTIL -#include -#include -#include -#include -#endif +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -56,8 +50,40 @@ grub_burn_stack (grub_size_t size) grub_burn_stack (size - sizeof (buf)); } +void +_gcry_burn_stack (int size) +{ + grub_burn_stack (size); +} -void +void __attribute__ ((noreturn)) +_gcry_assert_failed (const char *expr, const char *file, int line, + const char *func) + +{ + grub_fatal ("assertion %s at %s:%d (%s) failed\n", expr, file, line, func); +} + + +void _gcry_log_error (const char *fmt, ...) +{ + va_list args; + const char *debug = grub_env_get ("debug"); + + if (! debug) + return; + + if (grub_strword (debug, "all") || grub_strword (debug, "gcrypt")) + { + grub_printf ("gcrypt error: "); + va_start (args, fmt); + grub_vprintf (fmt, args); + va_end (args); + grub_refresh (); + } +} + +void grub_cipher_register (gcry_cipher_spec_t *cipher) { cipher->next = grub_ciphers; @@ -76,14 +102,14 @@ grub_cipher_unregister (gcry_cipher_spec_t *cipher) } } -void +void grub_md_register (gcry_md_spec_t *digest) { digest->next = grub_digests; grub_digests = digest; } -void +void grub_md_unregister (gcry_md_spec_t *cipher) { gcry_md_spec_t **ciph; @@ -99,7 +125,10 @@ void grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in, grub_size_t inlen) { - grub_uint8_t ctx[hash->contextsize]; + GRUB_PROPERLY_ALIGNED_ARRAY (ctx, GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE); + + if (hash->contextsize > sizeof (ctx)) + grub_fatal ("Too large md context"); hash->init (&ctx); hash->write (&ctx, in, inlen); hash->final (&ctx); @@ -174,15 +203,18 @@ gcry_err_code_t grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher, void *out, const void *in, grub_size_t size) { - const grub_uint8_t *inptr; - grub_uint8_t *outptr, *end; + const grub_uint8_t *inptr, *end; + grub_uint8_t *outptr; + grub_size_t blocksize; if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; - if (size % cipher->cipher->blocksize != 0) + blocksize = cipher->cipher->blocksize; + if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) + || ((size & (blocksize - 1)) != 0)) return GPG_ERR_INV_ARG; - end = (grub_uint8_t *) in + size; + end = (const grub_uint8_t *) in + size; for (inptr = in, outptr = out; inptr < end; - inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) + inptr += blocksize, outptr += blocksize) cipher->cipher->decrypt (cipher->ctx, outptr, inptr); return GPG_ERR_NO_ERROR; } @@ -191,40 +223,47 @@ gcry_err_code_t grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher, void *out, const void *in, grub_size_t size) { - const grub_uint8_t *inptr; - grub_uint8_t *outptr, *end; + const grub_uint8_t *inptr, *end; + grub_uint8_t *outptr; + grub_size_t blocksize; if (!cipher->cipher->encrypt) return GPG_ERR_NOT_SUPPORTED; - if (size % cipher->cipher->blocksize != 0) + blocksize = cipher->cipher->blocksize; + if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) + || ((size & (blocksize - 1)) != 0)) return GPG_ERR_INV_ARG; - end = (grub_uint8_t *) in + size; + end = (const grub_uint8_t *) in + size; for (inptr = in, outptr = out; inptr < end; - inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) + inptr += blocksize, outptr += blocksize) cipher->cipher->encrypt (cipher->ctx, outptr, inptr); return GPG_ERR_NO_ERROR; } gcry_err_code_t grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher, - void *out, void *in, grub_size_t size, + void *out, const void *in, grub_size_t size, void *iv_in) { - grub_uint8_t *inptr, *outptr, *end; + grub_uint8_t *outptr; + const grub_uint8_t *inptr, *end; void *iv; - if (!cipher->cipher->decrypt) + grub_size_t blocksize; + if (!cipher->cipher->encrypt) return GPG_ERR_NOT_SUPPORTED; - if (size % cipher->cipher->blocksize != 0) + blocksize = cipher->cipher->blocksize; + if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) + || ((size & (blocksize - 1)) != 0)) return GPG_ERR_INV_ARG; - end = (grub_uint8_t *) in + size; + end = (const grub_uint8_t *) in + size; iv = iv_in; for (inptr = in, outptr = out; inptr < end; - inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) + inptr += blocksize, outptr += blocksize) { - grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize); + grub_crypto_xor (outptr, inptr, iv, blocksize); cipher->cipher->encrypt (cipher->ctx, outptr, outptr); iv = outptr; } - grub_memcpy (iv_in, iv, cipher->cipher->blocksize); + grub_memcpy (iv_in, iv, blocksize); return GPG_ERR_NO_ERROR; } @@ -233,21 +272,26 @@ grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher, void *out, const void *in, grub_size_t size, void *iv) { - const grub_uint8_t *inptr; - grub_uint8_t *outptr, *end; - grub_uint8_t ivt[cipher->cipher->blocksize]; + const grub_uint8_t *inptr, *end; + grub_uint8_t *outptr; + grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE]; + grub_size_t blocksize; if (!cipher->cipher->decrypt) return GPG_ERR_NOT_SUPPORTED; - if (size % cipher->cipher->blocksize != 0) + blocksize = cipher->cipher->blocksize; + if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0) + || ((size & (blocksize - 1)) != 0)) return GPG_ERR_INV_ARG; - end = (grub_uint8_t *) in + size; + if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE) + return GPG_ERR_INV_ARG; + end = (const grub_uint8_t *) in + size; for (inptr = in, outptr = out; inptr < end; - inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) + inptr += blocksize, outptr += blocksize) { - grub_memcpy (ivt, inptr, cipher->cipher->blocksize); + grub_memcpy (ivt, inptr, blocksize); cipher->cipher->decrypt (cipher->ctx, outptr, inptr); - grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); - grub_memcpy (iv, ivt, cipher->cipher->blocksize); + grub_crypto_xor (outptr, outptr, iv, blocksize); + grub_memcpy (iv, ivt, blocksize); } return GPG_ERR_NO_ERROR; } @@ -270,7 +314,7 @@ grub_crypto_hmac_init (const struct gcry_md_spec *md, if (!ctx) goto err; - if ( keylen > md->blocksize ) + if ( keylen > md->blocksize ) { helpkey = grub_malloc (md->mdlen); if (!helpkey) @@ -291,7 +335,7 @@ grub_crypto_hmac_init (const struct gcry_md_spec *md, grub_memcpy ( ipad, key, keylen ); grub_memcpy ( opad, key, keylen ); - for (i=0; i < md->blocksize; i++ ) + for (i=0; i < md->blocksize; i++ ) { ipad[i] ^= 0x36; opad[i] ^= 0x5c; @@ -404,53 +448,21 @@ grub_crypto_memcmp (const void *a, const void *b, grub_size_t n) return !!counter; } +#ifndef GRUB_UTIL + int grub_password_get (char buf[], unsigned buf_size) { -#ifdef GRUB_UTIL - FILE *in; - struct termios s, t; - int tty_changed = 0; - char *ptr; - - /* Disable echoing. Based on glibc. */ - in = fopen ("/dev/tty", "w+c"); - if (in == NULL) - in = stdin; - - if (tcgetattr (fileno (in), &t) == 0) - { - /* Save the old one. */ - s = t; - /* Tricky, tricky. */ - t.c_lflag &= ~(ECHO|ISIG); - tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0); - } - else - tty_changed = 0; - fgets (buf, buf_size, stdin); - ptr = buf + strlen (buf) - 1; - while (buf <= ptr && (*ptr == '\n' || *ptr == '\r')) - *ptr-- = 0; - /* Restore the original setting. */ - if (tty_changed) - (void) tcsetattr (fileno (in), TCSAFLUSH, &s); - - grub_xputs ("\n"); - grub_refresh (); - - return 1; -#else unsigned cur_len = 0; int key; while (1) { - key = grub_getkey (); + key = grub_getkey (); if (key == '\n' || key == '\r') break; - if (key == '\e') + if (key == GRUB_TERM_ESC) { cur_len = 0; break; @@ -458,7 +470,8 @@ grub_password_get (char buf[], unsigned buf_size) if (key == '\b') { - cur_len--; + if (cur_len) + cur_len--; continue; } @@ -474,6 +487,7 @@ grub_password_get (char buf[], unsigned buf_size) grub_xputs ("\n"); grub_refresh (); - return (key != '\e'); -#endif + return (key != GRUB_TERM_ESC); } +#endif + diff --git a/grub-core/normal/datetime.c b/grub-core/lib/datetime.c similarity index 57% rename from grub-core/normal/datetime.c rename to grub-core/lib/datetime.c index bbc2cdea9..8f0922fb0 100644 --- a/grub-core/normal/datetime.c +++ b/grub-core/lib/datetime.c @@ -19,6 +19,13 @@ #include #include +#include +#include +#ifdef GRUB_MACHINE_EMU +#include + +GRUB_MOD_LICENSE ("GPLv3+"); +#endif static const char *const grub_weekday_names[] = { @@ -34,9 +41,12 @@ static const char *const grub_weekday_names[] = int grub_get_weekday (struct grub_datetime *datetime) { - int a, y, m; + unsigned a, y, m; - a = (14 - datetime->month) / 12; + if (datetime->month <= 2) + a = 1; + else + a = 0; y = datetime->year - a; m = datetime->month + 12 * a - 2; @@ -52,50 +62,61 @@ grub_get_weekday_name (struct grub_datetime *datetime) #define SECPERMIN 60 #define SECPERHOUR (60*SECPERMIN) #define SECPERDAY (24*SECPERHOUR) -#define SECPERYEAR (365*SECPERDAY) -#define SECPER4YEARS (4*SECPERYEAR+SECPERDAY) +#define DAYSPERYEAR 365 +#define DAYSPER4YEARS (4*DAYSPERYEAR+1) void -grub_unixtime2datetime (grub_int32_t nix, struct grub_datetime *datetime) +grub_unixtime2datetime (grub_int64_t nix, struct grub_datetime *datetime) { int i; - int div; grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /* In the period of validity of unixtime all years divisible by 4 are bissextile*/ /* Convenience: let's have 3 consecutive non-bissextile years - at the beginning of the epoch. So count from 1973 instead of 1970 */ - nix -= 3*SECPERYEAR + SECPERDAY; - /* Transform C divisions and modulos to mathematical ones */ - div = nix / SECPER4YEARS; - if (nix < 0) - div--; - datetime->year = 1973 + 4 * div; - nix -= div * SECPER4YEARS; + at the beginning of the counting date. So count from 1901. */ + int days_epoch; + /* Number of days since 1st Januar, 1901. */ + unsigned days; + /* Seconds into current day. */ + unsigned secs_in_day; + /* Transform C divisions and modulos to mathematical ones */ + if (nix < 0) + /* + * The result of division here shouldn't be larger than GRUB_INT_MAX. + * So, it's safe to store the result back in an int. + */ + days_epoch = -(grub_divmod64 (((grub_int64_t) (SECPERDAY) - nix - 1), SECPERDAY, NULL)); + else + days_epoch = grub_divmod64 (nix, SECPERDAY, NULL); + + secs_in_day = nix - days_epoch * SECPERDAY; + days = days_epoch + 69 * DAYSPERYEAR + 17; + + datetime->year = 1901 + 4 * (days / DAYSPER4YEARS); + days %= DAYSPER4YEARS; /* On 31st December of bissextile years 365 days from the beginning of the year elapsed but year isn't finished yet */ - if (nix / SECPERYEAR == 4) + if (days / DAYSPERYEAR == 4) { datetime->year += 3; - nix -= 3*SECPERYEAR; + days -= 3*DAYSPERYEAR; } else { - datetime->year += nix / SECPERYEAR; - nix %= SECPERYEAR; + datetime->year += days / DAYSPERYEAR; + days %= DAYSPERYEAR; } for (i = 0; i < 12 - && nix >= ((grub_int32_t) (i==1 && datetime->year % 4 == 0 - ? 29 : months[i]))*SECPERDAY; i++) - nix -= ((grub_int32_t) (i==1 && datetime->year % 4 == 0 - ? 29 : months[i]))*SECPERDAY; + && days >= (i==1 && datetime->year % 4 == 0 + ? 29 : months[i]); i++) + days -= (i==1 && datetime->year % 4 == 0 + ? 29 : months[i]); datetime->month = i + 1; - datetime->day = 1 + (nix / SECPERDAY); - nix %= SECPERDAY; - datetime->hour = (nix / SECPERHOUR); - nix %= SECPERHOUR; - datetime->minute = nix / SECPERMIN; - datetime->second = nix % SECPERMIN; + datetime->day = 1 + days; + datetime->hour = (secs_in_day / SECPERHOUR); + secs_in_day %= SECPERHOUR; + datetime->minute = secs_in_day / SECPERMIN; + datetime->second = secs_in_day % SECPERMIN; } diff --git a/grub-core/lib/disk.c b/grub-core/lib/disk.c new file mode 100644 index 000000000..123993dd4 --- /dev/null +++ b/grub-core/lib/disk.c @@ -0,0 +1,161 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2004,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#include "../kern/disk_common.c" + +static void +grub_disk_cache_invalidate (unsigned long dev_id, unsigned long disk_id, + grub_disk_addr_t sector) +{ + unsigned cache_index; + struct grub_disk_cache *cache; + + sector &= ~((grub_disk_addr_t) GRUB_DISK_CACHE_SIZE - 1); + cache_index = grub_disk_cache_get_index (dev_id, disk_id, sector); + cache = grub_disk_cache_table + cache_index; + + if (cache->dev_id == dev_id && cache->disk_id == disk_id + && cache->sector == sector && cache->data) + { + cache->lock = 1; + grub_free (cache->data); + cache->data = 0; + cache->lock = 0; + } +} + +grub_err_t +grub_disk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_off_t offset, grub_size_t size, const void *buf) +{ + unsigned real_offset; + grub_disk_addr_t aligned_sector; + + grub_dprintf ("disk", "Writing `%s'...\n", disk->name); + + if (grub_disk_adjust_range (disk, §or, &offset, size) != GRUB_ERR_NONE) + return -1; + + aligned_sector = (sector & ~((1ULL << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) - 1)); + real_offset = offset + ((sector - aligned_sector) << GRUB_DISK_SECTOR_BITS); + sector = aligned_sector; + + while (size) + { + if (real_offset != 0 || (size < (1U << disk->log_sector_size) + && size != 0)) + { + char *tmp_buf; + grub_size_t len; + grub_partition_t part; + + tmp_buf = grub_malloc (1U << disk->log_sector_size); + if (!tmp_buf) + return grub_errno; + + part = disk->partition; + disk->partition = 0; + if (grub_disk_read (disk, sector, + 0, (1U << disk->log_sector_size), tmp_buf) + != GRUB_ERR_NONE) + { + disk->partition = part; + grub_free (tmp_buf); + goto finish; + } + disk->partition = part; + + len = (1U << disk->log_sector_size) - real_offset; + if (len > size) + len = size; + + grub_memcpy (tmp_buf + real_offset, buf, len); + + grub_disk_cache_invalidate (disk->dev->id, disk->id, sector); + + if ((disk->dev->disk_write) (disk, grub_disk_to_native_sector (disk, sector), + 1, tmp_buf) != GRUB_ERR_NONE) + { + grub_free (tmp_buf); + goto finish; + } + + grub_free (tmp_buf); + + sector += (1U << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); + buf = (const char *) buf + len; + size -= len; + real_offset = 0; + } + else + { + grub_size_t len; + grub_size_t n; + + len = size & ~((1ULL << disk->log_sector_size) - 1); + n = size >> disk->log_sector_size; + + if (n > (disk->max_agglomerate + << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size))) + n = (disk->max_agglomerate + << (GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS + - disk->log_sector_size)); + + if ((disk->dev->disk_write) (disk, grub_disk_to_native_sector (disk, sector), + n, buf) != GRUB_ERR_NONE) + goto finish; + + while (n--) + { + grub_disk_cache_invalidate (disk->dev->id, disk->id, sector); + sector += (1U << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)); + } + + buf = (const char *) buf + len; + size -= len; + } + } + + finish: + + return grub_errno; +} + +GRUB_MOD_INIT(disk) +{ + grub_disk_write_weak = grub_disk_write; +} + +GRUB_MOD_FINI(disk) +{ + grub_disk_write_weak = NULL; +} diff --git a/grub-core/lib/division.c b/grub-core/lib/division.c new file mode 100644 index 000000000..35606fea7 --- /dev/null +++ b/grub-core/lib/division.c @@ -0,0 +1,74 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2015 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_uint64_t +abs64(grub_int64_t a) +{ + return a > 0 ? a : -a; +} + +grub_int64_t +grub_divmod64s (grub_int64_t n, + grub_int64_t d, + grub_int64_t *ro) +{ + grub_uint64_t ru; + grub_int64_t q, r; + q = grub_divmod64 (abs64(n), abs64(d), &ru); + r = ru; + /* Now: |n| = |d| * q + r */ + if (n < 0) + { + /* -|n| = |d| * (-q) + (-r) */ + q = -q; + r = -r; + } + /* Now: n = |d| * q + r */ + if (d < 0) + { + /* n = (-|d|) * (-q) + r */ + q = -q; + } + /* Now: n = d * q + r */ + if (ro) + *ro = r; + return q; +} + +grub_uint32_t +grub_divmod32 (grub_uint32_t n, grub_uint32_t d, grub_uint32_t *ro) +{ + grub_uint64_t q, r; + q = grub_divmod64 (n, d, &r); + *ro = r; + return q; +} + +grub_int32_t +grub_divmod32s (grub_int32_t n, grub_int32_t d, grub_int32_t *ro) +{ + grub_int64_t q, r; + q = grub_divmod64s (n, d, &r); + *ro = r; + return q; +} diff --git a/grub-core/lib/dummy/datetime.c b/grub-core/lib/dummy/datetime.c new file mode 100644 index 000000000..cf693fc6b --- /dev/null +++ b/grub-core/lib/dummy/datetime.c @@ -0,0 +1,40 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* No simple platform-independent RTC access exists in U-Boot. */ + +grub_err_t +grub_get_datetime (struct grub_datetime *datetime __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_INVALID_COMMAND, + "can\'t get datetime on this machine"); +} + +grub_err_t +grub_set_datetime (struct grub_datetime * datetime __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_INVALID_COMMAND, + "can\'t set datetime on this machine"); +} diff --git a/grub-core/lib/dummy/halt.c b/grub-core/lib/dummy/halt.c new file mode 100644 index 000000000..378d50f3f --- /dev/null +++ b/grub-core/lib/dummy/halt.c @@ -0,0 +1,32 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include + +void +grub_halt (void) +{ + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); + + /* Just stop here */ + + while (1); +} diff --git a/grub-core/lib/dummy/reboot.c b/grub-core/lib/dummy/reboot.c new file mode 100644 index 000000000..b8cbed8f8 --- /dev/null +++ b/grub-core/lib/dummy/reboot.c @@ -0,0 +1,32 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include + +void +grub_reboot (void) +{ + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN); + + /* Just stop here */ + + while (1); +} diff --git a/grub-core/lib/efi/datetime.c b/grub-core/lib/efi/datetime.c index 0fd1b5fbd..b03e4df5e 100644 --- a/grub-core/lib/efi/datetime.c +++ b/grub-core/lib/efi/datetime.c @@ -32,8 +32,7 @@ grub_get_datetime (struct grub_datetime *datetime) grub_efi_status_t status; struct grub_efi_time efi_time; - status = efi_call_2 (grub_efi_system_table->runtime_services->get_time, - &efi_time, 0); + status = grub_efi_system_table->runtime_services->get_time (&efi_time, 0); if (status) return grub_error (GRUB_ERR_INVALID_COMMAND, @@ -57,8 +56,7 @@ grub_set_datetime (struct grub_datetime *datetime) grub_efi_status_t status; struct grub_efi_time efi_time; - status = efi_call_2 (grub_efi_system_table->runtime_services->get_time, - &efi_time, 0); + status = grub_efi_system_table->runtime_services->get_time (&efi_time, 0); if (status) return grub_error (GRUB_ERR_INVALID_COMMAND, @@ -71,8 +69,7 @@ grub_set_datetime (struct grub_datetime *datetime) efi_time.minute = datetime->minute; efi_time.second = datetime->second; - status = efi_call_1 (grub_efi_system_table->runtime_services->set_time, - &efi_time); + status = grub_efi_system_table->runtime_services->set_time (&efi_time); if (status) return grub_error (GRUB_ERR_INVALID_COMMAND, diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c index 5ebf2cd1d..a58a747e5 100644 --- a/grub-core/lib/efi/halt.c +++ b/grub-core/lib/efi/halt.c @@ -23,16 +23,19 @@ #include #include #include +#include void grub_halt (void) { - grub_machine_fini (); -#ifndef __ia64__ + grub_machine_fini (GRUB_LOADER_FLAG_NORETURN | + GRUB_LOADER_FLAG_EFI_KEEP_ALLOCATED_MEMORY); +#if !defined(__ia64__) && !defined(__arm__) && !defined(__aarch64__) && \ + !defined(__loongarch__) && !defined(__riscv) grub_acpi_halt (); #endif - efi_call_4 (grub_efi_system_table->runtime_services->reset_system, - GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); + grub_efi_system_table->runtime_services->reset_system (GRUB_EFI_RESET_SHUTDOWN, + GRUB_EFI_SUCCESS, 0, NULL); while (1); } diff --git a/grub-core/lib/efi/relocator.c b/grub-core/lib/efi/relocator.c index 0d346bea3..b4518d000 100644 --- a/grub-core/lib/efi/relocator.c +++ b/grub-core/lib/efi/relocator.c @@ -26,7 +26,7 @@ #define NEXT_MEMORY_DESCRIPTOR(desc, size) \ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) -unsigned +unsigned grub_relocator_firmware_get_max_events (void) { grub_efi_uintn_t mmapsize = 0, descriptor_size = 0; @@ -39,7 +39,7 @@ grub_relocator_firmware_get_max_events (void) return 2 * (mmapsize / descriptor_size + 10); } -unsigned +unsigned grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) { grub_efi_uintn_t mmapsize = 0, desc_size = 0; @@ -65,7 +65,7 @@ grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) grub_uint64_t start = desc->physical_start; grub_uint64_t end = desc->physical_start + (desc->num_pages << 12); - /* post-4G addresses are never supported on 32-bit EFI. + /* post-4G addresses are never supported on 32-bit EFI. Moreover it has been reported that some 64-bit EFI contrary to the spec don't map post-4G pages. So if you enable post-4G allocations, map pages manually or check that they are mapped. @@ -81,7 +81,7 @@ grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) counter++; events[counter].type = REG_FIRMWARE_END; events[counter].pos = end; - counter++; + counter++; } return counter; @@ -96,13 +96,13 @@ grub_relocator_firmware_alloc_region (grub_addr_t start, grub_size_t size) if (grub_efi_is_finished) return 1; - +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF grub_dprintf ("relocator", "EFI alloc: %llx, %llx\n", (unsigned long long) start, (unsigned long long) size); - +#endif b = grub_efi_system_table->boot_services; - status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ADDRESS, - GRUB_EFI_LOADER_DATA, size >> 12, &address); + status = b->allocate_pages (GRUB_EFI_ALLOCATE_ADDRESS, + GRUB_EFI_LOADER_DATA, size >> 12, &address); return (status == GRUB_EFI_SUCCESS); } @@ -115,5 +115,5 @@ grub_relocator_firmware_free_region (grub_addr_t start, grub_size_t size) return; b = grub_efi_system_table->boot_services; - efi_call_2 (b->free_pages, start, size >> 12); + b->free_pages (start, size >> 12); } diff --git a/grub-core/lib/efi/tcg2.c b/grub-core/lib/efi/tcg2.c new file mode 100644 index 000000000..841bf50bb --- /dev/null +++ b/grub-core/lib/efi/tcg2.c @@ -0,0 +1,143 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Microsoft Corporation + * Copyright (C) 2024 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include + +#include + +static grub_err_t +tcg2_get_caps (grub_efi_tpm2_protocol_t *protocol, int *tpm2, grub_size_t *max_output_size) +{ + grub_efi_status_t status; + static bool has_caps = 0; + static EFI_TCG2_BOOT_SERVICE_CAPABILITY caps = + { + .Size = (grub_uint8_t) sizeof (caps) + }; + + if (has_caps) + goto exit; + + status = protocol->get_capability (protocol, &caps); + if (status != GRUB_EFI_SUCCESS || !caps.TPMPresentFlag) + return GRUB_ERR_FILE_NOT_FOUND; + + has_caps = 1; + + exit: + if (tpm2 != NULL) + *tpm2 = caps.TPMPresentFlag; + if (max_output_size != NULL) + *max_output_size = caps.MaxResponseSize; + + return GRUB_ERR_NONE; +} + +static grub_err_t +tcg2_get_protocol (grub_efi_tpm2_protocol_t **protocol) +{ + static grub_guid_t tpm2_guid = EFI_TPM2_GUID; + static grub_efi_tpm2_protocol_t *tpm2_protocol = NULL; + int tpm2; + grub_efi_handle_t *handles; + grub_efi_uintn_t num_handles; + grub_efi_handle_t tpm2_handle; + grub_err_t err = GRUB_ERR_FILE_NOT_FOUND; + + if (tpm2_protocol != NULL) + { + *protocol = tpm2_protocol; + return GRUB_ERR_NONE; + } + + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &tpm2_guid, NULL, + &num_handles); + if (handles == NULL || num_handles == 0) + return err; + + tpm2_handle = handles[0]; + + tpm2_protocol = grub_efi_open_protocol (tpm2_handle, &tpm2_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (tpm2_protocol == NULL) + goto exit; + + err = tcg2_get_caps (tpm2_protocol, &tpm2, NULL); + if (err != GRUB_ERR_NONE || tpm2 == 0) + goto exit; + + *protocol = tpm2_protocol; + err = GRUB_ERR_NONE; + + exit: + grub_free (handles); + return err; +} + +grub_err_t +grub_tcg2_get_max_output_size (grub_size_t *size) +{ + grub_err_t err; + grub_size_t max; + grub_efi_tpm2_protocol_t *protocol; + + if (size == NULL) + return GRUB_ERR_BAD_ARGUMENT; + + err = tcg2_get_protocol (&protocol); + if (err != GRUB_ERR_NONE) + return err; + + err = tcg2_get_caps (protocol, NULL, &max); + if (err != GRUB_ERR_NONE) + return err; + + *size = max; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_tcg2_submit_command (grub_size_t input_size, + grub_uint8_t *input, + grub_size_t output_size, + grub_uint8_t *output) +{ + grub_err_t err; + grub_efi_status_t status; + grub_efi_tpm2_protocol_t *protocol; + + if (input_size == 0 || input == NULL || + output_size == 0 || output == NULL) + return GRUB_ERR_BAD_ARGUMENT; + + err = tcg2_get_protocol (&protocol); + if (err != GRUB_ERR_NONE) + return err; + + status = protocol->submit_command (protocol, input_size, input, + output_size, output); + if (status != GRUB_EFI_SUCCESS) + return GRUB_ERR_INVALID_COMMAND; + + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/envblk.c b/grub-core/lib/envblk.c index 311927bd8..2e4e78b13 100644 --- a/grub-core/lib/envblk.c +++ b/grub-core/lib/envblk.c @@ -143,7 +143,7 @@ grub_envblk_set (grub_envblk_t envblk, const char *name, const char *value) /* Move the following characters backward, and fill the new space with harmless characters. */ grub_memmove (p + vl, p + len, pend - (p + len)); - grub_memset (space + len - vl, '#', len - vl); + grub_memset (space - (len - vl), '#', len - vl); } else /* Move the following characters forward. */ @@ -225,7 +225,8 @@ grub_envblk_delete (grub_envblk_t envblk, const char *name) void grub_envblk_iterate (grub_envblk_t envblk, - int hook (const char *name, const char *value)) + void *hook_data, + int hook (const char *name, const char *value, void *hook_data)) { char *p, *pend; @@ -285,7 +286,7 @@ grub_envblk_iterate (grub_envblk_t envblk, } *q = '\0'; - ret = hook (name, value); + ret = hook (name, value, hook_data); grub_free (name); if (ret) return; diff --git a/grub-core/lib/fdt.c b/grub-core/lib/fdt.c new file mode 100644 index 000000000..73cfa94a2 --- /dev/null +++ b/grub-core/lib/fdt.c @@ -0,0 +1,531 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define FDT_SUPPORTED_VERSION 17 + +#define FDT_BEGIN_NODE 0x00000001 +#define FDT_END_NODE 0x00000002 +#define FDT_PROP 0x00000003 +#define FDT_NOP 0x00000004 +#define FDT_END 0x00000009 + +#define struct_end(fdt) \ + ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt) \ + + grub_fdt_get_size_dt_struct(fdt)) + +/* Size needed by a node entry: 2 tokens (FDT_BEGIN_NODE and FDT_END_NODE), plus + the NULL-terminated string containing the name, plus padding if needed. */ +#define node_entry_size(node_name) \ + (2 * sizeof(grub_uint32_t) \ + + ALIGN_UP (grub_strlen (name) + 1, sizeof(grub_uint32_t))) + +#define SKIP_NODE_NAME(name, token, end) \ + name = (char *) ((token) + 1); \ + while (name < (char *) end) \ + { \ + if (!*name++) \ + break; \ + } \ + token = (grub_uint32_t *) ALIGN_UP((grub_addr_t) (name), sizeof(*token)) + + +static grub_uint32_t *get_next_node (const void *fdt, char *node_name) +{ + grub_uint32_t *end = (void *) struct_end (fdt); + grub_uint32_t *token; + + if (node_name >= (char *) end) + return NULL; + while (*node_name++) + { + if (node_name >= (char *) end) + return NULL; + } + token = (grub_uint32_t *) ALIGN_UP ((grub_addr_t) node_name, 4); + while (token < end) + { + switch (grub_be_to_cpu32(*token)) + { + case FDT_BEGIN_NODE: + token = get_next_node (fdt, (char *) (token + 1)); + if (!token) + return NULL; + break; + case FDT_END_NODE: + token++; + if (token >= end) + return NULL; + return token; + case FDT_PROP: + /* Skip property token and following data (len, nameoff and property + value). */ + token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1))) + / sizeof(*token); + break; + case FDT_NOP: + token++; + break; + default: + return NULL; + } + } + return NULL; +} + +static int get_mem_rsvmap_size (const void *fdt) +{ + int size = 0; + grub_unaligned_uint64_t *ptr = (void *) ((grub_addr_t) fdt + + grub_fdt_get_off_mem_rsvmap (fdt)); + + do + { + size += 2 * sizeof(*ptr); + if (!ptr[0].val && !ptr[1].val) + return size; + ptr += 2; + } while ((grub_addr_t) ptr <= (grub_addr_t) fdt + grub_fdt_get_totalsize (fdt) + - 2 * sizeof(grub_uint64_t)); + return -1; +} + +static grub_uint32_t get_free_space (void *fdt) +{ + int mem_rsvmap_size = get_mem_rsvmap_size (fdt); + + if (mem_rsvmap_size < 0) + /* invalid memory reservation block */ + return 0; + return (grub_fdt_get_totalsize (fdt) - sizeof(grub_fdt_header_t) + - mem_rsvmap_size - grub_fdt_get_size_dt_strings (fdt) + - grub_fdt_get_size_dt_struct (fdt)); +} + +static int add_subnode (void *fdt, int parentoffset, const char *name) +{ + grub_uint32_t *token = (void *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct(fdt) + + parentoffset); + grub_uint32_t *end = (void *) struct_end (fdt); + unsigned int entry_size = node_entry_size (name); + unsigned int struct_size = grub_fdt_get_size_dt_struct(fdt); + char *node_name; + + SKIP_NODE_NAME(node_name, token, end); + + /* Insert the new subnode just after the properties of the parent node (if + any).*/ + while (1) + { + if (token >= end) + return -1; + switch (grub_be_to_cpu32(*token)) + { + case FDT_PROP: + /* Skip len, nameoff and property value. */ + token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1))) + / sizeof(*token); + break; + case FDT_BEGIN_NODE: + case FDT_END_NODE: + goto insert; + case FDT_NOP: + token++; + break; + default: + /* invalid token */ + return -1; + } + } +insert: + grub_memmove (token + entry_size / sizeof(*token), token, + (grub_addr_t) end - (grub_addr_t) token); + *token = grub_cpu_to_be32_compile_time(FDT_BEGIN_NODE); + token[entry_size / sizeof(*token) - 2] = 0; /* padding bytes */ + grub_strcpy((char *) (token + 1), name); + token[entry_size / sizeof(*token) - 1] = grub_cpu_to_be32_compile_time(FDT_END_NODE); + grub_fdt_set_size_dt_struct (fdt, struct_size + entry_size); + return ((grub_addr_t) token - (grub_addr_t) fdt + - grub_fdt_get_off_dt_struct(fdt)); +} + +/* Rearrange FDT blocks in the canonical order: first the memory reservation + block (just after the FDT header), then the structure block and finally the + strings block. No free space is left between the first and the second block, + while the space between the second and the third block is given by the + clearance argument. */ +static int rearrange_blocks (void *fdt, unsigned int clearance) +{ + grub_uint32_t off_mem_rsvmap = ALIGN_UP(sizeof(grub_fdt_header_t), 8); + grub_uint32_t off_dt_struct = off_mem_rsvmap + get_mem_rsvmap_size (fdt); + grub_uint32_t off_dt_strings = off_dt_struct + + grub_fdt_get_size_dt_struct (fdt) + + clearance; + grub_uint8_t *fdt_ptr = fdt; + grub_uint8_t *tmp_fdt; + + if ((grub_fdt_get_off_mem_rsvmap (fdt) == off_mem_rsvmap) + && (grub_fdt_get_off_dt_struct (fdt) == off_dt_struct)) + { + /* No need to allocate memory for a temporary FDT, just move the strings + block if needed. */ + if (grub_fdt_get_off_dt_strings (fdt) != off_dt_strings) + { + grub_memmove(fdt_ptr + off_dt_strings, + fdt_ptr + grub_fdt_get_off_dt_strings (fdt), + grub_fdt_get_size_dt_strings (fdt)); + grub_fdt_set_off_dt_strings (fdt, off_dt_strings); + } + return 0; + } + tmp_fdt = grub_malloc (grub_fdt_get_totalsize (fdt)); + if (!tmp_fdt) + return -1; + grub_memcpy (tmp_fdt + off_mem_rsvmap, + fdt_ptr + grub_fdt_get_off_mem_rsvmap (fdt), + get_mem_rsvmap_size (fdt)); + grub_fdt_set_off_mem_rsvmap (fdt, off_mem_rsvmap); + grub_memcpy (tmp_fdt + off_dt_struct, + fdt_ptr + grub_fdt_get_off_dt_struct (fdt), + grub_fdt_get_size_dt_struct (fdt)); + grub_fdt_set_off_dt_struct (fdt, off_dt_struct); + grub_memcpy (tmp_fdt + off_dt_strings, + fdt_ptr + grub_fdt_get_off_dt_strings (fdt), + grub_fdt_get_size_dt_strings (fdt)); + grub_fdt_set_off_dt_strings (fdt, off_dt_strings); + + /* Copy reordered blocks back to fdt. */ + grub_memcpy (fdt_ptr + off_mem_rsvmap, tmp_fdt + off_mem_rsvmap, + grub_fdt_get_totalsize (fdt) - off_mem_rsvmap); + + grub_free(tmp_fdt); + return 0; +} + +static grub_uint32_t *find_prop (const void *fdt, unsigned int nodeoffset, + const char *name) +{ + grub_uint32_t *prop = (void *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct (fdt) + + nodeoffset); + grub_uint32_t *end = (void *) struct_end(fdt); + grub_uint32_t nameoff; + char *node_name; + + SKIP_NODE_NAME(node_name, prop, end); + while (prop < end - 2) + { + if (grub_be_to_cpu32(*prop) == FDT_PROP) + { + nameoff = grub_be_to_cpu32(*(prop + 2)); + if ((nameoff + grub_strlen (name) < grub_fdt_get_size_dt_strings (fdt)) + && !grub_strcmp (name, (char *) fdt + + grub_fdt_get_off_dt_strings (fdt) + nameoff)) + { + if (prop + grub_fdt_prop_entry_size(grub_be_to_cpu32(*(prop + 1))) + / sizeof (*prop) >= end) + return NULL; + return prop; + } + prop += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(prop + 1))) / sizeof (*prop); + } + else if (grub_be_to_cpu32(*prop) == FDT_NOP) + prop++; + else + return NULL; + } + return NULL; +} + +/* Check the FDT header for consistency and adjust the totalsize field to match + the size allocated for the FDT; if this function is called before the other + functions in this file and returns success, the other functions are + guaranteed not to access memory locations outside the allocated memory. */ +int grub_fdt_check_header_nosize (const void *fdt) +{ + if (((grub_addr_t) fdt & 0x3) || (grub_fdt_get_magic (fdt) != FDT_MAGIC) + || (grub_fdt_get_version (fdt) < FDT_SUPPORTED_VERSION) + || (grub_fdt_get_last_comp_version (fdt) > FDT_SUPPORTED_VERSION) + || (grub_fdt_get_off_dt_struct (fdt) & 0x00000003) + || (grub_fdt_get_size_dt_struct (fdt) & 0x00000003) + || (grub_fdt_get_off_dt_struct (fdt) + grub_fdt_get_size_dt_struct (fdt) + > grub_fdt_get_totalsize (fdt)) + || (grub_fdt_get_off_dt_strings (fdt) + grub_fdt_get_size_dt_strings (fdt) + > grub_fdt_get_totalsize (fdt)) + || (grub_fdt_get_off_mem_rsvmap (fdt) & 0x00000007) + || (grub_fdt_get_off_mem_rsvmap (fdt) + > grub_fdt_get_totalsize (fdt) - 2 * sizeof(grub_uint64_t))) + return -1; + return 0; +} + +int grub_fdt_check_header (const void *fdt, unsigned int size) +{ + if (size < sizeof (grub_fdt_header_t) + || (grub_fdt_get_totalsize (fdt) > size) + || grub_fdt_check_header_nosize (fdt) == -1) + return -1; + return 0; +} + +static const grub_uint32_t * +advance_token (const void *fdt, const grub_uint32_t *token, const grub_uint32_t *end, int skip_current) +{ + for (; token < end; skip_current = 0) + { + switch (grub_be_to_cpu32 (*token)) + { + case FDT_BEGIN_NODE: + if (skip_current) + { + token = get_next_node (fdt, (char *) (token + 1)); + continue; + } + char *ptr; + for (ptr = (char *) (token + 1); *ptr && ptr < (char *) end; ptr++) + ; + if (ptr >= (char *) end) + return 0; + return token; + case FDT_PROP: + /* Skip property token and following data (len, nameoff and property + value). */ + if (token >= end - 1) + return 0; + token += grub_fdt_prop_entry_size(grub_be_to_cpu32(*(token + 1))) + / sizeof(*token); + break; + case FDT_NOP: + token++; + break; + default: + return 0; + } + } + return 0; +} + +int grub_fdt_next_node (const void *fdt, unsigned int currentoffset) +{ + const grub_uint32_t *token = (const grub_uint32_t *) fdt + (currentoffset + grub_fdt_get_off_dt_struct (fdt)) / 4; + token = advance_token (fdt, token, (const void *) struct_end (fdt), 1); + if (!token) + return -1; + return (int) ((grub_addr_t) token - (grub_addr_t) fdt + - grub_fdt_get_off_dt_struct (fdt)); +} + +int grub_fdt_first_node (const void *fdt, unsigned int parentoffset) +{ + const grub_uint32_t *token, *end; + char *node_name; + + if (parentoffset & 0x3) + return -1; + token = (const void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt) + + parentoffset); + end = (const void *) struct_end (fdt); + if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE)) + return -1; + SKIP_NODE_NAME(node_name, token, end); + token = advance_token (fdt, token, end, 0); + if (!token) + return -1; + return (int) ((grub_addr_t) token - (grub_addr_t) fdt + - grub_fdt_get_off_dt_struct (fdt)); +} + +/* Find a direct sub-node of a given parent node. */ +int grub_fdt_find_subnode (const void *fdt, unsigned int parentoffset, + const char *name) +{ + const grub_uint32_t *token, *end; + const char *node_name; + int skip_current = 0; + + if (parentoffset & 0x3) + return -1; + token = (const void *) ((grub_addr_t) fdt + grub_fdt_get_off_dt_struct(fdt) + + parentoffset); + end = (const void *) struct_end (fdt); + if ((token >= end) || (grub_be_to_cpu32(*token) != FDT_BEGIN_NODE)) + return -1; + SKIP_NODE_NAME(node_name, token, end); + while (1) { + token = advance_token (fdt, token, end, skip_current); + if (!token) + return -1; + skip_current = 1; + node_name = (const char *) token + 4; + if (grub_strcmp (node_name, name) == 0) + return (int) ((grub_addr_t) token - (grub_addr_t) fdt + - grub_fdt_get_off_dt_struct (fdt)); + } +} + +const char * +grub_fdt_get_nodename (const void *fdt, unsigned int nodeoffset) +{ + return (const char *) fdt + grub_fdt_get_off_dt_struct(fdt) + nodeoffset + 4; +} + +int grub_fdt_add_subnode (void *fdt, unsigned int parentoffset, + const char *name) +{ + unsigned int entry_size = node_entry_size(name); + + if ((parentoffset & 0x3) || (get_free_space (fdt) < entry_size)) + return -1; + + /* The new node entry will increase the size of the structure block: rearrange + blocks such that there is sufficient free space between the structure and + the strings block, then add the new node entry. */ + if (rearrange_blocks (fdt, entry_size) < 0) + return -1; + return add_subnode (fdt, parentoffset, name); +} + +const void * +grub_fdt_get_prop (const void *fdt, unsigned int nodeoffset, const char *name, + grub_uint32_t *len) +{ + grub_uint32_t *prop; + if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3) + || (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct (fdt) + nodeoffset)) + != FDT_BEGIN_NODE)) + return 0; + prop = find_prop (fdt, nodeoffset, name); + if (!prop) + return 0; + if (len) + *len = grub_be_to_cpu32 (*(prop + 1)); + return prop + 3; +} + +int grub_fdt_set_prop (void *fdt, unsigned int nodeoffset, const char *name, + const void *val, grub_uint32_t len) +{ + grub_uint32_t *prop; + int prop_name_present = 0; + grub_uint32_t nameoff = 0; + + if ((nodeoffset >= grub_fdt_get_size_dt_struct (fdt)) || (nodeoffset & 0x3) + || (grub_be_to_cpu32(*(grub_uint32_t *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct (fdt) + nodeoffset)) + != FDT_BEGIN_NODE)) + return -1; + prop = find_prop (fdt, nodeoffset, name); + if (prop) + { + grub_uint32_t prop_len = ALIGN_UP(grub_be_to_cpu32 (*(prop + 1)), + sizeof(grub_uint32_t)); + grub_uint32_t i; + + prop_name_present = 1; + for (i = 0; i < prop_len / sizeof(grub_uint32_t); i++) + *(prop + 3 + i) = grub_cpu_to_be32_compile_time (FDT_NOP); + if (len > ALIGN_UP(prop_len, sizeof(grub_uint32_t))) + { + /* Length of new property value is greater than the space allocated + for the current value: a new entry needs to be created, so save the + nameoff field of the current entry and replace the current entry + with NOP tokens. */ + nameoff = grub_be_to_cpu32 (*(prop + 2)); + *prop = *(prop + 1) = *(prop + 2) = grub_cpu_to_be32_compile_time (FDT_NOP); + prop = NULL; + } + } + if (!prop || !prop_name_present) { + unsigned int needed_space = 0; + + if (!prop) + needed_space = grub_fdt_prop_entry_size(len); + if (!prop_name_present) + needed_space += grub_strlen (name) + 1; + if (needed_space > get_free_space (fdt)) + return -1; + if (rearrange_blocks (fdt, !prop ? grub_fdt_prop_entry_size(len) : 0) < 0) + return -1; + } + if (!prop_name_present) { + /* Append the property name at the end of the strings block. */ + nameoff = grub_fdt_get_size_dt_strings (fdt); + grub_strcpy ((char *) fdt + grub_fdt_get_off_dt_strings (fdt) + nameoff, + name); + grub_fdt_set_size_dt_strings (fdt, grub_fdt_get_size_dt_strings (fdt) + + grub_strlen (name) + 1); + } + if (!prop) { + char *node_name = (char *) ((grub_addr_t) fdt + + grub_fdt_get_off_dt_struct (fdt) + nodeoffset + + sizeof(grub_uint32_t)); + + prop = (void *) (node_name + ALIGN_UP(grub_strlen(node_name) + 1, 4)); + grub_memmove (prop + grub_fdt_prop_entry_size(len) / sizeof(*prop), prop, + struct_end(fdt) - (grub_addr_t) prop); + grub_fdt_set_size_dt_struct (fdt, grub_fdt_get_size_dt_struct (fdt) + + grub_fdt_prop_entry_size(len)); + *prop = grub_cpu_to_be32_compile_time (FDT_PROP); + *(prop + 2) = grub_cpu_to_be32 (nameoff); + } + *(prop + 1) = grub_cpu_to_be32 (len); + + /* Insert padding bytes at the end of the value; if they are not needed, they + will be overwritten by the following memcpy. */ + *(prop + grub_fdt_prop_entry_size(len) / sizeof(grub_uint32_t) - 1) = 0; + + grub_memcpy (prop + 3, val, len); + return 0; +} + +int +grub_fdt_create_empty_tree (void *fdt, unsigned int size) +{ + struct grub_fdt_empty_tree *et; + + if (size < GRUB_FDT_EMPTY_TREE_SZ) + return -1; + + grub_memset (fdt, 0, size); + et = fdt; + + et->empty_node.tree_end = grub_cpu_to_be32_compile_time (FDT_END); + et->empty_node.node_end = grub_cpu_to_be32_compile_time (FDT_END_NODE); + et->empty_node.node_start = grub_cpu_to_be32_compile_time (FDT_BEGIN_NODE); + ((struct grub_fdt_empty_tree *) fdt)->header.off_mem_rsvmap = + grub_cpu_to_be32_compile_time (ALIGN_UP (sizeof (grub_fdt_header_t), 8)); + + grub_fdt_set_off_dt_strings (fdt, sizeof (*et)); + grub_fdt_set_off_dt_struct (fdt, + sizeof (et->header) + sizeof (et->empty_rsvmap)); + grub_fdt_set_version (fdt, FDT_SUPPORTED_VERSION); + grub_fdt_set_last_comp_version (fdt, FDT_SUPPORTED_VERSION); + grub_fdt_set_size_dt_struct (fdt, sizeof (et->empty_node)); + grub_fdt_set_totalsize (fdt, size); + grub_fdt_set_magic (fdt, FDT_MAGIC); + + return 0; +} diff --git a/grub-core/lib/getline.c b/grub-core/lib/getline.c new file mode 100644 index 000000000..edb8e9ffe --- /dev/null +++ b/grub-core/lib/getline.c @@ -0,0 +1,92 @@ +/* main.c - the normal mode main routine */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000,2001,2002,2003,2005,2006,2007,2008,2009,2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Read a line from the file FILE. */ +char * +grub_file_getline (grub_file_t file) +{ + char c; + grub_size_t pos = 0; + char *cmdline; + int have_newline = 0; + grub_size_t max_len = 64; + + /* Initially locate some space. */ + cmdline = grub_malloc (max_len); + if (! cmdline) + return 0; + + while (1) + { + if (grub_file_read (file, &c, 1) != 1) + break; + + /* Skip all carriage returns. */ + if (c == '\r') + continue; + + + if (pos + 1 >= max_len) + { + char *old_cmdline = cmdline; + max_len = max_len * 2; + cmdline = grub_realloc (cmdline, max_len); + if (! cmdline) + { + grub_free (old_cmdline); + return 0; + } + } + + if (c == '\n') + { + have_newline = 1; + break; + } + + cmdline[pos++] = c; + } + + cmdline[pos] = '\0'; + + /* If the buffer is empty, don't return anything at all. */ + if (pos == 0 && !have_newline) + { + grub_free (cmdline); + cmdline = 0; + } + + return cmdline; +} diff --git a/grub-core/lib/gnulib-patches/fix-width.patch b/grub-core/lib/gnulib-patches/fix-width.patch new file mode 100644 index 000000000..15f091c0d --- /dev/null +++ b/grub-core/lib/gnulib-patches/fix-width.patch @@ -0,0 +1,217 @@ +diff --git a/lib/argp-fmtstream.c b/lib/argp-fmtstream.c +index ba6a407f7..d0685b3d4 100644 +--- a/lib/argp-fmtstream.c ++++ b/lib/argp-fmtstream.c +@@ -28,9 +28,11 @@ + #include + #include + #include ++#include + + #include "argp-fmtstream.h" + #include "argp-namefrob.h" ++#include "mbswidth.h" + + #ifndef ARGP_FMTSTREAM_USE_LINEWRAP + +@@ -115,6 +117,51 @@ weak_alias (__argp_fmtstream_free, argp_fmtstream_free) + #endif + #endif + ++ ++/* Return the pointer to the first character that doesn't fit in l columns. */ ++static inline const ptrdiff_t ++add_width (const char *ptr, const char *end, size_t l) ++{ ++ mbstate_t ps; ++ const char *ptr0 = ptr; ++ ++ memset (&ps, 0, sizeof (ps)); ++ ++ while (ptr < end) ++ { ++ wchar_t wc; ++ size_t s, k; ++ ++ s = mbrtowc (&wc, ptr, end - ptr, &ps); ++ if (s == (size_t) -1) ++ break; ++ if (s == (size_t) -2) ++ { ++ if (1 >= l) ++ break; ++ l--; ++ ptr++; ++ continue; ++ } ++ ++ if (wc == '\e' && ptr + 3 < end ++ && ptr[1] == '[' && (ptr[2] == '0' || ptr[2] == '1') ++ && ptr[3] == 'm') ++ { ++ ptr += 4; ++ continue; ++ } ++ ++ k = wcwidth (wc); ++ ++ if (k >= l) ++ break; ++ l -= k; ++ ptr += s; ++ } ++ return ptr - ptr0; ++} ++ + /* Process FS's buffer so that line wrapping is done from POINT_OFFS to the + end of its buffer. This code is mostly from glibc stdio/linewrap.c. */ + void +@@ -168,13 +215,15 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + if (!nl) + { + /* The buffer ends in a partial line. */ ++ size_t display_width = mbsnwidth (buf, fs->p - buf, ++ MBSW_STOP_AT_NUL); + +- if (fs->point_col + len < fs->rmargin) ++ if (fs->point_col + display_width < fs->rmargin) + { + /* The remaining buffer text is a partial line and fits + within the maximum line width. Advance point for the + characters to be written and stop scanning. */ +- fs->point_col += len; ++ fs->point_col += display_width; + break; + } + else +@@ -182,14 +231,18 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + the end of the buffer. */ + nl = fs->p; + } +- else if (fs->point_col + (nl - buf) < (ssize_t) fs->rmargin) +- { +- /* The buffer contains a full line that fits within the maximum +- line width. Reset point and scan the next line. */ +- fs->point_col = 0; +- buf = nl + 1; +- continue; +- } ++ else ++ { ++ size_t display_width = mbsnwidth (buf, nl - buf, MBSW_STOP_AT_NUL); ++ if (display_width < (ssize_t) fs->rmargin) ++ { ++ /* The buffer contains a full line that fits within the maximum ++ line width. Reset point and scan the next line. */ ++ fs->point_col = 0; ++ buf = nl + 1; ++ continue; ++ } ++ } + + /* This line is too long. */ + r = fs->rmargin - 1; +@@ -225,7 +278,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + char *p, *nextline; + int i; + +- p = buf + (r + 1 - fs->point_col); ++ p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); + while (p >= buf && !isblank ((unsigned char) *p)) + --p; + nextline = p + 1; /* This will begin the next line. */ +@@ -243,7 +296,7 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + { + /* A single word that is greater than the maximum line width. + Oh well. Put it on an overlong line by itself. */ +- p = buf + (r + 1 - fs->point_col); ++ p = buf + add_width (buf, fs->p, (r + 1 - fs->point_col)); + /* Find the end of the long word. */ + if (p < nl) + do +@@ -277,7 +330,8 @@ __argp_fmtstream_update (argp_fmtstream_t fs) + && fs->p > nextline) + { + /* The margin needs more blanks than we removed. */ +- if (fs->end - fs->p > fs->wmargin + 1) ++ if (mbsnwidth (fs->p, fs->end - fs->p, MBSW_STOP_AT_NUL) ++ > fs->wmargin + 1) + /* Make some space for them. */ + { + size_t mv = fs->p - nextline; +diff --git a/lib/argp-help.c b/lib/argp-help.c +index e5375a0f0..5d8f451ec 100644 +--- a/lib/argp-help.c ++++ b/lib/argp-help.c +@@ -52,6 +52,7 @@ + #include "argp.h" + #include "argp-fmtstream.h" + #include "argp-namefrob.h" ++#include "mbswidth.h" + + #ifndef SIZE_MAX + # define SIZE_MAX ((size_t) -1) +@@ -1547,7 +1548,7 @@ argp_args_usage (const struct argp *argp, const struct argp_state *state, + + /* Manually do line wrapping so that it (probably) won't get wrapped at + any embedded spaces. */ +- space (stream, 1 + nl - cp); ++ space (stream, 1 + mbsnwidth (cp, nl - cp, MBSW_STOP_AT_NUL)); + + __argp_fmtstream_write (stream, cp, nl - cp); + } +diff --git a/lib/mbswidth.c b/lib/mbswidth.c +index 408a15e34..b3fb7f83a 100644 +--- a/lib/mbswidth.c ++++ b/lib/mbswidth.c +@@ -38,6 +38,14 @@ + /* Get INT_MAX. */ + #include + ++#ifndef FALLTHROUGH ++# if __GNUC__ < 7 ++# define FALLTHROUGH ((void) 0) ++# else ++# define FALLTHROUGH __attribute__ ((__fallthrough__)) ++# endif ++#endif ++ + /* Returns the number of columns needed to represent the multibyte + character string pointed to by STRING. If a non-printable character + occurs, and MBSW_REJECT_UNPRINTABLE is specified, -1 is returned. +@@ -90,6 +98,10 @@ mbsnwidth (const char *string, size_t nbytes, int flags) + p++; + width++; + break; ++ case '\0': ++ if (flags & MBSW_STOP_AT_NUL) ++ return width; ++ FALLTHROUGH; + default: + /* If we have a multibyte sequence, scan it up to its end. */ + { +@@ -168,6 +180,9 @@ mbsnwidth (const char *string, size_t nbytes, int flags) + { + unsigned char c = (unsigned char) *p++; + ++ if (c == 0 && (flags & MBSW_STOP_AT_NUL)) ++ return width; ++ + if (isprint (c)) + { + if (width == INT_MAX) +diff --git a/lib/mbswidth.h b/lib/mbswidth.h +index 2b5c53c37..45a123e63 100644 +--- a/lib/mbswidth.h ++++ b/lib/mbswidth.h +@@ -40,6 +40,10 @@ extern "C" { + control characters and 1 otherwise. */ + #define MBSW_REJECT_UNPRINTABLE 2 + ++/* If this bit is set \0 is treated as the end of string. ++ Otherwise it's treated as a normal one column width character. */ ++#define MBSW_STOP_AT_NUL 4 ++ + + /* Returns the number of screen columns needed for STRING. */ + #define mbswidth gnu_mbswidth /* avoid clash with UnixWare 7.1.1 function */ diff --git a/grub-core/lib/i386/backtrace.c b/grub-core/lib/i386/backtrace.c index 7a7796a12..c3e03c727 100644 --- a/grub-core/lib/i386/backtrace.c +++ b/grub-core/lib/i386/backtrace.c @@ -56,11 +56,11 @@ void grub_backtrace (void) { #ifdef __x86_64__ - asm volatile ("movq %rbp, %rdi\n" - "call " EXT_C("grub_backtrace_pointer")); + asm volatile ("movq %%rbp, %%rdi\n" + "callq *%%rax": :"a"(grub_backtrace_pointer)); #else - asm volatile ("movl %ebp, %eax\n" - "call " EXT_C("grub_backtrace_pointer")); + asm volatile ("movl %%ebp, %%eax\n" + "calll *%%ecx": :"c"(grub_backtrace_pointer)); #endif } diff --git a/grub-core/lib/i386/halt.c b/grub-core/lib/i386/halt.c index bd878c9bf..2364fe4d7 100644 --- a/grub-core/lib/i386/halt.c +++ b/grub-core/lib/i386/halt.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include const char bochs_shutdown[] = "Shutdown"; @@ -37,6 +39,23 @@ stop (void) } } +static int +grub_shutdown_pci_iter (grub_pci_device_t dev, grub_pci_id_t pciid, + void *data __attribute__ ((unused))) +{ + /* QEMU. */ + if (pciid == 0x71138086) + { + grub_pci_address_t addr; + addr = grub_pci_make_address (dev, 0x40); + grub_pci_write (addr, 0x7001); + addr = grub_pci_make_address (dev, 0x80); + grub_pci_write (addr, grub_pci_read (addr) | 1); + grub_outw (0x2000, 0x7004); + } + return 0; +} + void grub_halt (void) { @@ -47,12 +66,14 @@ grub_halt (void) #endif /* Disable interrupts. */ - __asm__ __volatile__ ("cli"); + asm volatile ("cli"); - /* Bochs, QEMU, etc. */ + /* Bochs, QEMU, etc. Removed in newer QEMU releases. */ for (i = 0; i < sizeof (bochs_shutdown) - 1; i++) grub_outb (bochs_shutdown[i], 0x8900); + grub_pci_iterate (grub_shutdown_pci_iter, NULL); + grub_puts_ (N_("GRUB doesn't know how to halt this machine yet!")); /* In order to return we'd have to check what the previous status of IF diff --git a/grub-core/lib/i386/random.c b/grub-core/lib/i386/random.c new file mode 100644 index 000000000..cd83d2f8f --- /dev/null +++ b/grub-core/lib/i386/random.c @@ -0,0 +1,103 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2016 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +static int have_tsc = -1, have_pmtimer = -1; +static grub_port_t pmtimer_port; + +static int +detect_pmtimer (void) +{ + struct grub_acpi_fadt *fadt; + fadt = grub_acpi_find_fadt (); + if (!fadt) + return 0; + pmtimer_port = fadt->pmtimer; + if (!pmtimer_port) + return 0; + return 1; +} + +static int +pmtimer_tsc_get_random_bit (void) +{ + /* It's hard to come up with figures about pmtimer and tsc jitter but + 50 ppm seems to be typical. So we need 10^6/50 tsc cycles to get drift + of one tsc cycle. With TSC at least of 800 MHz it means 1/(50*800) + = 1/40000 s or about 3579545 / 40000 = 90 pmtimer ticks. + This gives us rate of 40000 bit/s or 5 kB/s. + */ + grub_uint64_t tsc_diff; + tsc_diff = grub_pmtimer_wait_count_tsc (pmtimer_port, 90); + if (tsc_diff == 0) + { + have_pmtimer = 0; + return -1; + } + return tsc_diff & 1; +} + +static int +pmtimer_tsc_get_random_byte (void) +{ + grub_uint8_t ret = 0; + int i, c; + for (i = 0; i < 8; i++) + { + c = pmtimer_tsc_get_random_bit (); + if (c < 0) + return -1; + ret |= c << i; + } + return ret; +} + +static int +pmtimer_fill_buffer (void *buffer, grub_size_t sz) +{ + grub_uint8_t *p = buffer; + int c; + while (sz) + { + c = pmtimer_tsc_get_random_byte (); + if (c < 0) + return 0; + *p++ = c; + sz--; + } + return 1; +} + +int +grub_crypto_arch_get_random (void *buffer, grub_size_t sz) +{ + if (have_tsc == -1) + have_tsc = grub_cpu_is_tsc_supported (); + if (!have_tsc) + return 0; + if (have_pmtimer == -1) + have_pmtimer = detect_pmtimer (); + if (!have_pmtimer) + return 0; + return pmtimer_fill_buffer (buffer, sz); +} diff --git a/grub-core/lib/i386/reboot.c b/grub-core/lib/i386/reboot.c index 0587f1477..d0fd6a50e 100644 --- a/grub-core/lib/i386/reboot.c +++ b/grub-core/lib/i386/reboot.c @@ -16,6 +16,8 @@ * along with GRUB. If not, see . */ +#ifndef GRUB_MACHINE_EFI + #include #include #include @@ -53,9 +55,10 @@ grub_reboot (void) state.a20 = 0; grub_stop_floppy (); - + err = grub_relocator16_boot (relocator, state); while (1); } +#endif /* GRUB_MACHINE_EFI */ diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index df25b30fa..54a1dcd8b 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -28,19 +28,6 @@ #include #include -extern grub_uint8_t grub_relocator_forward_start; -extern grub_uint8_t grub_relocator_forward_end; -extern grub_uint8_t grub_relocator_backward_start; -extern grub_uint8_t grub_relocator_backward_end; - -extern void *grub_relocator_backward_dest; -extern void *grub_relocator_backward_src; -extern grub_size_t grub_relocator_backward_chunk_size; - -extern void *grub_relocator_forward_dest; -extern void *grub_relocator_forward_src; -extern grub_size_t grub_relocator_forward_chunk_size; - extern grub_uint8_t grub_relocator16_start; extern grub_uint8_t grub_relocator16_end; extern grub_uint16_t grub_relocator16_cs; @@ -54,6 +41,7 @@ extern grub_uint16_t grub_relocator16_sp; extern grub_uint32_t grub_relocator16_edx; extern grub_uint32_t grub_relocator16_ebx; extern grub_uint32_t grub_relocator16_esi; +extern grub_uint32_t grub_relocator16_ebp; extern grub_uint16_t grub_relocator16_keep_a20_enabled; @@ -76,7 +64,6 @@ extern grub_uint64_t grub_relocator64_rbx; extern grub_uint64_t grub_relocator64_rcx; extern grub_uint64_t grub_relocator64_rdx; extern grub_uint64_t grub_relocator64_rip; -extern grub_uint64_t grub_relocator64_rip_addr; extern grub_uint64_t grub_relocator64_rsp; extern grub_uint64_t grub_relocator64_rsi; extern grub_addr_t grub_relocator64_cr3; @@ -84,75 +71,6 @@ extern struct grub_i386_idt grub_relocator16_idt; #define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start) -grub_size_t grub_relocator_align = 1; -grub_size_t grub_relocator_forward_size; -grub_size_t grub_relocator_backward_size; -#ifdef __x86_64__ -grub_size_t grub_relocator_jumper_size = 12; -#else -grub_size_t grub_relocator_jumper_size = 7; -#endif - -void -grub_cpu_relocator_init (void) -{ - grub_relocator_forward_size = RELOCATOR_SIZEOF(_forward); - grub_relocator_backward_size = RELOCATOR_SIZEOF(_backward); -} - -void -grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) -{ - grub_uint8_t *ptr; - ptr = rels; -#ifdef __x86_64__ - /* movq imm64, %rax (for relocator) */ - *(grub_uint8_t *) ptr = 0x48; - ptr++; - *(grub_uint8_t *) ptr = 0xb8; - ptr++; - *(grub_uint64_t *) ptr = addr; - ptr += sizeof (grub_uint64_t); -#else - /* movl imm32, %eax (for relocator) */ - *(grub_uint8_t *) ptr = 0xb8; - ptr++; - *(grub_uint32_t *) ptr = addr; - ptr += sizeof (grub_uint32_t); -#endif - /* jmp $eax/$rax */ - *(grub_uint8_t *) ptr = 0xff; - ptr++; - *(grub_uint8_t *) ptr = 0xe0; - ptr++; -} - -void -grub_cpu_relocator_backward (void *ptr, void *src, void *dest, - grub_size_t size) -{ - grub_relocator_backward_dest = dest; - grub_relocator_backward_src = src; - grub_relocator_backward_chunk_size = size; - - grub_memmove (ptr, - &grub_relocator_backward_start, - RELOCATOR_SIZEOF (_backward)); -} - -void -grub_cpu_relocator_forward (void *ptr, void *src, void *dest, - grub_size_t size) -{ - grub_relocator_forward_dest = dest; - grub_relocator_forward_src = src; - grub_relocator_forward_chunk_size = size; - - grub_memmove (ptr, - &grub_relocator_forward_start, - RELOCATOR_SIZEOF (_forward)); -} - grub_err_t grub_relocator32_boot (struct grub_relocator *rel, struct grub_relocator32_state state, @@ -162,11 +80,13 @@ grub_relocator32_boot (struct grub_relocator *rel, void *relst; grub_relocator_chunk_t ch; - err = grub_relocator_alloc_chunk_align (rel, &ch, 0, - (0xffffffff - RELOCATOR_SIZEOF (32)) - + 1, RELOCATOR_SIZEOF (32), 16, - GRUB_RELOCATOR_PREFERENCE_NONE, - avoid_efi_bootservices); + /* Specific memory range due to Global Descriptor Table for use by payload + that we will store in returned chunk. The address range and preference + are based on "THE LINUX/x86 BOOT PROTOCOL" specification. */ + err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x1000, 0x9a000, + RELOCATOR_SIZEOF (32), 16, + GRUB_RELOCATOR_PREFERENCE_LOW, + avoid_efi_bootservices); if (err) return err; @@ -204,17 +124,14 @@ grub_relocator16_boot (struct grub_relocator *rel, grub_relocator_chunk_t ch; /* Put it higher than the byte it checks for A20 check. */ - err = grub_relocator_alloc_chunk_align (rel, &ch, 0x8010, - 0xa0000 - RELOCATOR_SIZEOF (16) - - GRUB_RELOCATOR16_STACK_SIZE, - RELOCATOR_SIZEOF (16) - + GRUB_RELOCATOR16_STACK_SIZE, 16, - GRUB_RELOCATOR_PREFERENCE_NONE, - 0); + err = grub_relocator_alloc_chunk_align_safe (rel, &ch, 0x8010, 0xa0000, + RELOCATOR_SIZEOF (16) + + GRUB_RELOCATOR16_STACK_SIZE, 16, + GRUB_RELOCATOR_PREFERENCE_NONE, 0); if (err) return err; - grub_relocator16_cs = state.cs; + grub_relocator16_cs = state.cs; grub_relocator16_ip = state.ip; grub_relocator16_ds = state.ds; @@ -225,6 +142,7 @@ grub_relocator16_boot (struct grub_relocator *rel, grub_relocator16_ss = state.ss; grub_relocator16_sp = state.sp; + grub_relocator16_ebp = state.ebp; grub_relocator16_ebx = state.ebx; grub_relocator16_edx = state.edx; grub_relocator16_esi = state.esi; @@ -261,11 +179,9 @@ grub_relocator64_boot (struct grub_relocator *rel, void *relst; grub_relocator_chunk_t ch; - err = grub_relocator_alloc_chunk_align (rel, &ch, min_addr, - max_addr - RELOCATOR_SIZEOF (64), - RELOCATOR_SIZEOF (64), 16, - GRUB_RELOCATOR_PREFERENCE_NONE, - 0); + err = grub_relocator_alloc_chunk_align_safe (rel, &ch, min_addr, max_addr, + RELOCATOR_SIZEOF (64), 16, + GRUB_RELOCATOR_PREFERENCE_NONE, 0); if (err) return err; diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S index e79d87551..e9238119b 100644 --- a/grub-core/lib/i386/relocator16.S +++ b/grub-core/lib/i386/relocator16.S @@ -38,15 +38,21 @@ VARIABLE(grub_relocator16_start) #ifdef __APPLE__ LOCAL(cs_base_bytes12_offset) = LOCAL (cs_base_bytes12) - LOCAL (base) LOCAL(cs_base_byte3_offset) = LOCAL (cs_base_byte3) - LOCAL (base) + LOCAL(ds_base_bytes12_offset) = LOCAL (ds_base_bytes12) - LOCAL (base) + LOCAL(ds_base_byte3_offset) = LOCAL (ds_base_byte3) - LOCAL (base) movl %esi, %eax movw %ax, (LOCAL(cs_base_bytes12_offset)) (RSI, 1) + movw %ax, (LOCAL(ds_base_bytes12_offset)) (RSI, 1) shrl $16, %eax movb %al, (LOCAL (cs_base_byte3_offset)) (RSI, 1) + movb %al, (LOCAL (ds_base_byte3_offset)) (RSI, 1) #else movl %esi, %eax movw %ax, (LOCAL (cs_base_bytes12) - LOCAL (base)) (RSI, 1) + movw %ax, (LOCAL (ds_base_bytes12) - LOCAL (base)) (RSI, 1) shrl $16, %eax movb %al, (LOCAL (cs_base_byte3) - LOCAL (base)) (RSI, 1) + movb %al, (LOCAL (ds_base_byte3) - LOCAL (base)) (RSI, 1) #endif RELOAD_GDT @@ -88,15 +94,15 @@ VARIABLE(grub_relocator16_start) LOCAL(segment_offset) = LOCAL (segment) - LOCAL (base) LOCAL(idt_offset) = LOCAL(relocator16_idt) - LOCAL (base) LOCAL(cont2_offset) = LOCAL (cont2) - LOCAL(base) - movw %ax, LOCAL(segment_offset) (%esi, 1) - lidt LOCAL(idt_offset) (%esi, 1) + movw %ax, (LOCAL(segment_offset)) + lidt (LOCAL(idt_offset)) /* jump to a 16 bit segment */ ljmp $PSEUDO_REAL_CSEG, $(LOCAL(cont2_offset)) #else - movw %ax, (LOCAL (segment) - LOCAL (base)) (%esi, 1) + movw %ax, (LOCAL (segment) - LOCAL (base)) - lidt (EXT_C(grub_relocator16_idt) - LOCAL (base)) (%esi, 1) + lidt (EXT_C(grub_relocator16_idt) - LOCAL (base)) /* jump to a 16 bit segment */ ljmp $PSEUDO_REAL_CSEG, $(LOCAL (cont2) - LOCAL(base)) @@ -204,8 +210,9 @@ LOCAL(gate_a20_check_state): ret LOCAL(gate_a20_done): - /* we are in real mode now - * set up the real mode segment registers : DS, SS, ES + /* + * We are in real mode now. Set up the real mode segment registers and + * all the other general purpose registers. cs is updated with ljmp. */ /* movw imm16, %ax. */ .byte 0xb8 @@ -259,6 +266,11 @@ VARIABLE(grub_relocator16_edx) VARIABLE(grub_relocator16_ebx) .long 0 + /* movl imm32, %ebp. */ + .byte 0x66, 0xbd +VARIABLE(grub_relocator16_ebp) + .long 0 + /* Cleared direction flag is of no problem with any current payload and makes this implementation easier. */ cld @@ -293,7 +305,7 @@ LOCAL(gdt): .byte 0, 0x92, 0xCF, 0 /* -- 16 bit real mode CS -- - * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present + * base = filled by code, limit 0x0FFFF (1 B Granularity), present * type = 16 bit code execute/read only/conforming, DPL = 0 */ .word 0xFFFF @@ -305,11 +317,17 @@ LOCAL(cs_base_byte3): .byte 0x9E, 0, 0 /* -- 16 bit real mode DS -- - * base = 0x00000000, limit 0x0FFFF (1 B Granularity), present + * base = filled by code, limit 0x0FFFF (1 B Granularity), present * type = 16 bit data read/write, DPL = 0 */ - .word 0xFFFF, 0 - .byte 0, 0x92, 0, 0 + .word 0xFFFF +LOCAL(ds_base_bytes12): + .word 0 +LOCAL(ds_base_byte3): + .byte 0 + + .byte 0x92, 0, 0 + LOCAL(gdt_end): #ifdef __APPLE__ diff --git a/grub-core/lib/i386/relocator64.S b/grub-core/lib/i386/relocator64.S index e4648d818..c80538e7e 100644 --- a/grub-core/lib/i386/relocator64.S +++ b/grub-core/lib/i386/relocator64.S @@ -63,7 +63,9 @@ VARIABLE(grub_relocator64_cr3) movq %rax, %cr3 #endif +#ifdef __x86_64__ .code64 +#endif /* mov imm64, %rax */ .byte 0x48 @@ -71,16 +73,54 @@ VARIABLE(grub_relocator64_cr3) VARIABLE(grub_relocator64_rsp) .quad 0 +#ifdef __x86_64__ movq %rax, %rsp +#else + /* movq %rax, %rsp */ + .byte 0x48 + .byte 0x89 + .byte 0xc4 +#endif +#ifdef GRUB_MACHINE_EFI + jmp LOCAL(skip_efi_stack_align) + + /* + * Here is grub_relocator64_efi_start() entry point. Most of the + * code below is shared between grub_relocator64_efi_start() + * and grub_relocator64_start(). + * + * Think twice before changing anything there!!! + */ +VARIABLE(grub_relocator64_efi_start) + /* Align the stack as UEFI spec requires. */ +#ifdef __x86_64__ + andq $~15, %rsp +#else + /* andq $~15, %rsp */ + .byte 0x48 + .byte 0x83 + .byte 0xe4 + .byte 0xf0 +#endif + +LOCAL(skip_efi_stack_align): +#endif /* mov imm64, %rax */ .byte 0x48 .byte 0xb8 VARIABLE(grub_relocator64_rsi) .quad 0 +#ifdef __x86_64__ movq %rax, %rsi - +#else + /* movq %rax, %rsi */ + .byte 0x48 + .byte 0x89 + .byte 0xc6 +#endif + /* mov imm64, %rax */ .byte 0x48 .byte 0xb8 @@ -109,9 +149,9 @@ VARIABLE(grub_relocator64_rdx) payload and makes this implementation easier. */ cld -#ifdef __APPLE__ +#if defined (__APPLE__) || !defined (__x86_64__) .byte 0xff, 0x25 - .quad 0 + .long 0 #else jmp *LOCAL(jump_addr) (%rip) #endif @@ -120,6 +160,11 @@ LOCAL(jump_addr): VARIABLE(grub_relocator64_rip) .quad 0 +#ifdef GRUB_MACHINE_EFI + /* Here grub_relocator64_efi_start() ends. Ufff... */ +VARIABLE(grub_relocator64_efi_end) +#endif + #ifndef __x86_64__ .p2align 4 LOCAL(gdt): diff --git a/grub-core/lib/i386/relocator_common.S b/grub-core/lib/i386/relocator_common.S index b9d99e10e..1b5210dd3 100644 --- a/grub-core/lib/i386/relocator_common.S +++ b/grub-core/lib/i386/relocator_common.S @@ -29,8 +29,6 @@ #endif .macro DISABLE_PAGING -#ifdef GRUB_MACHINE_IEEE1275 -#endif movl %cr0, %eax andl $(~GRUB_MEMORY_CPU_CR0_PAGING_ON), %eax @@ -42,7 +40,9 @@ LOCAL(base): /* %rax contains now our new 'base'. */ mov RAX, RSI -#ifdef __APPLE__ +#if defined (__APPLE__) && defined (__x86_64__) + leaq LOCAL(cont0) (%rip), RAX +#elif defined (__APPLE__) LOCAL(cont0_offset) = LOCAL(cont0) - LOCAL(base) add $LOCAL(cont0_offset), RAX #else diff --git a/grub-core/lib/i386/relocator_common_c.c b/grub-core/lib/i386/relocator_common_c.c new file mode 100644 index 000000000..7be609b73 --- /dev/null +++ b/grub-core/lib/i386/relocator_common_c.c @@ -0,0 +1,109 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009-2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +#include +#include +#include + +#include +#include + +extern grub_uint8_t grub_relocator_forward_start; +extern grub_uint8_t grub_relocator_forward_end; +extern grub_uint8_t grub_relocator_backward_start; +extern grub_uint8_t grub_relocator_backward_end; + +extern void *grub_relocator_backward_dest; +extern void *grub_relocator_backward_src; +extern grub_size_t grub_relocator_backward_chunk_size; + +extern void *grub_relocator_forward_dest; +extern void *grub_relocator_forward_src; +extern grub_size_t grub_relocator_forward_chunk_size; + +#define RELOCATOR_SIZEOF(x) (&grub_relocator##x##_end - &grub_relocator##x##_start) + +grub_size_t grub_relocator_align = 1; +grub_size_t grub_relocator_forward_size; +grub_size_t grub_relocator_backward_size; +#ifdef __x86_64__ +grub_size_t grub_relocator_jumper_size = 12; +#else +grub_size_t grub_relocator_jumper_size = 7; +#endif + +void +grub_cpu_relocator_init (void) +{ + grub_relocator_forward_size = RELOCATOR_SIZEOF (_forward); + grub_relocator_backward_size = RELOCATOR_SIZEOF (_backward); +} + +void +grub_cpu_relocator_jumper (void *rels, grub_addr_t addr) +{ + grub_uint8_t *ptr; + ptr = rels; +#ifdef __x86_64__ + /* movq imm64, %rax (for relocator) */ + *(grub_uint8_t *) ptr = 0x48; + ptr++; + *(grub_uint8_t *) ptr = 0xb8; + ptr++; + *(grub_uint64_t *) ptr = addr; + ptr += sizeof (grub_uint64_t); +#else + /* movl imm32, %eax (for relocator) */ + *(grub_uint8_t *) ptr = 0xb8; + ptr++; + *(grub_uint32_t *) ptr = addr; + ptr += sizeof (grub_uint32_t); +#endif + /* jmp $eax/$rax */ + *(grub_uint8_t *) ptr = 0xff; + ptr++; + *(grub_uint8_t *) ptr = 0xe0; + ptr++; +} + +void +grub_cpu_relocator_backward (void *ptr, void *src, void *dest, + grub_size_t size) +{ + grub_relocator_backward_dest = dest; + grub_relocator_backward_src = src; + grub_relocator_backward_chunk_size = size; + + grub_memmove (ptr, + &grub_relocator_backward_start, RELOCATOR_SIZEOF (_backward)); +} + +void +grub_cpu_relocator_forward (void *ptr, void *src, void *dest, + grub_size_t size) +{ + grub_relocator_forward_dest = dest; + grub_relocator_forward_src = src; + grub_relocator_forward_chunk_size = size; + + grub_memmove (ptr, + &grub_relocator_forward_start, RELOCATOR_SIZEOF (_forward)); +} diff --git a/grub-core/lib/i386/xen/relocator.S b/grub-core/lib/i386/xen/relocator.S new file mode 100644 index 000000000..dab4d8ace --- /dev/null +++ b/grub-core/lib/i386/xen/relocator.S @@ -0,0 +1,165 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2013 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include + + .p2align 4 /* force 16-byte alignment */ + +VARIABLE(grub_relocator_xen_remap_start) +LOCAL(base): + /* Remap the remapper to it's new address. */ + /* mov imm32, %ebx - %ebx: new virtual address of remapper */ + .byte 0xbb +VARIABLE(grub_relocator_xen_remapper_virt) + .long 0 + + /* mov imm32, %ecx - %ecx: low part of page table entry */ + .byte 0xb9 +VARIABLE(grub_relocator_xen_remapper_map) + .long 0 + + /* mov imm32, %edx - %edx: high part of page table entry */ + .byte 0xba +VARIABLE(grub_relocator_xen_remapper_map_high) + .long 0 + + movl %ebx, %ebp /* %ebx is clobbered by hypercall */ + + movl $UVMF_INVLPG, %esi /* esi: flags (inv. single entry) */ + movl $__HYPERVISOR_update_va_mapping, %eax + int $0x82 + + movl %ebp, %ebx + addl $(LOCAL(cont) - LOCAL(base)), %ebx + + jmp *%ebx /* Continue with new virtual address */ + +LOCAL(cont): + /* Modify mappings of new page tables to be read-only. */ + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_paging_areas_addr) + .long 0 + movl %eax, %ebx +1: + movl 0(%ebx), %ebp /* Get start pfn of the current area */ + movl GRUB_TARGET_SIZEOF_LONG(%ebx), %ecx /* Get # of pg tables */ + testl %ecx, %ecx /* 0 -> last area reached */ + jz 3f + addl $(2 * GRUB_TARGET_SIZEOF_LONG), %ebx + movl %ebx, %esp /* Save current area pointer */ + +2: + movl %ecx, %edi + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_mfn_list) + .long 0 + movl 0(%eax, %ebp, 4), %ecx /* mfn */ + movl %ebp, %ebx + shll $GRUB_PAGE_SHIFT, %ebx /* virtual address (1:1 mapping) */ + movl %ecx, %edx + shll $GRUB_PAGE_SHIFT, %ecx /* prepare pte low part */ + shrl $(32 - GRUB_PAGE_SHIFT), %edx /* pte high part */ + orl $(GRUB_PAGE_PRESENT | GRUB_PAGE_USER), %ecx /* pte low */ + movl $UVMF_INVLPG, %esi + movl $__HYPERVISOR_update_va_mapping, %eax + int $0x82 /* parameters: eax, ebx, ecx, edx, esi */ + + incl %ebp /* next pfn */ + movl %edi, %ecx + + loop 2b + + mov %esp, %ebx /* restore area poniter */ + jmp 1b + +3: + /* Switch page tables: pin new L3 pt, load cr3, unpin old L3. */ + /* mov imm32, %ebx */ + .byte 0xbb +VARIABLE(grub_relocator_xen_mmu_op_addr) + .long 0 + movl $3, %ecx /* 3 mmu ops */ + movl $0, %edx /* pdone (not used) */ + movl $DOMID_SELF, %esi + movl $__HYPERVISOR_mmuext_op, %eax + int $0x82 + + /* Continue in virtual kernel mapping. */ + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_remap_continue) + .long 0 + + jmp *%eax + +VARIABLE(grub_relocator_xen_paging_areas) + .long 0, 0, 0, 0, 0, 0, 0, 0 + +VARIABLE(grub_relocator_xen_mmu_op) + .space 256 + +VARIABLE(grub_relocator_xen_remap_end) + + +VARIABLE(grub_relocator_xen_start) + /* Unmap old remapper area. */ + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_remapper_virt2) + .long 0 + + movl %eax, %ebx + + xorl %ecx, %ecx /* Invalid pte */ + xorl %edx, %edx + + movl $UVMF_INVLPG, %esi + movl $__HYPERVISOR_update_va_mapping, %eax + int $0x82 + + /* Prepare registers for starting kernel. */ + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_stack) + .long 0 + + movl %eax, %esp + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_start_info) + .long 0 + + movl %eax, %esi + + cld + + /* mov imm32, %eax */ + .byte 0xb8 +VARIABLE(grub_relocator_xen_entry_point) + .long 0 + + /* Now start the new kernel. */ + jmp *%eax + +VARIABLE(grub_relocator_xen_end) diff --git a/grub-core/lib/ia64/longjmp.S b/grub-core/lib/ia64/longjmp.S index 729bdc76e..38afb2243 100644 --- a/grub-core/lib/ia64/longjmp.S +++ b/grub-core/lib/ia64/longjmp.S @@ -40,10 +40,10 @@ /* __longjmp(__jmp_buf buf, int val) */ - .text - .global longjmp - .proc longjmp -longjmp: + .text + + .proc EXT_C(grub_longjmp) +FUNCTION(grub_longjmp) alloc r8=ar.pfs,2,1,0,0 mov r27=ar.rsc add r2=0x98,in0 // r2 <- &jmpbuf.orig_jmp_buf_addr @@ -159,4 +159,4 @@ longjmp: invala // virt. -> phys. regnum mapping may change mov pr=r24,-1 br.ret.dptk.few rp - .endp longjmp + .endp EXT_C(grub_longjmp) diff --git a/grub-core/lib/ia64/setjmp.S b/grub-core/lib/ia64/setjmp.S index dc19be0ce..a0382d83d 100644 --- a/grub-core/lib/ia64/setjmp.S +++ b/grub-core/lib/ia64/setjmp.S @@ -74,13 +74,13 @@ GRUB_MOD_LICENSE "GPLv2+" /* The following two entry points are the traditional entry points: */ .text - .global setjmp - .proc setjmp -setjmp: + + .proc EXT_C(grub_setjmp) +FUNCTION(grub_setjmp) alloc r8=ar.pfs,2,0,0,0 mov in1=1 br.cond.sptk.many __sigsetjmp - .endp setjmp + .endp EXT_C(grub_setjmp) /* __sigsetjmp(__jmp_buf buf, int savemask) */ diff --git a/grub-core/lib/ieee1275/cmos.c b/grub-core/lib/ieee1275/cmos.c index fa57db9e7..1400cfb67 100644 --- a/grub-core/lib/ieee1275/cmos.c +++ b/grub-core/lib/ieee1275/cmos.c @@ -23,53 +23,55 @@ #include volatile grub_uint8_t *grub_cmos_port = 0; + +/* Helper for grub_cmos_find_port. */ +static int +grub_cmos_find_port_iter (struct grub_ieee1275_devalias *alias) +{ + grub_ieee1275_phandle_t dev; + grub_uint32_t addr[2]; + grub_ssize_t actual; + /* Enough to check if it's "m5819" */ + char compat[100]; + if (grub_ieee1275_finddevice (alias->path, &dev)) + return 0; + if (grub_ieee1275_get_property (dev, "compatible", compat, sizeof (compat), + 0)) + return 0; + if (grub_strcmp (compat, "m5819") != 0) + return 0; + if (grub_ieee1275_get_integer_property (dev, "address", + addr, sizeof (addr), &actual)) + return 0; + if (actual == 4) + { + grub_cmos_port = (volatile grub_uint8_t *) (grub_addr_t) addr[0]; + return 1; + } + +#if GRUB_CPU_SIZEOF_VOID_P == 8 + if (actual == 8) + { + grub_cmos_port = (volatile grub_uint8_t *) + ((((grub_addr_t) addr[0]) << 32) | addr[1]); + return 1; + } +#else + if (actual == 8 && addr[0] == 0) + { + grub_cmos_port = (volatile grub_uint8_t *) addr[1]; + return 1; + } +#endif + return 0; +} + grub_err_t grub_cmos_find_port (void) { - auto int hook (struct grub_ieee1275_devalias *alias); - int hook (struct grub_ieee1275_devalias *alias) - { - grub_ieee1275_phandle_t dev; - grub_uint32_t addr[2]; - grub_ssize_t actual; - /* Enough to check if it's "m5819" */ - char compat[100]; - if (grub_ieee1275_finddevice (alias->path, &dev)) - return 0; - if (grub_ieee1275_get_property (dev, "compatible", compat, sizeof (compat), - 0)) - return 0; - if (grub_strcmp (compat, "m5819") != 0) - return 0; - if (grub_ieee1275_get_integer_property (dev, "address", - addr, sizeof (addr), &actual)) - return 0; - if (actual == 4) - { - grub_cmos_port = (volatile grub_uint8_t *) (grub_addr_t) addr[0]; - return 1; - } - -#if GRUB_CPU_SIZEOF_VOID_P == 8 - if (actual == 8) - { - grub_cmos_port = (volatile grub_uint8_t *) - ((((grub_addr_t) addr[0]) << 32) | addr[1]); - return 1; - } -#else - if (actual == 8 && addr[0] == 0) - { - grub_cmos_port = (volatile grub_uint8_t *) addr[1]; - return 1; - } -#endif - return 0; - } - - grub_ieee1275_devices_iterate (hook); + grub_ieee1275_devices_iterate (grub_cmos_find_port_iter); if (!grub_cmos_port) return grub_error (GRUB_ERR_IO, "no cmos found"); - + return GRUB_ERR_NONE; } diff --git a/grub-core/lib/ieee1275/datetime.c b/grub-core/lib/ieee1275/datetime.c index 1947135fe..74578f15a 100644 --- a/grub-core/lib/ieee1275/datetime.c +++ b/grub-core/lib/ieee1275/datetime.c @@ -30,22 +30,23 @@ GRUB_MOD_LICENSE ("GPLv3+"); static char *rtc = 0; static int no_ieee1275_rtc = 0; +/* Helper for find_rtc. */ +static int +find_rtc_iter (struct grub_ieee1275_devalias *alias) +{ + if (grub_strcmp (alias->type, "rtc") == 0) + { + grub_dprintf ("datetime", "Found RTC %s\n", alias->path); + rtc = grub_strdup (alias->path); + return 1; + } + return 0; +} + static void find_rtc (void) { - auto int hook (struct grub_ieee1275_devalias *alias); - int hook (struct grub_ieee1275_devalias *alias) - { - if (grub_strcmp (alias->type, "rtc") == 0) - { - grub_dprintf ("datetime", "Found RTC %s\n", alias->path); - rtc = grub_strdup (alias->path); - return 1; - } - return 0; - } - - grub_ieee1275_devices_iterate (hook); + grub_ieee1275_devices_iterate (find_rtc_iter); if (!rtc) no_ieee1275_rtc = 1; } @@ -89,7 +90,7 @@ grub_get_datetime (struct grub_datetime *datetime) grub_ieee1275_close (ihandle); - if (status == -1) + if (status == -1 || args.catch_result) return grub_error (GRUB_ERR_IO, "get-time failed"); datetime->year = args.year; @@ -148,7 +149,7 @@ grub_set_datetime (struct grub_datetime *datetime) grub_ieee1275_close (ihandle); - if (status == -1) + if (status == -1 || args.catch_result) return grub_error (GRUB_ERR_IO, "set-time failed"); return GRUB_ERR_NONE; diff --git a/grub-core/lib/ieee1275/halt.c b/grub-core/lib/ieee1275/halt.c index 7ede29de9..8fc16d243 100644 --- a/grub-core/lib/ieee1275/halt.c +++ b/grub-core/lib/ieee1275/halt.c @@ -25,8 +25,8 @@ grub_halt (void) { /* Not standardized. We try three known commands. */ - grub_ieee1275_interpret ("shut-down", 0); grub_ieee1275_interpret ("power-off", 0); + grub_ieee1275_interpret ("shut-down", 0); grub_ieee1275_interpret ("poweroff", 0); while (1); diff --git a/grub-core/lib/ieee1275/relocator.c b/grub-core/lib/ieee1275/relocator.c index 021f0ce71..918392f1e 100644 --- a/grub-core/lib/ieee1275/relocator.c +++ b/grub-core/lib/ieee1275/relocator.c @@ -21,65 +21,77 @@ #include #include -unsigned +/* Helper for grub_relocator_firmware_get_max_events. */ +static int +count (grub_uint64_t addr __attribute__ ((unused)), + grub_uint64_t len __attribute__ ((unused)), + grub_memory_type_t type __attribute__ ((unused)), void *data) +{ + int *counter = data; + + (*counter)++; + return 0; +} + +unsigned grub_relocator_firmware_get_max_events (void) { int counter = 0; - auto int NESTED_FUNC_ATTR count (grub_uint64_t addr __attribute__ ((unused)), - grub_uint64_t len __attribute__ ((unused)), - grub_memory_type_t type __attribute__ ((unused))); - int NESTED_FUNC_ATTR count (grub_uint64_t addr __attribute__ ((unused)), - grub_uint64_t len __attribute__ ((unused)), - grub_memory_type_t type __attribute__ ((unused))) - { - counter++; - return 0; - } - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET)) - return 0; - grub_machine_mmap_iterate (count); + grub_machine_mmap_iterate (count, &counter); return 2 * counter; } -unsigned +/* Context for grub_relocator_firmware_fill_events. */ +struct grub_relocator_firmware_fill_events_ctx +{ + struct grub_relocator_mmap_event *events; + int counter; +}; + +/* Helper for grub_relocator_firmware_fill_events. */ +static int +grub_relocator_firmware_fill_events_iter (grub_uint64_t addr, + grub_uint64_t len, + grub_memory_type_t type, void *data) +{ + struct grub_relocator_firmware_fill_events_ctx *ctx = data; + + if (type != GRUB_MEMORY_AVAILABLE) + return 0; + + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) + { + if (addr + len <= 0x180000) + return 0; + + if (addr < 0x180000) + { + len = addr + len - 0x180000; + addr = 0x180000; + } + } + + ctx->events[ctx->counter].type = REG_FIRMWARE_START; + ctx->events[ctx->counter].pos = addr; + ctx->counter++; + ctx->events[ctx->counter].type = REG_FIRMWARE_END; + ctx->events[ctx->counter].pos = addr + len; + ctx->counter++; + + return 0; +} + +unsigned grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) { - int counter = 0; - auto int NESTED_FUNC_ATTR fill (grub_uint64_t addr, grub_uint64_t len, - grub_memory_type_t type); - int NESTED_FUNC_ATTR fill (grub_uint64_t addr, grub_uint64_t len, - grub_memory_type_t type) - { - if (type != GRUB_MEMORY_AVAILABLE) - return 0; + struct grub_relocator_firmware_fill_events_ctx ctx = { + .events = events, + .counter = 0 + }; - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) - { - if (addr + len <= 0x180000) - return 0; - - if (addr < 0x180000) - { - len = addr + len - 0x180000; - addr = 0x180000; - } - } - - events[counter].type = REG_FIRMWARE_START; - events[counter].pos = addr; - counter++; - events[counter].type = REG_FIRMWARE_END; - events[counter].pos = addr + len; - counter++; - - return 0; - } - - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_INTERPRET)) - return 0; - grub_machine_mmap_iterate (fill); - return counter; + grub_machine_mmap_iterate (grub_relocator_firmware_fill_events_iter, &ctx); + return ctx.counter; } int diff --git a/grub-core/lib/ieee1275/tcg2.c b/grub-core/lib/ieee1275/tcg2.c new file mode 100644 index 000000000..40161c2f9 --- /dev/null +++ b/grub-core/lib/ieee1275/tcg2.c @@ -0,0 +1,157 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2024 IBM Corporation + * Copyright (C) 2024 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +#include + +grub_ieee1275_ihandle_t grub_ieee1275_tpm_ihandle = GRUB_IEEE1275_IHANDLE_INVALID; + +grub_err_t +grub_ieee1275_tpm_init (void) +{ + static bool init_tried = false; + grub_ieee1275_phandle_t vtpm; + char buffer[20]; + + if (init_tried == false) + { + init_tried = true; + + if (grub_ieee1275_open ("/vdevice/vtpm", &grub_ieee1275_tpm_ihandle) < 0 || + grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) || + grub_ieee1275_get_property (vtpm, "compatible", buffer, sizeof (buffer), NULL) || + grub_strcmp (buffer, "IBM,vtpm20")) + { + if (grub_ieee1275_tpm_ihandle != GRUB_IEEE1275_IHANDLE_INVALID) + grub_ieee1275_close (grub_ieee1275_tpm_ihandle); + + grub_ieee1275_tpm_ihandle = GRUB_IEEE1275_IHANDLE_INVALID; + } + } + + if (grub_ieee1275_tpm_ihandle == GRUB_IEEE1275_IHANDLE_INVALID) + return GRUB_ERR_UNKNOWN_DEVICE; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_tcg2_get_max_output_size (grub_size_t *size) +{ + struct tpm_get_maximum_cmd_size + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t catch_result; + grub_ieee1275_cell_t size; + }; + struct tpm_get_maximum_cmd_size args; + static bool error_displayed = false; + grub_err_t err; + + err = grub_ieee1275_tpm_init (); + if (err != GRUB_ERR_NONE) + return err; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 2, 2); + args.method = (grub_ieee1275_cell_t) "get-maximum-cmd-size"; + args.ihandle = grub_ieee1275_tpm_ihandle; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return GRUB_ERR_INVALID_COMMAND; + + /* + * args.catch_result is set if firmware does not support get-maximum-cmd-size. + * rc is GRUB_IEEE1275_CELL_FALSE (0) on failure. + */ + if (args.catch_result) + { + if (error_displayed == false) + { + error_displayed = true; + return grub_error (GRUB_ERR_BAD_DEVICE, + "get-maximum-cmd-size failed: Firmware is likely too old"); + } + return GRUB_ERR_INVALID_COMMAND; + } + + *size = args.size; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_tcg2_submit_command (grub_size_t input_size, + grub_uint8_t *input, + grub_size_t output_size, + grub_uint8_t *output) +{ + struct tpm_pass_through_to_tpm + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t method; + grub_ieee1275_cell_t ihandle; + grub_ieee1275_cell_t buf_size; + grub_ieee1275_cell_t buf_addr; + grub_ieee1275_cell_t catch_result; + grub_ieee1275_cell_t resp_size; + }; + struct tpm_pass_through_to_tpm args; + static bool error_displayed = false; + grub_err_t err; + + if (input_size == 0 || input == NULL || + output_size == 0 || output == NULL) + return GRUB_ERR_BAD_ARGUMENT; + + err = grub_ieee1275_tpm_init (); + if (err != GRUB_ERR_NONE) + return err; + + INIT_IEEE1275_COMMON (&args.common, "call-method", 4, 2); + args.method = (grub_ieee1275_cell_t) "pass-through-to-tpm"; + args.ihandle = grub_ieee1275_tpm_ihandle; + args.buf_size = (grub_ieee1275_cell_t) input_size; + args.buf_addr = (grub_ieee1275_cell_t) input; + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return GRUB_ERR_INVALID_COMMAND; + + /* args.catch_result is set if firmware does not support pass-through-to-tpm. */ + if (args.catch_result) + { + if (error_displayed == false) + { + error_displayed = true; + return grub_error (GRUB_ERR_BAD_DEVICE, + "pass-through-to-tpm failed: Firmware is likely too old"); + } + return GRUB_ERR_INVALID_COMMAND; + } + + grub_memcpy (output, input, args.resp_size); + + return GRUB_ERR_NONE; +} diff --git a/grub-core/lib/json/jsmn.h b/grub-core/lib/json/jsmn.h new file mode 100644 index 000000000..3178dcc97 --- /dev/null +++ b/grub-core/lib/json/jsmn.h @@ -0,0 +1,471 @@ +/* + * MIT License + * + * Copyright (c) 2010 Serge Zaitsev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef JSMN_H +#define JSMN_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef JSMN_STATIC +#define JSMN_API static +#else +#define JSMN_API extern +#endif + +/** + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ +typedef enum { + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1, + JSMN_ARRAY = 2, + JSMN_STRING = 3, + JSMN_PRIMITIVE = 4 +} jsmntype_t; + +enum jsmnerr { + /* Not enough tokens were provided */ + JSMN_ERROR_NOMEM = -1, + /* Invalid character inside JSON string */ + JSMN_ERROR_INVAL = -2, + /* The string is not a full JSON packet, more bytes expected */ + JSMN_ERROR_PART = -3 +}; + +/** + * JSON token description. + * type type (object, array, string etc.) + * start start position in JSON data string + * end end position in JSON data string + */ +typedef struct jsmntok { + jsmntype_t type; + int start; + int end; + int size; +#ifdef JSMN_PARENT_LINKS + int parent; +#endif +} jsmntok_t; + +/** + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string. + */ +typedef struct jsmn_parser { + unsigned int pos; /* offset in the JSON string */ + unsigned int toknext; /* next token to allocate */ + int toksuper; /* superior token node, e.g. parent object or array */ +} jsmn_parser; + +/** + * Create JSON parser over an array of tokens + */ +JSMN_API void jsmn_init(jsmn_parser *parser); + +/** + * Run JSON parser. It parses a JSON data string into and array of tokens, each + * describing + * a single JSON object. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens); + +#ifndef JSMN_HEADER +/** + * Allocates a fresh unused token from the token pool. + */ +static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *tok; + if (parser->toknext >= num_tokens) { + return NULL; + } + tok = &tokens[parser->toknext++]; + tok->start = tok->end = -1; + tok->size = 0; +#ifdef JSMN_PARENT_LINKS + tok->parent = -1; +#endif + return tok; +} + +/** + * Fills token type and boundaries. + */ +static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, + const int start, const int end) { + token->type = type; + token->start = start; + token->end = end; + token->size = 0; +} + +/** + * Fills next available token with JSON primitive. + */ +static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + int start; + + start = parser->pos; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + switch (js[parser->pos]) { +#ifndef JSMN_STRICT + /* In strict mode primitive must be followed by "," or "}" or "]" */ + case ':': +#endif + case '\t': + case '\r': + case '\n': + case ' ': + case ',': + case ']': + case '}': + goto found; + default: + /* to quiet a warning from gcc*/ + break; + } + if (js[parser->pos] < 32 || js[parser->pos] >= 127) { + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } +#ifdef JSMN_STRICT + /* In strict mode primitive must be followed by a comma/object/array */ + parser->pos = start; + return JSMN_ERROR_PART; +#endif + +found: + if (tokens == NULL) { + parser->pos--; + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + parser->pos--; + return 0; +} + +/** + * Fills next token with JSON string. + */ +static int jsmn_parse_string(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + + int start = parser->pos; + + parser->pos++; + + /* Skip starting quote */ + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c = js[parser->pos]; + + /* Quote: end of string */ + if (c == '\"') { + if (tokens == NULL) { + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + return 0; + } + + /* Backslash: Quoted symbol expected */ + if (c == '\\' && parser->pos + 1 < len) { + int i; + parser->pos++; + switch (js[parser->pos]) { + /* Allowed escaped symbols */ + case '\"': + case '/': + case '\\': + case 'b': + case 'f': + case 'r': + case 'n': + case 't': + break; + /* Allows escaped symbol \uXXXX */ + case 'u': + parser->pos++; + for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; + i++) { + /* If it isn't a hex character we have an error */ + if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ + (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ + (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ + parser->pos = start; + return JSMN_ERROR_INVAL; + } + parser->pos++; + } + parser->pos--; + break; + /* Unexpected symbol */ + default: + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } + } + parser->pos = start; + return JSMN_ERROR_PART; +} + +/** + * Parse JSON string and fill tokens. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens) { + int r; + int i; + jsmntok_t *token; + int count = parser->toknext; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c; + jsmntype_t type; + + c = js[parser->pos]; + switch (c) { + case '{': + case '[': + count++; + if (tokens == NULL) { + break; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + return JSMN_ERROR_NOMEM; + } + if (parser->toksuper != -1) { + jsmntok_t *t = &tokens[parser->toksuper]; +#ifdef JSMN_STRICT + /* In strict mode an object or array can't become a key */ + if (t->type == JSMN_OBJECT) { + return JSMN_ERROR_INVAL; + } +#endif + t->size++; +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + } + token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); + token->start = parser->pos; + parser->toksuper = parser->toknext - 1; + break; + case '}': + case ']': + if (tokens == NULL) { + break; + } + type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); +#ifdef JSMN_PARENT_LINKS + if (parser->toknext < 1) { + return JSMN_ERROR_INVAL; + } + token = &tokens[parser->toknext - 1]; + for (;;) { + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + token->end = parser->pos + 1; + parser->toksuper = token->parent; + break; + } + if (token->parent == -1) { + if (token->type != type || parser->toksuper == -1) { + return JSMN_ERROR_INVAL; + } + break; + } + token = &tokens[token->parent]; + } +#else + for (i = parser->toknext - 1; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + parser->toksuper = -1; + token->end = parser->pos + 1; + break; + } + } + /* Error if unmatched closing bracket */ + if (i == -1) { + return JSMN_ERROR_INVAL; + } + for (; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + parser->toksuper = i; + break; + } + } +#endif + break; + case '\"': + r = jsmn_parse_string(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + case '\t': + case '\r': + case '\n': + case ' ': + break; + case ':': + parser->toksuper = parser->toknext - 1; + break; + case ',': + if (tokens != NULL && parser->toksuper != -1 && + tokens[parser->toksuper].type != JSMN_ARRAY && + tokens[parser->toksuper].type != JSMN_OBJECT) { +#ifdef JSMN_PARENT_LINKS + parser->toksuper = tokens[parser->toksuper].parent; +#else + for (i = parser->toknext - 1; i >= 0; i--) { + if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { + if (tokens[i].start != -1 && tokens[i].end == -1) { + parser->toksuper = i; + break; + } + } + } +#endif + } + break; +#ifdef JSMN_STRICT + /* In strict mode primitives are: numbers and booleans */ + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 't': + case 'f': + case 'n': + /* And they must not be keys of the object */ + if (tokens != NULL && parser->toksuper != -1) { + const jsmntok_t *t = &tokens[parser->toksuper]; + if (t->type == JSMN_OBJECT || + (t->type == JSMN_STRING && t->size != 0)) { + return JSMN_ERROR_INVAL; + } + } +#else + /* In non-strict mode every unquoted value is a primitive */ + default: +#endif + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + +#ifdef JSMN_STRICT + /* Unexpected char in strict mode */ + default: + return JSMN_ERROR_INVAL; +#endif + } + } + + if (tokens != NULL) { + for (i = parser->toknext - 1; i >= 0; i--) { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) { + return JSMN_ERROR_PART; + } + } + } + + return count; +} + +/** + * Creates a new parser based over a given buffer with an array of tokens + * available. + */ +JSMN_API void jsmn_init(jsmn_parser *parser) { + parser->pos = 0; + parser->toknext = 0; + parser->toksuper = -1; +} + +#endif /* JSMN_HEADER */ + +#ifdef __cplusplus +} +#endif + +#endif /* JSMN_H */ diff --git a/grub-core/lib/json/json.c b/grub-core/lib/json/json.c new file mode 100644 index 000000000..1eadd1ce9 --- /dev/null +++ b/grub-core/lib/json/json.c @@ -0,0 +1,382 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2019 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#include +#include + +#define JSMN_STATIC +#include "jsmn.h" +#include "json.h" + +GRUB_MOD_LICENSE ("GPLv3"); + +grub_err_t +grub_json_parse (grub_json_t **out, char *string, grub_size_t string_len) +{ + grub_json_t *json = NULL; + jsmn_parser parser; + grub_err_t ret = GRUB_ERR_NONE; + int jsmn_ret; + + if (!string) + return GRUB_ERR_BAD_ARGUMENT; + + json = grub_zalloc (sizeof (*json)); + if (!json) + return GRUB_ERR_OUT_OF_MEMORY; + json->string = string; + + /* + * Parse the string twice: first to determine how many tokens + * we need to allocate, second to fill allocated tokens. + */ + jsmn_init (&parser); + jsmn_ret = jsmn_parse (&parser, string, string_len, NULL, 0); + if (jsmn_ret <= 0) + { + ret = GRUB_ERR_BAD_ARGUMENT; + goto err; + } + + json->tokens = grub_calloc (jsmn_ret, sizeof (jsmntok_t)); + if (!json->tokens) + { + ret = GRUB_ERR_OUT_OF_MEMORY; + goto err; + } + + jsmn_init (&parser); + jsmn_ret = jsmn_parse (&parser, string, string_len, json->tokens, jsmn_ret); + if (jsmn_ret <= 0) + { + ret = GRUB_ERR_BAD_ARGUMENT; + goto err; + } + + *out = json; + + err: + if (ret) + grub_json_free (json); + + return ret; +} + +void +grub_json_free (grub_json_t *json) +{ + if (json) + { + grub_free (json->tokens); + grub_free (json); + } +} + +grub_err_t +grub_json_getsize (grub_size_t *out, const grub_json_t *json) +{ + int size; + + size = json->tokens[json->idx].size; + if (size < 0) + return GRUB_ERR_OUT_OF_RANGE; + + *out = (grub_size_t) size; + return GRUB_ERR_NONE; +} + +grub_err_t +grub_json_gettype (grub_json_type_t *out, const grub_json_t *json) +{ + switch (json->tokens[json->idx].type) + { + case JSMN_OBJECT: + *out = GRUB_JSON_OBJECT; + break; + case JSMN_ARRAY: + *out = GRUB_JSON_ARRAY; + break; + case JSMN_STRING: + *out = GRUB_JSON_STRING; + break; + case JSMN_PRIMITIVE: + *out = GRUB_JSON_PRIMITIVE; + break; + default: + return GRUB_ERR_BAD_ARGUMENT; + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_json_getchild (grub_json_t *out, const grub_json_t *parent, grub_size_t n) +{ + grub_size_t offset = 1, size; + jsmntok_t *p; + + if (grub_json_getsize (&size, parent) || n >= size) + return GRUB_ERR_OUT_OF_RANGE; + + /* + * Skip the first n children. For each of the children, we need + * to skip their own potential children (e.g. if it's an + * array), as well. We thus add the children's size to n on + * each iteration. + */ + p = &parent->tokens[parent->idx]; + while (n--) + n += p[offset++].size; + + out->string = parent->string; + out->tokens = parent->tokens; + out->idx = parent->idx + offset; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_json_getvalue (grub_json_t *out, const grub_json_t *parent, const char *key) +{ + grub_json_type_t type; + grub_size_t i, size; + + if (grub_json_gettype (&type, parent) || type != GRUB_JSON_OBJECT) + return GRUB_ERR_BAD_ARGUMENT; + + if (grub_json_getsize (&size, parent)) + return GRUB_ERR_BAD_ARGUMENT; + + for (i = 0; i < size; i++) + { + grub_json_t child; + const char *s; + + if (grub_json_getchild (&child, parent, i) || + grub_json_getstring (&s, &child, NULL) || + grub_strcmp (s, key) != 0) + continue; + + return grub_json_getchild (out, &child, 0); + } + + return GRUB_ERR_FILE_NOT_FOUND; +} + +static grub_err_t +get_value (grub_json_type_t *out_type, const char **out_string, const grub_json_t *parent, const char *key) +{ + const grub_json_t *p = parent; + grub_json_t child; + grub_err_t ret; + jsmntok_t *tok; + + if (key) + { + ret = grub_json_getvalue (&child, parent, key); + if (ret) + return ret; + p = &child; + } + + tok = &p->tokens[p->idx]; + p->string[tok->end] = '\0'; + + *out_string = p->string + tok->start; + + return grub_json_gettype (out_type, p); +} + +grub_err_t +grub_json_getstring (const char **out, const grub_json_t *parent, const char *key) +{ + grub_json_type_t type; + const char *value; + grub_err_t ret; + + ret = get_value (&type, &value, parent, key); + if (ret) + return ret; + if (type != GRUB_JSON_STRING) + return GRUB_ERR_BAD_ARGUMENT; + + *out = value; + return GRUB_ERR_NONE; +} + +grub_err_t +grub_json_getuint64 (grub_uint64_t *out, const grub_json_t *parent, const char *key) +{ + grub_json_type_t type; + const char *value; + const char *end; + grub_err_t ret; + + ret = get_value (&type, &value, parent, key); + if (ret) + return ret; + if (type != GRUB_JSON_STRING && type != GRUB_JSON_PRIMITIVE) + return GRUB_ERR_BAD_ARGUMENT; + + grub_errno = GRUB_ERR_NONE; + *out = grub_strtoul (value, &end, 10); + if (grub_errno != GRUB_ERR_NONE || *end) + return GRUB_ERR_BAD_NUMBER; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_json_getint64 (grub_int64_t *out, const grub_json_t *parent, const char *key) +{ + grub_json_type_t type; + const char *value; + const char *end; + grub_err_t ret; + + ret = get_value (&type, &value, parent, key); + if (ret) + return ret; + if (type != GRUB_JSON_STRING && type != GRUB_JSON_PRIMITIVE) + return GRUB_ERR_BAD_ARGUMENT; + + grub_errno = GRUB_ERR_NONE; + *out = grub_strtol (value, &end, 10); + if (grub_errno != GRUB_ERR_NONE || *end) + return GRUB_ERR_BAD_NUMBER; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_json_unescape (char **out, grub_size_t *outlen, const char *in, grub_size_t inlen) +{ + grub_err_t ret = GRUB_ERR_NONE; + grub_size_t inpos, resultpos; + char *result; + + if (out == NULL || outlen == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("output parameters are not set")); + + result = grub_calloc (1, inlen + 1); + if (result == NULL) + return GRUB_ERR_OUT_OF_MEMORY; + + for (inpos = resultpos = 0; inpos < inlen; inpos++) + { + if (in[inpos] == '\\') + { + inpos++; + if (inpos >= inlen) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("expected escaped character")); + goto err; + } + + switch (in[inpos]) + { + case '"': + result[resultpos++] = '"'; + break; + + case '/': + result[resultpos++] = '/'; + break; + + case '\\': + result[resultpos++] = '\\'; + break; + + case 'b': + result[resultpos++] = '\b'; + break; + + case 'f': + result[resultpos++] = '\f'; + break; + + case 'r': + result[resultpos++] = '\r'; + break; + + case 'n': + result[resultpos++] = '\n'; + break; + + case 't': + result[resultpos++] = '\t'; + break; + + case 'u': + { + char values[4] = {0}; + unsigned i; + + inpos++; + if (inpos + ARRAY_SIZE(values) > inlen) + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unicode sequence too short")); + goto err; + } + + for (i = 0; i < ARRAY_SIZE(values); i++) + { + char c = in[inpos++]; + + if (c >= '0' && c <= '9') + values[i] = c - '0'; + else if (c >= 'A' && c <= 'F') + values[i] = c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + values[i] = c - 'a' + 10; + else + { + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unicode sequence with invalid character '%c'"), c); + goto err; + } + } + + if (values[0] != 0 || values[1] != 0) + result[resultpos++] = values[0] << 4 | values[1]; + result[resultpos++] = values[2] << 4 | values[3]; + + /* Offset the increment that's coming in via the loop increment. */ + inpos--; + + break; + } + + default: + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized escaped character '%c'"), in[inpos]); + goto err; + } + } + else + result[resultpos++] = in[inpos]; + } + + *out = result; + *outlen = resultpos; + + err: + if (ret != GRUB_ERR_NONE) + grub_free (result); + + return ret; +} diff --git a/grub-core/lib/json/json.h b/grub-core/lib/json/json.h new file mode 100644 index 000000000..626074c35 --- /dev/null +++ b/grub-core/lib/json/json.h @@ -0,0 +1,140 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2019 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB 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 GRUB. If not, see . + */ + +#ifndef GRUB_JSON_JSON_H +#define GRUB_JSON_JSON_H 1 + +#include + +enum grub_json_type +{ + /* Unordered collection of key-value pairs. */ + GRUB_JSON_OBJECT, + /* Ordered list of zero or more values. */ + GRUB_JSON_ARRAY, + /* Zero or more Unicode characters. */ + GRUB_JSON_STRING, + /* Number, boolean or empty value. */ + GRUB_JSON_PRIMITIVE, + /* Invalid token. */ + GRUB_JSON_UNDEFINED, +}; +typedef enum grub_json_type grub_json_type_t; + +/* Forward-declaration to avoid including jsmn.h. */ +struct jsmntok; + +struct grub_json +{ + struct jsmntok *tokens; + char *string; + grub_size_t idx; +}; +typedef struct grub_json grub_json_t; + +/* + * Parse a JSON-encoded string. Note that the string passed to + * this function will get modified on subsequent calls to + * grub_json_get*(). Returns the root object of the parsed JSON + * object, which needs to be free'd via grub_json_free(). Callers + * must ensure that the string outlives the returned root object, + * and that child objects must not be used after the root object + * has been free'd. + */ +extern grub_err_t EXPORT_FUNC(grub_json_parse) (grub_json_t **out, + char *string, + grub_size_t string_len); + +/* + * Free the structure and its contents. The string passed to + * grub_json_parse() will not be free'd. + */ +extern void EXPORT_FUNC(grub_json_free) (grub_json_t *json); + +/* + * Get the child count of a valid grub_json_t instance. Children + * are present for arrays, objects (dicts) and keys of a dict. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getsize) (grub_size_t *out, + const grub_json_t *json); + +/* Get the type of a valid grub_json_t instance. */ +extern grub_err_t EXPORT_FUNC(grub_json_gettype) (grub_json_type_t *out, + const grub_json_t *json); + +/* + * Get n'th child of a valid object, array or key. Will return an + * error if no such child exists. The result does not need to be + * free'd. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getchild) (grub_json_t *out, + const grub_json_t *parent, + grub_size_t n); + +/* + * Get value of key from a valid grub_json_t instance. The result + * does not need to be free'd. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getvalue) (grub_json_t *out, + const grub_json_t *parent, + const char *key); + +/* + * Get the string representation of a valid grub_json_t instance. + * If a key is given and parent is a JSON object, this function + * will return the string value of a child mapping to the key. + * If no key is given, it will return the string value of the + * parent itself. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getstring) (const char **out, + const grub_json_t *parent, + const char *key); + +/* + * Get the uint64 representation of a valid grub_json_t instance. + * Returns an error if the value pointed to by `parent` cannot be + * converted to an uint64. See grub_json_getstring() for details + * on the key parameter. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getuint64) (grub_uint64_t *out, + const grub_json_t *parent, + const char *key); + +/* + * Get the int64 representation of a valid grub_json_t instance. + * Returns an error if the value pointed to by `parent` cannot be + * converted to an int64. See grub_json_getstring() for + * details on the key parameter. + */ +extern grub_err_t EXPORT_FUNC(grub_json_getint64) (grub_int64_t *out, + const grub_json_t *parent, + const char *key); + +/* + * Unescape escaped characters and Unicode sequences in the + * given JSON-encoded string. Returns a newly allocated string + * passed back via the `out` parameter that has a length of + * `*outlen`. + * + * See https://datatracker.ietf.org/doc/html/rfc8259#section-7 for more + * information on escaping in JSON. + */ +extern grub_err_t EXPORT_FUNC(grub_json_unescape) (char **out, grub_size_t *outlen, + const char *in, grub_size_t inlen); + +#endif diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 775eaad1f..fa0131a1e 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2010 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2010,2012 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,8 @@ #include #include +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + struct legacy_command { const char *name; @@ -65,28 +67,32 @@ struct legacy_command */ static struct legacy_command legacy_commands[] = { + /* FIXME: background unsupported. */ {"blocklist", "blocklist '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", "Print the blocklist notation of the file FILE."}, {"boot", "boot\n", NULL, 0, 0, {}, 0, 0, "Boot the OS/chain-loader which has been loaded."}, - {"bootp", "net_bootp; net_ls_addr; if [ x%s = x--with-configfile ]; then " + {"bootp", "net_bootp; net_ls_addr; echo $\"" N_("Default server is ${net_default_server}") "\"; if [ x%s = x--with-configfile ]; then " "if net_get_dhcp_option configfile_name pxe 150 string; then " "configfile $configfile_name; fi; fi\n", NULL, 0, 1, {TYPE_WITH_CONFIGFILE_OPTION}, FLAG_IGNORE_REST, "[--with-configfile]", "Initialize a network device via BOOTP. If the option `--with-configfile'" " is given, try to load a configuration file specified by the 150 vendor" " tag."}, + /* FIXME: border unsupported. */ {"cat", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", "Print the contents of the file FILE."}, {"chainloader", "chainloader %s '%s'\n", NULL, 0, 2, {TYPE_FORCE_OPTION, TYPE_FILE}, 0, "[--force] FILE", "Load the chain-loader FILE. If --force is specified, then load it" " forcibly, whether the boot loader signature is present or not."}, + {"clear", "clear\n", NULL, 0, 0, {}, 0, 0, + "Clear the screen."}, {"cmp", "cmp '%s' '%s'\n", NULL, 0, 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST, "FILE1 FILE2", "Compare the file FILE1 with the FILE2 and inform the different values" " if any."}, - {"color", "set color_normal='%s'; set color_highlight='%s'\n", NULL, 0, + {"color", "set color_normal='%s'; set color_highlight='%s'\n", NULL, 0, 2, {TYPE_VERBATIM, TYPE_VERBATIM}, FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE, "NORMAL [HIGHLIGHT]", "Change the menu colors. The color NORMAL is used for most" @@ -109,7 +115,7 @@ static struct legacy_command legacy_commands[] = 0, {}, 0, 0, "Turn on/off the debug mode."}, {"default", "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; " - "set default=\"$saved_entry\"; fi\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, + "set default=\"$saved_entry\"; fi\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "[NUM | `saved']", "Set the default entry to entry number NUM (if not specified, it is" " 0, the first entry) or the entry number saved by savedefault."}, @@ -122,9 +128,10 @@ static struct legacy_command legacy_commands[] = " tag."}, {"displayapm", "lsapm\n", NULL, 0, 0, {}, 0, 0, "Display APM BIOS information."}, - {"displaymem", "lsmmap\n", NULL, 0, 0, {}, 0, 0, + {"displaymem", "lsmmap\n", NULL, 0, 0, {}, 0, 0, "Display what GRUB thinks the system address space map of the" " machine is, including all regions of physical RAM installed."}, + /* FIXME: device and efimap unsupported. */ /* NOTE: embed unsupported. */ {"fallback", "set fallback='%s'\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "NUM...", @@ -136,6 +143,8 @@ static struct legacy_command legacy_commands[] = {"find", "search -f '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILENAME", "Search for the filename FILENAME in all of partitions and print the list of" " the devices which contain the file."}, + /* FIXME: findiso unsupported. */ + /* FIXME: foreground unsupported. */ /* FIXME: fstest unsupported. */ /* NOTE: The obsolete C/H/S geometry isn't shown anymore. */ {"geometry", "insmod regexp; ls -l (%s*)\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "DRIVE", @@ -204,7 +213,7 @@ static struct legacy_command legacy_commands[] = 1, {TYPE_BOOL}, FLAG_FALLBACK_AVAILABLE, "[FLAG]", "Toggle pager mode with no argument. If FLAG is given and its value" " is `on', turn on the mode. If FLAG is `off', turn off the mode."}, - {"pager", + {"pager", "if [ \"$pager\" = 1 ]; then pager=0; echo Internal pager is now off;" "else pager=1; echo Internal pager is now on; fi\n", NULL, 0, 0, {}, FLAG_FALLBACK, NULL, NULL}, @@ -243,6 +252,10 @@ static struct legacy_command legacy_commands[] = {"pause", "echo %s; if ! sleep -i 60; then return; fi\n", NULL, 0, 1, {TYPE_REST_VERBATIM}, 0, "[MESSAGE ...]", "Print MESSAGE, then wait until a key is pressed."}, + {"print", "echo %s\n", NULL, 0, 1, + {TYPE_REST_VERBATIM}, 0, + "[MESSAGE ...]", "Print MESSAGE."}, + /* FIXME: quit unsupported. */ /* FIXME: rarp unsupported. */ {"read", "read_dword %s\n", NULL, 0, 1, {TYPE_INT}, 0, "ADDR", "Read a 32-bit value from memory at address ADDR and" @@ -278,7 +291,7 @@ static struct legacy_command legacy_commands[] = "Save the current entry as the default boot entry if no argument is" " specified. If a number is specified, this number is saved. If" " `fallback' is used, next fallback entry is saved."}, - {"serial", "serial %s\n", NULL, 0, 1, {TYPE_REST_VERBATIM}, 0, + {"serial", "serial %s\n", NULL, 0, 1, {TYPE_REST_VERBATIM}, 0, "[--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] " "[--parity=PARITY] [--stop=STOP] [--device=DEV]", "Initialize a serial device. UNIT is a digit that specifies which serial" @@ -288,14 +301,18 @@ static struct legacy_command legacy_commands[] = " STOP is the length of stop bit(s). The option --device can be used only" " in the grub shell, which specifies the file name of a tty device. The" " default values are COM1, 9600, 8N1."}, + /* FIXME: shade unsupported. */ + /* FIXME: silent unsupported. */ + /* FIXME: splashimage unsupported. */ /* FIXME: setkey unsupported. */ /* NUL_TERMINATE */ /* NOTE: setup unsupported. */ - /* FIXME: --no-echo, --no-edit, hercules unsupported. */ + /* FIXME: --no-echo, --no-edit unsupported. */ /* NOTE: both terminals are activated so --silent and --timeout are useless. */ + /* FIXME: graphics unsupported. */ {"terminal", NULL, NULL, 0, 0, {}, FLAG_TERMINAL | FLAG_IGNORE_REST, "[--dumb] [--no-echo] [--no-edit] [--timeout=SECS] [--lines=LINES] " - "[--silent] [console] [serial] [hercules]", + "[--silent] [console] [serial] [hercules] [graphics]", "Select a terminal. When multiple terminals are specified, wait until" " you push any key to continue. If both console and serial are specified," " the terminal to which you input a key first will be selected. If no" @@ -307,7 +324,7 @@ static struct legacy_command legacy_commands[] = " seconds. The option --lines specifies the maximum number of lines." " The option --silent is used to suppress messages."}, /* FIXME: terminfo unsupported. */ /* NUL_TERMINATE */ - {"testload", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", + {"testload", "testload '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", "Read the entire contents of FILE in several different ways and" " compares them, to test the filesystem code. " " If this test succeeds, then a good next" @@ -334,6 +351,9 @@ static struct legacy_command legacy_commands[] = " the information about only the mode."}, {"vbeprobe", "insmod vbe; videoinfo\n", NULL, 0, 0, {}, FLAG_FALLBACK, NULL, NULL} + /* FIXME: verbose unsupported. */ + /* FIXME: version unsupported. */ + /* FIXME: viewport unsupported. */ }; char * @@ -373,9 +393,32 @@ adjust_file (const char *in, grub_size_t len) if (*ptr == '\'' || *ptr == '\\') overhead++; comma = ptr; + if (*comma == ')' && comma - in == 3 + && in[1] == 'n' && in[2] == 'd') + { + rest = comma + 1; + for (ptr = rest; ptr < in + len && *ptr; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + + ret = grub_malloc (ptr - in + overhead + 15); + if (!ret) + return NULL; + + outptr = grub_stpcpy (ret, "(tftp)");; + for (ptr = rest; ptr < in + len; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + *outptr = 0; + return ret; + } if (*comma != ',') return grub_legacy_escape (in, len); - part = grub_strtoull (comma + 1, (char **) &rest, 0); + part = grub_strtoull (comma + 1, &rest, 0); if (rest[0] == ',' && rest[1] >= 'a' && rest[1] <= 'z') { subpart = rest[1] - 'a'; @@ -386,7 +429,7 @@ adjust_file (const char *in, grub_size_t len) overhead++; /* 35 is enough for any 2 numbers. */ - ret = grub_malloc (ptr - in + overhead + 35); + ret = grub_malloc (ptr - in + overhead + 35 + 5); if (!ret) return NULL; @@ -395,7 +438,7 @@ adjust_file (const char *in, grub_size_t len) { if (*ptr == '\'' || *ptr == '\\') *outptr++ = '\\'; - + *outptr++ = *ptr; } if (subpart != -1) @@ -408,7 +451,7 @@ adjust_file (const char *in, grub_size_t len) { if (*ptr == '\'' || *ptr == '\\') *outptr++ = '\\'; - + *outptr++ = *ptr; } *outptr = 0; @@ -446,7 +489,7 @@ is_option (enum arg_type opt, const char *curarg, grub_size_t len) return (len >= 2 && curarg[0] == '-' && curarg[1] == '-'); default: return 0; - } + } } char * @@ -507,11 +550,11 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) int dumb = 0, lines = 24; #ifdef TODO int no_echo = 0, no_edit = 0; - int hercules = 0; #endif - int console = 0, serial = 0; + int hercules = 0; + int console = 0, serial = 0, graphics = 0; /* Big enough for any possible resulting command. */ - char outbuf[256] = ""; + char outbuf[512] = ""; char *outptr; while (*ptr) { @@ -541,45 +584,40 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) if (grub_memcmp (ptr, "serial", sizeof ("serial") - 1) == 0) serial = 1; -#ifdef TODO if (grub_memcmp (ptr, "hercules", sizeof ("hercules") - 1) == 0) hercules = 1; -#endif + if (grub_memcmp (ptr, "graphics", sizeof ("graphics") - 1) == 0) + graphics = 1; while (*ptr && !grub_isspace (*ptr)) ptr++; while (*ptr && grub_isspace (*ptr)) ptr++; } - if (!console && !serial) + if (!console && !serial && !hercules && !graphics) return grub_strdup ("terminal_input; terminal_output; terminfo\n"); - grub_strcpy (outbuf, "terminal_input "); - outptr = outbuf + grub_strlen (outbuf); + outptr = outbuf; + + if (graphics) + outptr = grub_stpcpy (outptr, "insmod all_video; "); + + outptr = grub_stpcpy (outptr, "terminal_input "); if (serial) - { - grub_strcpy (outptr, "serial "); - outptr += grub_strlen (outptr); - } - if (console) - { - grub_strcpy (outptr, "console "); - outptr += grub_strlen (outptr); - } - grub_strcpy (outptr, "; terminal_output "); - outptr += grub_strlen (outptr); + outptr = grub_stpcpy (outptr, "serial "); + if (console || hercules || graphics) + outptr = grub_stpcpy (outptr, "console "); + outptr = grub_stpcpy (outptr, "; terminal_output "); if (serial) - { - grub_strcpy (outptr, "serial "); - outptr += grub_strlen (outptr); - } + outptr = grub_stpcpy (outptr, "serial "); if (console) - { - grub_strcpy (outptr, "console "); - outptr += grub_strlen (outptr); - } - grub_strcpy (outptr, "; "); - outptr += grub_strlen (outptr); + outptr = grub_stpcpy (outptr, "console "); + if (hercules) + outptr = grub_stpcpy (outptr, "mda_text "); + if (graphics) + outptr = grub_stpcpy (outptr, "gfxterm "); + outptr = grub_stpcpy (outptr, "; "); + *outptr = '\0'; if (serial) { grub_snprintf (outptr, outbuf + sizeof (outbuf) - outptr, @@ -597,7 +635,7 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) { int hold_arg = 0; - const char *curarg = NULL; + const char *curarg = NULL; for (i = 0; i < legacy_commands[cmdnum].argc; i++) { grub_size_t curarglen; @@ -626,6 +664,7 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) { case TYPE_FILE_NO_CONSUME: hold_arg = 1; + /* Fallthrough. */ case TYPE_PARTITION: case TYPE_FILE: args[i] = adjust_file (curarg, curarglen); @@ -646,7 +685,7 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) ptr++; overhead += 3; } - + outptr0 = args[i] = grub_malloc (overhead + (ptr - curarg)); if (!outptr0) return NULL; @@ -780,14 +819,14 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: - case TYPE_OPTION: + case TYPE_OPTION: args[i] = grub_strdup (""); break; case TYPE_BOOL: case TYPE_INT: args[i] = grub_strdup ("0"); break; - case TYPE_VBE_MODE: + case TYPE_VBE_MODE: args[i] = grub_strdup ("auto"); break; } @@ -810,7 +849,7 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) if (!invert) return NULL; grub_memcpy (invert, slash + 1, len - (slash - corig) - 1); - invert[len - (slash - args[0]) - 1] = '/'; + invert[len - (slash - args[0]) - 1] = '/'; grub_memcpy (invert + len - (slash - corig), corig, slash - corig); invert[len] = 0; args[legacy_commands[cmdnum].argc] = invert; diff --git a/grub-core/lib/libgcrypt/cipher/ChangeLog b/grub-core/lib/libgcrypt/cipher/ChangeLog index 8924f17e1..1b3694f58 100644 --- a/grub-core/lib/libgcrypt/cipher/ChangeLog +++ b/grub-core/lib/libgcrypt/cipher/ChangeLog @@ -1,3 +1,93 @@ +2010-08-19 Werner Koch + + * cipher.c (gcry_cipher_open): Remove double release of the module. + Fixes bug#1263. + +2010-06-10 Jeff Johnson (wk) + + * ecc.c (ecc_generate_ext): Parse transient-key flag. + (generate_key): Add arg TRANSIENT_KEY and use it to set the random + level. + +2010-04-12 Brad Hards (wk) + + Spelling fixes. + +2010-03-26 Werner Koch + + * tiger.c (asn): Unfetter the old TIGER from an OID. + (TIGER_CONTEXT): Add field VARIANT. + (tiger_init): Factor code out to ... + (do_init): New. + (tiger1_init, tiger2_init): New. + (_gcry_digest_spec_tiger1, _gcry_digest_spec_tiger2): New. + * md.c (digest_table): Add TIGER1 and TIGER2 variants. + +2009-12-11 Werner Koch + + * sha256.c (Cho, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables + + * sha512.c (ROTR, Ch, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables. + Suggested by Christian Grothoff. + +2009-12-10 Werner Koch + + * Makefile.am (o_flag_munging): New. + (tiger.o, tiger.lo): Use it. + + * cipher.c (do_ctr_encrypt): Add arg OUTBUFLEN. Check for + suitable value. Add check for valid inputlen. Wipe temporary + memory. + (do_ctr_decrypt): Likewise. + (do_cbc_encrypt, do_cbc_decrypt): Add arg OUTBUFLEN. Check for + suitable value. Move check for valid inputlen to here; change + returned error from INV_ARG to INV_LENGTH. + (do_ecb_encrypt, do_ecb_decrypt): Ditto. + (do_cfb_encrypt, do_cfb_decrypt): Ditto. + (do_ofb_encrypt, do_ofb_decrypt): Ditto. + (cipher_encrypt, cipher_encrypt): Adjust for above changes. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Simplify. + +2009-12-09 Werner Koch + + * cipher.c (gcry_cipher_open): Allow for GCRY_CIPHER_MODE_AESWRAP. + (cipher_encrypt, cipher_decrypt): Ditto. + (do_aeswrap_encrypt, do_aeswrap_decrypt): New. + (struct gcry_cipher_handle): Add field marks. + (cipher_setkey, cipher_setiv): Update marks flags. + (cipher_reset): Reset marks. + (cipher_encrypt, cipher_decrypt): Add new arg OUTBUFLEN. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Pass outbuflen to + cipher_encrypt. Replace GPG_ERR_TOO_SHORT by + GPG_ERR_BUFFER_TOO_SHORT. + +2009-08-21 Werner Koch + + * dsa.c (dsa_generate_ext): Release retfactors array before + setting it to NULL. Reported by Daiko Ueno. + +2009-07-02 Werner Koch + + * md.c (md_read): Fix incomplete check for NULL. + Reported by Fabian Kail. + +2009-03-31 Werner Koch + + * rsa.c (rsa_check_secret_key): Return GPG_ERR_BAD_SECKEY and not + GPG_ERR_PUBKEY_ALGO. + +2009-02-16 Werner Koch + + * rsa.c (generate_x931): Do not initialize TBL with automatic + variables. + * whirlpool.c, tiger.c, sha256.c, sha1.c, rmd160.c, md5.c + * md4.c, crc.c: Remove memory.h. This is garbage from gnupg. + Reported by Dan Fandrich. + 2009-01-22 Werner Koch * ecc.c (compute_keygrip): Remove superfluous const. @@ -3888,8 +3978,8 @@ Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de) (digest_algo_to_string): New. - Copyright 1998,1999,2000,2001,2002,2003,2004,2005,2006 - 2007, 2008, 2009 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is free software; as a special exception the author gives unlimited permission to copy and/or distribute it, with or without diff --git a/grub-core/lib/libgcrypt/cipher/ChangeLog-2011 b/grub-core/lib/libgcrypt/cipher/ChangeLog-2011 new file mode 100644 index 000000000..05516c99e --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/ChangeLog-2011 @@ -0,0 +1,4247 @@ +2011-12-01 Werner Koch + + NB: ChangeLog files are no longer manually maintained. Starting + on December 1st, 2011 we put change information only in the GIT + commit log, and generate a top-level ChangeLog file from logs at + "make dist". See doc/HACKING for details. + +2011-06-29 Werner Koch + + * cipher.c (cipher_get_keylen): Return zero for an invalid algorithm. + (cipher_get_blocksize): Ditto. + +2011-06-13 Werner Koch + + * dsa.c (selftest_sign_1024): Use the raw and not the pkcs1 flag. + + * pubkey.c (gcry_pk_sign): Special case output generation for PKCS1. + (sexp_data_to_mpi): Parse "random-override" for pkcs1 encryption. + (pkcs1_encode_for_encryption): Add args RANDOM_OVERRIDE and + RANDOM_OVERRIDE_LEN. + (gcry_pk_encrypt): Special case output generation for PKCS1. + (sexp_data_to_mpi): Use GCRYMPI_FMT_USG for raw encoding. + +2011-06-10 Werner Koch + + * pubkey.c (gcry_pk_sign): Use format specifier '%M' to avoid + leading zeroes. Special case output generation for PSS. + (gcry_pk_encrypt): Special case output generation for OAEP. + (sexp_data_to_mpi): Use GCRYMPI_FMT_USG for PSS verify. + +2011-06-09 Werner Koch + + * pubkey.c (oaep_decode): Make use of octet_string_from_mpi. + (sexp_to_enc): Skip "random-override". + + * pubkey.c (oaep_encode, pss_encode): Add args RANDOM_OVERRIDE and + RANDOM_OVERRIDE_LEN. + (sexp_data_to_mpi): Extract new random-override parameter. + + * pubkey.c (pss_encode, pss_verify): Use VALUE verbatim for MHASH. + (octet_string_from_mpi): Add arg SPACE. + +2011-06-08 Werner Koch + + * pubkey.c (pss_encode, pss_verify): Restructure and comment code + to match rfc-3447. Replace secure allocs by plain allocs and + wipememory. Use gcry_md_hash_buffer. + (octet_string_from_mpi): New. + +2011-06-03 Werner Koch + + * pubkey.c (oaep_decode): Add more comments and restructure to + match the description in RFC-3447. + (oaep_encode): Check for mgf1 error. s/dlen/hlen/. + +2011-05-31 Werner Koch + + * pubkey.c (mgf1): Optimize by using gcry_md_reset. Re-implement + for easier readability. + (oaep_encode): Add more comments and restructure to match the + description in RFC-3447. + + * pubkey.c (pkcs1_encode_for_signature, oaep_decode): Change + return value from one MPI to a buffer. + (gcry_pk_decrypt): Adjust for this change. + +2011-05-30 Werner Koch + + * pubkey.c (pkcs1_decode_for_encryption): Change handling of + leading zero byte. + +2011-05-27 Daiki Ueno + + * pubkey.c (gcry_pk_decrypt): Fix double-free when un-padding + invalid data. Thanks to Tom Ritter. + +2011-05-24 Daiki Ueno + + * rsa.c (rsa_verify): Use CMP if given, to check the decrypted + sig. + + * pubkey.c (sexp_to_enc, sexp_data_to_mpi): Factor out + CTX initialization to ... + (init_encoding_ctx): .. new. + (gcry_pk_verify): Pass verify func and the arg to pubkey_verify. + (pss_encode, pss_verify, pss_verify_cmp): New. + +2011-05-23 Daiki Ueno + + * pubkey.c (pkcs1_decode_for_encryption, oaep_decode): Fix memleak + when gcry_mpi_print fails. + +2011-05-18 Daiki Ueno + + * pubkey.c (sexp_data_to_mpi): Factor some code out to ... + (pkcs1_encode_for_encryption): .. new, + (pkcs1_encode_for_signature): .. new. + (pkcs1_decode_for_encryption): New. + (gcry_pk_decrypt): Do un-padding for PKCS#1 as well as OAEP. + (sexp_to_enc): Abolish "unpad" flag, which is not necessary since + we can do un-padding implicitly when "pkcs1" or "oaep" is given. + +2011-05-11 Werner Koch + + * pubkey.c (sexp_to_enc, sexp_data_to_mpi): Set LABEL to NULL + after free. + (sexp_to_enc, sexp_data_to_mpi): Do not allow multiple encoding + flags. + (oaep_encode, oaep_decode, sexp_to_key, sexp_to_sig) + (sexp_to_enc, sexp_data_to_mpi, gcry_pk_encrypt, gcry_pk_sign) + (gcry_pk_genkey, _gcry_pk_get_elements): Replace access to ERRNO + by gpg_err_code_from_syserror. + +2011-05-11 Daiki Ueno + + * pubkey.c (sexp_data_to_mpi): Factor some code out to ... + (get_hash_algo): .. new. + (mgf1, oaep_encode, oaep_decode): New. + (sexp_to_enc): Add arg CTX. Remove arg RET_WANT_PKCS1. Support + OAEP. + (sexp_data_to_mpi): Add arg CTX. Support OAEP. + (gcry_pk_encrypt): Pass a CTX to sexp_data_to_mpi. + (gcry_pk_decrypt): Pass a CTX tp sexp_to_enc and replace + WANT_PKCS1. Implement unpadding for OAEP. + (gcry_pk_sign): Pass NULL for CTX arg of sexp_data_to_mpi. + (gcry_pk_verify): Ditto. + +2011-04-19 Werner Koch + + * cipher.c (gcry_cipher_open): Replace gpg_err_code_from_errno by + gpg_err_code_from_syserror. + +2011-04-11 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): Avoid double free of L2. + + * cipher.c (_gcry_cipher_setctr): Clear unused lastiv info. + (gcry_cipher_ctl) : Implement by calling + _gcry_cipher_setctr. + (do_ctr_encrypt): Save last counter and reuse it. + + * cipher.c (do_ctr_encrypt): Allow arbitrary length inputs to + match the 1.4 behaviour. + +2011-04-04 Werner Koch + + * ecc.c (compute_keygrip): Release L1 while parsing "curve". + + * pubkey.c (gcry_pk_get_keygrip): Always release NAME and L2. + Reported by Ben Kibbey. + +2011-03-28 Werner Koch + + * primegen.c (_gcry_generate_elg_prime): Make sure that PRIME is + NULL if the called func ever returns an error. + + * pubkey.c (gcry_pk_decrypt): Remove unused var PUBKEY. + +2011-03-09 Werner Koch + + * kdf.c: New. + +2011-02-22 Werner Koch + + * rijndael.c (aesni_cleanup_2_4): New. + (aesenc_xmm1_xmm0, do_aesni_ctr_4): New. + (_gcry_aes_ctr_enc): New. + * cipher.c (struct gcry_cipher_handle): Add CTR_ENC. Move field + CTR into an u_ctr union and adjust all users. + (gcry_cipher_open): Use _gcry_aes_ctr_enc. + (do_ctr_encrypt): Use bulk mode. + +2011-02-18 Werner Koch + + * rijndael.c (u32_a_t): New. + (do_encrypt_aligned, do_encrypt_aligned): Use the new type to + avoid problems with strict aliasing rules. + +2011-02-16 Werner Koch + + * rijndael.c (do_aesni_cfb) [USE_AESNI]: New. + (_gcry_aes_cfb_enc, _gcry_aes_cfb_dec) [USE_AESNI]: Use new fucntion. + +2011-02-15 Werner Koch + + * rijndael.c (do_aesni_enc_aligned, do_aesni_dec_aligned): Use + movdqa for the key but keep using movdqu for the data. + (do_aesni): Remove alignment detection. Don't burn the stack. + (aesni_prepare, aesni_cleanup): New macros. + (rijndael_encrypt, _gcry_aes_cfb_enc, _gcry_aes_cbc_enc) + (rijndael_decrypt, _gcry_aes_cfb_dec, _gcry_aes_cbc_dec): Use + these macros. Don't burn the stack in the USE_AESNI case. + (do_setkey): Add disabled code to use aeskeygenassist. + +2011-02-14 Werner Koch + + * rijndael.c (ATTR_ALIGNED_16): New + (do_aesni): Do not copy if already aligned. + (do_encrypt, do_decrypt): Ditto. + (rijndael_decrypt, rijndael_encrypt): Increase stack burning amount. + + * rijndael.c (RIJNDAEL_context): Reorder fields. Change fieldname + ROUNDS to rounds. Move padlock_key into u1. + (keySched, keySched2): Rename macros to keyscherr and keyschdec + and change all users. + (padlockkey): New macro. Change all users of padlock_key. + * cipher.c (NEED_16BYTE_ALIGNED_CONTEXT): Always define if using gcc. + (struct gcry_cipher_handle): Align U_IV to at least 16 byte. + +2011-02-13 Werner Koch + + * rijndael.c (USE_AESNI): New. Define for ia32 and gcc >= 4. + (m128i_t) [USE_AESNI]: New. + (RIJNDAEL_context) [USE_AESNI]: Add field use_aesni. + (do_setkey): Set USE_AESNI for all key lengths. + (prepare_decryption) [USE_AESNI]: Use aesimc instn if requested. + (do_aesni_enc_aligned, do_aesni_dec_aligned) + (do_aesni) [USE_AESNI]: New. + (rijndael_encrypt, _gcry_aes_cfb_enc, _gcry_aes_cbc_enc) + (rijndael_decrypt, _gcry_aes_cfb_dec) + (_gcry_aes_cbc_dec) [USE_AESNI]: Use do_aesni. + +2011-02-01 Werner Koch + + * pubkey.c (gcry_pk_get_curve): New. + (sexp_to_key): Add arg OVERRIDE_ELEMS. + (sexp_elements_extract_ecc): Allow for params only. + (gcry_pk_get_param): New. + * ecc.c (ecc_get_curve): New. + (ecc_get_param_sexp): New. + +2011-01-28 Werner Koch + + * pubkey.c (gcry_pk_genkey): Hack to insert the used curve name. + +2011-01-27 Werner Koch + + * ecc.c (fill_in_curve): Remove. + (generate_curve): Rename to .. + (fill_in_curve): this. Remove setting of NAME_OID. + (ecc_encrypt_raw): Change name of arg DATA to K for better + readability. Use ECC_public_key instead of ECC_secret_key. + Require a caller to pass a complete pkey array. + (ecc_decrypt_raw): Require a caller to pass a complete skey array. + (elliptic_curve_t): Add field NAME. + (fill_in_curve): Set field. + (generate_key): Add arg R_USED_CURVE. + (ecc_generate_ext): Return used curve name. + +2011-01-13 Andrey Jivsov (wk) + + * ecc.c (ec2os): Do not free passed parameters X and Y. Adjust + callers. + (ecc_encrypt_raw, ecc_decrypt_raw): New. + (ecdh_names, _gcry_pubkey_spec_ecdh): New. + * pubkey.c (pubkey_table): Support ECDH. + +2010-08-19 Werner Koch + + * cipher.c (gcry_cipher_open): Remove double release of the module. + Fixes bug#1263. + +2010-06-10 Jeff Johnson (wk) + + * ecc.c (ecc_generate_ext): Parse transient-key flag. + (generate_key): Add arg TRANSIENT_KEY and use it to set the random + level. + +2010-04-12 Brad Hards (wk) + + Spelling fixes. + +2010-03-26 Werner Koch + + * tiger.c (asn): Unfetter the old TIGER from an OID. + (TIGER_CONTEXT): Add field VARIANT. + (tiger_init): Factor code out to ... + (do_init): New. + (tiger1_init, tiger2_init): New. + (_gcry_digest_spec_tiger1, _gcry_digest_spec_tiger2): New. + * md.c (digest_table): Add TIGER1 and TIGER2 variants. + +2009-12-11 Werner Koch + + * sha256.c (Cho, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables + + * sha512.c (ROTR, Ch, Maj, Sum0, Sum1): Turn macros into inline + functions. + (transform): Partly unroll to interweave the chain variables. + Suggested by Christian Grothoff. + +2009-12-10 Werner Koch + + * Makefile.am (o_flag_munging): New. + (tiger.o, tiger.lo): Use it. + + * cipher.c (do_ctr_encrypt): Add arg OUTBUFLEN. Check for + suitable value. Add check for valid inputlen. Wipe temporary + memory. + (do_ctr_decrypt): Likewise. + (do_cbc_encrypt, do_cbc_decrypt): Add arg OUTBUFLEN. Check for + suitable value. Move check for valid inputlen to here; change + returned error from INV_ARG to INV_LENGTH. + (do_ecb_encrypt, do_ecb_decrypt): Ditto. + (do_cfb_encrypt, do_cfb_decrypt): Ditto. + (do_ofb_encrypt, do_ofb_decrypt): Ditto. + (cipher_encrypt, cipher_encrypt): Adjust for above changes. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Simplify. + +2009-12-09 Werner Koch + + * cipher.c (gcry_cipher_open): Allow for GCRY_CIPHER_MODE_AESWRAP. + (cipher_encrypt, cipher_decrypt): Ditto. + (do_aeswrap_encrypt, do_aeswrap_decrypt): New. + (struct gcry_cipher_handle): Add field marks. + (cipher_setkey, cipher_setiv): Update marks flags. + (cipher_reset): Reset marks. + (cipher_encrypt, cipher_decrypt): Add new arg OUTBUFLEN. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Pass outbuflen to + cipher_encrypt. Replace GPG_ERR_TOO_SHORT by + GPG_ERR_BUFFER_TOO_SHORT. + +2009-08-21 Werner Koch + + * dsa.c (dsa_generate_ext): Release retfactors array before + setting it to NULL. Reported by Daiko Ueno. + +2009-07-02 Werner Koch + + * md.c (md_read): Fix incomplete check for NULL. + Reported by Fabian Kail. + +2009-03-31 Werner Koch + + * rsa.c (rsa_check_secret_key): Return GPG_ERR_BAD_SECKEY and not + GPG_ERR_PUBKEY_ALGO. + +2009-02-16 Werner Koch + + * rsa.c (generate_x931): Do not initialize TBL with automatic + variables. + * whirlpool.c, tiger.c, sha256.c, sha1.c, rmd160.c, md5.c + * md4.c, crc.c: Remove memory.h. This is garbage from gnupg. + Reported by Dan Fandrich. + +2009-01-22 Werner Koch + + * ecc.c (compute_keygrip): Remove superfluous const. + +2009-01-06 Werner Koch + + * rmd160.c (oid_spec_rmd160): Add TeleTrust identifier. + +2008-12-10 Werner Koch + + * dsa.c (generate): Add arg DOMAIN and use it if specified. + (generate_fips186): Ditto. + (dsa_generate_ext): Parse and check the optional "domain" + parameter and pass them to the generate functions. + + * rijndael.c (rijndael_names): Add "AES128" and "AES-128". + (rijndael192_names): Add "AES-192". + (rijndael256_names): Add "AES-256". + +2008-12-05 Werner Koch + + * dsa.c (generate): Add arg TRANSIENT_KEY and use it to detrmine + the RNG quality needed. + (dsa_generate_ext): Parse the transient-key flag und pass it to + generate. + +2008-11-28 Werner Koch + + * dsa.c (generate_fips186): Add arg DERIVEPARMS and use the seed + value if available. + + * primegen.c (_gcry_generate_fips186_2_prime): Fix inner p loop. + +2008-11-26 Werner Koch + + * primegen.c (_gcry_generate_fips186_3_prime): New. + * dsa.c (generate_fips186): Add arg USE_FIPS186_2. + (dsa_generate_ext): Parse new flag use-fips183-2. + +2008-11-25 Werner Koch + + * dsa.c (generate_fips186): New. + (dsa_generate_ext): Use new function if derive-parms are given or + if in FIPS mode. + * primegen.c (_gcry_generate_fips186_2_prime): New. + +2008-11-24 Werner Koch + + * pubkey.c (gcry_pk_genkey): Insert code to output extrainfo. + (pubkey_generate): Add arg R_EXTRAINFO and pass it to the extended + key generation function. + * rsa.c (gen_x931_parm_xp, gen_x931_parm_xi): New. + (generate_x931): Generate params if not given. + (rsa_generate_ext): Parse use-x931 flag. Return p-q-swapped + indicator. + * dsa.c (dsa_generate_ext): Put RETFACTORS into R_EXTRAINFO if + possible. + + * pubkey.c (gcry_pk_genkey): Remove parsing of almost all + parameters and pass the parameter S-expression to pubkey_generate. + (pubkey_generate): Simplify by requitring modules to parse the + parameters. Remove the special cases for Elgamal and ECC. + (sexp_elements_extract_ecc): Add arg EXTRASPEC and use it. Fix + small memory leak. + (sexp_to_key): Pass EXTRASPEC to sexp_elements_extract_ecc. + (pubkey_table) [USE_ELGAMAL]: Add real extraspec. + * rsa.c (rsa_generate_ext): Adjust for new calling convention. + * dsa.c (dsa_generate_ext): Ditto. + * elgamal.c (_gcry_elg_generate): Ditto. Rename to elg_generate_ext. + (elg_generate): New. + (_gcry_elg_generate_using_x): Remove after merging code with + elg_generate_ext. + (_gcry_pubkey_extraspec_elg): New. + (_gcry_elg_check_secret_key, _gcry_elg_encrypt, _gcry_elg_sign) + (_gcry_elg_verify, _gcry_elg_get_nbits): Make static and remove + _gcry_ prefix. + * ecc.c (_gcry_ecc_generate): Rename to ecc_generate_ext and + adjust for new calling convention. + (_gcry_ecc_get_param): Rename to ecc_get_param and make static. + (_gcry_pubkey_extraspec_ecdsa): Add ecc_generate_ext and + ecc_get_param. + +2008-11-20 Werner Koch + + * pubkey.c (pubkey_generate): Add arg DERIVEPARMS. + (gcry_pk_genkey): Parse derive-parms and pass it to above. + * rsa.c (generate_x931): New. + (rsa_generate_ext): Add arg DERIVEPARMS and call new function in + fips mode or if DERIVEPARMS is given. + * primegen.c (_gcry_derive_x931_prime, find_x931_prime): New. + +2008-11-19 Werner Koch + + * rsa.c (rsa_decrypt): Use gcry_create_nonce for blinding. + (generate): Rename to generate_std. + +2008-11-05 Werner Koch + + * md.c (md_open): Use a switch to set the Bsize. + (prepare_macpads): Fix long key case for SHA384 and SHA512. + + * cipher.c (gcry_cipher_handle): Add field EXTRASPEC. + (gcry_cipher_open): Set it. + (gcry_cipher_ctl): Add private control code to disable weak key + detection and to return the current input block. + * des.c (_tripledes_ctx): Add field FLAGS. + (do_tripledes_set_extra_info): New. + (_gcry_cipher_extraspec_tripledes): Add new function. + (do_tripledes_setkey): Disable weak key detection. + +2008-10-24 Werner Koch + + * md.c (digest_table): Allow MD5 in fips mode. + (md_register_default): Take special action for MD5. + (md_enable, gcry_md_hash_buffer): Ditto. + +2008-09-30 Werner Koch + + * rijndael.c (do_setkey): Properly align "t" and "tk". + (prepare_decryption): Properly align "w". Fixes bug #936. + +2008-09-18 Werner Koch + + * pubkey.c (gcry_pk_genkey): Parse domain parameter. + (pubkey_generate): Add new arg DOMAIN and remove special case for + DSA with qbits. + * rsa.c (rsa_generate): Add dummy args QBITS, NAME and DOMAIN and + rename to rsa_generate_ext. Change caller. + (_gcry_rsa_generate, _gcry_rsa_check_secret_key) + (_gcry_rsa_encrypt, _gcry_rsa_decrypt, _gcry_rsa_sign) + (_gcry_rsa_verify, _gcry_rsa_get_nbits): Make static and remove + _gcry_ prefix. + (_gcry_pubkey_spec_rsa, _gcry_pubkey_extraspec_rsa): Adjust names. + * dsa.c (dsa_generate_ext): New. + (_gcry_dsa_generate): Replace code by a call to dsa_generate. + (_gcry_dsa_check_secret_key, _gcry_dsa_sign, _gcry_dsa_verify) + (_gcry_dsa_get_nbits): Make static and remove _gcry prefix. + (_gcry_dsa_generate2): Remove. + (_gcry_pubkey_spec_dsa): Adjust to name changes. + (_gcry_pubkey_extraspec_rsa): Add dsa_generate_ext. + +2008-09-16 Werner Koch + + * ecc.c (run_selftests): Add arg EXTENDED. + +2008-09-12 Werner Koch + + * rsa.c (test_keys): Do a bad case signature check. + * dsa.c (test_keys): Do a bad case check. + + * cipher.c (_gcry_cipher_selftest): Add arg EXTENDED and pass it + to the called tests. + * md.c (_gcry_md_selftest): Ditto. + * pubkey.c (_gcry_pk_selftest): Ditto. + * rijndael.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftest_fips_128): Add arg EXTENDED and run only one test + non-extended mode. + (selftest_fips_192): Add dummy arg EXTENDED. + (selftest_fips_256): Ditto. + * hmac-tests.c (_gcry_hmac_selftest): Ditto. + (run_selftests): Ditto. + (selftests_sha1): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha224, selftests_sha256): Ditto. + (selftests_sha384, selftests_sha512): Ditto. + * sha1.c (run_selftests): Add arg EXTENDED and pass it to the + called test. + (selftests_sha1): Add arg EXTENDED and run only one test + non-extended mode. + * sha256.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftests_sha224): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha256): Ditto. + * sha512.c (run_selftests): Add arg EXTENDED and pass it to the + called tests. + (selftests_sha384): Add arg EXTENDED and run only one test + non-extended mode. + (selftests_sha512): Ditto. + * des.c (run_selftests): Add arg EXTENDED and pass it to the + called test. + (selftest_fips): Add dummy arg EXTENDED. + * rsa.c (run_selftests): Add dummy arg EXTENDED. + + * dsa.c (run_selftests): Add dummy arg EXTENDED. + + * rsa.c (extract_a_from_sexp): New. + (selftest_encr_1024): Check that the ciphertext does not match the + plaintext. + (test_keys): Improve tests and return an error status. + (generate): Return an error if test_keys fails. + * dsa.c (test_keys): Add comments and return an error status. + (generate): Return an error if test_keys failed. + +2008-09-11 Werner Koch + + * rsa.c (_gcry_rsa_decrypt): Return an error instead of calling + BUG in case of a practically impossible condition. + (sample_secret_key, sample_public_key): New. + (selftest_sign_1024, selftest_encr_1024): New. + (selftests_rsa): Implement tests. + * dsa.c (sample_secret_key, sample_public_key): New. + (selftest_sign_1024): New. + (selftests_dsa): Implement tests. + +2008-09-09 Werner Koch + + * hmac-tests.c (selftests_sha1): Add tests. + (selftests_sha224, selftests_sha384, selftests_sha512): Make up tests. + + * hash-common.c, hash-common.h: New. + * sha1.c (selftests_sha1): Add 3 tests. + * sha256.c (selftests_sha256, selftests_sha224): Ditto. + * sha512.c (selftests_sha512, selftests_sha384): Ditto. + +2008-08-29 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): Remove the special case for RSA + and check whether a custom computation function has been setup. + * rsa.c (compute_keygrip): New. + (_gcry_pubkey_extraspec_rsa): Setup this function. + * ecc.c (compute_keygrip): New. + (_gcry_pubkey_extraspec_ecdsa): Setup this function. + +2008-08-28 Werner Koch + + * cipher.c (cipher_decrypt, cipher_encrypt): Return an error if + mode NONE is used. + (gcry_cipher_open): Allow mode NONE only with a debug flag set and + if not in FIPS mode. + +2008-08-26 Werner Koch + + * pubkey.c (pubkey_generate): Add arg KEYGEN_FLAGS. + (gcry_pk_genkey): Implement new parameter "transient-key" and + pass it as flags to pubkey_generate. + (pubkey_generate): Make use of an ext_generate function. + * rsa.c (generate): Add new arg transient_key and pass appropriate + args to the prime generator. + (_gcry_rsa_generate): Factor all code out to ... + (rsa_generate): .. new func with extra arg KEYGEN_FLAGS. + (_gcry_pubkey_extraspec_ecdsa): Setup rsa_generate. + * primegen.c (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Add new arg RANDOM_LEVEL. + +2008-08-21 Werner Koch + + * primegen.c (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Use a constant macro for the random + level. + +2008-08-19 Werner Koch + + * pubkey.c (sexp_elements_extract_ecc) [!USE_ECC]: Do not allow + allow "curve" parameter. + +2008-08-15 Werner Koch + + * pubkey.c (_gcry_pk_selftest): New. + * dsa.c (selftests_dsa, run_selftests): New. + * rsa.c (selftests_rsa, run_selftests): New. + * ecc.c (selftests_ecdsa, run_selftests): New. + + * md.c (_gcry_md_selftest): New. + * sha1.c (run_selftests, selftests_sha1): New. + * sha256.c (selftests_sha224, selftests_sha256, run_selftests): New. + * sha512.c (selftests_sha384, selftests_sha512, run_selftests): New. + + * des.c (selftest): Remove static variable form selftest. + (des_setkey): No on-the-fly self test in fips mode. + (tripledes_set3keys): Ditto. + + * cipher.c (_gcry_cipher_setkey, _gcry_cipher_setiv): + + * dsa.c (generate): Bail out in fips mode if NBITS is less than 1024. + * rsa.c (generate): Return an error code if the the requested size + is less than 1024 and we are in fpis mode. + (_gcry_rsa_generate): Take care of that error code. + + * ecc.c (generate_curve): In fips mode enable only NIST curves. + + * cipher.c (_gcry_cipher_selftest): New. + + * sha512.c (_gcry_digest_extraspec_sha384) + (_gcry_digest_extraspec_sha512): New. + * sha256.c (_gcry_digest_extraspec_sha224) + (_gcry_digest_extraspec_sha256): New. + * sha1.c (_gcry_digest_extraspec_sha1): New. + * ecc.c (_gcry_pubkey_extraspec_ecdsa): New. + * dsa.c (_gcry_pubkey_extraspec_dsa): New. + * rsa.c (_gcry_pubkey_extraspec_rsa): New. + * rijndael.c (_gcry_cipher_extraspec_aes) + (_gcry_cipher_extraspec_aes192, _gcry_cipher_extraspec_aes256): New. + * des.c (_gcry_cipher_extraspec_tripledes): New. + + * cipher.c (gcry_cipher_register): Rename to _gcry_cipher_register. + Add arg EXTRASPEC. + (dummy_extra_spec): New. + (cipher_table_entry): Add extraspec field. + * md.c (_gcry_md_register): Rename to _gcry_md_register. Add + arg EXTRASPEC. + (dummy_extra_spec): New. + (digest_table_entry): Add extraspec field. + * pubkey.c (gcry_pk_register): Rename to _gcry_pk_register. Add + arg EXTRASPEC. + (dummy_extra_spec): New. + (pubkey_table_entry): Add extraspec field. + + * ac.c: Let most public functions return GPG_ERR_UNSUPPORTED in + fips mode. + + * pubkey.c (pubkey_table_entry): Add field FIPS_ALLOWED and mark + appropriate algorithms. + (dummy_generate, dummy_check_secret_key, dummy_encrypt) + (dummy_decrypt, dummy_sign, dummy_verify, dummy_get_nbits): Signal + a fips error when used. + (gcry_pk_register): In fips mode do not allow to register new + algorithms. + + * md.c (digest_table): Add field FIPS_ALLOWED and mark appropriate + algorithms. + (md_register_default): In fips mode register only fips algorithms. + (gcry_md_register): In fips mode do not allow to register new + algorithms. + (gcry_md_get): Signal a fips error if called. + (gcry_md_hash_buffer): Do not allow rmd160 when not in fips mode. + (md_start_debug): Disable in fips_mode. + + * md.c (gcry_md_register_default): Rename to .. + (md_register_default): .. this. + (md_digest): Remove this commented fucntion. + * pubkey.c (gcry_pk_register_default): Rename to .. + (pk_register_default): .. this. + + * cipher.c (cipher_table_entry): Add field FIPS_ALLOWED. + (gcry_cipher_register_default): Register only fips approved + algorithms. + (gcry_cipher_register): Do not allow to register new ciphers. + (cipher_setiv): Signal fips error. + + * cipher (gcry_cipher_register_default): Rename to .. + (cipher_register_default): .. this. + (REGISTER_DEFAULT_CIPHERS): Adjust for that change. + +2008-07-05 Werner Koch + + * random-daemon.c, random.h, rndhw.c, rndunix.c, rand-internal.h + * random.c, rndegd.c, rndlinux.c, rndw32.c: Move to ../cipher. + * Makefile.am: Remove random stuff. + +2008-06-24 Szakats Istvan (wk) + + * ac.c (_gcry_ac_key_destroy, _gcry_ac_key_pair_generate): Relase + some more memory. + +2008-04-22 Werner Koch + + * rijndael.c (_gcry_aes_cfb_enc, _gcry_aes_cbc_enc) + (_gcry_aes_cfb_dec, _gcry_aes_cbc_dec): Use Padlock if possible. + +2008-04-18 Werner Koch + + * sha1.c (transform_aligned): Remove. That is will obviosuly not + work because we need a scratch working area and our internal API + does not allow to modify the buffers. + + * rijndael.c: Factor tables out to .. + * rijndael-tables.h: .. new. + + * ac.c (ac_data_extract): Make static. + + * camellia.h [HAVE_CONFIG_H]: Include config.h. + + * rndw32.c (registry_poll): Only print the performance data + problem warning once. Suggested by Simon Josefsson. + +2008-03-19 Werner Koch + + * cipher.c (gcry_cipher_open) [USE_AES]: Init bulk encryption only + if requested. Suggested by Dirk Stoecker. + +2008-03-18 Werner Koch + + * sha1.c: Include stdint.h. + (transform): Add arg NBLOCKS so that we can work on more than one + block and avoid updates of the chaining variables. Changed all + callers to use 1. + (sha1_write): Replace loop around transform. + (transform_aligned) [WORDS_BIGENDIAN]: New. + (TRANSFORM): New macro to replace all direct calls of transform. + +2008-03-17 Werner Koch + + * rijndael.c (_gcry_aes_cfb_dec): New. + (do_encrypt): Factor code out to .. + (do_encrypt_aligned): .. New. + (_gcry_aes_cfb_enc, _gcry_aes_cfb_dec): Use new function. + (do_decrypt): Factor code out to .. + (do_decrypt_aligned): .. new. + (_gcry_aes_cbc_enc, _gcry_aes_cbc_dec): New. + * cipher.c (struct gcry_cipher_handle): Put field IV into new + union U_IV to enforce proper alignment. Change all users. + (do_cfb_decrypt): Optimize. + (do_cbc_encrypt, do_cbc_decrypt): Optimize. + +2008-03-15 Werner Koch + + * rijndael.c (_gcry_aes_cfb_enc): New. + * cipher.c (struct gcry_cipher_handle): Add field ALGO and BULK. + (gcry_cipher_open): Set ALGO and BULK. + (do_cfb_encrypt): Optimize. + +2008-02-18 Werner Koch + + * rsa.c (_gcry_rsa_verify) [IS_DEVELOPMENT_VERSION]: Print + intermediate results. + +2008-01-08 Werner Koch + + * random.c (add_randomness): Do not just increment + POOL_FILLED_COUNTER but update it by the actual amount of data. + +2007-12-13 Werner Koch + + * pubkey.c (sexp_data_to_mpi): Support SHA-224. + +2007-12-05 Werner Koch + + * rijndael.c (USE_PADLOCK): Depend on ENABLE_PADLOCK_SUPPORT. + * rndhw.c (USE_PADLOCK): Ditto + + * rsa.c (secret): Fixed condition test for using CRT. Reported by + Dean Scarff. Fixes bug#864. + (_gcry_rsa_check_secret_key): Return an erro if the optional + parameters are missing. + * pubkey.c (sexp_elements_extract): Add arg ALGO_NAME. Changed all + callers to pass NULL. Add hack to allow for optional RSA + parameters. + (sexp_to_key): Pass algo name to sexp_elements_extract. + +2007-12-03 Werner Koch + + * random.c (gcry_random_add_bytes): Implement it. + * rand-internal.h (RANDOM_ORIGIN_EXTERNAL): New. + +2007-11-30 Werner Koch + + * rndhw.c: New. + * rndlinux.c (_gcry_rndlinux_gather_random): Try to read 50% + directly from the hwrng. + * random.c (do_fast_random_poll): Also run the hw rng fast poll. + (_gcry_random_dump_stats): Tell whether the hw rng failed. + +2007-11-29 Werner Koch + + * rijndael.c (USE_PADLOCK): Define new macro used for ia32. + (RIJNDAEL_context) [USE_PADLOCK]: Add fields USE_PADLOCK and + PADLOCK_KEY. + (do_setkey) [USE_PADLOCK]: Enable padlock if available for 128 bit + AES. + (do_padlock) [USE_PADLOCK]: New. + (rijndael_encrypt, rijndael_decrypt) [USE_PADLOCK]: Divert to + do_padlock. + * cipher.c (cipher_context_alignment_t): New. Use it in this + module in place of PROPERLY_ALIGNED_TYPE. + (NEED_16BYTE_ALIGNED_CONTEXT): Define macro for ia32. + (struct gcry_cipher_handle): Add field HANDLE_OFFSET. + (gcry_cipher_open): Take care of increased alignment requirements. + (gcry_cipher_close): Ditto. + +2007-11-28 Werner Koch + + * sha256.c (asn224): Fixed wrong template. It happened due to a + bug in RFC4880. SHA-224 is not in the stable version of libgcrypt + so the consequences are limited to users of this devel version. + +2007-10-31 Werner Koch + + * ac.c (gcry_ac_data_new): Remove due to the visibility wrapper. + (gcry_ac_data_destroy, gcry_ac_data_copy, gcry_ac_data_length) + (gcry_ac_data_set, gcry_ac_data_get_name, gcry_ac_data_get_index) + (gcry_ac_data_to_sexp, gcry_ac_data_from_sexp) + (gcry_ac_data_clear, gcry_ac_io_init, gcry_ac_open) + (gcry_ac_close, gcry_ac_key_init, gcry_ac_key_pair_generate) + (gcry_ac_key_pair_extract, gcry_ac_key_destroy) + (gcry_ac_key_pair_destroy, gcry_ac_key_data_get) + (gcry_ac_key_test, gcry_ac_key_get_nbits, gcry_ac_key_get_grip) + (gcry_ac_data_encrypt, gcry_ac_data_decrypt, gcry_ac_data_sign) + (gcry_ac_data_verify, gcry_ac_data_encode, gcry_ac_data_decode) + (gcry_ac_mpi_to_os, gcry_ac_mpi_to_os_alloc, gcry_ac_os_to_mpi) + (gcry_ac_data_encrypt_scheme, gcry_ac_data_decrypt_scheme) + (gcry_ac_data_sign_scheme, gcry_ac_data_verify_scheme) + (gcry_ac_io_init_va): Ditto. + (gcry_ac_id_to_name, gcry_ac_name_to_id): Remove as these + deprecated functions are now implemented by visibility.c. + +2007-10-26 Werner Koch + + * rndw32.c: Disable debug flag. + +2007-10-25 Werner Koch + + * rndw32.c: Updated from current cryptlib snapshot and modified + for our use. Removed support from pre NT systems. + (slow_gatherer_windows95): Remove. + (_gcry_rndw32_gather_random): Require an NT platform. + (init_system_rng, read_system_rng, read_mbm_data): New. + (slow_gatherer_windowsNT): Rename to ... + (slow_gatherer): .. this. Read system RNG and MBM. + (registry_poll): New with code factored out from slow_gatherer. + +2007-08-23 Werner Koch + + * random.c (pool_filled_counter): New. + (add_randomness): Use it. + +2007-08-22 Werner Koch + + * rndw32.c, rndunix.c: Switched to LGPL. + +2007-05-30 Werner Koch + + * camellia.h, camellia.c: Replace by new LGPL version and adjusted + camellia.h. + +2007-05-09 Marcus Brinkmann + + * ac.c (_gcry_ac_io_init_va, _gcry_ac_io_write, _gcry_ac_io_read): + Adjust users of gcry_ac_io_t because union is not anonymous + anymore. + +2007-05-02 Werner Koch + + * camellia-glue.c (camellia_setkey, camellia_encrypt) + (camellia_decrypt): Recalculated used stack size in called + functions. + * camellia.h: Redefine external symbols. + +2007-05-02 David Shaw + + * Makefile.am, cipher.c: Add Camellia. + + * camellia-glue.c: New. The necessary glue to interface libgcrypt + to the stock NTT Camellia distribution. + + * camellia.h, camellia.c: The stock NTT Camellia distribution + (GPL). + +2007-04-30 David Shaw + + * cipher.c: Use #if instead of #ifdef as configure defines the + USE_cipher defines as 0 for disabled. + +2007-04-30 Werner Koch + + * rndegd.c (_gcry_rndegd_set_socket_name): New. + +2007-04-30 Marcus Brinkmann + + * ecc.c (ec2os): Fix relocation of short numbers. + + * ecc.c (generate_key): Do not allocate D, which will be allocated + by GEN_K. Remove G. Fix test if g_x, g_y resp. q_x, q_y are + requested. + (_gcry_ecc_generate): Release unneeded members of SK. + * pubkey.c (sexp_to_key): Release NAME. + +2007-04-28 Marcus Brinkmann + + * ac.c (gcry_ac_mpi): Remove member NAME_PROVIDED. + (ac_data_mpi_copy, _gcry_ac_data_set, _gcry_ac_data_get_name) + (_gcry_ac_data_get_index, ac_data_construct): Adjust handling of + NAME accordingly. + +2007-04-20 Werner Koch + + * ecc.c (domain_parms): Add standard brainpool curves. + +2007-04-18 Werner Koch + + * ecc.c (generate_curve): Implement alias mechanism. + + * pubkey.c (sexp_elements_extract_ecc): New. + (sexp_to_key): Add special case for ecc. + (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_genkey): Replace + name_terminated stuff by a call to _gcry_sexp_nth_string. + (gcry_pk_get_keygrip): Ditto. + +2007-04-16 Werner Koch + + * ecc.c (_gcry_ecc_generate): Renamed DUMMY to CURVE and use it. + +2007-04-13 Marcus Brinkmann + + * ac.c (ac_data_construct): Cast const away to suppress compiler + warning. + + * ecc.c (ecc_generate): Avoid compiler warning for unused argument + DUMMY. + (ecc_verify): Avoid compiler warning for unused arguments CMP and + OPAQUEV. + +2007-04-06 Werner Koch + + * sha1.c (oid_spec_sha1): Add another oid from X9.62. + +2007-03-28 Werner Koch + + * pubkey.c (gcry_pk_genkey): Do not issue misc-key-info if it is + empty. + (gcry_pk_genkey): New parameter "curve". + + * ecc.c: Entirely rewritten with only a few traces of the old + code left. + (_gcry_ecc_generate): New. + (generate_key) New arg NAME. + (generate_curve): Ditto. Return actual number of NBITS. + +2007-03-26 Werner Koch + + * pubkey.c (gcry_pk_genkey): Increase size of SKEY array and add a + runtime bounds check. + +2007-03-23 Werner Koch + + * ecc.c (ecc_ctx_init, ecc_ctx_free, ecc_mod, ecc_mulm): New. + (duplicate_point, sum_points, escalar_mult): Don't use a + copy of base->p. Replaced all mpi_mulm by ecc_mulm so that we can + experiment with different algorithms. + (generate_key, check_secret_key, sign, verify): Initialize a + computation context for use by ecc_mulm. + +2007-03-22 Werner Koch + + * pubkey.c (pubkey_table): Initialize ECC. + * Makefile.am (EXTRA_libcipher_la_SOURCES): Add ecc.c. + * ecc.c: New. Heavily reformatted and changed for use in libgcrypt. + (point_init): New. + (escalar_mult): Make arg R the first arg to be similar to the mpi + functions. + (duplicate_point): Ditto + (sum_points): Ditto + (sign, verify): Remove unneeded copy operations. + (sum_points): Removed memory leaks and optimized some compares. + (verify): Simplified input check. + +2007-03-14 Werner Koch + + * random.c (MASK_LEVEL): Removed macro as it was used only at one + place. Open coded it there. + (gcry_randomize, _gcry_update_random_seed_file) + (_gcry_fast_random_poll): Factor lock code out to .. + (lock_pool, unlock_pool): .. new. + (initialize): Look the pool while allocating. + (read_random_source, do_fast_random_poll): Moved intialization to ... + (initialize): .. here. + (_gcry_enable_quick_random_gen): No more need for initialization. + (is_initialized): Moved this global flag to .. + (initialize): .. here and changed all users to unconditionally call + initialize. + (add_randomness): Remove initalization here. It simply can't + happen. + + * random.c (enum random_origins): Moved to .. + * rand-internal.h: .. here. + * rndunix.c (_gcry_rndunix_gather_random): Use enum in prototype + for ORIGIN and renamed REQUESTOR to ORIGIN. + * rndegd.c (_gcry_rndegd_gather_random): Ditto. + * rndlinux.c (_gcry_rndlinux_gather_random): Ditto. + * rndw32.c (_gcry_rndw32_gather_random): Ditto. + (_gcry_rndw32_gather_random_fast): Ditto. + +2007-03-13 Werner Koch + + * random.c (enum random_origins): New. + (add_randomness): Renamed arg SOURCE to ORIGIN. + (read_random_source): Renamed arg REQUESTOR to ORIGIN. + (getfnc_gather_random): Removed static variable because this + function is only called one and thus we don't need this + optimization. + (_gcry_quick_random_gen): Removed and replaced by.. + (_gcry_enable_quick_random_gen): .. this. It is onlyu used to + enable it and it does not make sense to disable it later. Changed + the only one caller too. + (get_random_bytes): Removed. + (gcry_random_bytes, gcry_random_bytes_secure): Implement in terms + of gcry_randomize. + * random-daemon.c (_gcry_daemon_get_random_bytes): Removed. + +2007-02-23 Werner Koch + + * elgamal.c (generate): Removed unused variable TEMP. + (test_keys): New arg NODIE. + (generate_using_x, _gcry_elg_generate_using_x): New. + * pubkey.c (pubkey_generate): New arg XVALUE and direct call to + the new elgamal generate fucntion. + (gcry_pk_genkey): Parse the new "xvalue" tag. + +2007-02-22 Werner Koch + + * pubkey.c (sexp_data_to_mpi): Handle dynamically allocated + algorithms. Suggested by Neil Dunbar. Fixes bug#596. + + * rndw32.c (_gcry_rndw32_gather_random_fast): Make it return void. + + * cipher.c (gcry_cipher_algo_name): Simplified. + + * random.c: Use the daemon only if compiled with USE_RANDOM_DAEMON. + + * Makefile.am (libcipher_la_SOURCES): Build random-daemon support + only if requested. + +2007-02-21 Werner Koch + + * random.c (rndpool, keypool): Make unsigned. + (mix_pool): Change char* variables to unsigned char*. + (gcry_randomize): Make arg BUFFER a void*. + (gcry_create_nonce): Ditto. + + * rmd160.c (gcry_rmd160_mixblock): Make BUFFER a void*. + (_gcry_rmd160_hash_buffer): Make OUTBUF and BUFFER void*. + * sha1.c (_gcry_sha1_hash_buffer): Ditto. + + * cipher.c (gcry_cipher_encrypt, cry_cipher_decrypt): Change + buffer args to void*. + (gcry_cipher_register): Make ALGORITHM_ID a int *. + + * md.c (md_start_debug): Make SUFFIX a const char*. Use snprintf. + (gcry_md_debug): New. + (gcry_md_ctl): Changed arg BUFFER from unsigned char*. + + * md.c (md_write): Make INBUF a const void*. + (gcry_md_write): Remove needless cast. + * crc.c (crc32_write): Make INBUF a const void* + (update_crc32, crc24rfc2440_write): Ditto. + * sha512.c (sha512_write, transform): Ditto. + * sha256.c (sha256_write, transform): Ditto. + * rmd160.c (rmd160_write, transform): Ditto. + * md5.c (md5_write, transform): Ditto. + * md4.c (md4_write, transform): Ditto. + * sha1.c (sha1_write, transform): Ditto. + + * tiger.c (tiger_write, transform): Ditto. + * whirlpool.c (whirlpool_write, whirlpool_add, transform): Ditto. + + * elgamal.c (elg_names): Change to a const*. + * dsa.c (dsa_names): Ditto. + * rsa.c (rsa_names): Ditto. + * pubkey.c (gcry_pk_lookup_func_name): Make ALIASES a const. + +2007-02-20 Werner Koch + + * rndlinux.c (open_device): Remove unsused arg MINOR. + +2007-01-30 Werner Koch + + * sha256.c (oid_spec_sha256): Add alias from pkcs#1. + * sha512.c (oid_spec_sha512): Ditto. + (oid_spec_sha384): Ditto. + +2006-12-18 Werner Koch + + * rndlinux.c (set_cloexec_flag): New. + (open_device): Set close-on-exit flags. Suggested by Max + Kellermann. Fixes Debian#403613. + + * Makefile.am (AM_CPPFLAGS, AM_CFLAGS): Splitted and merged + Moritz' changes. + (INCLUDES): Removed. + +2006-11-30 Werner Koch + + * serpent.c (byte_swap_32): Remove trailing semicolon. + +2006-11-15 Werner Koch + + * Makefile.am (INCLUDES): Include ../src/ + +2006-11-03 Werner Koch + + * random.c [HAVE_GETTIMEOFDAY]: Included sys/time.h and not + sys/times.h. Reported by RafaĂ«l CarrĂ©. + +2006-11-05 Moritz Schulte + + * Makefile.am (AM_CFLAGS): Added -I$(top_builddir)/src so that the + new gcrypt.h is used, not the one installed in the system. + +2006-10-25 Werner Koch + + * primegen.c (prime_generate_internal): Tweaked use of secure + memory and entropy use. Safe unused primes from the pool. Allocate + at least a pool of 30. + (save_pool_prime, get_pool_prime): New. + +2006-10-23 Werner Koch + + * ac.c (_gcry_ac_data_from_sexp): Reset sexp_tmp for failsafe + means. Release sexp_cur if needed. Reported by Dirk Stoecker. + + * pubkey.c (pubkeys_registered_lock): Intialized it. It is not + realy needed because this is a mere initialization to 0 anyway. + Noted by Victor Stinner. + +2006-10-17 Werner Koch + + * dsa.c (_gcry_dsa_generate2): New. + (generate): New arg QBITS. Add sanity checks for reasonable qbits + and nbits. + * pubkey.c (gcry_pk_genkey): Parse an qbits element. + (pubkey_generate): New arg QBITS. Pass it to the DSA generation. + +2006-10-05 Werner Koch + + * md.c (gcry_md_algo_info) : Check that the algo is + available. + +2006-10-04 David Shaw (wk) + + * tiger.c (round): Rename to tiger_round as gcc 4 has a built-in + round function that this conflicts with. + +2006-09-11 Werner Koch + + * rndw32.c (slow_gatherer_windowsNT): While adding data use the + size of the diskPerformance and not its address. Has been fixed in + GnuPG more than a year ago. Noted by Lee Fisher. + +2006-08-30 Werner Koch + + * pubkey.c (sexp_data_to_mpi): Need to allow "ripemd160" here as + this is the canonical name. + +2006-08-29 Hye-Shik Chang (wk) + + * seed.c: New. + +2006-08-03 Werner Koch + + * random-daemon.c (_gcry_daemon_initialize_basics): Don't + initialize the socket. Remove arg SOCKETNAME. + (connect_to_socket): Make sure that daemon is set to -1 on error. + (call_daemon): Initialize the socket on the first call. + (_gcry_daemon_randomize, _gcry_daemon_get_random_bytes) + (_gcry_daemon_create_nonce): New arg SOCKETNAME. + * random.c (initialize): Call new daemon initializator. + (get_random_bytes, gcry_randomize, gcry_create_nonce): Pass socket + name to daemon call and reset allow_daemon on failure. + +2006-07-26 Werner Koch + + * rmd160.c (_gcry_rmd160_mixblock): Add cast to transform call. + + * blowfish.c (selftest): Cast string to usnigned char*. + + * primegen.c (prime_generate_internal): Cast unsigned/char* + mismatch in calling m_out_of_n. + (is_prime): Changed COUNT to unsigned int *. + + * ac.c (_gcry_ac_data_copy): Initialize DATA_MPIS. + + * random.c (gcry_create_nonce): Update the pid after a fork. + Reported by Uoti Urpala. + +2006-07-04 Marcus Brinkmann + + * sha512.c: Fix typo in copyright notice. + +2006-06-21 Werner Koch + + * rsa.c (_gcry_rsa_generate): Replace xcalloc by calloc. + * pubkey.c (gcry_pk_encrypt, gcry_pk_sign): Ditto. + (sexp_to_key, sexp_to_sig, sexp_to_enc, gcry_pk_encrypt) + (gcry_pk_sign, gcry_pk_genkey, gcry_pk_get_keygrip): Ditto. + * md.c (md_copy): Ditto. + +2006-04-22 Moritz Schulte + + * random-daemon.c (_gcry_daemon_initialize_basics): New argument: + SOCKETNAME. Passing on to connect_to_socket() if non-NULL. + (connect_to_socket, writen, readn, call_daemon): New functions. + (_gcry_daemon_randomize, _gcry_daemon_get_random_bytes) + (_gcry_daemon_create_nonce): Call call_daemon(). + (RANDOM_DAEMON_SOCKET): New symbol. + (daemon_socket): New static variable. + + * random.h (_gcry_daemon_initialize_basics): New parameter: + SOCKETNAME. + (_gcry_set_random_daemon_socket): New declaration. + + * random.c (initialize_basics): Pass DAEMON_SOCKET_NAME to + _gcry_daemon_initialize_basics. + (_gcry_set_random_daemon_socket): New function, setting + DAEMON_SOCKET_NAME. + +2006-04-01 Moritz Schulte + + * ac.c (eme_pkcs_v1_5_encode): Use KEY_SIZE directly, no need to + call gcry_ac_key_get_nbits. + (eme_pkcs_v1_5_decode): Likewise. + (ac_es_dencode_prepare_pkcs_v1_5): Fill options_em structure with + key_size. + (_gcry_ac_data_dump, gcry_ac_data_dump): New functions. + (_gcry_ac_data_to_sexp, _gcry_ac_data_from_sexp): More or less + rewritten; changed S-Expression format so that it matches the one + used in pubkey.c. + +2006-03-15 Werner Koch + + * random-daemon.c: New. + * random.c (_gcry_use_random_daemon): New. + (get_random_bytes, gcry_randomize, gcry_create_nonce): Try + diverting to the daemon functions. + +2006-03-14 Werner Koch + + * random.c (lock_seed_file): New. + (read_seed_file, _gcry_update_random_seed_file): Use it. + + * random.c (gcry_create_nonce): Detect a fork and re-seed. + (read_pool): Fixed the fork detection; it used to work only for + multi-threaded processes. + +2006-03-12 Brad Hards (wk) + + * md.c (md_open): Use new variable macpads_Bsize instead of + hardwiring the block size. Changed at all places. + +2006-03-10 Brad Hards (wk, patch 2005-04-22) + + * md.c, sha256.c: Add support for SHA-224. + (sha224_init): New. + +2006-01-18 Brad Hards (wk 2006-03-07) + + * cipher.c (cipher_encrypt, cipher_decrypt, do_ofb_encrypt) + (do_ofb_decrypt, gcry_cipher_open): Implement Output Feedback Mode. + +2005-11-02 Moritz Schulte + + * pubkey.c (gcry_pk_algo_name): Return "?" instead of NULL for + unknown algorithm IDs. + * cipher.c (cipher_algo_to_string): Likewise. + +2005-11-01 Moritz Schulte + + * pubkey.c (gcry_pk_algo_info): Don't forget to break after switch + case. + +2005-09-19 Werner Koch + + * dsa.c (generate): Add preliminary support for 2 and 4 keys. + Return an error code if the key size is not supported. + (_gcry_dsa_generate): Return an error. + +2005-08-22 Werner Koch + + * primegen.c (check_prime): New arg RM_ROUNDS. + (prime_generate_internal): Call it here with 5 rounds as used + before. + (gcry_prime_check): But here with 64 rounds. + (is_prime): Make sure never to use less than 5 rounds. + +2005-04-16 Moritz Schulte + + * ac.c (_gcry_ac_init): New function. + +2005-04-12 Moritz Schulte + + * ac.c (_gcry_ac_io_write, _gcry_ac_io_read): Initialize err to + make the compiler happy. + Always use errno, now that gcry_malloc() is guaranteed to set + errno on failure. + (_gcry_ac_data_to_sexp): Don't forget to goto out after error in + loop. + (_gcry_ac_data_to_sexp): Remove unused variable: mpi_list; + (_gcry_ac_data_to_sexp): Always deallocate sexp_buffer. + (_gcry_ac_data_from_sexp): Don't forget to initialize data_set_new. + (_gcry_ac_data_from_sexp): Handle special case, which is + necessary, since gcry_sexp_nth() does not distinguish between + "element does not exist" and "element is the empty list". + (_gcry_ac_io_init_va): Use assert to make sure that mode and type + are correct. + Use gcry_error_t types where gcry_err_code_t types have been used + before. + +2005-04-11 Moritz Schulte + + * ac.c (_gcry_ac_data_sign_scheme): Don't forget to initialize + buffer. + + * whirlpool.c: New file. + * md.c (digest_table): Add whirlpool. + * Makefile.am (EXTRA_libcipher_la_SOURCES): Added: whirlpool.c. + +2005-03-30 Moritz Schulte + + * ac.c (_gcry_ac_data_from_sexp): Use length of SEXP_CUR, not + length of SEXP; do not forget to set SEXP_TMP to NULL after it has + been released. + + (struct gcry_ac_mpi): New member: name_provided. + (_gcry_ac_data_set): Rename variable `name_final' to `name_cp'; + remove const qualifier; change code to not cast away const + qualifiers; use name_provided member as well. + (_gcry_ac_data_set, _gcry_ac_data_get_name): Use name_provided + member of named mpi structure. + + (gcry_ac_name_to_id): Do not forget to initialize err. + (_gcry_ac_data_get_index): Do not forget to initialize mpi_return; + use gcry_free() instead of free(); remove unnecessary cast; rename + mpi_return and name_return to mpi_cp and name_cp; adjust code. + (ac_data_mpi_copy): Do not cast away const qualifier. + (ac_data_values_destroy): Likewise. + (ac_data_construct): Likewise. + + (ac_data_mpi_copy): Initialize flags to GCRY_AC_FLAG_DEALLOC. + (ac_data_extract): Use GCRY_AC_FLAG_DEALLOC instead of + GCRY_AC_FLAG_COPY. + + (_gcry_ac_io_init_va, _gcry_ac_io_init, gcry_ac_io_init) + (gcry_ac_io_init_va, _gcry_ac_io_write, _gcry_ac_io_read) + (_gcry_ac_io_read_all, _gcry_ac_io_process): New functions. + (gry_ac_em_dencode_t): Use gcry_ac_io_t in prototype instead of + memroy strings directly; adjust encode/decode functions to use io + objects. + (emsa_pkcs_v1_5_encode_data_cb): New function ... + (emsa_pkcs_v1_5_encode): ... use it here. + (ac_data_dencode): Use io objects. + (_gcry_ac_data_encode, _gcry_ac_data_decode, gcry_ac_data_encode) + (gcry_ac_data_decode): Likewise. + (_gcry_ac_data_encrypt_scheme, gcry_ac_data_encrypt_scheme) + (_gcry_ac_data_decrypt_scheme, gcry_ac_data_decrypt_scheme) + (_gcry_ac_data_sign_scheme, gcry_ac_data_sign_scheme) + (_gcry_ac_data_verify_scheme, gcry_ac_data_verify_scheme): + Likewise. + +2005-03-23 Werner Koch + + * rndw32.c (_gcry_rndw32_gather_random_fast): While adding data + use the size of the object and not the one of its address. Bug + reported by Sascha Kiefer. + +2005-03-19 Moritz Schulte + + * cipher.c (do_cbc_encrypt): Be careful to not overwrite data, + which is to be used later on. This happend, in case CTS is + enabled and OUTBUF is equal to INBUF. + +2005-02-25 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): Allow for shadowed-private-key. + +2005-02-13 Moritz Schulte + + * serpent.c: Updated from 1.2 branch: + + s/u32_t/u32/ and s/byte_t/byte/. Too match what we have always + used and are using in all other files too + (serpent_test): Moved prototype out of a fucntion. + +2005-02-07 Moritz Schulte + + * ac.c: Major parts rewritten. + * pubkey.c (_gcry_pk_get_elements): New function. + +2004-12-09 Werner Koch + + * serpent.c (serpent_setkey): Moved prototype of serpent_test to + outer scope. + +2004-09-11 Moritz Schulte + + * pubkey.c (pubkey_table): Added an alias entry for GCRY_PK_ELG_E. + +2004-08-23 Moritz Schulte + + * ac.c: Do not include . + * rndegd.c: Likewise. + * sha1.c: Likewise. + * rndunix.c: Likewise. + * rndlinux.c: Likewise. + * rmd160.c: Likewise. + * md5.c: Likewise. + * md4.c: Likewise. + * cipher.c: Likewise. + * crc.c: Likewise. + * blowfish.c: Likewise. + + * pubkey.c (dummy_generate, dummy_check_secret_key) + (dummy_encrypt, dummy_decrypt, dummy_sign, dummy_verify): Return + err code GPG_ERR_NOT_IMPLEMENTED instead of aborting through + log_bug(). + (dummy_get_nbits): Return 0 instead of aborting though log_bug(). + +2004-08-19 Werner Koch + + * pubkey.c (sexp_data_to_mpi): Changed the zero random byte + substituting code to actually do clever things. Thanks to + Matthias Urlichs for noting the implementation problem. + +2004-08-09 Moritz Schulte + + * pubkey.c (gcry_pk_sign): Fixed memory leak; fix provided by + Modestas Vainius. + +2004-07-16 Werner Koch + + * rijndael.c (do_encrypt): Fix alignment problem. Bugs found by + Matthias Urlichs. + (do_decrypt): Ditto. + (keySched, keySched2): Use 2 macros along with unions in the key + schedule context. + +2004-07-14 Moritz Schulte + + * rsa.c (_gcry_rsa_decrypt): Don't forget to free "a". Thanks to + Nikos Mavroyanopoulos. + +2004-05-09 Werner Koch + + * random.c (read_pool): Mix the PID in to better protect after a + fork. + +2004-07-04 Moritz Schulte + + * serpent.c: Use "u32_t" instead of "unsigned long", do not + declare S-Box variables as "register". Fixes failure on + OpenBSD/sparc64, reported by Nikolay Sturm. + +2004-05-07 Werner Koch + + * random.c (initialize): Factored out some code to .. + (initialize_basics): .. new function. + (_gcry_random_initialize): Just call initialize_basics unless the + new arg FULL is set to TRUE. + (_gcry_fast_random_poll): Don't do anything unless the random + system has been really initialized. + +2004-05-07 Moritz Schulte + + * ac.c (gcry_ac_open): Do not dereference NULL pointer. Reported + by Umberto Salsi. + +2004-02-20 Werner Koch + + * primegen.c (check_prime): New args CB_FUNC and CB_ARG; call them + at different stages. Pass these arguments through all callers. + +2004-02-06 Werner Koch + + * des.c: Add a new OID as used by pkcs#12. + + * rfc2268.c: New. Taken from libgcrypt. + * cipher.c: Setup the rfc2268 algorithm. + +2004-01-25 Moritz Schulte + + * primegen.c (prime_generate_internal): Do not forget to free + `q_factor'; fixed by Brieuc Jeunhomme. + (prime_generate_internal): Do not forget to free `prime'. + +2004-01-14 Moritz Schulte + + * ac.c (gcry_ac_data_set): New argument: flags; slightly + rewritten. + (gcry_ac_data_get_name, gcry_ac_data_get_index): Likewise. + (gcry_ac_key_pair_generate): New argument: misc_data; modified + order of arguments. + (gcry_ac_key_test): New argument: handle. + (gcry_ac_key_get_nbits, gcry_ac_key_get_grip): Likewise. + Use GCRY_AC_FLAG_NO_BLINDING instead of + GCRY_AC_DATA_FLAG_NO_BLINDING. + (gcry_ac_mpi): New member: flags. + (gcry_ac_data_search, gcry_ac_data_add): Removed functions. + +2003-12-22 Werner Koch + + * primegen.c (is_prime): Release A2. + +2003-12-19 Werner Koch + + * md.c: Moved a couple of functions down below the data structure + definitions. + (struct gcry_md_context): New field ACTUAL_HANDLE_SIZE. + (md_open): Set it here. + (strcut gcry_md_list): New field ACTUAL_STRUCT_SIZE. + (md_enable): Set it here. + (md_close): Wipe the context memory. + secure memory. + * cipher.c (struct gcry_cipher_handle): New field ACTUAL_HANDLE_SIZE. + (gcry_cipher_open): Set it here. + (gcry_cipher_close): Use it to always wipe out the handle data. + + * ac.c (gcry_ac_open): Make sure HANDLE gets initialized even when + the function is not successful. + (gcry_ac_close): Allow a NULL handle. + (gcry_ac_key_destroy, gcry_ac_key_pair_destroy): Ditto. + (gcry_ac_key_get_grip): Return INV_OBJ on error. + + * primegen.c (prime_generate_internal): Fixed error code for + failed malloc. Replaced the !err if chain by gotos. + (gcry_prime_group_generator): Remove the extra sanity check. + + * md.c: Minor code and comment cleanups. + +2003-12-16 Werner Koch + + * primegen.c (gen_prime): Doc fix. Thanks to Newton Hammet. + +2003-12-11 Werner Koch + + * rndunix.c (slow_poll): Don't use #warning but #error. + + * rndegd.c: Changed indentation. + (my_make_filename): Removd the var_arg cruft becuase we + don't need it here. Changed caller. + + * rndlinux.c: Changed indentation. + (open_device): Remove the superfluous stat call and clarify + comment. + + * rsa.c: Changed indentation. + (secret): Use the standard algorithm if p, q and u are not + available. + (rsa_blind, rsa_unblind): Renamed from _gcry_rsa_blind, + _gcry_rsa_unblind and moved more to the top. + + * md4.c: Changed indentation. Removed unnecessary casts. + * md5.c, rmd160.c, sha1.c, tiger.c: Ditto. + * rijndael.c, twofish.c: Ditto. + * serpent.c: Removed unnecessary casts. + * sha256.c, sha512.c: Ditto. + +2003-12-09 Werner Koch + + * dsa.c: Unified indentation style. + * elgamal.c: Ditto. + * des.c (des_key_schedule): Code beautifications. + * blowfish.c: Changed indentation style. + * cast5.c (do_cast_setkey): Ditto. + + * pubkey.c (gcry_pk_encrypt): Replaced the chain of if(!err) tests + by straightforward gotos. Other cleanups. + (gcry_pk_decrypt): Ditto. + (gcry_pk_sign): Ditto. + (gcry_pk_verify): Ditto. + (gcry_pk_genkey): Ditto. Use strtoul instead of strtol. + (gcry_pk_ctl): Use GPG_ERR_INV_ARG to indicate bad arguments. + +2003-12-07 Werner Koch + + * pubkey.c (gcry_pk_register_default): Undef the helper macro. + (gcry_pk_map_name): Allow NULL for string. + (sexp_to_key): Use memcpy and not strncpy. Use gcry_free and not + free. + (sexp_to_sig): Ditto. + (sexp_to_enc): Ditto. Replaced the chain of if(!err) tests by + straightforward gotos. + +2003-12-05 Werner Koch + + * cipher.c: Documentation cleanups. + (gcry_cipher_mode_from_oid): Allow NULL for STRING. + +2003-12-03 Werner Koch + + * elgamal.c (sign, do_encrypt, gen_k): Make sure that a small K is + only used for encryption. + +2003-11-18 Werner Koch + + * random.h (rndw32_set_dll_name): Removed unused prototype. + + * Makefile.am (EXTRA_DIST): Added Manifest. + +2003-11-11 Werner Koch + + * Manifest: New. + +2003-11-04 Werner Koch + + * md.c (gcry_md_hash_buffer): Use shortcut for SHA1 + * sha1.c (_gcry_sha1_hash_buffer): New. + + * random.c: Reformatted most functions. + (mix_pool): Moved the failsafe_digest from global + scope to here. + (do_fast_random_poll): Use the generic fucntions even if a fast + gathering function has been used. + (read_pool): Detect a fork and retry. + (gcry_randomize, get_random_bytes): Don't distinguish anymore + between weak and strong random. + (gcry_create_nonce): New. + +2003-10-31 Werner Koch + + * rndw32.c (slow_gatherer_windowsNT): Use a plain buffer for the + disk performance values and not the W32 API structure. + + * dsa.c (verify): s/exp/ex/ due to shadowing of a builtin. + * elgamal.c (verify): Ditto. + + * ac.c (gcry_ac_data_get_index): s/index/idx/ + (gcry_ac_data_copy_internal): Remove the cast in _gcry_malloc. + (gcry_ac_data_add): Must use gcry_realloc instead of realloc. + * pubkey.c (sexp_elements_extract): s/index/idx/ as tribute to the + forehackers. + (gcry_pk_encrypt): Removed shadowed definition of I. Reordered + arguments to malloc for clarity. + (gcry_pk_sign, gcry_pk_genkey): Ditto. + * primegen.c (prime_generate_internal): s/random/randomlevel/. + +2003-10-27 Moritz Schulte + + * pubkey.c (gcry_pk_encrypt): Don't forget to deallocate pkey. + +2003-10-27 Werner Koch + + * random.c (gcry_random_add_bytes): Return if buflen is zero to + avoid gcc warning about unsed parameter. + (MASK_LEVEL): Simplified; does now work for signed and unsigned + w/o warnings. + + * md.c (md_start_debug): Removed the const from SUFFIX, because + this function is called from the control fucntion which does not + require const. + + Prefixed all (pubkey,digest,cipher}_spec_* globale variables with + _gcry_. + + * ac.c (ac_key_identifiers): Made static. + + * random.c (getfnc_gather_random,getfnc_fast_random_poll): Move + prototypes to .. + * rand-internal.h: .. here + * random.c (getfnc_gather_random): Include rndw32 gatherer. + * rndunix.c, rndw32.c, rndegd.c: Include them here. + * rndlinux.c (_gcry_rndlinux_gather_random): Prepend the _gcry_ + prefix. Changed all callers. + * rndegd.c (_gcry_rndegd_gather_random): Likewise. + (_gcry_rndegd_connect_socket): Likewise. + * rndunix.c (_gcry_rndunix_gather_random): Likewise. + (waitpid): Made static. + * rndw32.c: Removed the old and unused winseed.dll cruft. + (_gcry_rndw32_gather_random_fast): Renamed from + gather_random_fast. + (_gcry_rndw32_gather_random): Renamed from gather_random. Note, + that the changes 2003-04-08 somehow got lost. + + * sha512.c (sha512_init, sha384_init): Made static. + + * cipher.c (do_ctr_decrypt): Removed "return" from this void + function. + +2003-10-24 Moritz Schulte + + * serpent.c: Fix an issue on big-endian systems. + + * rndw32.c: Removed IS_MODULE -cruft. + * rndlinux.c (rndlinux_gather_random): Likewise. + +2003-10-10 Werner Koch + + * primegen.c (gen_prime): Bail out if NBITS is less than 16. + (prime_generate_internal): Initialize prime variable to suppress + compiler warning. Check pbits, initialize qbits when passed as + zero. + + * primegen.c (prime_generate_internal): New arg + ALL_FACTORS. Changed all callers. + (gcry_prime_generate): Make the factors arg optional. Request + all_factors. Make sure PRIME is set to NULL even on error. + (gcry_prime_group_generator): New. + (gcry_prime_release_factors): New. + +2003-10-06 Werner Koch + + * primegen.c (gen_prime): Assert that NBITS is never zero, it + would cause a segv. + +2003-09-28 Moritz Schulte + + * ac.c: Include "cipher.h". + +2003-09-27 Moritz Schulte + + * rndegd.c (do_read): Return nread instead of nbytes; thanks to + Michael Caerwyn. + +2003-09-04 Werner Koch + + * pubkey.c (_gcry_pk_aliased_algo_name): New. + * ac.c (gcry_ac_open): Use it here. + + * Makefile.am (EXTRA_libcipher_la_SOURCES): Add serpent.c + +2003-09-02 Moritz Schulte + + * primegen.c (gcry_prime_check, gcry_prime_generate): New + functions. + (prime_generate_internal): New function, based on + _gcry_generate_elg_prime. + (_gcry_generate_elg_prime): Rewritten as a wrapper for + prime_generate_internal. + +2003-08-28 Werner Koch + + * pubkey.c (gcry_pk_encrypt): Don't include the flags list in the + return value. This does not make sense and breaks any programs + parsing the output strictly (e.g. current gpgsm). + (gcry_pk_encrypt): If aliases for the algorithm name exists, take + the first one instead of the regular name to adhere to SPKI + conventions. + (gcry_pk_genkey): Ditto. + (gcry_pk_sign): Ditto. Removed unused KEY_ALGO_NAME. + +2003-08-19 Moritz Schulte + + * cipher.c: Add support for Serpent + * serpent.c: New file. + +2003-08-10 Moritz Schulte + + * rsa.c (_gcry_rsa_blind, _gcry_rsa_unblind): Declare static. + +2003-08-09 Timo Schulz + + * random.c (getfnc_gather_random): Don't check NAME_OF_DEV_RANDOM + two times, but also the NAME_OF_DEV_URANDOM device. + +2003-08-08 Moritz Schulte + + * pubkey.c (sexp_to_enc): Fixed extraction of S-Expression: do not + fail if no `flags' sub S-Expression is found. + +2003-07-27 Werner Koch + + * md.c (gcry_md_lookup_func_oid): Allow for empty OID lists. + +2003-07-23 Moritz Schulte + + * ac.c (gcry_ac_data_construct): New argument: include_flags, only + include `flags' S-expression, if include_flags is true. Adjust + callers. Thanks for triggering a bug caused by `flags' + sub-S-expression where they are not expected to Ralf Schneider. + +2003-07-21 Moritz Schulte + + * pubkey.c (gcry_pk_lookup_func_name): Use new member name + `aliases' instead of `sexp_names'. + + * ac.c (gcry_ac_key_data_get): New function. + + * cipher.c (gcry_cipher_lookup_func_name): Fix return value. + +2003-07-20 Moritz Schulte + + * blowfish.c: Adjusted for new gcry_cipher_spec_t structure. + * cast5.c: Likewise. + * twofish.c: Likewise. + * arcfour.c: Likewise. + * rijndael.c (rijndael_oids, rijndael192_oids, rijndael256_oids): + New variables, adjust for new gcry_cipher_spec_t structure. + * des.c (oids_tripledes): New variable, adjust for new + gcry_cipher_spec_t structure. + + * md.c (oid_table): Removed. + + * tiger.c (oid_spec_tiger): New variable. + (digest_spec_tiger): Adjusted for new gry_md_spec_t structure. + + * sha512.c (oid_spec_sha512): New variable. + (digest_spec_sha512): Adjusted for new gry_md_spec_t structure. + + * sha512.c (oid_spec_sha384): New variable. + (digest_spec_sha384): Adjusted for new gry_md_spec_t structure. + + * sha256.c (oid_spec_sha256): New variable. + (digest_spec_sha256): Adjusted for new gry_md_spec_t structure. + + * sha1.c (oid_spec_sha1): New variable. + (digest_spec_sha1): Adjusted for new gry_md_spec_t structure. + + * rmd160.c (oid_spec_rmd160): New variable. + (digest_spec_rnd160): Adjusted for new gry_md_spec_t structure. + + * md5.c (oid_spec_md5): New variable. + (digest_spec_md5): Adjusted for new gry_md_spec_t structure. + + * md4.c (oid_spec_md4): New variable. + (digest_spec_md4): Adjusted for new gry_md_spec_t structure. + + * crc.c (digest_spec_crc32, digest_spec_crc32_rfc1510, + digest_spec_crc32_rfc2440): Adjusted for new gry_md_spec_t + structure. + +2003-07-19 Moritz Schulte + + * md.c (gcry_md_lookup_func_oid): New function. + (search_oid): New function, copied from cipher.c. + (gcry_md_map_name): Adjust for new search_oid_interface. + + * cipher.c (oid_table): Removed table. + (gcry_cipher_lookup_func_oid): New function. + (search_oid): Rewritten to use the module functions. + (gcry_cipher_map_name): Adjust for new search_oid interface. + (gcry_cipher_mode_from_oid): Likewise. + +2003-07-18 Werner Koch + + * md.c (gcry_md_hash_buffer): Convert ERR to gpg_error_t in + gpg_strerror. + +2003-07-14 Moritz Schulte + + * cipher.c (gcry_cipher_lookup_func_name): Also check the cipher + name aliases, not just the primary name. + (gcry_cipher_map_name): Remove kludge for aliasing Rijndael to + AES. + + * arcfour.c, blowfish.c, cast5.c, des.c, twofish.c: Adjust cipher + specification structures. + + * rijndael.c (rijndael_names, rijndael192_names, + rijndael256_names): New variables, use them in the cipher + specifications. + + * rmd160test.c: Removed file. + + * ac.c, arcfour.c, blowfish.c, cast5.c, cipher.c, des.c, dsa.c, + elgamal.c, md.c, pubkey.c, random.c, rijndael.c, rsa.c, twofish.c: + Used gcry_err* wrappers for libgpg symbols. + + * primegen.c (gen_prime): Correct the order arguments to + extra_check. + +2003-07-12 Moritz Schulte + + * ac.c: Replaced all public occurences of gpg_error_t with + gcry_error_t. + * cipher.c: Likewise. + * md.c: Likewise. + * pubkey.c: Likewise. + * random.c: Likewise. + + * cipher.c: Added support for TWOFISH128. + +2003-07-08 Moritz Schulte + + * ac.c (gcry_ac_data_copy_internal): New function, based on + gcry_ac_data_copy. + (gcry_ac_data_copy): Made public, use gcry_ac_data_copy_internal. + (gcry_ac_key_init): Use gcry_ac_data_copy_internal. + +2003-07-07 Moritz Schulte + + * ac.c (gcry_ac_data_set): Only release old MPI value if it is + different from the new value. Bug reported by Simon Josefsson + . + + * pubkey.c (gcry_pk_list): New function. + * md.c (gcry_md_list): New function. + + * ac.c (gcry_ac_key_pair_generate): Fix calculation of format + string size. + +2003-07-05 Moritz Schulte + + * md.c: Named struct of digest_table `digest_table_entry'. + (digest_table_entry): New member: algorithm; filled in. + (digest_table_entry): Removed unused member: flags. + (gcry_md_register): New argument: algorithm_id, filled in. + (gcry_md_register_default): Used algorithm ID from module + structure. + (gcry_md_map_name): Likewise. + (md_enable): Likewise. + (md_read): Likewise. + (gcry_md_info): Likewise. + + * pubkey.c: Named truct for pubkey_table `pubkey_table_entry'. + (pubkey_table_entry): New member: algorithm; filled in. + (gcry_pk_register_default): Used algorithm ID from pubkey_table. + (gcry_pk_register): New argument: algorithm_id, filled in. + (gcry_pk_map_name): Used algorithm ID from module structure. + (gcry_pk_decrypt): Likewise. + (gcry_pk_encrypt): Likewise. + (gcry_pk_verify): Likewise. + (gcry_pk_sign): Likewise. + (gcry_pk_testkey): Likewise. + (gcry_pk_genkey): Likewise. + (gcry_pk_get_nbits): Likewise. + (sexp_to_key): Removed unused variable: algo. + (sexp_to_sig): Likewise. + + * cipher.c: Named struct for cipher_table `cipher_table_entry'. + (cipher_table_entry): New member: algorithm; filled in. + (gcry_cipher_register_default): Used algorithm ID from + cipher_table. + (gcry_cipher_register): New argument: algorithm_id, filled in. + (gcry_cipher_map_name): Used algorithm ID from module structure. + + * arcfour.c (cipher_spec_arcfour): Removed algorithm ID. + * blowfish.c (cipher_spec_blowfish): Likewise. + * cast5.c (cipher_spec_cast5): Likewise. + * crc.c (digest_spec_crc32): Likewise. + * crc.c (digest_spec_crc32_rfc1510): Likewise. + * crc.c (digest_spec_crc32_rfc2440): Likewise. + * des.c (cipher_spec_des): Likewise. + * des.c (cipher_spec_tripledes): Likewise. + * dsa.c (pubkey_spec_dsa): Likewise. + * elgamal.c (pubkey_spec_elg): Likewise. + * md4.c (digest_spec_md4): Likewise. + * md5.c (digest_spec_md5): Likewise. + * aes.c (cipher_spec_aes): Likewise. + * aes.c (cipher_spec_aes192): Likewise. + * aes.c (cipher_spec_aes256): Likewise. + * rsa.c (pubkey_spec_rsa): Likewise. + * sha1.c (digest_spec_sha1): Likewise. + * sha256.c (digest_spec_sha256): Likewise. + * sha512.c (digest_spec_sha512): Likewise. + * tiger.c (digest_spec_tiger): Likewise. + * twofish.c (cipher_spec_twofish): Likewise. + * twofish.c (cipher_spec_twofish128): Likewise. + + * Makefile.am (EXTRA_libcipher_la_SOURCES): Fix list of source + files; reported by Simon Josefsson . + + * pubkey.c: Replaced all occurences of `id' with `algorithm', + since `id' is a keyword in obj-c. + * md.c: Likewise. + * cipher.c: Likewise. + + * crc.c, md4.c, md5.c, rmd160.c, sha1.c, sha256.c, tiger.c: + Replaced all occurences of gcry_digest_spec_t with gcry_md_spec_t. + + * dsa.c, rsa.c, elgamal.c: Replaced all occurencens of + gcry_pubkey_spec_t with gcry_pk_spec_t. + + * md.c: Replaced all occurences of gcry_digest_spec_t with + gcry_md_spec_t. + (gcry_digest_register_default): Renamed to ... + (gcry_md_register_default): ... this; adjusted callers. + (gcry_digest_lookup_func_name): Renamed to ... + (gcry_md_lookup_func_name): ... this; adjusted callers. + (gcry_digest_lookup_name): Renamed to ... + (gcry_md_lookup_name): ... this; adjusted callers. + (gcry_digest_register): Renamed to ... + (gcry_md_register): ... this. + (gcry_digest_unregister): Renamed to ... + (gcry_md_unregister): ... this. + + * pubkey.c (gcry_pubkey_register): Renamed to ... + (gcry_pk_register): ... this. + (gcry_pubkey_unregister): Renamed to ... + (gcry_pk_unregister): ... this. + Replaced all occurences of gcry_pubkey_spec_t with gcry_pk_spec_t. + (gcry_pubkey_register_default): Renamed to ... + (gcry_pk_register_default): ... this; adjusted callers. + (gcry_pubkey_lookup_func_name): Renamed to ... + (gcry_pk_lookup_func_name): ... this; adjusted callers. + (gcry_pubkey_lookup_name): Renamed to ... + (gcry_pk_lookup_name): ... this; adjusted callers. + + * md.c (gcry_md_hash_buffer): Fix error checking. Thanks to Simon + Josefsson . + +2003-07-04 Moritz Schulte + + * cipher.c (gcry_cipher_list): New function. + +2003-07-01 Moritz Schulte + + * pubkey.c (sexp_to_sig): Accept a `flags' S-expression to be more + consistent with sexp_to_enc. + +2003-06-30 Moritz Schulte + + * Makefile.am (libcipher_la_SOURCES): Added: ac.c. + + * pubkey.c (_gcry_pk_module_lookup): New function. + (_gcry_pk_module_release): New function. + +2003-06-29 Moritz Schulte + + * ac.c: New file. + +2003-06-26 Werner Koch + + * md.c (gcry_md_hash_buffer): Trigger BUG correcly with new API. + +2003-06-19 Werner Koch + + * md.c (gcry_md_is_enabled): Fixed. + +2003-06-18 Werner Koch + + * cipher.c (gcry_cipher_get_algo_keylen): New. + (gcry_cipher_get_algo_blklen): New. + +2003-06-18 Moritz Schulte + + * arcfour.c, cipher.c, blowfish.c, md.c, cast5.c, pubkey.c, crc.c, + des.c, dsa.c, elgamal.c, md4.c, md5.c, random.c, rijndael.c, + rmd160.c, rsa.c, sha1.c, sha256.c, sha512.c, tiger.c, twofish.c: + Replaced older types GcryDigestSpec, GcryCipherSpec and + GcryPubkeySpec with newer types: gcry_digest_spec_t, + gcry_cipher_spec_t and gcry_pubkey_spec_t. + + * md.c (gcry_digest_id_new): Removed function. + (gcry_digest_register): Removed code for generating a new module + ID. + + * pubkey.c (gcry_pubkey_id_new): Removed function. + (gcry_pubkey_register): Removed code for generating a new module + ID. + + * cipher.c, md.c, pubkey.c: Replace old type GcryModule with newer + one: gcry_module_t. + (gcry_cipher_id_new): Removed function. + (gcry_cipher_register): Removed code for generating a new module + ID. + + * cipher.c (gcry_cipher_register): Adjust call to + _gcry_module_add. + (gcry_cipher_register_default): Likewise. + * pubkey.c (gcry_pubkey_register_default): Likewise. + (gcry_pubkey_register): Likewise. + * md.c (gcry_digest_register_default): Likewise. + (gcry_digest_register): Likewise. + + * md.c (gcry_digest_lookup_func_id): Removed function. + (gcry_digest_lookup_id): Likewise. + (gcry_digest_id_new): Use _gcry_module_lookup_id instead of + gcry_digest_lookup_id. + (digest_algo_to_string): Likewise. + (check_digest_algo): Likewise. + (md_enable): Likewise. + (md_digest_length): Likewise. + (md_asn_oid): Likewise. + + * pubkey.c (gcry_pubkey_lookup_id): Removed function. + (gcry_pubkey_lookup_func_id): Likewise. + (gcry_pubkey_id_new): Use _gcry_module_lookup_id instead of + gcry_pubkey_id_new. + (gcry_pk_algo_name): Likewise. + (disable_pubkey_algo): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_get_npkey): Likewise. + (pubkey_get_nskey): Likewise. + (pubkey_get_nsig): Likewise. + (pubkey_get_nenc): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (gcry_pk_algo_info): Likewise. + + * cipher.c (gcry_cipher_lookup_func_id): Removed function. + (gcry_cipher_lookup_id): Likewise. + (cipher_algo_to_string): use _gcry_module_lookup_id instead of + gcry_cipher_lookup_id. + (disable_cipher_algo): Likewise. + (check_cipher_algo): Likewise. + (cipher_get_blocksize): Likewise. + (gcry_cipher_open): Likewise. + (gcry_cipher_id_new): Likewise. + +2003-06-17 Moritz Schulte + + * Makefile.am (GCRYPT_MODULES): Set to @GCRYPT_CIPHERS@, + @GCRYPT_PUBKEY_CIPHERS@, @GCRYPT_DIGESTS@ and @GCRYPT_RANDOM@. + (libcipher_la_DEPENDENCIES): Set to $(GCRYPT_MODULES). + (libcipher_la_LIBADD): Likewise. + (AM_CFLAGS): Added: @GPG_ERROR_CFLAGS@. + (EXTRA_libcipher_la_SOURCES): Added all conditional sources. + + * md.c (md_open): Use _gcry_fast_random_poll instead of + fast_random_poll. + * cipher.c (gcry_cipher_open): Likewise. + + * random.h (fast_random_poll): Removed macro. + + * blowfish.c, md4.c, md5.c, rmd160.c, sha1.c, sha256.c, sha512.c, + tiger.c: Use Autoconf's WORDS_BIGENDIAN instead of our own + BIG_ENDIAN_HOST. + +2003-06-16 Moritz Schulte + + * random.c (getfnc_gather_random): Do not special-case + USE_ALL_RANDOM_MODULES, make it the default. + + * dsa.c: Replace last occurences of old type names with newer + names (i.e. replace MPI with gcry_mpi_t). + * elgamal.c: Likewise. + * primegen.c: Likewise. + * pubkey.c: Likewise. + * rsa.c: Likewise. + +2003-06-14 Moritz Schulte + + * des.c (des_setkey): Add selftest check. + (tripledes_set3keys): Likewise. + (do_tripledes_setkey): Remove selftest check. + (do_des_setkey): Likewise. + +2003-06-11 Moritz Schulte + + * md.c (_gcry_md_init): New function. + * cipher.c (_gcry_cipher_init): New function. + * pubkey.c (_gcry_pk_init): New function. + +2003-06-13 Werner Koch + + * md.c (gcry_md_get_algo): Reverted to old API. This is a + convenience function anyway and error checking is not approriate. + (gcry_md_is_secure): New. + (gcry_md_is_enabled): New. + +2003-06-12 Werner Koch + + * cipher.c (gcry_cipher_open): Make sure HANDLE is set to NULL on + error. + +2003-06-11 Werner Koch + + * md.c (gcry_md_open): Make sure H receives either NULL or an + valid handle. + (gcry_md_copy): Swapped arguments so that it is more in lione with + md_open and most other API fucntions like memcpy (destination + comes first). Make sure HANDLE is set to NULL on error. + + * rijndael.c (do_encrypt): Hack to force correct alignment. It + seems not to be not sufficient, though. We should rework this + fucntions and remove all these ugly casts. Let the compiler + optimize or have an assembler implementation. + +2003-06-09 Moritz Schulte + + * Makefile.am: Removed rules serpent, since that is not commited + yet. + +2003-06-08 Moritz Schulte + + * pubkey.c (gcry_pk_encrypt): Improve calculation for size of the + format string. + +2003-06-07 Moritz Schulte + + * arcfour.c, bithelp.h, blowfish.c, cast5.c, cipher.c, crc.c, + des.c, dsa.c, elgamal.c, md4.c, md5.c, md.c, primegen.c, pubkey.c, + rand-internal.h, random.c, random.h, rijndael.c, rmd160.c, + rmd160test.c, rmd.h, rndeged.c, rndlinux.c, rndunix.c, rndw32.c, + rsa.c, sha1.c, sha256.c, sha512.c, tiger.c, twofish.c: Edited all + preprocessor instructions to remove whitespace before the '#'. + This is not required by C89, but there are some compilers out + there that don't like it. Replaced any occurence of the now + deprecated type names with the new ones. + +2003-06-04 Moritz Schulte + + * pubkey.c (gcry_pk_encrypt): Construct an arg_list and use + gcry_sexp_build_array instead of gcry_sexp_build. + (gcry_pk_sign): Likewise. + (gcry_pk_genkey): Likewise. + +2003-06-01 Moritz Schulte + + * dsa.c (_gcry_dsa_generate): Do not check wether the algorithm ID + does indeed belong to DSA. + (_gcry_dsa_sign): Likewise. + (_gcry_dsa_verify): Likewise. + (_gcry_dsa_get_nbits): Likewise. + + * elgamal.c (_gcry_elg_check_secret_key): Do not check wether the + algorithm ID does indeed belong to ElGamal. + (_gcry_elg_encrypt): Likewise. + (_gcry_elg_decrypt): Likewise. + (_gcry_elg_sign): Likewise. + (_gcry_elg_verify): Likewise. + (_gcry_elg_get_nbits): Likewise. + (_gcry_elg_generate): Likewise. + + * rsa.c (_gcry_rsa_generate): Do not check wether the algorithm ID + does indeed belong to RSA. + (_gcry_rsa_encrypt): Likewise. + (_gcry_rsa_decrypt): Likewise. + (_gcry_rsa_sign): Likewise. + (_gcry_rsa_verify): Likewise. + (_gcry_rsa_get_nbits): Likewise. + +2003-05-30 Moritz Schulte + + * md.c (md_get_algo): Return zero in case to algorithm is enabled. + + * md.c (gcry_md_info): Adjusted for new no-errno-API. + (md_final): Likewise. + (gcry_md_get_algo): Likewise. + * pubkey.c (gcry_pk_get_keygrip): Likewise. + (gcry_pk_ctl): Likewise. + (gcry_pk_algo_info): Likewise. + * des.c (selftest): Likewise. + +2003-05-29 Moritz Schulte + + * md.c (md_enable): Do not forget to release module on error. + (gcry_md_open): Adjusted for new no-errno-API. + (md_open): Likewise. + (md_copy): Likewise. + (gcry_md_copy): Likewise. + (gcry_md_setkey): Likewise. + (gcry_md_algo_info): Likewise. + + * cipher.c (gcry_cipher_open): Adjusted for new no-errno-API and + also fixed a locking bug. + (gcry_cipher_encrypt): Adjusted for new no-errno-API. + (gcry_cipher_decrypt): Likewise. + (gcry_cipher_ctl): Likewise. + (gcry_cipher_info): Likewise. + (gcry_cipher_algo_info): Likewise. + +2003-05-28 Moritz Schulte + + * md.c (md_enable): Adjusted for libgpg-error. + (gcry_md_enable): Likewise. + (gcry_digest_register_default): Likewise. + (gcry_digest_register): Likewise. + (check_digest_algo): Likewise. + (prepare_macpads): Likewise. + (gcry_md_setkey): Likewise. + (gcry_md_ctl): Likewise. + (gcry_md_get): Likewise. + (gcry_md_algo_info): Likewise. + (gcry_md_info): Likewise. + * dsa.c (_gcry_dsa_generate): Likewise. + (_gcry_dsa_check_secret_key): Likewise. + (_gcry_dsa_sign): Likewie. + (_gcry_dsa_verify): Likewise. + * twofish.c (do_twofish_setkey): Likewise. + (twofish_setkey): Likewise. + * cipher.c (gcry_cipher_register): Likewise. + +2003-05-25 Moritz Schulte + + * rijndael.c (do_setkey): Adjusted for libgpg-error. + (rijndael_setkey): Likewise. + * random.c (gcry_random_add_bytes): Likewise. + * elgamal.c (_gcry_elg_generate): Likewise. + (_gcry_elg_check_secret_key): Likewise. + (_gcry_elg_encrypt): Likewise. + (_gcry_elg_decrypt): Likewise. + (_gcry_elg_sign): Likewise. + (_gcry_elg_verify): Likewise. + * rsa.c (_gcry_rsa_generate): Likewise. + (_gcry_rsa_check_secret_key): Likewise. + (_gcry_rsa_encrypt): Likewise. + (_gcry_rsa_decrypt): Likewise. + (_gcry_rsa_sign): Likewise. + (_gcry_rsa_verify): Likewise. + * pubkey.c (dummy_generate, dummy_check_secret_key, dummy_encrypt, + dummy_decrypt, dummy_sign, dummy_verify): Likewise. + (gcry_pubkey_register): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (sexp_elements_extract): Likewise. + (sexp_to_key): Likewise. + (sexp_to_sig): Likewise. + (sexp_to_enc): Likewise. + (sexp_data_to_mpi): Likewise. + (gcry_pk_encrypt): Likewise. + (gcry_pk_decrypt): Likewise. + (gcry_pk_sign): Likewise. + (gcry_pk_verify): Likewise. + (gcry_pk_testkey): Likewise. + (gcry_pk_genkey): Likewise. + (gcry_pk_ctl): Likewise. + * cipher.c (dummy_setkey): Likewise. + (check_cipher_algo): Likewise. + (gcry_cipher_open): Likewise. + (cipher_setkey): Likewise. + (gcry_cipher_ctl): Likewise. + (cipher_encrypt): Likewise. + (gcry_cipher_encrypt): Likewise. + (cipher_decrypt): Likewise. + (gcry_cipher_decrypt): Likewise. + (gcry_cipher_info): Likewise. + (gcry_cipher_algo_info): Likewise. + * cast5.c (cast_setkey): Likewise. + (do_cast_setkey): Likewise. + * arcfour.c (arcfour_setkey): Likewise. + (do_arcfour_setkey): Likewise. + * blowfish.c (do_bf_setkey): Likewise. + (bf_setkey): Likewise. + * des.c (do_des_setkey): Likewise. + (do_tripledes_setkey): Likewise. + +2003-05-22 Moritz Schulte + + * tiger.c: Merged code ussing the U64_C macro from GnuPG. + + * sha512.c: Likewise. + +2003-05-17 Moritz Schulte + + * pubkey.c (gcry_pk_genkey): Fix type: acquire a lock, instead of + releasing it. + +2003-05-11 Moritz Schulte + + * pubkey.c (gcry_pk_testkey): Call REGISTER_DEFAULT_CIPHERS. + (gcry_pk_ctl): Likewise. + +2003-04-27 Moritz Schulte + + * pubkey.c (gcry_pk_genkey): Release sexp after extracted data has + been used. + + * md.c (gcry_md_get_algo_dlen): Simplified, simply call + md_digest_length to do the job. + + * des.c (do_des_setkey): Check for selftest failure not only + during initialization. + (do_tripledes_setkey): Include check for selftest failure. + + * pubkey.c (gcry_pubkey_register_default): New macro + `pubkey_use_dummy', use it. + + * elgamal.c (elg_names): New variable. + (pubkey_spec_elg): Include elg_names. + + * dsa.c (dsa_names): New variable. + (pubkey_spec_dsa): Include dsa_names. + + * rsa.c (rsa_names): New variable. + (pubkey_spec_rsa): Include rsa_names. + + * pubkey.c (gcry_pubkey_lookup_func_name): Compare name also with + the names listed in `sexp_names'. + +2003-04-24 Moritz Schulte + + * pubkey.c (sexp_to_key): New variables: module, pubkey. Adjusted + to new module interface. + (sexp_to_key): Changend type of argument `retalgo' from `int *' to + `GcryModule **'. Adjusted all callers. Removed argument: + r_algotblidx. + (sexp_to_sig): Changend type of argument `retalgo' from `int *' to + `GcryModule **'. Adjusted all callers. + (sexp_to_enc): Likewise. + + (pubkey_get_npkey, pubkey_get_nskey, pubkey_get_nsig, + pubkey_get_nenc): Use strlen to find out the number. + + * rsa.c: Adjust pubkey_spec_rsa to new internal interface. + * dsa.c: Likewise. + * elgamal.c: Likewise. + +2003-04-17 Moritz Schulte + + * pubkey.c (sexp_elements_extract): New function. + * pubkey.c (sexp_to_key): Removed variable `idx', added `err', use + sexp_elements_extract. + (sexp_to_sig): Likewise. + (sexp_to_enc): Likewise. + + * pubkey.c: Terminate list correctly. + * md.c: Include sha512/sha384 in digest_table. + +2003-04-16 Moritz Schulte + + * Makefile.am: Include support for sha512.c. + + * sha512.c: New file, merged from GnuPG, with few modifications + for libgcrypt. + + * rand-internal.h: Removed declarations for constructor functions. + + * md.c (md_copy): Call _gcry_module_use for incrementing the usage + counter of the digest modules. + + * rsa.c: Do not include "rsa.h". + * dsa.c: Do not include "dsa.h". + * elgamal.c: Do not include "elgamal.h". + * des.c: Do not include "des.h". + * cast5.c: Do not include "cast5.h". + * blowfish.c: Do not include "blowfish.h". + * arcfour.c: Do not include "arcfour.h". + + * Makefile.am (libcipher_la_DEPENDENCIES): Removed. + (libcipher_la_LIBADD): Removed. + Use Automake conditionals for conditional compilation. + +2003-04-13 Moritz Schulte + + * cipher.c (gcry_cipher_open): Call REGISTER_DEFAULT_CIPHERS. + + * md.c (gcry_md_list): New member: module. + (md_enable): New variable: module, changed use of module and + digest. + (md_enable): Initialize member: module. + (md_close): Call _gcry_module_release. + + * cipher.c (gcry_cipher_open): New variable: module, changed use of + module and cipher. + (struct gcry_cipher_handle): New member: module. + (gcry_cipher_open): Initialize member: module. + (gcry_cipher_close): Call _gcry_module_release. + +2003-04-09 Moritz Schulte + + * cipher.c: Include "ath.h". + * md.c: Likewise. + * pubkey.c: Likewise. + + * cipher.c (ciphers_registered_lock): New variable. + * md.c (digests_registered_lock): New variable. + * pubkey.c (pubkeys_registered_lock): New variable. + + * rndlinux.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndlinux_constructor): Removed function. + + * rndegd.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndegd_constructor): Removed function. + + * rndunix.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndunix_constructor): Removed function. + + * rndw32.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rndw32_constructor): Removed function. + + * rndegd.c (rndegd_connect_socket): Simplify code for creating the + egd socket address. + (rndegd_connect_socket): Call log_fatal use instead of + g10_log_fatal. + (egd_gather_random): Renamed to ... + (rndegd_gather_random): ... here. + +2003-04-08 Moritz Schulte + + * rndlinux.c: Do not include "dynload.h". + * rndunix.c: Likewise. + * rndw32.c: Likewise. + + * rndegd.c (rndegd_connect_socket): Factored out from ... + (egd_gather_random): here; call it. + (egd_socket): New variable. + (egd_gather_random): Initialize fd with egd_socket, do not declare + fd static. + (do_read): Merged few changes from GnuPG. FIXME - not finished? + Do not include "dynload.h". + + * rndw32.c (gather_random): Renamed to rndw32_gather_random, do + not declare static. + (gather_random_fast): Renamed to rndw32_gather_random_fast, do not + declare static. + + * rndunix.c (gather_random): Renamed to rndunix_gather_random, do + not declare static. + * rndegd.c (gather_random): Renamed to rndegd_gather_random, do + not declare static. + * rndlinux.c (gather_random): Renamed to rndlinux_gather_random, + do not declare static. + +2003-04-07 Moritz Schulte + + * Makefile.am (libcipher_la_SOURCES): Removed construct.c. + (libcipher_la_SOURCES): Added sha1.c, sha256.c, rmd160.c, md4.c, + md5.c, tiger.c and crc.c + (EXTRA_PROGRAMS): Removed sha1, sha256, rmd160, md4, md5, tiger + and crc. Removed definitions: EXTRA_md4_SOURCES, + EXTRA_md5_SOURCES, EXTRA_rmd160_SOURCES, EXTRA_sha1_SOURCES, + EXTRA_sha256_SOURCES, EXTRA_tiger_SOURCES and EXTRA_crc_SOURCES, + BUILT_SOURCES, DISTCLEANFILES. + + * pubkey.c: Do not include "elgamal.h", "dsa.h" and "rsa.h". + + * Makefile.am (libcipher_la_SOURCES): Removed rsa.h, elgamal.h, + dsa.h, des.h, cast5.h, arcfour.h and blowfish.h. + + * rsa.h: Removed file. + * elgamal.h: Removed file. + * dsa.h: Removed file. + * des.h: Removed file. + * cast5.h: Removed file. + * arcfour.h: Removed file. + * blowfish.h: Removed file. + + * Makefile.am (libcipher_la_SOURCES): Removed dynload.c and + dynload.h. + + * rsa.c (pubkey_spec_rsa): New variable. + * dsa.c (pubkey_spec_rsa): New variable. + * elgamal.c (pubkey_spec_elg): New variable. + + * rsa.c (_gcry_rsa_get_info): Removed function. + * elgamal.c (_gcry_elg_get_info): Removed function. + * dsa.c (_gcry_dsa_get_info): Removed function. + + * tiger.c (tiger_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_tiger_constructor): Removed function. + + * sha1.c (sha1_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_sha1_constructor): Removed function. + + * sha256.c (sha256_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_sha256_constructor): Removed function. + + * rmd160.c (rmd160_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_rmd160_constructor): Removed function. + + * md5.c (md5_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_md5_constructor): Removed function. + + * md4.c (md4_get_info): Removed function. + (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func): Removed function. + (_gcry_md4_constructor): Removed function. + + * crc.c (crc_get_info): Removed function. + + * arcfour.c (do_arcfour_setkey): Changed type of context argument + to `void *', added local variable for cast, adjusted callers. + (arcfour_setkey): Likewise. + (encrypt_stream): Likewise. + * cast5.c (cast_setkey): Likewise. + (encrypt_block): Likewise. + * rijndael.c (rijndael_setkey): Likewise. + (rijndael_encrypt): Likewise. + (rijndael_decrypt): Likewise. + * twofish.c (twofish_setkey): Likewise. + (twofish_encrypt): Likewise. + (twofish_decrypt): Likewise. + * des.c (do_des_setkey): Likewise. + (do_des_encrypt): Likewise. + (do_des_encrypt): Likewise. + (do_tripledes_encrypt): Likewise. + (do_tripledes_encrypt): Likewise. + * blowfish.c (bf_setkey: Likewise. + (encrypt_block): Likewise. + (decrypt_block): Likewise. + + * arcfour.c (encrypt_stream): Likewise. + + * rijndael.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func) Removed function. + + * twofish.c (gnupgext_version, func_table): Removed definitions. + (gnupgext_enum_func) Removed function. + + * cast5.c (CIPHER_ALGO_CAST5): Removed. + + * blowfish.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Removed macros. + (CIPHER_ALGO_BLOWFISH): Removed symbol. + * cast5.c (FNCCAST_SETKEY, FNCCAST_CRYPT): Likewise. + * des.c (selftest_failed): Removed. + (initialized): New variable. + (do_des_setkey): Run selftest, if not yet done. + (FNCCAST_SETKEY, FNCCAST_CRYPT): Removed macros. + + * arcfour.c (_gcry_arcfour_get_info): Removed function. + * blowfish.c (_gcry_blowfish_get_info): Removed function. + * cast5.c (_gcry_cast5_get_info): Removed function. + * des.c (_gcry_des_get_info): Removed function. + * rijndael.c (_gcry_rijndael_get_info): Removed function. + * twofish.c (_gcry_twofish_get_info): Removed function. + + * arcfour.c (cipher_spec_arcfour): New variable. + * twofish.c (cipher_spec_twofish, cipher_spec_twofish128): New + variables. + * rijndael.c (cipher_spec_aes, cipher_spec_aes192, + cipher_spec256): New variables. + * des.c (cipher_spec_des, cipher_spec_tripledes): New variables. + * cast5.c (cipher_spec_cast5): New variable. + * blowfish.c (cipher_spec_blowfish): Likewise. + + * twofish.c: Do not include "dynload.h". + * rijndael.c: Likewise. + * des.c: Likewise. + * cast5.c: Likewise. + * blowfish.c: Likewise. + * cipher.c: Likewise. + * crc.c: Likewise. + * md4.c: Likewise. + * md5.c: Likewise. + * md.c: Likewise. + * pubkey.c: Likewise. + * rijndael.c: Likewise. + * sha1.c: Likewise. + * sha256.c: Likewise. + + * arcfour.c: Include "cipher.h". + * twofish.c: Likewise. + * rijndael.c: Likewise. + * des.c: Likewise. + * cast5.c: Likewise. + * blowfish.c: Likewise. + + * twofish.c (twofish_setkey): Declared argument `key' const. + (twofish_encrypt): Declared argument `inbuf' const. + (twofish_decrypt): Likewise. + + * rijndael.c (rijndael_setkey): Declared argument `key' const. + (rijndael_encrypt): Declared argument `inbuf' const. + (rijndael_decrypt): Likewise. + + * des.c (do_des_setkey): Declared argument `key' const. + (do_tripledes_setkey): Likewise. + (do_des_encrypt): Declared argument `inbuf' const. + (do_des_decrypt): Likewise. + (do_tripledes_encrypt): Likewise. + (do_tripledes_decrypt): Likewise. + + * cast5.c (encrypt_block): Declared argument `inbuf' const. + (decrypt_block): Likewise. + (cast_setkey): Declared argument `key' const. + + * blowfish.c (do_bf_setkey): Declared argument `key' const. + (encrypt_block): Declared argument `inbuf' const. + (encrypt_block): Likewise. + + + + * cipher.c: Remove CIPHER_ALGO_DUMMY related code. + Removed struct cipher_table_s. + Changed definition of cipher_table. + Removed definition of disabled_algos. + (ciphers_registered, default_ciphers_registered): New variables. + (REGISTER_DEFAULT_CIPHERS): New macro. + (dummy_setkey): Declared argument `key' const. + (dummy_encrypt_block): Declared argument `inbuf' const. + (dummy_encrypt_block): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_setkey): Use `unsigned char' instead of `byte'. + (dummy_encrypt_block): Likewise. + (dummy_decrypt_block): Likewise. + (dummy_encrypt_stream): Likewise. + (dummy_decrypt_stream): Likewise. + (gcry_cipher_register_default): New function. + (gcry_cipher_lookup_func_id): New function. + (gcry_cipher_lookup_func_name): New function. + (gcry_cipher_lookup_id): New function. + (gcry_cipher_lookup_name): New function. + (gcry_cipher_id_new): New function. + (gcry_cipher_register): New function. + (gcry_cipher_unregister): New function. + (setup_cipher_table): Removed function. + (load_cipher_modules): Removed function. + (gcry_cipher_map_name): Adjusted to use new module management. + (cipher_algo_to_string): Likewise. + (disable_cipher_algo): Likewise. + (check_cipher_algo): Likewise. + (cipher_get_keylen): Likewise. + (cipher_get_blocksize): Likewise. + (gcry_cipher_open): Likewise. + (struct gcry_cipher_handle): Replaced members algo, algo_index, + blocksize, setkey, encrypt, decrypt, stencrypt, stdecrypt with one + member: cipher. + (gcry_cipher_open): Adjusted code for new handle structure. + (cipher_setkey): Likewise. + (cipher_setiv): Likewise. + (cipher_reset): Likewise. + (do_ecb_encrypt): Likewise. + (do_ecb_decrypt): Likewise. + (do_cbc_encrypt): Likewise. + (do_cbc_decrypt): Likewise. + (do_cfb_encrypt): Likewise. + (do_cfb_decrypt): Likewise. + (do_ctr_encrypt): Likewise. + (cipher_encrypt): Likewise. + (gcry_cipher_encrypt): Likewise. + (cipher_decrypt): Likewise. + (gcry_cipher_decrypt): Likewise. + (cipher_sync): Likewise. + (gcry_cipher_ctl): Likewise. + + * pubkey.c: Removed struct pubkey_table_s. + Changed definition of pubkey_table. + Removed definition of disabled_algos. + (pubkeys_registered, default_pubkeys_registered): New variables. + (REGISTER_DEFAULT_PUBKEYS): New macro. + (setup_pubkey_table): Removed function. + (load_pubkey_modules): Removed function. + (gcry_pubkey_register_default): New function. + (gcry_pubkey_lookup_func_id): New function. + (gcry_pubkey_lookup_func_name): New function. + (gcry_pubkey_lookup_id): New function. + (gcry_pubkey_lookup_name): New function. + (gcry_pubkey_id_new): New function. + (gcry_pubkey_register): New function. + (gcry_pubkey_unregister): New function. + (gcry_pk_map_name): Adjusted to use new module management. + (gcry_pk_algo_name): Likewise. + (disable_pubkey_algo): Likewise. + (check_pubkey_algo): Likewise. + (pubkey_get_npkey): Likewise. + (pubkey_get_nskey): Likewise. + (pubkey_get_nsig): Likewise. + (pubkey_get_nenc): Likewise. + (pubkey_generate): Likewise. + (pubkey_check_secret_key): Likewise. + (pubkey_encrypt): Likewise. + (pubkey_decrypt): Likewise. + (pubkey_sign): Likewise. + (pubkey_verify): Likewise. + (gcry_pk_get_nbits): Likewise. + (gcry_pk_algo_info): Likewise. + + * md.c: Removed struct md_digest_list_s. + (digest_list): Changed definition. + (digests_registered, default_digests_registered): New variables. + (REGISTER_DEFAULT_DIGESTS): New macro. + (new_list_item): Removed function. + (setup_md_table): Removed function. + (load_digest_module): Removed function. + (gcry_digest_register_default): New function. + (gcry_digest_lookup_func_id): New function. + (gcry_digest_lookup_func_name): New function. + (gcry_digest_lookup_id): New function. + (gcry_digest_lookup_name): New function. + (gcry_digest_id_new): New function. + (gcry_digest_register): New function. + (gcry_digest_unregister): New function. + (GcryDigestEntry): New type. + (struct gcry_md_context): Adjusted type of `list'. + (gcry_md_map_name): Adjusted to use new module management. + (digest_algo_to_string): Likewise. + (check_digest_algo): Likewise. + (md_enable): Likewise. + (md_digest_length): Likewise. + (md_asn_oid): Likewise. + +2003-04-07 Moritz Schulte + + * pubkey.c: Replaced PUBKEY_ALGO_DSA with GCRY_PK_DSA, + PUBKEY_ALGO_RSA with GCRY_PK_RSA and PUBKEY_ALGO_ELGAMAL with + GCRY_PK_ELG. + + * dsa.c: Replaced PUBKEY_ALGO_DSA with GCRY_PK_DSA. + +2003-04-01 Moritz Schulte + + * des.c: Removed checks for GCRY_CIPHER_3DES and GCRY_CIPHER_DES. + +2003-03-31 Moritz Schulte + + * tiger.c (tiger_get_info): Do not declare static. + * sha256.c (sha256_get_info): Likewise. + * sha1.c (sha1_get_info): Likewise. + * rmd160.c (rmd160_get_info): Likewise. + * md5.c (md5_get_info): Likewise. + * md4.c (md4_get_info): Likewise. + * crc.c (crc_get_info): Likewise. + + * md.c (load_digest_module): Call setup_md_table during + initialization. + (new_list_item): Link new element into digest_list. + + * cipher.c (do_ctr_decrypt): Made do_ctr_encrypt act as a wrapper + for do_ctr_encrypt, since these functions are identical. + +2003-03-30 Simon Josefsson + + * cipher.c (struct gcry_cipher_handle): Add counter field. + (gcry_cipher_open): Add CTR. + (cipher_reset): Clear counter field. + (do_ctr_encrypt, do_ctr_decrypt): New functions. + (cipher_encrypt, cipher_decrypt): Call CTR functions. + (gcry_cipher_ctl): Add SET_CTR to set counter. + +2003-03-30 Moritz Schulte + + * rsa.c (_gcry_rsa_blind): New function. + (_gcry_rsa_unblind): New function. + (_gcry_rsa_decrypt): Use _gcry_rsa_blind and _gcry_rsa_decrypt. + +2003-03-26 Moritz Schulte + + * dynload.c (_gcry_enum_gnupgext_pubkeys): Adjust `encrypt' and + `decrypt' function arguments. + (_gcry_enum_gnupgext_pubkeys): Likewise. + * dynload.h: Likewise. + + * pubkey.c (dummy_decrypt): Add argument: int flags. + (dummy_encrypt): Likewise. + + * elgamal.c (_gcry_elg_encrypt): Add argument: int flags. + (_gcry_elg_decrypt): Likewise. + + * rsa.c (_gcry_rsa_encrypt): Add argument: int flags. + (_gcry_rsa_decrypt): Likewise. + + * pubkey.c: Add `flags' argument to members `encrypt' and + `decrypt' of struct `pubkey_table_s'. + + * rsa.h: Add `flags' argument to function declarations. + * elgamal.h: Likewise. + + * pubkey.c (sexp_data_to_mpi): New variable: int parsed_flags. + (sexp_data_to_mpi): Set `parsed_flags'. + (sexp_data_to_mpi): New argument: int *flags. + (gcry_pk_encrypt): New variable: int flags. + (gcry_pk_encrypt): Pass `flags' to pubkey_encrypt. + (pubkey_encrypt): New variable: int flags. + (pubkey_encrypt): Pass `flags' to pubkey encrypt function. + (pubkey_decrypt): Likewise. + (pubkey_decrypt): Pass `flags' to pubkey encrypt function. + (gcry_pk_encrypt): Include `flags' s-exp in return list. + (sexp_to_enc): New argument: int *flags. + (gcry_pk_decrypt): New variable: int flags. + (gcry_pk_decrypt): Pass `flags' to pubkey_decrypt. + (sexp_to_enc): New variable: int parsed_flags. + (sexp_to_enc): Set `parsed_flags'. + +2003-03-22 Simon Josefsson + + * cipher.c (gcry_cipher_open, do_cbc_encrypt) + (gcry_cipher_encrypt): Support GCRY_CIPHER_CBC_MAC. + (gcry_cipher_ctl): Support GCRYCTL_SET_CBC_MAC. + +2003-03-19 Werner Koch + + * primegen.c (gen_prime): New args EXTRA_CHECK and EXTRA_CHECK_ARG + to allow for a user callback. Changed all callers. + (_gcry_generate_secret_prime) + (_gcry_generate_public_prime): Ditto, pass them to gen_prime. + * rsa.c (check_exponent): New. + (generate): Use a callback to ensure that a given exponent is + actually generated. + +2003-03-12 Moritz Schulte + + * primegen.c: Initialize `no_of_small_prime_numbers' statically. + (gen_prime): Remove calculation of `no_of_small_prime_numbers'. + +2003-03-03 Moritz Schulte + + * md.c (gcry_md_ctl): Rewritten to use same style like the other + functions dispatchers. + +2003-03-02 Moritz Schulte + + * cipher.c (struct gcry_cipher_handle): New member: algo_index. + (gcry_cipher_open): Allocate memory for two cipher contexts. + Initialize algo_index. + (cipher_setkey): Duplicate context into reserved memory. + (cipher_reset): New function, which resets the context and clear + the IV. + (gcry_cipher_ctl): Call cipher_reset. + +2003-02-23 Moritz Schulte + + * cipher.c: Remove (bogus) `digitp' macro definition. + * md.c: Likewise. + + * blowfish.c (burn_stack): Removed. + * arcfour.c (burn_stack): Likewise. + * cast5.c (burn_stack): Likewise. + * des.c (burn_stack): Likewise. + * md4.c (burn_stack): Likewise. + * md5.c (burn_stack): Likewise. + * random.c (burn_stack): Likewise. + * rijndael.c (burn_stack): Likewise. + * rmd160.c (burn_stack): Likewise. + * sha1.c (burn_stack): Likewise. + * sha256.c (burn_stack): Likewise. + * tiger.c (burn_stack): Likewise. + * twofish.c (burn_stack): Likewise. + + * blowfish.c: Changed all occurences of burn_stack to + _gcry_burn_stack. + * arcfour.c: Likewise. + * cast5.c: Likewise. + * des.c: Likewise. + * md4.c: Likewise. + * md5.c: Likewise. + * random.c: Likewise. + * rijndael.c: Likewise. + * rmd160.c: Likewise. + * sha1.c: Likewise. + * sha256.c: Likewise. + * tiger.c: Likewise. + * twofish.c: Likewise. + + * arcfour.c (_gcry_arcfour_get_info): Use GCRY_CIPHER_ARCFOUR + instead of hard-coded value `301'. + +2003-01-24 Werner Koch + + * random.c (_gcry_register_random_progress): New. + (_gcry_random_progress): New. + + * rndlinux.c (gather_random): Call the random progress function. + +2003-01-23 Werner Koch + + * rsa.c (generate): New arg USE_E to request a specific public + exponent. + (_gcry_rsa_generate): Ditto. + * elgamal.c (_gcry_elg_generate): Must add an dummy argument + instead of USE_E. + * dsa.c (_gcry_dsa_generate): Ditto. + * pubkey.c (dummy_generate): Ditto. + (pubkey_generate): Add USE_E arg and pass it down. + (gcry_pk_genkey): Detect "rsa-use-e" parameter and pass it to generate. + + * pubkey.c (sexp_to_enc): New arg RET_MODERN. + (gcry_pk_decrypt): Make use of it to return a real S-expression. + Return better error codes. + (gcry_pk_verify): Return better error codes. + +2003-01-21 Werner Koch + + * random.c (gcry_random_add_bytes): Add QUALITY argument, let + function return an error code and disable its core for now. + +2003-01-21 Timo Schulz + + * random.c (gcry_random_add_bytes): New. Function to add external + random to the pool. + +2003-01-20 Simon Josefsson + + * crc.c: New. + * Makefile.am (EXTRA_PROGRAMS, EXTRA_crc_SOURCES): Add crc.c. + * md.c (gcry_md_get_algo_dlen): Add values for CRC. + +2003-01-20 Werner Koch + + * sha256.c: New. + * bithelp.h (ror): New. + * Makfile.am: Add sha256.c. + * md.c (oid_table): Add values for SHA256 et al. + (gcry_md_get_algo_dlen): Likewise + +2003-01-20 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): Implemented keygrips for DSA + and ElGamal. + +2003-01-17 Werner Koch + + * cipher.c (gcry_cipher_encrypt): Reworked so that the output will + never contain the plaintext even if the caller did not checked the + return value. + + * md.c (gcry_md_get_algo): Changed error code to GCRYERR_GENERAL + because we don't have an invalid md algo but no algorithm enabled. + + * pubkey.c (gcry_pk_genkey): Changed error code for bounds check + of table parameters to GCRYERR_INTERNAL. + + * md.c (gcry_md_open): Partly reverted Timo's change from + 2002-10-10 by removing the check for the algorithm. An algorithm + of 0 is allowed and anyway we should not double check it or check + it using a different function. Also fixed the flags check. + + * pubkey.c (gcry_pk_encrypt): Make sure that R_CIPH points to NULL + on error. + (gcry_pk_decrypt): Ditto for R_PLAIN. + (gcry_pk_sign): Ditto for R_SIG. + (gcry_pk_genkey): Ditto for R_KEY. + +2003-01-16 Werner Koch + + * md.c (gcry_md_write): Changed 2nd argument type to void*. + (gcry_md_hash_buffer): Changed type of boths buffers to void*. + (gcry_md_setkey): Changed 2nd argument type to void*. + +2003-01-15 Werner Koch + + * pubkey.c (sexp_data_to_mpi): New. This handles pkcs1 padding. + (gcry_pk_sign, gcry_pk_verify): Use it here. + (gcry_pk_encrypt): And here. + (pubkey_verify): Add debug code. + (sexp_to_enc): Handle flags in the input and return the pkcs1 flag + in a new parameter. + (gcry_pk_decrypt): Prepare for future pkcs1 handling. + +2002-12-19 Werner Koch + + * random.c (_gcry_random_initialize): New. + +2002-12-16 Werner Koch + + * cipher.c: Added a Teletrust specific OID for 3DES. + +2002-12-12 Werner Koch + + * md.c: Added another oddball OIW OID (sha-1WithRSAEncryption). + +2002-11-23 Werner Koch + + * md.c (load_digest_module): Enlarged checked_algos bitmap. + * md4.c (func_table): Fixed entry for md4. + Both by Simon Josephson. + (transform): Copy data to get the alignment straight. Tested only + on i386. + +2002-11-10 Simon Josefsson + + * cipher.c (gcry_cipher_open): Don't reject CTS flag. + (do_cbc_encrypt, do_cbc_decrypt, cipher_encrypt) + (gcry_cipher_encrypt, cipher_decrypt) + (gcry_cipher_decrypt): Support CTS flag. + (gcry_cipher_ctl): Toggle CTS flag. + +2002-11-10 Werner Koch + + * md4.c: New. By Simon Josefsson. + * Makefile.am (EXTRA_PROGRAMS): Add md4.c. + * md.c (oid_table,gcry_md_get_algo_dlen): MD4 support. + +2002-10-14 Werner Koch + + * arcfour.c (do_encrypt_stream): Don't use increment op when + assigning to the same variable. + +2002-10-10 Timo Schulz + + * pubkey.c (gcry_pk_genkey): Check boundaries. + + * md.c (gcry_md_open): Check that algo is available and only + valid flag values are used. + (gcry_md_get_algo): Add error handling. + +2002-09-26 Werner Koch + + * md.c: Include an OID for TIGER. + * tiger.c (tiger_get_info): Use a regular OID. + +2002-09-17 Werner Koch + + * random.c: Replaced mutex.h by the new ath.h. Changed all calls. + +2002-09-16 Werner Koch + + * arcfour.c (do_encrypt_stream): Use register modifier and modulo. + According to Nikos Mavroyanopoulos this increases perfromace on + i386 system noticable. And I always tought gcc is clever enough. + * md5.c (transform): Use register modifier. + * rmd160.c (transform): Ditto. + * sha1.c (transform): Ditto. We hope that there are 6 free registers. + * random.c (gcry_randomize): Rewrote to avoid malloc calls. + + * rndlinux.c (gather_random): Replaced remaining fprintfs by log_*. + * arcfour.c (do_arcfour_setkey): Ditto. + * twofish.c (do_twofish_setkey): Ditto. + * rndegd.c (gather_random): Ditto. + * rijndael.c (do_setkey): Ditto. + * random.c (_gcry_random_dump_stats): Ditto. + * primegen.c (_gcry_generate_elg_prime): Ditto. + * des.c (_gcry_des_get_info): Ditto. + * cast5.c (do_cast_setkey): Ditto. + * blowfish.c (do_bf_setkey): Ditto. + +2002-08-26 Werner Koch + + * des.c (weak_keys): Fixed one entry in the table and compared + all entries against the literature. + (selftest): Checksum the weak key table. + +2002-08-21 Werner Koch + + * pubkey.c: Enable keygrip calculation for "openpgp-rsa". + +2002-08-17 Werner Koch + + * cipher.c (setup_cipher_table): Don't overwrite the DES entry + with the entry for DUMMY. + +2002-08-14 Werner Koch + + * des.c (do_des_setkey,do_des_encrypt, do_des_decrypt): New. + (_gcry_des_get_info): Support plain old DES. + * cipher.c (setup_cipher_table): Put DES into the table. + +2002-07-25 Werner Koch + + * rndunix.c (_gcry_rndunix_constructor): Prefixed with _gcry_. + Noted by Stephan Austermuehle. + +2002-07-08 Timo Schulz + + * rndw32.c: Replaced the m_ memory functions with the real + gcry_ functions. Renamed all g10_ prefixed functions to log_. + +2002-06-12 Werner Koch + + * rsa.c (generate): Use e = 65537 for now. + +2002-06-11 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): Allow a "protected-private-key". + +2002-06-05 Timo Schulz + + * cipher.c (gcry_cipher_encrypt, gcry_cipher_decrypt): + Check that the input size is a multiple of the blocksize. + +2002-05-23 Werner Koch + + * md.c (oid_table): Add an rsadsi OID for MD5. + +2002-05-21 Werner Koch + + * primegen.c, elgamal.c, dsa.c (progress): Do not print anything + by default. Pass an extra identifying string to the callback and + reserved 2 argumenst for current and total counters. Changed the + register function prototype. + +2002-05-17 Werner Koch + + * rndegd.c (rndegd_constructor): Fixed name of register function + and prefixed the function name with _gcry_. + * rndw32.c (rndw32_constructor): Ditto. + * tiger.c (tiger_constructor): Ditto. + + * Makefile.am: Removed all dynamic loading stuff. + * dynload.c: Ditto. Now only used for the constructor system. + +2002-05-15 Werner Koch + + * random.c (gcry_random_bytes,gcry_random_bytes_secure) + (gcry_randomize): Make sure we are initialized. + +2002-05-14 Werner Koch + + Changed license of most files to the LGPL. + +2002-05-02 Werner Koch + + * random.c (_gcry_fast_random_poll): Initialize the module so the + mutex can be used. + + * primegen.c (small_prime_numbers): Moved table from smallprime.c + * smallprime.c: File removed. + + * des.c (leftkey_swap, rightkey_swap, working_memcmp): Made static. + + * cipher.c (gcry_cipher_map_name): Map "RIJNDAEL" to "AES". + * rijndael.c (rijndael_get_info): We do only support a 128 bit + blocksize so it makes sense to change the algorithm strings to + AES. + + * tiger.c (tiger_final): Removed superfluous token pasting operators. + * md5.c (md5_final): Ditto. + +2002-04-30 Werner Koch + + * cipher.c: Fixed list of copyright years. + +2002-03-18 Werner Koch + + * random.c (initialize): Initialize the new pool lock mutex. + (_gcry_fast_random_poll): Add locking and moved main + code out to... + (do_fast_random_poll): new function. + (read_pool): Use the new function here. + (get_random_bytes): Add locking. + (_gcry_update_random_seed_file): Ditto. + +2002-03-11 Werner Koch + + * md.c: Add rsaSignatureWithripemd160 to OID table. + +2002-02-20 Werner Koch + + * sha1.c: Removed a left over comment note. The code has been + rewritten from scratch in 1998. Thanks to Niels Möller for + reporting this misleading comment. + +2002-02-18 Werner Koch + + * rndunix.c (rndunix_constructor): Use the the new prefixed + function name. Reported by Jordi Mallach. + +2002-02-10 Werner Koch + + * random.c (mix_pool): Carry an extra failsafe_digest buffer + around to make the function more robust. + +2002-02-08 Werner Koch + + * random.c (add_randomness): Xor new data into the pool and not + just copy it. This avoids any choosen input attacks which are not + serious in our setting because an outsider won't be able to mix + data in and even then we keep going with a PRNG. Thanks to Stefan + Keller for pointing this out. + +2002-01-04 Werner Koch + + * pubkey.c (gcry_pk_genkey): Do not release skey - it is static. + + * primegen.c (gen_prime): Of course we should use set_bit + and not set_highbit to set the second high bit. + +2001-12-18 Werner Koch + + * rsa.c (generate): Loop until we find the exact modulus size. + Changed the exponent to 41. + (rsa_get_info): s/usage/r_usage/ to avoid shadow warnings. + * primegen.c (gen_prime): Set 2 high order bits for secret primes. + + * Makefile.am (DISTCLEANFILES): Include construct.c. + +2001-12-17 Werner Koch + + * pubkey.c (gcry_pk_get_keygrip): New - experimental. + +2001-12-11 Werner Koch + + * cipher.c: Added OIDs for AES. + (gcry_cipher_mode_from_oid): New. + (gcry_cipher_map_name): Moved OID search code to .. + (search_oid): .. new function. + +2001-12-10 Werner Koch + + * pubkey.c (gcry_pk_encrypt): Find the signature algorithm by name + and not by number. + + * pubkey.c (gcry_pk_encrypt,gcry_pk_decrypt,gcry_pk_sign) + (gcry_pk_verify,gcry_pk_testkey, gcry_pk_genkey) + (gcry_pk_get_nbits): Release the arrays. Noted by Nikos + Mavroyanopoulos. + +2001-12-06 Werner Koch + + * cipher.c (gcry_cipher_map_name): Look also for OIDs prefixed + with "oid." or "OID.". + +2001-12-05 Werner Koch + + * pubkey.c (algo_info_table): Fixed entry for openpgp-rsa. + +2001-11-24 Werner Koch + + * pubkey.c: Added the rsaEncryption OID to the tables. + (sexp_to_key): Add an arg to return the index of the algorithm, + changed all callers. + (gcry_pk_sign): Find the signature algorithm by name and not by + number. + (gcry_pk_get_nbits): Fixed so that we can now really pass a secret + key to get the result. + + * md.c (gcry_md_map_name): Look also for OIDs prefixed with "oid." + or "OID." so that an OID string can be used as an S-Exp token. + +2001-11-20 Werner Koch + + * md.c (gcry_md_map_name): Lookup by OID if the the name begins + with a digit. + (oid_table): New. + +2001-11-16 Werner Koch + + * md.c (gcry_md_info): New operator GCRYCTL_IS_ALGO_ENABLED. + +2001-11-07 Werner Koch + + * md.c (gcry_md_hash_buffer): Close the handle which was left open + for algorithms other than rmd160. + +2001-08-08 Werner Koch + + * rndw32.c (gather_random): Use toolhelp in addition to the NT + gatherer for Windows2000. Suggested by Sami Tolvanen. + + * random.c (read_pool): Fixed length check, this used to be one + byte to strict. Made an assert out of it because the caller has + already made sure that only poolsize bytes are requested. + Reported by Marcus Brinkmann. + +2001-08-03 Werner Koch + + * cipher.c (cipher_encrypt, cipher_decrypt): Prepare to return + errors. We have to change the interface to all ciphers to make + this really work but we should do so to prepare for hardware + encryption modules. + (gcry_cipher_encrypt, gcry_cipher_decrypt): Return the error and + set lasterr. + (gcry_cipher_ctl): Make sure that errors from setkey are returned. + +2001-08-02 Werner Koch + + * rndlinux.c (gather_random): casted a size_t arg to int so that + the format string is correct. Casting is okay here and avoids + translation changes. + + * random.c (fast_random_poll): Do not check the return code of + getrusage. + + * rndunix.c: Add a signal.h header to avoid warnings on Solaris 7 + and 8. + + * tiger.c (print_abc,print_data): Removed. + + * rijndael.c, des.c, blowfish.c, twofish.c, cast5.c, arcfour.c + (burn_stack): New. Add wrappers for most functions to be able to + call burn_stack after the function invocation. This methods seems + to be the most portable way to zeroise the stack used. It does + only work on stack frame based machines but it is highly portable + and has no side effects. Just setting the automatic variables at + the end of a function to zero does not work well because the + compiler will optimize them away - marking them as volatile would + be bad for performance. + * md5.c, sha1.c, rmd160.c, tiger.c (burn_stack): Likewise. + * random.c (burn_stack): New. + (mix_pool): Use it here to burn the stack of the mixblock function. + + * primegen.c (_gcry_generate_elg_prime): Freed q at 3 places. + Thanks to Tommi Komulainen. + + * arcfour.c (arcfour_setkey): Check the minimim keylength against + bytes and not bits. + (selftest): Must reset the key before decryption. + +2001-05-31 Werner Koch + + * sha1.c (sha1_init): Made static. + + Changed all g10_ prefixed function names as well as some mpi_ + function names to cope with the introduced naming changes. + + * md.c (prepare_macpads): Made key const. + +2001-05-28 Werner Koch + + * rndegd.c (gather_random): Removed the use of tty_printf. + +2001-03-29 Werner Koch + + * md5.c (md5_final): Fixed calculation of hashed length. Thanks + to disastry@saiknes.lv for pointing out that it was horrible wrong + for more than 512MB of input. + * sha1.c (sha1_final): Ditto. + * rmd160.c (rmd160_final): Ditto. + * tiger.c (tiger_final): Ditto. + + * blowfish.c (encrypt,do_encrypt): Changed name to do_encrypt to + avoid name clashes with an encrypt function in stdlib.h of + Dynix/PIX. Thanks to Gene Carter. + * elgamal.c (encrypt,do_encrypt): Ditto. + + * twofish.c (gnupgext_enum_func): Use only when when compiled as a + module. + * rijndael.c (gnupgext_enum_func): Ditto. + + * tiger.c (tiger_get_info): Return "TIGER192" and not just + "TIGER". By Edwin Woudt. + + * random.c: Always include time.h - standard requirement. Thanks + to James Troup. + + * rndw32.c: Fixes to the macros. + +2001-01-11 Werner Koch + + * cipher.c (cipher_encrypt,gcry_cipher_encrypt): Use blocksize and + not 8. + +2000-12-19 Werner Koch + + Major change: + Removed all GnuPG stuff and renamed this piece of software + to gcrypt. + +2000-11-14 Werner Koch + + * dsa.c (test_keys): Replaced mpi_alloc by gcry_mpi_new and + mpi_free by gcry_mpi_release. + * elgamal.c (test_keys,generate): Ditto, also for mpi_alloc_secure. + * rsa.c (test_keys,generate,rsa_verify): Ditto. + * primegen.c (generate_elg_prime): Ditto. + (gen_prime): Ditto and removed nlimbs. + + * rsa.c (generate): Allocate 2 more vars in secure memory. + + * Makefile.am (OMIT_DEPENDENCIES): Hack to work around dependency + problems. + +2000-10-09 Werner Koch + + * arcfour.c, arcfour.h: New. + * cipher.c (cipher_encrypt, cipher_decrypt): Add stream mode. + (setup_cipher_table): Add Arcfour. + (gcry_cipher_open): Kludge to allow stream mode. + +Wed Oct 4 13:16:18 CEST 2000 Werner Koch + + * sha1.c (transform): Use rol() macro. Actually this is not needed + for a newer gcc but there are still aoter compilers. + + * rsa.c (test_keys): Use new random function. + + * md.c (gcry_md_setkey): New function to overcome problems with + const conflics. + (gcry_md_ctl): Pass set key to the new functions. + + * rijndael.c: New. + * cipher.c: Add Rijndael support. + +Mon Sep 18 16:35:45 CEST 2000 Werner Koch + + * rndlinux.c (open_device): Loose random device checking. + By Nils Ellmenreich. + + * random.c (fast_random_poll): Check ENOSYS for getrusage. + * rndunix.c: Add 2 sources for QNX. By Sam Roberts. + + * pubkey.c (gcry_pk_algo_info): Add GCRYCTL_GET_ALGO_USAGE. + + * rsa.c: Changed the comment about the patent. + (secret): Speed up by using the CRT. For a 2k keys this + is about 3 times faster. + (stronger_key_check): New but unused code to check the secret key. + * Makefile.am: Included rsa.[ch]. + * pubkey.c: Enabled RSA support. + (pubkey_get_npkey): Removed RSA workaround. + +Mon Jul 31 10:04:47 CEST 2000 Werner Koch + + * pubkey.c: Replaced all gcry_sexp_{car,cdr}_{data,mpi} by the new + gcry_sexp_nth_{data,mpi} functions. + +Tue Jul 25 17:44:15 CEST 2000 Werner Koch + + * pubkey.c (exp_to_key,sexp_to_sig,sexp_to_enc,gcry_pk_encrypt, + gcry_pk_decrypt,gcry_pk_sign,gcry_pk_genkey): Changed to work with + the new S-Exp interface. + +Mon Jul 17 16:35:47 CEST 2000 Werner Koch + + * random.c (gather_faked): Replaced make_timestamp by time(2) again. + +Fri Jul 14 19:38:23 CEST 2000 Werner Koch + + * md.c (gcry_md_ctl): Support GCRYCTL_{START,STOP}_DUMP. + + * Makefile.am: Never compile mingw32 as module. + + * Makefile.am: Tweaked module build and removed libtool + + * Makefile.am: Replaced -O1 by -O. Suggested by Alec Habig. + + * elgamal.c (sign): Removed inactive code. + + * rsa.c, rsa.h: New based on the old module version (only in CVS for now). + * pubkey.c (setup_pubkey_table): Added commented support for RSA. + + * rndunix.c (waitpid): New. For UTS 2.1. All by Dave Dykstra. + (my_popen): Do the FD_CLOEXEC only if it is available + (start_gatherer): Cope with missing _SC_OPEN_MAX + + * rndunix.c: Add some more headers for QNX. By Sam Roberts. + + * rndegd.c (gather_random): Shortcut level 0. + * rndunix.c (gather_random): Ditto. + * rndw32.c (gather_random): Ditto. + + * rndw32.c: Replaced with code from Cryptlib and commented the old stuff. + * rndw32.c: Add some debuging code enabled by an environment variable. + + * random.c (read_seed_file): Binary open for DOSish system + (update_random_seed_file): Ditto. + * random.c [MINGW32]: Include process.h for getpid. + * random.c (fast_random_poll): Add clock_gettime() as fallback for + system which support this POSIX.4 fucntion. By Sam Roberts. + + * random.c (read_seed_file): Removed the S_ISLNK test becuase it + is already covered by !S_ISREG and is not defined in Unixware. + Reported by Dave Dykstra. + (update_random_seed_file): Silently ignore update request when pool + is not filled. + + * random.c (read_seed_file): New. + (set_random_seed_file): New. + (read_pool): Try to read the seeding file. + (update_random_seed_file): New. + + (read_pool): Do an initial extra seeding when level 2 quality random + is requested the first time. This requestes at least POOLSIZE/2 bytes + of entropy. Compined with the seeding file this should make normal + random bytes cheaper and increase the quality of the random bytes + used for key generation. + + * random.c (read_pool): Print a more friendly error message in + cases when too much random is requested in one call. + + * random.c (fast_random_poll): Check whether RUSAGE_SELF is defined; + this is not the case for some ESIX and Unixware, although they have + getrusage(). + + * primegen.c (generate_elg_prime): All primes are now generated with + the lowest random quality level. Because they are public anyway we + don't need stronger random and by this we do not drain the systems + entropy so much. + + * primegen.c (register_primegen_progress): New. + * dsa.c (register_pk_dsa_progress): New. + * elgamal.c (register_pk_elg_progress): New. + + * elgamal.c (wiener_map): New. + (gen_k): Use a much smaller k. + (generate): Calculate the qbits using the wiener map and + choose an x at a size comparable to the one choosen in gen_k + + * rmd160.c (rmd160_get_info): Moved casting to the left side due to a + problem with UTS4.3. Suggested by Dave Dykstra. + * sha1.c (sha1_get_info): Ditto. + * tiger.c (tiger_get_info): Ditto. + * md5.c (md5_get_info): Ditto + * des.c (des_get_info): Ditto. + * blowfish.c (blowfish_get_info): Ditto. + * cast5.c (cast5_get_info): Ditto. + * twofish.c (twofish_get_info): Ditto. + +Fri Mar 24 11:25:45 CET 2000 Werner Koch + + * md.c (md_open): Add hmac arg and allocate space for the pads. + (md_finalize): Add HMAC support. + (md_copy): Ditto. + (md_close): Ditto. + (gcry_md_reset): Ditto. + (gcry_md_ctl): Ditto. + (prepare_macpdas): New. + +Mon Mar 13 19:22:46 CET 2000 Werner Koch + + * md.c (gcry_md_hash_buffer): Add support for the other algorithms. + +Mon Jan 31 16:37:34 CET 2000 Werner Koch + + * genprime.c (generate_elg_prime): Fixed returned factors which never + worked for non-DSA keys. + +Thu Jan 27 18:00:44 CET 2000 Werner Koch + + * pubkey.c (sexp_to_key): Fixed mem leaks in case of errors. + +Mon Jan 24 22:24:38 CET 2000 Werner Koch + + * pubkey.c (gcry_pk_decrypt): Implemented. + (gcry_pk_encrypt): Implemented. + (gcry_pk_testkey): New. + (gcry_pk_genkey): New. + (pubkey_decrypt): Made static. + (pubkey_encrypt): Ditto. + (pubkey_check_secret_key): Ditto. + (pubkey_generate): Ditto. + +Mon Jan 24 13:04:28 CET 2000 Werner Koch + + * pubkey.c (pubkey_nbits): Removed and replaced by ... + (gcry_pk_get_nbits): this new one. + +Wed Dec 8 21:58:32 CET 1999 Werner Koch + + * dsa.c: s/mpi_powm/gcry_mpi_powm/g + * elgamal.c: Ditto. + * primegen.c: Ditto. + + * : Replaced g10_opt_verbose by g10_log_verbosity(). + + * Makefile.am (INCLUDES): removed intl, add ../gcrypt + +Fri Nov 19 17:15:20 CET 1999 Werner Koch + + * dynload.c (cmp_filenames): New to replaced compare_filename() in + module. + (register_cipher_extension): Removed the tilde expansion stuff. + * rndeg.c (my_make_filename): New. + + * : Replaced header util.h by g10lib.h + + * random.c (gather_faked): Replaced make_timestamp by time(2). + Disabled wrning printed with tty_printf. + * rndlinux.c (gather_random): Always use fprintf instead of tty_xxx; + this should be replaced by a callback function. + + * primegen.c (gen_prime): Use gcry_mpi_randomize. + (is_prime): Ditto. + * elgamal.c (test_keys): Ditto. + * dsa.c (test_keys): Ditto. + + * cipher.c (gcry_cipher_close): Die on invalid handle. + +Mon Nov 15 21:36:02 CET 1999 Werner Koch + + * elgamal.c (gen_k): Use the new random API. + (generate): Ditto. + * dsa.c (gen_k): Ditto. + (generate): Ditto. + +Sat Nov 13 17:44:23 CET 1999 Werner Koch + + * pubkey.c (disable_pubkey_algo): Made static. + (gcry_pk_ctl): New. + + * random.c (get_random_bits): Renamed to ... + (get_random_bytes): ... this and made static. + (gcry_random_bytes): New. + (gcry_random_bytes_secure): New. + (randomize_buffer): Renamed to ... + (gcry_randomize): ...this. + + * md.c (gcry_md_hash_buffer): New. + + * pubkey.c (gcry_pk_algo_info): 4 new commands. + (pubkey_get_npkey): Made static. + (pubkey_get_nskey): Made static. + (pubkey_get_nsig): Made static. + (pubkey_get_nenc): Made static. + + * pubkey.c: Removed all G10ERR_xxx. + * cipher.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_CIPHER_ALGO. + * md.c: Changed all GCRYERR_INV_ALGO to GCRYERR_INV_MD_ALGO. + * cast5.c (cast_setkey): Changed errocodes to GCRYERR_xxx. + * blowfish.c: Ditto. + * des.c: Ditto. + * twofish.c: Ditto. + * dsa.c: Ditto. + * elgamal.c: Ditto. + + * g10c.c: Removed + + * cipher.c (gcry_cipher_open): Replaced alloc functions and return NULL + if we are out of core. + * dynload.c: Replaced all memory allocation functions. + * md.c: Ditto. + * primegen.c: Ditto. + * pubkey.c: Ditto. + * random.c: Ditto. + * rndw32.c: Ditto. + * elgamal.c: Ditto. + * dsa.c: Ditto. + +Tue Oct 26 14:10:21 CEST 1999 Werner Koch + + * elgamal.c (sign): Hugh found strange code here. Replaced by BUG(). + + * cipher.c: Merged with gcrypt/symapi.c. + + * pubkey.c (string_to_pubkey_algo): Renamed function to ... + (gcry_pk_map_name): ... this. + (pubkey_algo_to_string): Renamed function to ... + (gcry_pk_algo_name): ... this. + (gcry_pk_algo_info): New. + * pubkey.c: Merged with gcrypt/pkapi.c. + + * md.c (md_reset): Clear finalized; thanks to Ulf Moeller for + fixing this bug. + + * md.c: Merged with gcrypt/mdapi.c + +Wed Sep 15 14:39:59 CEST 1999 Michael Roth + + * des.c: Various speed improvements: One bit pre rotation + trick after initial permutation (Richard Outerbridge). + Finished test of SSLeay Tripple-DES patterns. + +Wed Sep 15 16:22:17 CEST 1999 Werner Koch + + * rndw32.c: New. + +Mon Sep 13 10:51:29 CEST 1999 Werner Koch + + * bithelp.h: New. + * rmd160.h, sha1.h, md5.h: Use the rol macro from bithelp.h + +Tue Sep 7 16:23:36 CEST 1999 Werner Koch + + * Makefile.am: Fixed seds for latest egcc. By Ollivier Robert. + +Mon Sep 6 19:59:08 CEST 1999 Werner Koch + + * des.c (selftest): Add some testpattern + +Mon Aug 30 20:38:33 CEST 1999 Werner Koch + + * cipher.c (do_cbc_encrypt): Fixed serious bug occuring when not using + in place encryption. Pointed out by Frank Stajano. + +Mon Jul 26 09:34:46 CEST 1999 Werner Koch + + * md5.c (md5_final): Fix for a SCO cpp bug. + +Thu Jul 15 10:15:35 CEST 1999 Werner Koch + + * elgamal.c (elg_check_secret_key,elg_encrypt + elg_decrypt,elg_sign,elg_verify): Sanity check on the args. + * dsa.c (dsa_check_secret_key,dsa_sign,dsa_verify): Ditto. + + * pubkey.c (disable_pubkey_algo): New. + (check_pubkey_algo2): Look at disabled algo table. + * cipher.c (disable_cipher_algo): New. + (check_cipher_algo): Look at disabled algo table. + +Wed Jul 7 13:08:40 CEST 1999 Werner Koch + + * Makefile.am: Support for libtool. + +Fri Jul 2 11:45:54 CEST 1999 Werner Koch + + * dsa.c (gen_k): Changed algorithm to consume less random bytes + * elgamal.c (gen_k): Ditto. + + * random.c (random_dump_stats): New. + +Thu Jul 1 12:47:31 CEST 1999 Werner Koch + + * primegen.c, elgamal.c, dsa.c (progess): New and replaced all + fputc with a call to this function. + +Sat Jun 26 12:15:59 CEST 1999 Werner Koch + + * rndegd.c (do_write): s/ssize_t/int/ due to SunOS 4.1 probs. + + * cipher.c (do_cbc_encrypt, do_cbc_decrypt): New. + + * dynload.c (HAVE_DL_SHL_LOAD): Map hpux API to dlopen (Dave Dykstra). + * Makefile.am (install-exec-hook): Removed. + +Sun May 23 14:20:22 CEST 1999 Werner Koch + + * cipher.c (setup_cipher_table): Enable Twofish + + * random.c (fast_random_poll): Disable use of times() for mingw32. + +Mon May 17 21:54:43 CEST 1999 Werner Koch + + * dynload.c (register_internal_cipher_extension): Minor init fix. + +Tue May 4 15:47:53 CEST 1999 Werner Koch + + * primegen.c (gen_prime): Readded the Fermat test. Fixed the bug + that we didn't correct for step when passing the prime to the + Rabin-Miller test which led to bad performance (Stefan Keller). + (check_prime): Add a first Fermat test. + +Sun Apr 18 10:11:28 CEST 1999 Werner Koch + + * cipher.c (cipher_setiv): Add ivlen arg, changed all callers. + + * random.c (randomize_buffer): alway use secure memory because + we can't use m_is_secure() on a statically allocated buffer. + + * twofish.c: Replaced some macros by a loop to reduce text size. + * Makefile.am (twofish): No more need for sed editing. + +Fri Apr 9 12:26:25 CEST 1999 Werner Koch + + * cipher.c (cipher_open): Reversed the changes for AUTO_CFB. + + * blowfish.c: Dropped the Blowfish 160 mode. + * cipher.c (cipher_open): Ditto. + (setup_cipher_table): Ditto. And removed support of twofish128 + +Wed Apr 7 20:51:39 CEST 1999 Werner Koch + + * random.c (get_random_bits): Can now handle requests > POOLSIZE + + * cipher.c (cipher_open): Now uses standard CFB for automode if + the blocksize is gt 8 (according to rfc2440). + + * twofish.c: Applied Matthew Skala's patches for 256 bit key. + +Tue Apr 6 19:58:12 CEST 1999 Werner Koch + + * random.c (get_random_bits): Can now handle requests > POOLSIZE + + * cipher.c (cipher_open): Now uses standard CFB for automode if + the blocksize is gt 8 (according to rfc2440). + +Sat Mar 20 11:44:21 CET 1999 Werner Koch + + * rndlinux.c (tty_printf) [IS_MODULE]: Removed. + + * rndegd.c (gather_random): Some fixes. + +Wed Mar 17 13:09:03 CET 1999 Werner Koch + + * rndegd.c (do_read): New. + (gather_random): Changed the implementation. + +Mon Mar 8 20:47:17 CET 1999 Werner Koch + + * dynload.c (DLSYM_NEEDS_UNDERSCORE): Renamed. + +Fri Feb 26 17:55:41 CET 1999 Werner Koch + + * md.c: Nearly a total rewrote. + +Wed Feb 24 11:07:27 CET 1999 Werner Koch + + * cipher.c (context): Fixed alignment + * md.c: Ditto. + + * rndegd.c: New + +Mon Feb 22 20:04:00 CET 1999 Werner Koch + + * rndegd.c: New. + +Wed Feb 10 17:15:39 CET 1999 Werner Koch + + * Makefile.am: Modules are now figured out by configure + * construct.c: New. Generated by configure. Changed all modules + to work with that. + * sha1.h: Removed. + * md5.h: Removed. + + * twofish.c: Changed interface to allow Twofish/256 + + * rndunix.c (start_gatherer): Die on SIGPIPE. + +Wed Jan 20 18:59:49 CET 1999 Werner Koch + + * rndunix.c (gather_random): Fix to avoid infinite loop. + +Sun Jan 17 11:04:33 CET 1999 Werner Koch + + * des.c (is_weak_key): Replace system memcmp due to bugs + in SunOS's memcmp. + (des_get_info): Return error on failed selftest. + * twofish.c (twofish_setkey): Return error on failed selftest or + invalid keylength. + * cast5.c (cast_setkey): Ditto. + * blowfish.c (bf_setkey): Return error on failed selftest. + +Tue Jan 12 11:17:18 CET 1999 Werner Koch + + * random.c (random_is_faked): New. + + * tiger.c: Only compile if we have the u64 type + +Sat Jan 9 16:02:23 CET 1999 Werner Koch + + * rndunix.c (gather_random): check for setuid. + + * Makefile.am: Add a way to staically link random modules + +Thu Jan 7 18:00:58 CET 1999 Werner Koch + + * md.c (md_stop_debug): Do a flush first. + (md_open): size of buffer now depends on the secure parameter + +Sun Jan 3 15:28:44 CET 1999 Werner Koch + + * rndunix.c (start_gatherer): Fixed stupid ==/= bug + +1998-12-31 Geoff Keating + + * des.c (is_weak_key): Rewrite loop end condition. + +Tue Dec 29 14:41:47 CET 1998 Werner Koch + + * random.c: add unistd.h for getpid(). + (RAND_MAX): Fallback value for Sun. + +Wed Dec 23 17:12:24 CET 1998 Werner Koch + + * md.c (md_copy): Reset debug. + +Mon Dec 14 21:18:49 CET 1998 Werner Koch + + * random.c (read_random_source): Changed the interface to the + random gathering function. + (gather_faked): Use new interface. + * dynload.c (dynload_getfnc_fast_random_poll): Ditto. + (dynload_getfnc_gather_random): Ditto. + * rndlinux.c (gather_random): Ditto. + * rndunix.c (gather_random): Ditto. + +Sat Dec 12 18:40:32 CET 1998 Werner Koch + + * dynload.c (SYMBOL_VERSION): New to cope with system which needs + underscores. + + * rndunix.c: Rewrote large parts + +Thu Dec 10 20:15:36 CET 1998 Werner Koch + + * dynload.c (load_extension): increased needed verbosity level. + + * random.c (fast_random_poll): Fallback to a default fast random + poll function. + (read_random_source): Always use the faked entroy gatherer if no + gather module is available. + * rndlinux.c (fast_poll): Removed. + * rndunix.c (fast_poll): Removed. + + +Wed Nov 25 12:33:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-*.c: Removed. + * rndlinux.c : New. + * rndunix.c : New. + * random.c : Restructured the interface to the gather modules. + (intialize): Call constructor functions + (read_radnom_source): Moved to here. + * dynload.c (dynload_getfnc_gather_random): New. + (dynload_getfnc_fast_random_poll): New. + (register_internal_cipher_extension): New. + (register_cipher_extension): Support of internal modules. + +Sun Nov 8 17:44:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c (read_random_source): Removed the assert. + +Mon Oct 19 18:34:30 1998 me,,, (wk@tobold) + + * pubkey.c: Hack to allow us to give some info about RSA keys back. + +Thu Oct 15 11:47:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dynload.c: Support for DLD + +Wed Oct 14 12:13:07 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c: Now uses names from configure for /dev/random. + +1998-10-10 SL Baur + + * Makefile.am: fix sed -O substitutions to catch -O6, etc. + +Tue Oct 6 10:06:32 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-unix.c (HAVE_GETTIMEOFDAY): Fixed (was ..GETTIMEOFTIME :-) + * rand-dummy.c (HAVE_GETTIMEOFDAY): Ditto. + +Mon Sep 28 13:23:09 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_digest): New. + (md_reset): New. + +Wed Sep 23 12:27:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c (TIGER_CONTEXT): moved "buf", so that it is 64 bit aligned. + +Mon Sep 21 06:22:53 1998 Werner Koch (wk@(none)) + + * des.c: Some patches from Michael. + +Thu Sep 17 19:00:06 1998 Werner Koch (wk@(none)) + + * des.c : New file from Michael Roth + +Mon Sep 14 11:10:55 1998 Werner Koch (wk@(none)) + + * blowfish.c (bf_setkey): Niklas Hernaeus patch to detect weak keys. + +Mon Sep 14 09:19:25 1998 Werner Koch (wk@(none)) + + * dynload.c (RTLD_NOW): Now defined to 1 if it is undefined. + +Mon Sep 7 17:04:33 1998 Werner Koch (wk@(none)) + + * Makefile.am: Fixes to allow a different build directory + +Thu Aug 6 17:25:38 1998 Werner Koch,mobil,,, (wk@tobold) + + * random.c (get_random_byte): Removed and changed all callers + to use get_random_bits() + +Mon Jul 27 10:30:22 1998 Werner Koch (wk@(none)) + + * cipher.c : Support for other blocksizes + (cipher_get_blocksize): New. + * twofish.c: New. + * Makefile.am: Add twofish module. + +Mon Jul 13 21:30:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (read_pool): Simple alloc if secure_alloc is not set. + (get_random_bits): Ditto. + +Thu Jul 9 13:01:14 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dynload.c (load_extension): Function now nbails out if + the program is run setuid. + +Wed Jul 8 18:58:23 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (rmd160_hash_buffer): New. + +Thu Jul 2 10:50:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c (cipher_open): algos >=100 use standard CFB + +Thu Jun 25 11:18:25 1998 Werner Koch (wk@isil.d.shuttle.de) + + * Makefile.am: Support for extensions + +Thu Jun 18 12:09:38 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (mix_pool): simpler handling for level 0 + +Mon Jun 15 14:40:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c: Removed from dist, will reappear as dynload module + +Sat Jun 13 14:16:57 1998 Werner Koch (wk@isil.d.shuttle.de) + + * pubkey.c: Major changes to allow extensions. Changed the inteface + of all public key ciphers and added the ability to load extensions + on demand. + + * misc.c: Removed. + +Wed Jun 10 07:52:08 1998 Werner Koch,mobil,,, (wk@tobold) + + * dynload.c: New. + * cipher.c: Major changes to allow extensions. + +Mon Jun 8 22:43:00 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: Major internal chnages to support extensions. + * blowfish.c (blowfish_get_info): New and made all internal + functions static, changed heder. + * cast5.c (cast5_get_info): Likewise. + +Mon Jun 8 12:27:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c (transform): Fix for big endian + + * cipher.c (do_cfb_decrypt): Big endian fix. + +Fri May 22 07:30:39 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_get_oid): Add a new one for TIGER. + +Thu May 21 13:24:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: Add support for a dummy cipher + +Thu May 14 15:40:36 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (transform): fixed sigbus - I should better + add Christian von Roques's new implemenation of rmd160_write. + +Fri May 8 18:07:44 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rand-internal.h, rand-unix.c, rand-w32.c, rand_dummy.c: New + * random.c: Moved system specific functions to rand-****.c + +Fri May 8 14:01:17 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (fast_random_poll): add call to gethrtime. + +Tue May 5 21:28:55 1998 Werner Koch (wk@isil.d.shuttle.de) + + * elgamal.c (elg_generate): choosing x was not correct, could + yield 6 bytes which are not from the random pool, tsss, tsss.. + +Tue May 5 14:09:06 1998 Werner Koch (wk@isil.d.shuttle.de) + + * primegen.c (generate_elg_prime): Add arg mode, changed all + callers and implemented mode 1. + +Mon Apr 27 14:41:58 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c (cipher_get_keylen): New. + +Sun Apr 26 14:44:52 1998 Werner Koch (wk@isil.d.shuttle.de) + + * tiger.c, tiger.h: New. + +Wed Apr 8 14:57:11 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (check_pubkey_algo2): New. + +Tue Apr 7 18:46:49 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cipher.c: New + * misc.c (check_cipher_algo): Moved to cipher.c + * cast5.c: Moved many functions to cipher.c + * blowfish.c: Likewise. + +Sat Apr 4 19:52:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * cast5.c: Implemented and tested. + +Wed Apr 1 16:38:27 1998 Werner Koch (wk@isil.d.shuttle.de) + + * elgamal.c (elg_generate): Faster generation of x in some cases. + +Thu Mar 19 13:54:48 1998 Werner Koch (wk@isil.d.shuttle.de) + + * blowfish.c (blowfish_decode_cfb): changed XOR operation + (blowfish_encode_cfb): Ditto. + +Thu Mar 12 14:04:05 1998 Werner Koch (wk@isil.d.shuttle.de) + + * sha1.c (transform): Rewrote + + * blowfish.c (encrypt): Unrolled for rounds == 16 + (decrypt): Ditto. + +Tue Mar 10 16:32:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (transform): Unrolled the loop. + +Tue Mar 10 13:05:14 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (read_pool): Add pool_balance stuff. + (get_random_bits): New. + + * elgamal.c (elg_generate): Now uses get_random_bits to generate x. + + +Tue Mar 10 11:33:51 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_digest_length): New. + +Tue Mar 10 11:27:41 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dsa.c (dsa_verify): Works. + +Mon Mar 9 12:59:08 1998 Werner Koch (wk@isil.d.shuttle.de) + + * dsa.c, dsa.h: Removed some unused code. + +Wed Mar 4 10:39:22 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_open): Add call to fast_random_poll. + blowfish.c (blowfish_setkey): Ditto. + +Tue Mar 3 13:32:54 1998 Werner Koch (wk@isil.d.shuttle.de) + + * rmd160.c (rmd160_mixblock): New. + * random.c: Restructured to start with a new RNG implementation. + * random.h: New. + +Mon Mar 2 19:21:46 1998 Werner Koch (wk@isil.d.shuttle.de) + + * gost.c, gost.h: Removed because they did only contain trash. + +Sun Mar 1 16:42:29 1998 Werner Koch (wk@isil.d.shuttle.de) + + * random.c (fill_buffer): removed error message if n == -1. + +Fri Feb 27 16:39:34 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c (md_enable): No init if called twice. + +Thu Feb 26 07:57:02 1998 Werner Koch (wk@isil.d.shuttle.de) + + * primegen.c (generate_elg_prime): Changed the progress printing. + (gen_prime): Ditto. + +Tue Feb 24 12:28:42 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md5.c, md.5 : Replaced by a modified version of md5.c from + GNU textutils 1.22. + +Wed Feb 18 14:08:30 1998 Werner Koch (wk@isil.d.shuttle.de) + + * md.c, md.h : New debugging support + +Mon Feb 16 10:08:47 1998 Werner Koch (wk@isil.d.shuttle.de) + + * misc.c (cipher_algo_to_string): New + (pubkey_algo_to_string): New. + (digest_algo_to_string): New. + + + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/grub-core/lib/libgcrypt/cipher/Makefile.am b/grub-core/lib/libgcrypt/cipher/Makefile.am new file mode 100644 index 000000000..76cdc96ad --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/Makefile.am @@ -0,0 +1,83 @@ +# Makefile for cipher modules +# Copyright (C) 1998, 1999, 2000, 2001, 2002, +# 2003, 2009 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see . + +# Process this file with automake to produce Makefile.in + +EXTRA_DIST = Manifest + +# Need to include ../src in addition to top_srcdir because gcrypt.h is +# a built header. +AM_CPPFLAGS = -I../src -I$(top_srcdir)/src +AM_CFLAGS = $(GPG_ERROR_CFLAGS) + + +noinst_LTLIBRARIES = libcipher.la + +GCRYPT_MODULES = @GCRYPT_CIPHERS@ @GCRYPT_PUBKEY_CIPHERS@ @GCRYPT_DIGESTS@ + +libcipher_la_DEPENDENCIES = $(GCRYPT_MODULES) +libcipher_la_LIBADD = $(GCRYPT_MODULES) + +libcipher_la_SOURCES = \ +cipher.c pubkey.c ac.c md.c kdf.c \ +hmac-tests.c \ +bithelp.h \ +primegen.c \ +hash-common.c hash-common.h \ +rmd.h + +EXTRA_libcipher_la_SOURCES = \ +arcfour.c \ +blowfish.c \ +cast5.c \ +crc.c \ +des.c \ +dsa.c \ +elgamal.c \ +ecc.c \ +idea.c \ +md4.c \ +md5.c \ +rijndael.c rijndael-tables.h \ +rmd160.c \ +rsa.c \ +seed.c \ +serpent.c \ +sha1.c \ +sha256.c \ +sha512.c \ +tiger.c \ +whirlpool.c \ +twofish.c \ +rfc2268.c \ +camellia.c camellia.h camellia-glue.c + +if ENABLE_O_FLAG_MUNGING +o_flag_munging = sed -e 's/-O\([2-9s][2-9s]*\)/-O1/' -e 's/-Ofast/-O1/g' +else +o_flag_munging = cat +endif + + +# We need to lower the optimization for this module. +tiger.o: $(srcdir)/tiger.c + `echo $(COMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) ` + +tiger.lo: $(srcdir)/tiger.c + `echo $(LTCOMPILE) -c $(srcdir)/tiger.c | $(o_flag_munging) ` diff --git a/grub-core/lib/libgcrypt/cipher/Manifest b/grub-core/lib/libgcrypt/cipher/Manifest new file mode 100644 index 000000000..0cd64f71f --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/Manifest @@ -0,0 +1,73 @@ +# Manifest - checksums of the cipher directory +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of Libgcrypt. +# +# Libgcrypt is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser general Public License as +# published by the Free Software Foundation; either version 2.1 of +# the License, or (at your option) any later version. +# +# Libgcrypt 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser 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 + +# Checksums for all source files in this directory. Format is +# filename, blanks, base-64 part of an OpenPGP detached signature +# without the header lines. Blank lines and lines beginning with a +# hash mark are ignored. A tool to process this file is available by +# cvs -d :pserver:anoncvs@cvs.gnupg.org:/cvs/wk co misc-scripts/manifest-tool +# +# The special entry "$names$" holds a signature over all sorted +# filenames excluding itself. + + +# Algorithm API +cipher.c iQCVAwUAQDzrVjEAnp832S/7AQIPDgP+OVJ/YNWY5m7c09EBbPAzL/WsGoj6wrBNMmkRlMOqTHeh+OOtjuFHt1f9uhfM2Nzl7sJ5+h4ryZKLEZmQPRMTZTnAqkvGdsrJWJnigUA9QwYdV0ONqC9C63gpuG465gO9TZVOqlQu/FTxSRuTQYUulkaBNG71n8nZEOusBVwV2YA==58xH +pubkey.c iQCVAwUAP9XQ3jEAnp832S/7AQJ5UgQAyHfEBvPVJ8wTRg8c7ixS2GiVmIgwIo5tvQaiQJTPWASevvYrB+2Z2qa9cATyu50ACjLzbaquGBgPzjJV3dU/qttT1gCqRuN/LCNvXFe5qnIZezejc3RAadFNTw/pOTHq0wxD1Keg66ruei9R36Nba59pEQIWIBXTfubRft2hMYk==E09t +ac.c iQCVAwUAQDzsOzEAnp832S/7AQJCBQP/WI6EV/dsR4rmha6RVhvkjZo17kQ8z6pIl5J3cXOvqEkIFeD2HYu3HHrWST5l7yXlffhpDkVHkfMih4ruK76q6Fm0dxZ98pO4C/dVtgimlvvcy/wOQjpzsE0fYAe1BYdg81LJ09X33vW5x6C29lunfKROO2tPlV5i8ffeoFvmMF8==j26g +md.c iQCVAwUAP+NFGjEAnp832S/7AQJs8wP/Qdk0EAKsyr3O1/pmOSN8AG4rPKbd6KDTzvoBPAN4upFwKYY4hWwvy12Q3YU9DmECrzZkRCXHR7mljVQKs6B7CRZJKjFKmOELpcJDtKvu40vTs1bOH4k9iJYZpGgRA83nkQ+ELAcphAbCA+KIpVr2K4mCJAB0FhpC2uOQ50JHAko==BeF6 +primegen.c iQCVAwUAQDzsoDEAnp832S/7AQKYRwP/TqAQBm1rHTnF0HYE05PqXfWlOqa6EosqVpaOcs/OIW6PaqX0xH1UlrukK7jNOjK3xC4o1qNQ1UKzz2dvQaq1bMvNNizeavxAh10SJZc0hIc/ofc83IbjLh8SZVWQ67JxjsUd3DOXmSmhPZ+Pqd7cUIiw8fDoF+I9EZqy3COu1wY==1ebT + +# Algorithm implementations +arcfour.c iQCVAwUAP9XR/TEAnp832S/7AQJcRwP6AlvYEx++fpT4mIYo0xRDqKEQeqMQvbaRhIg2eV74JxItpHa3q5YsYIl+n1yUz5g35JRWWXSWmAZBwO5wLKsHii4kRUhgrKWnSoQZoPpl49L5+N3R58ON3S0ru5lsBiEJEze3xplf2vqwrH9v1QHVD+gU7UTlfNqrIJoOUXN+1O4==Tq+x +blowfish.c iQCVAwUAP9XTETEAnp832S/7AQJaEgQAgiqqfuO+zQtscgTB0rvOzVymIKjRKjYhFuLjVuc79G4z1RCAffvIn/YM2d7kt+Z/QF7zjcTAOgETCQL1XokpX2zz9HPAMi2tlDY5zsDufTNqj0n4WBL9nM7w6XAvsiwP1B3bqCTv9SjJV4KbxJ58vw1yQE+sqW74R/QIHFvC7mU==wZnX +cast5.c iQCVAwUAP9XT6DEAnp832S/7AQJ3xgP/ehLjEN3GELGudbqeo91Xd+PqitHrkuBbtRIYX7Udd/fyXLN+h8rMJVyIQX2m+mpxbBxudVU3x8/DNT8B0ZHAwK6qqJmEBLLhEYPgIuF76i9LMrP1KqUPhAwRZ2OppjIIugBQ+rP74aD4eLyd/aKQHNuXML8QGWR6KwQShohXM5I==/BRh +crc.c iQCVAwUAP7ouejEAnp832S/7AQIgwQQApg5Nm63tH5DQkbN+zPzMO9Ygoj3ukxfFTyTBPYSXYKMiTjEbESegaU40uN8jnz2vprcIQWcgZfzO4+opEJMcI35aPwzEk0vKOp0S/PrBLUY2rJfnDVkX5XgJFZa2Q7LLe826UEBzTVYW924utiCCe8oOaOEWVNpg1mqdknu3M9o==kz5D +des.c iQCVAwUAQCN2oDEAnp832S/7AQL/jwP6Auoq6nZCDBjpgc9tDzuIRwa9DqyuM3gX94uvgEpUwdHszb2bG43dz03kVmcYxtj1MzXbyCeCZOwox0b2SKmLgxIbrNP6yGbzVdTj6592gDYuf/ZXmc1ZNJ1DDldcPQ0n9fXUipUPwyPaNWo3mSZaNcMKSWWzdK0J6ciG6nk7SWI==9k/t +dsa.c iQCVAwUAP9XZHDEAnp832S/7AQLBRgP/XrBzTEYx5ccMj1MMb6sg37liEHdIyyy49zjvt6jUqxj4RuwVEN8S6v3u4q/QyJkHAi1E0EkREgENlyHW6PKWhYbcrd0vPIAN15yjnl2yqtrCrJImexUCoqJJewK0E4JOicGbabTil8MZjk+mbhEPnjJBqOkyP1w0i31pEDgE/8M==pC8s +elgamal.c iQCVAwUAP9XbYzEAnp832S/7AQLXagQA3HrvspZfbTGgmUH0IqLQTJ0exUPxJv5DET2TvoIy62trDmMN6lTAj5P+a7jQ8udcu0w+mR2vXUHcxUpNA2PxLaMwGzNSY4zRDNe9r3SFTDrFm6m4y9Ko2e8XtEA+WF6P/XLpck4Jn7vMEDmVGPwkNd22kXFFE8dBGwG6i5Hk1Mk==oBUs +md4.c iQCVAwUAP9h50DEAnp832S/7AQJhHgQAzNA/B6MWFDlCtPkIVaW8RpP1Eg0ZNMsy0s7SJkopOCBlu6CwXUOKe+8ppcSxhjYKh4i4uQr/QtfipYlBjzKJGnrafoF/NugXNCOHSTGT11TvK7mCiBuUMVgvZGAlOJImk6eTTfUjRrMfaXM/SWl8bdJ4ZpzdjEyVh89r7I5JrGk==x2UD +md5.c iQCVAwUAP9h7LzEAnp832S/7AQJUGQP/c0cbf6WZXCzmjufHxiE9FAQBzTsA0WtaNqdFcHl7fhmikGtknlaED8n5a7eYd/C481UQW6Wgq/oZdsvgoPWPhG3fOCy2CFP9cZVXITuMSf0ucyZTFUJNO15fnZ+nDfsUv+JPdv1aSeRinAUtfAcSKfkSyR9BCPZvkx+tgU6cphU==Zv+h +rijndael.c iQCVAwUAP9h9cTEAnp832S/7AQKF1AP+P2L/tPqDJRDg+/fwbOk8Ts0MNxnvvYEm3gE73TKuLt1S+B2+jkrZcKNvM5VGPnVMJbnS0lmIK04nmedHCOftGTOwhGulZAHHIaKGystT3Jql4iPws/JMgAjE7Fyxh5WZMtB9yEljKBpJ5XNqhrMvvxcHpnyP3+YzIXNwzk34V+c==dJ5k +rmd160.c iQCVAwUAP9h+bTEAnp832S/7AQK1OgP+PNKF6Nzi6X93easVlksdLqKEsArCAw2QjGWDGyxTnbiJM55qAl9JxR1mn3V+oOL7izLLwTt6EYK9evhzfcxY5N5Mni85RAcsLPsuAfQDEzjI6GUWHtQUKPbM+BaorzfhQjYFSZyvum/dZYJ/WfiwwwhqqIKyVU2ZFSqA38YGC/c==9jdA +rsa.c iQCVAwUAP9iHIzEAnp832S/7AQKAYwQAuWtnMte54QHN+Hij9t4sGuypXogajOb1vQQwGgS0fKsaBZsuSP2amze4o5diIvsQTsFQ4CzjvqoCVuBDoHM3xkSD8wGDizgvtCamAxkdbF7wmzldKFn8SpJqlVwWQMP6kk1IjXHEuYb4IDWGTbVMhfEu+eOlU8+PSK4IhZqNvt4==/3hp +serpent.c iQCVAwUAP9h/VzEAnp832S/7AQLyCwP/d1zbmb7l/PriZNa9/Z7mo01XFe5MnAqCfIwhl9GjeaMszcoS37jECNq5nLvrTTFIIJpm3rvBePwiCG4Wwx1I18HCxaP198pcSaR+BLOJ3Aj52EZPrxtqlDKuFr38ZOP5giyUqUYVYGVdrz4kRMNWAZQK53GeJnGhXCnhxojLEgA==ck46 +sha1.c iQCVAwUAP9iATTEAnp832S/7AQKcSwQAwAs/HnNqho3lU1ZUgCPNt5P2/Brm6W21+wWWGKJkSrra/c4NYVKJGDDwlsFE0b9ln1uZt7bHReFkKXK3JnrKTmNVcx/Cy64iCMRNMhaM72Mqy7wWx5yHBAmMBxzFGnNQKbmeY52zeGih5HsNLSibc2pPuOViWo2JPJ5Ci/wIwl8==/wtO +sha256.c iQCVAwUAP9iAtzEAnp832S/7AQJD2QP/UqvL0hhjG1wEFbGrdkV9tba1sMDXdnnK6X7HdLuRpVAgNiQiFf8JDmntd/dZ2Q71p4Uae2ctqve4WoEijPUZPjACnpuZfx0SEQL0lQBkwxzJp7lz9ujVtwQ2cM/aYexJkXcWgGcloJNLM3JbWPGIJnuYbr/IwJ6RQF9vgj0357o==UWO1 +sha512.c iQCVAwUAP9iBTDEAnp832S/7AQIPBAQA28CJSUQLiW0s2x9u8/OH2eKnxPjA4sZmb50WP7920Lem66P31C3BrOqwfBot4RLhjL+zh/+Uc4s3HPwApZuj9E4BxNMlqLv+Tqk++DAbdaOeYT4jeUt+mlhQQ6mH/RDsy32rZsNsGQ2bUGxazZmfG++PL3JyhawqCy00SUDr/o0==H+0X +tiger.c iQCVAwUAP9iCfjEAnp832S/7AQKufwP/fryv3MqSOYY+90325DH7X3/CtekxeooN0scGsHX0fxBakWSMecTNrj33KPddLS46gU/S89zIc2N/Bw/7EVIAXVFA3/3Ip+OrFOuIMO4Py1sCdB8o2Y+5ygv8iXLcsXIq1O0av79i9g774V3uaXa2qN9ZnXe0AEhcy8FHJ2i/wro==5XVB +twofish.c iQCVAwUAP9iD6TEAnp832S/7AQKUnQP/Rq8FaYeHTG7HbZuqAs9pbPitzjDbkdZddmInWR7NmevBkKvhsJALjVooc0KGQfo2lAAmy3Xi/4QQN8VPn51DVjDIgf7x+DQh/9TFJHMccxI9asUgi4+TNnmMqLU1k3N8S2PjyZ1sjeC8B79fKPpwCzj72WkqPkzZw3l2jArr+dU==NdJT +rfc2268.c iQCVAwUAQCN+3jEAnp832S/7AQLv1gQA1hJh29hAjKi4uLSGxXvJ6cyYmPdmevdKrbLnuHZWtHe4xvCgy/nTdEojEpxgLp/hL/ogasuWRC1W16Wiz9ryxf7YR0uhZWayO/bQNagpfU5MIkJTLuKqqgpwYumCSQfOugXVAqcgEzj+13eeyJaFVrzwrNa67sh84nmbjOjNjvE==0zBq + +# Random number related +random.c iQCVAwUAP7nsITEAnp832S/7AQK4SAQAtvfUgrtGOQ2PlxGMla0qJLPHjJacMwgq0ecusiI79elPdDsFfCCk6dK1Ug2kFbNm22nCGHNcUquqbX7noi7ZVQnmPBQXzyLNZd7GmrawRZfdlRerTUDBpSnR8V8ui/5+YYp627E7kKGC0hPSgqXFql6oBMIfno0LZwFJTjIevRY==L419 +random.h iQCVAwUAP7ovKDEAnp832S/7AQJ3bQQAjnPebnyTC7sphAv2I7uIz+yPgw1ZfbVhLv+OiWDlO9ish+fRyyMpy+HELBOgZjJdgRegqhlZC6qyns5arM/VglYi+PzvdLO3hIqHE/YFfpIFPz8wBrcmlqrYyd3CsGqcYsfjocXNttCBLeSWmoJ09ltKQH8yzJf3oAgN6X1yuc4==eNoU +rand-internal.h iQCVAwUAP7ouvDEAnp832S/7AQLYnAQAhdI7ERoJVCkV8GiV7MjaUxv1WIL7iZ+jIOvVhv4fNyhCGCGoEtTjkyput/lj7Nsh3FXEqRhypGGrCLf47x/gua5n+BwffogxVyUDqiOyyGhNTPpe3fQcNBvbPCtco8yMK4GJO5G3BqzlPyN+BMeogLymyV6Sm1mvh5LZDyAFbfQ==tZSE +rndlinux.c iQCVAwUAP9iPYTEAnp832S/7AQL6/AP/ZDrbOkVuB9qJ7sKeX1MImZEsz3mi0xPovJzaBtBU7a0idcUKrWYOvQFWRlLUeq0iCT6+h2l5bniP7q7hepzlKa+VPY9VWaQthqeJm2l5LN6QQ5PyMfBq04QuBncw9BJnCGmEyTLt3RxIXBAPdxmiVxtcRIFUqCBtQvoUXGLvemw==t37k +rndegd.c iQCVAwUAP9iPRDEAnp832S/7AQImBQP/WHKg+hKXcm1pQvilzML0jZpwK5PAMM4uBnnPJNIXWOYBO6I/Xg9d/tPLg8NlmmtyQCo2Eu0ybDSt+8mu+dWveAys+0LTi0MIqeP9BMzCKz8dnWH6+S8huLXwTF3m0IrqM0JLb6b71GK9SOq6sWQ22yW5vf61hXP8kH9dhIaoMZs==FaHV +rndunix.c iQCVAwUAP9iQlzEAnp832S/7AQL/KgQA29GnvcD4Xb5qjDMBgW9THEE4+4lfex/6k+Fh0IT61OLJsWVLJ7bJpRntburw4uQm4Tf7CO8vaiDFDYhKKrzXeOF1fmdpcL8hA+fNp9I/MUOc4e9kN9+YJ9wikVa0SZj1OBfhzgcFLd1xOtulkr3ii52HLF9vhrxzkgVwvD10Bi8==2cML +rndw32.c iQCVAwUAP9iRKDEAnp832S/7AQIuaAQA3AJr3WqnxNDsWCIdvehf8Suotthj+laX8nJsvDfFhXPKcXDpsg0wTTXSnnKgyED53+uYiMDnVRsxeWAyhKwvx1MjjlaSMMjzbH6isWTH8FaWpLgrxEkXoPeNqYf5FXpdUkcUxGX2RkQeuX/cIfiHLNE9CV0usaF2jysjBX2iERY==EEnO + +# Helper +bithelp.h iQCVAwUAP7ouPTEAnp832S/7AQKXggQAqjcgvihIF3WclOgw1JV2rbARw4ISIDRMFqdaNCqBRx6BwEz3UGsEIlz6+iR1sS/reqN61WvtjLb+D0+tujAkGrgQJhFLG85WtG2tB5UVoI3am1fpkwiRm+bR4rv0rGk0BYk81bC7+l4KrK9o5lVp4lCsrorlUKsd48lNmBHyAXM==mDDN +rmd.h iQCVAwUAP7oumjEAnp832S/7AQJiJQP/V4bJwjZaYndJzV+KRnIDbl1koHuw+ZK5heMYVu8Qk4ylqv//BGyeRa3jZCcfPHI35q6HilCs2VBm8hiBMjHSqY/VPn2ZQ0yg/lt6qEvl7YjsLmyMICvjG+ncszHoq9pRvnF3vTnM18sPIioXLk8fskuM0XOCNBs0ARBAQjY9UGI==olUN + +# Configuration +Makefile.am iQCVAwUAQCN33TEAnp832S/7AQKFJAQAz7BDkC814q+QiuE/jnutJHR5qlgbrm3ikGbQwdRzYUscst4bCCWy3uKL/sIPGLg+JQXtF5FnsQy3s4D9BOYhp72cA9ktYK65hhi4pNm/JQ0lXkZMNfk8Go5lNzKezlWwHvkMwRXR0Fep0wPdyeaKW5BfaW2ABvgep6Bp+hHEbyg==zSyi +$names$ iQCVAwUAQCN3EDEAnp832S/7AQJXLAP8DvHTpm5DkTF35EmzeKpi9ie59AZcZanD19ir/e/7+PaQxr2riuLHDGwFKTju+dcvvBsqrygXOC378GXVWzIF2OZwS4EdDcJ+pgojo9UpsqpKsJHouY4Ugx5cQialxba462kUn8hcihSBnMyc4LzbJ5WQ4puQuqy544d2x94+2ms==G4Ls diff --git a/grub-core/lib/libgcrypt/cipher/ac.c b/grub-core/lib/libgcrypt/cipher/ac.c index ee9498b23..63f6fcd11 100644 --- a/grub-core/lib/libgcrypt/cipher/ac.c +++ b/grub-core/lib/libgcrypt/cipher/ac.c @@ -1,19 +1,19 @@ /* ac.c - Alternative interface for asymmetric cryptography. Copyright (C) 2003, 2004, 2005, 2006 2007, 2008 Free Software Foundation, Inc. - + This file is part of Libgcrypt. - + Libgcrypt is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser general Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + Libgcrypt 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, see . */ @@ -115,7 +115,7 @@ struct gcry_ac_key_pair -/* +/* * Functions for working with data sets. */ @@ -151,7 +151,7 @@ static void ac_data_values_destroy (gcry_ac_data_t data) { unsigned int i; - + for (i = 0; i < data->data_n; i++) if (data->data[i].flags & GCRY_AC_FLAG_DEALLOC) { @@ -185,7 +185,7 @@ ac_data_mpi_copy (gcry_ac_mpi_t *data_mpis, unsigned int data_mpis_n, gcry_mpi_t mpi; char *label; - data_mpis_new = gcry_malloc (sizeof (*data_mpis_new) * data_mpis_n); + data_mpis_new = gcry_calloc (data_mpis_n, sizeof (*data_mpis_new)); if (! data_mpis_new) { err = gcry_error_from_errno (errno); @@ -256,7 +256,7 @@ _gcry_ac_data_copy (gcry_ac_data_t *data_cp, gcry_ac_data_t data) err = ac_data_mpi_copy (data->data, data->data_n, &data_mpis); if (err) goto out; - + data_new->data_n = data->data_n; data_new->data = data_mpis; *data_cp = data_new; @@ -524,13 +524,13 @@ _gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp, i++; } identifiers_n = i; - + if (! identifiers_n) /* If there are NO identifiers, we still add surrounding braces so that we have a list of named MPI value lists. Otherwise it wouldn't be too much fun to process these lists. */ sexp_buffer_n += 2; - + data_n = _gcry_ac_data_length (data); for (i = 0; i < data_n; i++) { @@ -572,7 +572,7 @@ _gcry_ac_data_to_sexp (gcry_ac_data_t data, gcry_sexp_t *sexp, } /* Add MPI list. */ - arg_list = gcry_malloc (sizeof (*arg_list) * (data_n + 1)); + arg_list = gcry_calloc (data_n + 1, sizeof (*arg_list)); if (! arg_list) { err = gcry_error_from_errno (errno); @@ -666,7 +666,7 @@ _gcry_ac_data_from_sexp (gcry_ac_data_t *data_set, gcry_sexp_t sexp, /* Identifier matches. Now we have to distinguish two cases: - + (i) we are at the last identifier: leave loop @@ -725,7 +725,7 @@ _gcry_ac_data_from_sexp (gcry_ac_data_t *data_set, gcry_sexp_t sexp, skip_name = 0; /* Create data set from S-expression data. */ - + err = gcry_ac_data_new (&data_set_new); if (err) goto out; @@ -793,7 +793,7 @@ _gcry_ac_data_from_sexp (gcry_ac_data_t *data_set, gcry_sexp_t sexp, gcry_sexp_release (sexp_tmp); gcry_mpi_release (mpi); gcry_free (string); - + if (err) gcry_ac_data_destroy (data_set_new); @@ -1005,7 +1005,7 @@ _gcry_ac_io_read (gcry_ac_io_t *ac_io, unsigned int nread, unsigned char *buffer, size_t *buffer_n) { gcry_error_t err; - + gcry_assert (ac_io->mode == GCRY_AC_IO_READABLE); err = 0; @@ -1072,7 +1072,7 @@ _gcry_ac_io_read_all (gcry_ac_io_t *ac_io, unsigned char **buffer, size_t *buffe err = gcry_error_from_errno (errno); break; } - + if (buffer_new != p) buffer_new = p; @@ -1132,7 +1132,7 @@ _gcry_ac_io_process (gcry_ac_io_t *ac_io, -/* +/* * Functions for converting data between the native ac and the * S-expression structure used by the pk interface. */ @@ -1283,7 +1283,7 @@ ac_data_construct (const char *identifier, int include_flags, /* We build a list of arguments to pass to gcry_sexp_build_array(). */ data_length = _gcry_ac_data_length (data); - arg_list = gcry_malloc (sizeof (*arg_list) * (data_length * 2)); + arg_list = gcry_calloc (data_length, sizeof (*arg_list) * 2); if (! arg_list) { err = gcry_error_from_errno (errno); @@ -1403,7 +1403,7 @@ _gcry_ac_open (gcry_ac_handle_t *handle, err = _gcry_pk_module_lookup (algorithm, &module); if (err) goto out; - + /* Allocate. */ handle_new = gcry_malloc (sizeof (*handle_new)); if (! handle_new) @@ -1420,7 +1420,7 @@ _gcry_ac_open (gcry_ac_handle_t *handle, *handle = handle_new; out: - + /* Deallocate resources. */ if (err) _gcry_pk_module_release (module); @@ -1443,7 +1443,7 @@ _gcry_ac_close (gcry_ac_handle_t handle) -/* +/* * Key management. */ @@ -1593,7 +1593,7 @@ _gcry_ac_key_pair_generate (gcry_ac_handle_t handle, unsigned int nbits, arg_list_n += 2; /* Allocate list. */ - arg_list = gcry_malloc (sizeof (*arg_list) * arg_list_n); + arg_list = gcry_calloc (arg_list_n, sizeof (*arg_list)); if (! arg_list) { err = gcry_error_from_errno (errno); @@ -1662,7 +1662,7 @@ _gcry_ac_key_pair_generate (gcry_ac_handle_t handle, unsigned int nbits, out: /* Deallocate resources. */ - + gcry_free (genkey_format); gcry_free (arg_list); gcry_sexp_release (genkey_sexp_request); @@ -1682,7 +1682,7 @@ _gcry_ac_key_pair_generate (gcry_ac_handle_t handle, unsigned int nbits, /* Returns the key of type WHICH out of the key pair KEY_PAIR. */ gcry_ac_key_t -_gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair, +_gcry_ac_key_pair_extract (gcry_ac_key_pair_t key_pair, gcry_ac_key_type_t which) { gcry_ac_key_t key; @@ -1851,7 +1851,7 @@ _gcry_ac_key_get_grip (gcry_ac_handle_t handle, -/* +/* * Functions performing cryptographic operations. */ @@ -2176,7 +2176,7 @@ em_randomize_nonzero (unsigned char *buffer, size_t buffer_n, for (i = 0; i < buffer_n; i++) buffer[i] = 0; - + do { /* Count zeros. */ @@ -2384,7 +2384,7 @@ emsa_pkcs_v1_5_encode (unsigned int flags, void *opts, unsigned int i; (void)flags; - + options = opts; buffer = NULL; md = NULL; @@ -2499,7 +2499,7 @@ typedef enum dencode_action dencode_action_t; /* Encode or decode a message according to the the encoding method - METHOD; ACTION specifies wether the message that is contained in + METHOD; ACTION specifies whether the message that is contained in BUFFER_IN and of length BUFFER_IN_N should be encoded or decoded. The resulting message will be stored in a newly allocated buffer in BUFFER_OUT and BUFFER_OUT_N. */ @@ -2656,7 +2656,7 @@ _gcry_ac_mpi_to_os_alloc (gcry_mpi_t mpi, unsigned char **os, size_t *os_n) err = gcry_error_from_errno (errno); goto out; } - + _gcry_ac_mpi_to_os (mpi, buffer, buffer_n); *os = buffer; *os_n = buffer_n; @@ -2676,7 +2676,7 @@ _gcry_ac_os_to_mpi (gcry_mpi_t mpi, unsigned char *os, size_t os_n) gcry_mpi_t xi; gcry_mpi_t x; gcry_mpi_t a; - + if (fips_mode ()) return; @@ -2692,7 +2692,7 @@ _gcry_ac_os_to_mpi (gcry_mpi_t mpi, unsigned char *os, size_t os_n) gcry_mpi_add (x, x, xi); gcry_mpi_mul_ui (a, a, 256); } - + gcry_mpi_release (xi); gcry_mpi_release (a); @@ -2702,7 +2702,7 @@ _gcry_ac_os_to_mpi (gcry_mpi_t mpi, unsigned char *os, size_t os_n) -/* +/* * Implementation of Encryption Schemes (ES) and Signature Schemes * with Appendix (SSA). */ @@ -2824,7 +2824,7 @@ ac_dencode_prepare (gcry_ac_handle_t handle, gcry_ac_key_t key, void *opts, err = gcry_error_from_errno (errno); goto out; } - + err = (*scheme.dencode_prepare) (handle, key, opts, options_em); if (err) goto out; @@ -3065,7 +3065,7 @@ _gcry_ac_data_decrypt_scheme (gcry_ac_handle_t handle, goto out; out: - + _gcry_ac_data_destroy (data_encrypted); gcry_mpi_release (mpi_encrypted); gcry_mpi_release (mpi_decrypted); @@ -3270,7 +3270,7 @@ _gcry_ac_data_verify_scheme (gcry_ac_handle_t handle, gcry_mpi_release (mpi_signature); mpi_signature = NULL; - + err = _gcry_ac_data_verify (handle, key, mpi_data, data_signed); out: @@ -3287,7 +3287,7 @@ _gcry_ac_data_verify_scheme (gcry_ac_handle_t handle, } -/* +/* * General functions. */ diff --git a/grub-core/lib/libgcrypt/cipher/arcfour.c b/grub-core/lib/libgcrypt/cipher/arcfour.c index 6bb0555c6..6ef07fb20 100644 --- a/grub-core/lib/libgcrypt/cipher/arcfour.c +++ b/grub-core/lib/libgcrypt/cipher/arcfour.c @@ -45,7 +45,7 @@ do_encrypt_stream( ARCFOUR_context *ctx, register int i = ctx->idx_i; register int j = ctx->idx_j; register byte *sbox = ctx->sbox; - register int t; + register int t; while ( length-- ) { @@ -56,7 +56,7 @@ do_encrypt_stream( ARCFOUR_context *ctx, t = sbox[i]; sbox[i] = sbox[j]; sbox[j] = t; *outbuf++ = *inbuf++ ^ sbox[(sbox[i] + sbox[j]) & 255]; } - + ctx->idx_i = i; ctx->idx_j = j; } @@ -80,7 +80,7 @@ do_arcfour_setkey (void *context, const byte *key, unsigned int keylen) byte karr[256]; ARCFOUR_context *ctx = (ARCFOUR_context *) context; - if (!initialized ) + if (!initialized ) { initialized = 1; selftest_failed = selftest(); @@ -98,14 +98,14 @@ do_arcfour_setkey (void *context, const byte *key, unsigned int keylen) ctx->sbox[i] = i; for (i=0; i < 256; i++ ) karr[i] = key[i%keylen]; - for (i=j=0; i < 256; i++ ) + for (i=j=0; i < 256; i++ ) { int t; j = (j + ctx->sbox[i] + karr[i]) % 256; t = ctx->sbox[i]; ctx->sbox[i] = ctx->sbox[j]; ctx->sbox[j] = t; - } + } memset( karr, 0, 256 ); return GPG_ERR_NO_ERROR; @@ -125,8 +125,8 @@ static const char* selftest(void) { ARCFOUR_context ctx; - byte scratch[16]; - + byte scratch[16]; + /* Test vector from Cryptlib labeled there: "from the State/Commerce Department". */ static byte key_1[] = @@ -153,4 +153,3 @@ gcry_cipher_spec_t _gcry_cipher_spec_arcfour = "ARCFOUR", NULL, NULL, 1, 128, sizeof (ARCFOUR_context), arcfour_setkey, NULL, NULL, encrypt_stream, encrypt_stream, }; - diff --git a/grub-core/lib/libgcrypt/cipher/blowfish.c b/grub-core/lib/libgcrypt/cipher/blowfish.c index 6ef68e371..b4d2b9c9a 100644 --- a/grub-core/lib/libgcrypt/cipher/blowfish.c +++ b/grub-core/lib/libgcrypt/cipher/blowfish.c @@ -501,7 +501,7 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) static int initialized; static const char *selftest_failed; - if( !initialized ) + if( !initialized ) { initialized = 1; selftest_failed = selftest(); @@ -513,7 +513,7 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) for(i=0; i < BLOWFISH_ROUNDS+2; i++ ) c->p[i] = ps[i]; - for(i=0; i < 256; i++ ) + for(i=0; i < 256; i++ ) { c->s0[i] = ks0[i]; c->s1[i] = ks1[i]; @@ -521,7 +521,7 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) c->s3[i] = ks3[i]; } - for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) + for(i=j=0; i < BLOWFISH_ROUNDS+2; i++ ) { #ifdef WORDS_BIGENDIAN ((byte*)&data)[0] = key[j]; @@ -545,7 +545,7 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) c->p[i] = datal; c->p[i+1] = datar; } - for(i=0; i < 256; i += 2 ) + for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s0[i] = datal; diff --git a/grub-core/lib/libgcrypt/cipher/bufhelp.h b/grub-core/lib/libgcrypt/cipher/bufhelp.h new file mode 100644 index 000000000..df3559472 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/bufhelp.h @@ -0,0 +1,432 @@ +/* bufhelp.h - Some buffer manipulation helpers + * Copyright (C) 2012 Jussi Kivilinna + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ +#ifndef GCRYPT_BUFHELP_H +#define GCRYPT_BUFHELP_H + + +#include "bithelp.h" + + +#undef BUFHELP_FAST_UNALIGNED_ACCESS +#if defined(HAVE_GCC_ATTRIBUTE_PACKED) && \ + defined(HAVE_GCC_ATTRIBUTE_ALIGNED) && \ + (defined(__i386__) || defined(__x86_64__) || \ + (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \ + defined(__aarch64__)) +/* These architectures are able of unaligned memory accesses and can + handle those fast. + */ +# define BUFHELP_FAST_UNALIGNED_ACCESS 1 +#endif + + +#ifdef BUFHELP_FAST_UNALIGNED_ACCESS +/* Define type with one-byte alignment on architectures with fast unaligned + memory accesses. + */ +typedef struct bufhelp_int_s +{ + uintptr_t a; +} __attribute__((packed, aligned(1))) bufhelp_int_t; +#else +/* Define type with default alignment for other architectures (unaligned + accessed handled in per byte loops). + */ +typedef struct bufhelp_int_s +{ + uintptr_t a; +} bufhelp_int_t; +#endif + + +/* Optimized function for small buffer copying */ +static inline void +buf_cpy(void *_dst, const void *_src, size_t len) +{ +#if __GNUC__ >= 4 && (defined(__x86_64__) || defined(__i386__)) + /* For AMD64 and i386, memcpy is faster. */ + memcpy(_dst, _src, len); +#else + byte *dst = _dst; + const byte *src = _src; + bufhelp_int_t *ldst; + const bufhelp_int_t *lsrc; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)dst | (uintptr_t)src) & longmask) + goto do_bytes; +#endif + + ldst = (bufhelp_int_t *)(void *)dst; + lsrc = (const bufhelp_int_t *)(const void *)src; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst++)->a = (lsrc++)->a; + + dst = (byte *)ldst; + src = (const byte *)lsrc; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst++ = *src++; +#endif /*__GNUC__ >= 4 && (__x86_64__ || __i386__)*/ +} + + +/* Optimized function for buffer xoring */ +static inline void +buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len) +{ + byte *dst = _dst; + const byte *src1 = _src1; + const byte *src2 = _src2; + bufhelp_int_t *ldst; + const bufhelp_int_t *lsrc1, *lsrc2; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)dst | (uintptr_t)src1 | (uintptr_t)src2) & longmask) + goto do_bytes; +#endif + + ldst = (bufhelp_int_t *)(void *)dst; + lsrc1 = (const bufhelp_int_t *)(const void *)src1; + lsrc2 = (const bufhelp_int_t *)(const void *)src2; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst++)->a = (lsrc1++)->a ^ (lsrc2++)->a; + + dst = (byte *)ldst; + src1 = (const byte *)lsrc1; + src2 = (const byte *)lsrc2; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst++ = *src1++ ^ *src2++; +} + + +/* Optimized function for in-place buffer xoring. */ +static inline void +buf_xor_1(void *_dst, const void *_src, size_t len) +{ + byte *dst = _dst; + const byte *src = _src; + bufhelp_int_t *ldst; + const bufhelp_int_t *lsrc; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)dst | (uintptr_t)src) & longmask) + goto do_bytes; +#endif + + ldst = (bufhelp_int_t *)(void *)dst; + lsrc = (const bufhelp_int_t *)(const void *)src; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst++)->a ^= (lsrc++)->a; + + dst = (byte *)ldst; + src = (const byte *)lsrc; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst++ ^= *src++; +} + + +/* Optimized function for buffer xoring with two destination buffers. Used + mainly by CFB mode encryption. */ +static inline void +buf_xor_2dst(void *_dst1, void *_dst2, const void *_src, size_t len) +{ + byte *dst1 = _dst1; + byte *dst2 = _dst2; + const byte *src = _src; + bufhelp_int_t *ldst1, *ldst2; + const bufhelp_int_t *lsrc; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)src | (uintptr_t)dst1 | (uintptr_t)dst2) & longmask) + goto do_bytes; +#endif + + ldst1 = (bufhelp_int_t *)(void *)dst1; + ldst2 = (bufhelp_int_t *)(void *)dst2; + lsrc = (const bufhelp_int_t *)(const void *)src; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + (ldst1++)->a = ((ldst2++)->a ^= (lsrc++)->a); + + dst1 = (byte *)ldst1; + dst2 = (byte *)ldst2; + src = (const byte *)lsrc; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + *dst1++ = (*dst2++ ^= *src++); +} + + +/* Optimized function for combined buffer xoring and copying. Used by mainly + CBC mode decryption. */ +static inline void +buf_xor_n_copy_2(void *_dst_xor, const void *_src_xor, void *_srcdst_cpy, + const void *_src_cpy, size_t len) +{ + byte *dst_xor = _dst_xor; + byte *srcdst_cpy = _srcdst_cpy; + const byte *src_xor = _src_xor; + const byte *src_cpy = _src_cpy; + byte temp; + bufhelp_int_t *ldst_xor, *lsrcdst_cpy; + const bufhelp_int_t *lsrc_cpy, *lsrc_xor; + uintptr_t ltemp; +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + const unsigned int longmask = sizeof(bufhelp_int_t) - 1; + + /* Skip fast processing if buffers are unaligned. */ + if (((uintptr_t)src_cpy | (uintptr_t)src_xor | (uintptr_t)dst_xor | + (uintptr_t)srcdst_cpy) & longmask) + goto do_bytes; +#endif + + ldst_xor = (bufhelp_int_t *)(void *)dst_xor; + lsrc_xor = (const bufhelp_int_t *)(void *)src_xor; + lsrcdst_cpy = (bufhelp_int_t *)(void *)srcdst_cpy; + lsrc_cpy = (const bufhelp_int_t *)(const void *)src_cpy; + + for (; len >= sizeof(bufhelp_int_t); len -= sizeof(bufhelp_int_t)) + { + ltemp = (lsrc_cpy++)->a; + (ldst_xor++)->a = (lsrcdst_cpy)->a ^ (lsrc_xor++)->a; + (lsrcdst_cpy++)->a = ltemp; + } + + dst_xor = (byte *)ldst_xor; + src_xor = (const byte *)lsrc_xor; + srcdst_cpy = (byte *)lsrcdst_cpy; + src_cpy = (const byte *)lsrc_cpy; + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS +do_bytes: +#endif + /* Handle tail. */ + for (; len; len--) + { + temp = *src_cpy++; + *dst_xor++ = *srcdst_cpy ^ *src_xor++; + *srcdst_cpy++ = temp; + } +} + + +/* Optimized function for combined buffer xoring and copying. Used by mainly + CFB mode decryption. */ +static inline void +buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len) +{ + buf_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, len); +} + + +/* Constant-time compare of two buffers. Returns 1 if buffers are equal, + and 0 if buffers differ. */ +static inline int +buf_eq_const(const void *_a, const void *_b, size_t len) +{ + const byte *a = _a; + const byte *b = _b; + size_t diff, i; + + /* Constant-time compare. */ + for (i = 0, diff = 0; i < len; i++) + diff -= !!(a[i] - b[i]); + + return !diff; +} + + +#ifndef BUFHELP_FAST_UNALIGNED_ACCESS + +/* Functions for loading and storing unaligned u32 values of different + endianness. */ +static inline u32 buf_get_be32(const void *_buf) +{ + const byte *in = _buf; + return ((u32)in[0] << 24) | ((u32)in[1] << 16) | \ + ((u32)in[2] << 8) | (u32)in[3]; +} + +static inline u32 buf_get_le32(const void *_buf) +{ + const byte *in = _buf; + return ((u32)in[3] << 24) | ((u32)in[2] << 16) | \ + ((u32)in[1] << 8) | (u32)in[0]; +} + +static inline void buf_put_be32(void *_buf, u32 val) +{ + byte *out = _buf; + out[0] = val >> 24; + out[1] = val >> 16; + out[2] = val >> 8; + out[3] = val; +} + +static inline void buf_put_le32(void *_buf, u32 val) +{ + byte *out = _buf; + out[3] = val >> 24; + out[2] = val >> 16; + out[1] = val >> 8; + out[0] = val; +} + + +/* Functions for loading and storing unaligned u64 values of different + endianness. */ +static inline u64 buf_get_be64(const void *_buf) +{ + const byte *in = _buf; + return ((u64)in[0] << 56) | ((u64)in[1] << 48) | \ + ((u64)in[2] << 40) | ((u64)in[3] << 32) | \ + ((u64)in[4] << 24) | ((u64)in[5] << 16) | \ + ((u64)in[6] << 8) | (u64)in[7]; +} + +static inline u64 buf_get_le64(const void *_buf) +{ + const byte *in = _buf; + return ((u64)in[7] << 56) | ((u64)in[6] << 48) | \ + ((u64)in[5] << 40) | ((u64)in[4] << 32) | \ + ((u64)in[3] << 24) | ((u64)in[2] << 16) | \ + ((u64)in[1] << 8) | (u64)in[0]; +} + +static inline void buf_put_be64(void *_buf, u64 val) +{ + byte *out = _buf; + out[0] = val >> 56; + out[1] = val >> 48; + out[2] = val >> 40; + out[3] = val >> 32; + out[4] = val >> 24; + out[5] = val >> 16; + out[6] = val >> 8; + out[7] = val; +} + +static inline void buf_put_le64(void *_buf, u64 val) +{ + byte *out = _buf; + out[7] = val >> 56; + out[6] = val >> 48; + out[5] = val >> 40; + out[4] = val >> 32; + out[3] = val >> 24; + out[2] = val >> 16; + out[1] = val >> 8; + out[0] = val; +} + +#else /*BUFHELP_FAST_UNALIGNED_ACCESS*/ + +typedef struct bufhelp_u32_s +{ + u32 a; +} __attribute__((packed, aligned(1))) bufhelp_u32_t; + +/* Functions for loading and storing unaligned u32 values of different + endianness. */ +static inline u32 buf_get_be32(const void *_buf) +{ + return be_bswap32(((const bufhelp_u32_t *)_buf)->a); +} + +static inline u32 buf_get_le32(const void *_buf) +{ + return le_bswap32(((const bufhelp_u32_t *)_buf)->a); +} + +static inline void buf_put_be32(void *_buf, u32 val) +{ + bufhelp_u32_t *out = _buf; + out->a = be_bswap32(val); +} + +static inline void buf_put_le32(void *_buf, u32 val) +{ + bufhelp_u32_t *out = _buf; + out->a = le_bswap32(val); +} + + +typedef struct bufhelp_u64_s +{ + u64 a; +} __attribute__((packed, aligned(1))) bufhelp_u64_t; + +/* Functions for loading and storing unaligned u64 values of different + endianness. */ +static inline u64 buf_get_be64(const void *_buf) +{ + return be_bswap64(((const bufhelp_u64_t *)_buf)->a); +} + +static inline u64 buf_get_le64(const void *_buf) +{ + return le_bswap64(((const bufhelp_u64_t *)_buf)->a); +} + +static inline void buf_put_be64(void *_buf, u64 val) +{ + bufhelp_u64_t *out = _buf; + out->a = be_bswap64(val); +} + +static inline void buf_put_le64(void *_buf, u64 val) +{ + bufhelp_u64_t *out = _buf; + out->a = le_bswap64(val); +} + + +#endif /*BUFHELP_FAST_UNALIGNED_ACCESS*/ + +#endif /*GCRYPT_BUFHELP_H*/ diff --git a/grub-core/lib/libgcrypt/cipher/camellia-glue.c b/grub-core/lib/libgcrypt/cipher/camellia-glue.c index 067af85bc..a26362177 100644 --- a/grub-core/lib/libgcrypt/cipher/camellia-glue.c +++ b/grub-core/lib/libgcrypt/cipher/camellia-glue.c @@ -32,7 +32,7 @@ * space of the library clean. The following macro is thus useful: * * #define CAMELLIA_EXT_SYM_PREFIX foo_ - * + * * This prefixes all external symbols with "foo_". */ #ifdef HAVE_CONFIG_H @@ -50,7 +50,7 @@ #define camellia_encrypt128 CAMELLIA_PREFIX(camellia_encrypt128) #define camellia_encrypt256 CAMELLIA_PREFIX(camellia_encrypt256) #define camellia_setup128 CAMELLIA_PREFIX(camellia_setup128) -#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) +#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) #define camellia_setup256 CAMELLIA_PREFIX(camellia_setup256) #endif /*CAMELLIA_EXT_SYM_PREFIX*/ @@ -99,7 +99,7 @@ camellia_setkey(void *c, const byte *key, unsigned keylen) +(4+32)*sizeof(u32)+2*sizeof(void*) /* camellia_setup192 */ +0+sizeof(int)+2*sizeof(void*) /* Camellia_Ekeygen */ +3*2*sizeof(void*) /* Function calls. */ - ); + ); return 0; } @@ -137,7 +137,7 @@ selftest(void) { CAMELLIA_context ctx; byte scratch[16]; - + /* These test vectors are from RFC-3713 */ const byte plaintext[]= { diff --git a/grub-core/lib/libgcrypt/cipher/camellia.c b/grub-core/lib/libgcrypt/cipher/camellia.c index 79cd49b7c..2e28bce2a 100644 --- a/grub-core/lib/libgcrypt/cipher/camellia.c +++ b/grub-core/lib/libgcrypt/cipher/camellia.c @@ -19,7 +19,7 @@ */ /* - * Algorithm Specification + * Algorithm Specification * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html */ @@ -937,7 +937,7 @@ void camellia_setup256(const unsigned char *key, u32 *subkey) CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw; dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw); CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw; - + return; } @@ -1049,14 +1049,14 @@ void camellia_encrypt128(const u32 *subkey, u32 *io) io[1] = io[3]; io[2] = t0; io[3] = t1; - + return; } void camellia_decrypt128(const u32 *subkey, u32 *io) { u32 il,ir,t0,t1; /* temporary valiables */ - + /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(24); io[1] ^= CamelliaSubkeyR(24); @@ -1267,7 +1267,7 @@ void camellia_decrypt256(const u32 *subkey, u32 *io) /* pre whitening but absorb kw2*/ io[0] ^= CamelliaSubkeyL(32); io[1] ^= CamelliaSubkeyR(32); - + /* main iteration */ CAMELLIA_ROUNDSM(io[0],io[1], CamelliaSubkeyL(31),CamelliaSubkeyR(31), @@ -1379,8 +1379,8 @@ void camellia_decrypt256(const u32 *subkey, u32 *io) * API for compatibility */ -void Camellia_Ekeygen(const int keyBitLength, - const unsigned char *rawKey, +void Camellia_Ekeygen(const int keyBitLength, + const unsigned char *rawKey, KEY_TABLE_TYPE keyTable) { switch(keyBitLength) { @@ -1399,9 +1399,9 @@ void Camellia_Ekeygen(const int keyBitLength, } -void Camellia_EncryptBlock(const int keyBitLength, - const unsigned char *plaintext, - const KEY_TABLE_TYPE keyTable, +void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, unsigned char *ciphertext) { u32 tmp[4]; @@ -1430,9 +1430,9 @@ void Camellia_EncryptBlock(const int keyBitLength, PUTU32(ciphertext + 12, tmp[3]); } -void Camellia_DecryptBlock(const int keyBitLength, - const unsigned char *ciphertext, - const KEY_TABLE_TYPE keyTable, +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *ciphertext, + const KEY_TABLE_TYPE keyTable, unsigned char *plaintext) { u32 tmp[4]; diff --git a/grub-core/lib/libgcrypt/cipher/camellia.h b/grub-core/lib/libgcrypt/cipher/camellia.h index 4425a3a2b..cccf786ca 100644 --- a/grub-core/lib/libgcrypt/cipher/camellia.h +++ b/grub-core/lib/libgcrypt/cipher/camellia.h @@ -25,7 +25,7 @@ * space of the library clean. The following macro is thus useful: * * #define CAMELLIA_EXT_SYM_PREFIX foo_ - * + * * This prefixes all external symbols with "foo_". */ #ifdef HAVE_CONFIG_H @@ -43,7 +43,7 @@ #define camellia_encrypt128 CAMELLIA_PREFIX(camellia_encrypt128) #define camellia_encrypt256 CAMELLIA_PREFIX(camellia_encrypt256) #define camellia_setup128 CAMELLIA_PREFIX(camellia_setup128) -#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) +#define camellia_setup192 CAMELLIA_PREFIX(camellia_setup192) #define camellia_setup256 CAMELLIA_PREFIX(camellia_setup256) #endif /*CAMELLIA_EXT_SYM_PREFIX*/ @@ -60,17 +60,17 @@ typedef unsigned int KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; void Camellia_Ekeygen(const int keyBitLength, - const unsigned char *rawKey, + const unsigned char *rawKey, KEY_TABLE_TYPE keyTable); void Camellia_EncryptBlock(const int keyBitLength, - const unsigned char *plaintext, - const KEY_TABLE_TYPE keyTable, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, unsigned char *cipherText); -void Camellia_DecryptBlock(const int keyBitLength, - const unsigned char *cipherText, - const KEY_TABLE_TYPE keyTable, +void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *cipherText, + const KEY_TABLE_TYPE keyTable, unsigned char *plaintext); diff --git a/grub-core/lib/libgcrypt/cipher/cast5.c b/grub-core/lib/libgcrypt/cipher/cast5.c index 333d55e91..9905f5cb9 100644 --- a/grub-core/lib/libgcrypt/cipher/cast5.c +++ b/grub-core/lib/libgcrypt/cipher/cast5.c @@ -569,7 +569,7 @@ do_cast_setkey( CAST5_context *c, const byte *key, unsigned keylen ) u32 z[4]; u32 k[16]; - if( !initialized ) + if( !initialized ) { initialized = 1; selftest_failed = selftest(); diff --git a/grub-core/lib/libgcrypt/cipher/cipher.c b/grub-core/lib/libgcrypt/cipher/cipher.c index 2c33ee94f..9852d6a5a 100644 --- a/grub-core/lib/libgcrypt/cipher/cipher.c +++ b/grub-core/lib/libgcrypt/cipher/cipher.c @@ -1,6 +1,6 @@ /* cipher.c - cipher dispatcher * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 - * 2005, 2007, 2008 Free Software Foundation, Inc. + * 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -33,9 +33,12 @@ #define CTX_MAGIC_NORMAL 0x24091964 #define CTX_MAGIC_SECURE 0x46919042 +/* Try to use 16 byte aligned cipher context for better performance. + We use the aligned attribute, thus it is only possible to implement + this with gcc. */ #undef NEED_16BYTE_ALIGNED_CONTEXT -#if defined (__i386__) && SIZEOF_UNSIGNED_LONG == 4 && defined (__GNUC__) -#define NEED_16BYTE_ALIGNED_CONTEXT 1 +#if defined (__GNUC__) +# define NEED_16BYTE_ALIGNED_CONTEXT 1 #endif /* A dummy extraspec so that we do not need to tests the extraspec @@ -58,39 +61,39 @@ static struct cipher_table_entry &dummy_extra_spec, GCRY_CIPHER_BLOWFISH }, #endif #if USE_DES - { &_gcry_cipher_spec_des, + { &_gcry_cipher_spec_des, &dummy_extra_spec, GCRY_CIPHER_DES }, { &_gcry_cipher_spec_tripledes, &_gcry_cipher_extraspec_tripledes, GCRY_CIPHER_3DES, 1 }, #endif #if USE_ARCFOUR - { &_gcry_cipher_spec_arcfour, + { &_gcry_cipher_spec_arcfour, &dummy_extra_spec, GCRY_CIPHER_ARCFOUR }, #endif #if USE_CAST5 - { &_gcry_cipher_spec_cast5, + { &_gcry_cipher_spec_cast5, &dummy_extra_spec, GCRY_CIPHER_CAST5 }, #endif #if USE_AES - { &_gcry_cipher_spec_aes, + { &_gcry_cipher_spec_aes, &_gcry_cipher_extraspec_aes, GCRY_CIPHER_AES, 1 }, - { &_gcry_cipher_spec_aes192, + { &_gcry_cipher_spec_aes192, &_gcry_cipher_extraspec_aes192, GCRY_CIPHER_AES192, 1 }, - { &_gcry_cipher_spec_aes256, + { &_gcry_cipher_spec_aes256, &_gcry_cipher_extraspec_aes256, GCRY_CIPHER_AES256, 1 }, #endif #if USE_TWOFISH { &_gcry_cipher_spec_twofish, &dummy_extra_spec, GCRY_CIPHER_TWOFISH }, - { &_gcry_cipher_spec_twofish128, + { &_gcry_cipher_spec_twofish128, &dummy_extra_spec, GCRY_CIPHER_TWOFISH128 }, #endif #if USE_SERPENT - { &_gcry_cipher_spec_serpent128, + { &_gcry_cipher_spec_serpent128, &dummy_extra_spec, GCRY_CIPHER_SERPENT128 }, { &_gcry_cipher_spec_serpent192, &dummy_extra_spec, GCRY_CIPHER_SERPENT192 }, - { &_gcry_cipher_spec_serpent256, + { &_gcry_cipher_spec_serpent256, &dummy_extra_spec, GCRY_CIPHER_SERPENT256 }, #endif #if USE_RFC2268 @@ -98,16 +101,20 @@ static struct cipher_table_entry &dummy_extra_spec, GCRY_CIPHER_RFC2268_40 }, #endif #if USE_SEED - { &_gcry_cipher_spec_seed, + { &_gcry_cipher_spec_seed, &dummy_extra_spec, GCRY_CIPHER_SEED }, #endif #if USE_CAMELLIA { &_gcry_cipher_spec_camellia128, &dummy_extra_spec, GCRY_CIPHER_CAMELLIA128 }, - { &_gcry_cipher_spec_camellia192, + { &_gcry_cipher_spec_camellia192, &dummy_extra_spec, GCRY_CIPHER_CAMELLIA192 }, { &_gcry_cipher_spec_camellia256, &dummy_extra_spec, GCRY_CIPHER_CAMELLIA256 }, +#endif +#ifdef USE_IDEA + { &_gcry_cipher_spec_idea, + &dummy_extra_spec, GCRY_CIPHER_IDEA }, #endif { NULL } }; @@ -118,7 +125,7 @@ static gcry_module_t ciphers_registered; /* This is the lock protecting CIPHERS_REGISTERED. */ static ath_mutex_t ciphers_registered_lock = ATH_MUTEX_INITIALIZER; -/* Flag to check wether the default ciphers have already been +/* Flag to check whether the default ciphers have already been registered. */ static int default_ciphers_registered; @@ -137,19 +144,20 @@ static int default_ciphers_registered; while (0) -/* A VIA processor with the Padlock engine requires an alignment of - most data on a 16 byte boundary. Because we trick out the compiler - while allocating the context, the align attribute as used in - rijndael.c does not work on its own. Thus we need to make sure - that the entire context structure is a aligned on that boundary. - We achieve this by defining a new type and use that instead of our - usual alignment type. */ -typedef union +/* A VIA processor with the Padlock engine as well as the Intel AES_NI + instructions require an alignment of most data on a 16 byte + boundary. Because we trick out the compiler while allocating the + context, the align attribute as used in rijndael.c does not work on + its own. Thus we need to make sure that the entire context + structure is a aligned on that boundary. We achieve this by + defining a new type and use that instead of our usual alignment + type. */ +typedef union { PROPERLY_ALIGNED_TYPE foo; #ifdef NEED_16BYTE_ALIGNED_CONTEXT char bar[16] __attribute__ ((aligned (16))); -#endif +#endif char c[1]; } cipher_context_alignment_t; @@ -166,7 +174,7 @@ struct gcry_cipher_handle /* The algorithm id. This is a hack required because the module interface does not easily allow to retrieve this value. */ - int algo; + int algo; /* A structure with function pointers for bulk operations. Due to limitations of the module system (we don't want to change the @@ -174,16 +182,19 @@ struct gcry_cipher_handle open function intializes them and the actual encryption routines use them if they are not NULL. */ struct { - void (*cfb_enc)(void *context, unsigned char *iv, + void (*cfb_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks); - void (*cfb_dec)(void *context, unsigned char *iv, + void (*cfb_dec)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks); - void (*cbc_enc)(void *context, unsigned char *iv, + void (*cbc_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks, int cbc_mac); - void (*cbc_dec)(void *context, unsigned char *iv, + void (*cbc_dec)(void *context, unsigned char *iv, + void *outbuf_arg, const void *inbuf_arg, + unsigned int nblocks); + void (*ctr_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, unsigned int nblocks); } bulk; @@ -192,19 +203,29 @@ struct gcry_cipher_handle int mode; unsigned int flags; - /* The initialization vector. To help code optimization we make - sure that it is aligned on an unsigned long and u32 boundary. */ + struct { + unsigned int key:1; /* Set to 1 if a key has been set. */ + unsigned int iv:1; /* Set to 1 if a IV has been set. */ + } marks; + + /* The initialization vector. For best performance we make sure + that it is properly aligned. In particular some implementations + of bulk operations expect an 16 byte aligned IV. */ union { - unsigned long dummy_iv; - u32 dummy_u32_iv; - unsigned char iv[MAX_BLOCKSIZE]; + cipher_context_alignment_t iv_align; + unsigned char iv[MAX_BLOCKSIZE]; } u_iv; + /* The counter for CTR mode. This field is also used by AESWRAP and + thus we can't use the U_IV union. */ + union { + cipher_context_alignment_t iv_align; + unsigned char ctr[MAX_BLOCKSIZE]; + } u_ctr; + + /* Space to save an IV or CTR for chaining operations. */ unsigned char lastiv[MAX_BLOCKSIZE]; - int unused; /* Number of unused bytes in the IV. */ - - unsigned char ctr[MAX_BLOCKSIZE]; /* For Counter (CTR) mode. */ - + int unused; /* Number of unused bytes in LASTIV. */ /* What follows are two contexts of the cipher in use. The first one needs to be aligned well enough for the cipher operation @@ -222,7 +243,7 @@ struct gcry_cipher_handle static gcry_err_code_t dummy_setkey (void *c, const unsigned char *key, unsigned int keylen) { - (void)c; + (void)c; (void)key; (void)keylen; return GPG_ERR_NO_ERROR; @@ -281,7 +302,7 @@ cipher_register_default (void) { gcry_err_code_t err = GPG_ERR_NO_ERROR; int i; - + for (i = 0; !err && cipher_table[i].cipher; i++) { if (! cipher_table[i].cipher->setkey) @@ -384,8 +405,8 @@ _gcry_cipher_register (gcry_cipher_spec_t *cipher, ath_mutex_lock (&ciphers_registered_lock); err = _gcry_module_add (&ciphers_registered, 0, - (void *)cipher, - (void *)(extraspec? extraspec : &dummy_extra_spec), + (void *)cipher, + (void *)(extraspec? extraspec : &dummy_extra_spec), &mod); ath_mutex_unlock (&ciphers_registered_lock); @@ -415,7 +436,7 @@ gcry_cipher_unregister (gcry_module_t module) ispassed as NULL. A pointer to the specification of the module implementing this algorithm is return in OID_SPEC unless passed as NULL.*/ -static int +static int search_oid (const char *oid, int *algorithm, gcry_cipher_oid_spec_t *oid_spec) { gcry_module_t module; @@ -479,7 +500,7 @@ gcry_cipher_map_name (const char *string) } ath_mutex_unlock (&ciphers_registered_lock); - + return algorithm; } @@ -588,15 +609,13 @@ check_cipher_algo (int algorithm) else err = GPG_ERR_CIPHER_ALGO; ath_mutex_unlock (&ciphers_registered_lock); - + return err; } -/* Return the standard length of the key for the cipher algorithm with - the identifier ALGORITHM. This function expects a valid algorithm - and will abort if the algorithm is not available or the length of - the key is not known. */ +/* Return the standard length in bits of the key for the cipher + algorithm with the identifier ALGORITHM. */ static unsigned int cipher_get_keylen (int algorithm) { @@ -614,17 +633,13 @@ cipher_get_keylen (int algorithm) log_bug ("cipher %d w/o key length\n", algorithm); _gcry_module_release (cipher); } - else - log_bug ("cipher %d not found\n", algorithm); ath_mutex_unlock (&ciphers_registered_lock); return len; } /* Return the block length of the cipher algorithm with the identifier - ALGORITHM. This function expects a valid algorithm and will abort - if the algorithm is not available or the length of the key is not - known. */ + ALGORITHM. This function return 0 for an invalid algorithm. */ static unsigned int cipher_get_blocksize (int algorithm) { @@ -642,8 +657,6 @@ cipher_get_blocksize (int algorithm) log_bug ("cipher %d w/o blocksize\n", algorithm); _gcry_module_release (cipher); } - else - log_bug ("cipher %d not found\n", algorithm); ath_mutex_unlock (&ciphers_registered_lock); return len; @@ -678,10 +691,10 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, /* If the application missed to call the random poll function, we do it here to ensure that it is used once in a while. */ _gcry_fast_random_poll (); - + REGISTER_DEFAULT_CIPHERS; - /* Fetch the according module and check wether the cipher is marked + /* Fetch the according module and check whether the cipher is marked available for use. */ ath_mutex_lock (&ciphers_registered_lock); module = _gcry_module_lookup_id (ciphers_registered, algo); @@ -693,7 +706,6 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, { /* Not available for use. */ err = GPG_ERR_CIPHER_ALGO; - _gcry_module_release (module); } else { @@ -707,7 +719,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, /* check flags */ if ((! err) - && ((flags & ~(0 + && ((flags & ~(0 | GCRY_CIPHER_SECURE | GCRY_CIPHER_ENABLE_SYNC | GCRY_CIPHER_CBC_CTS @@ -724,6 +736,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, case GCRY_CIPHER_MODE_CFB: case GCRY_CIPHER_MODE_OFB: case GCRY_CIPHER_MODE_CTR: + case GCRY_CIPHER_MODE_AESWRAP: if ((cipher->encrypt == dummy_encrypt_block) || (cipher->decrypt == dummy_decrypt_block)) err = GPG_ERR_INV_CIPHER_MODE; @@ -769,7 +782,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, h = gcry_calloc (1, size); if (! h) - err = gpg_err_code_from_errno (errno); + err = gpg_err_code_from_syserror (); else { size_t off = 0; @@ -805,9 +818,10 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, h->bulk.cfb_dec = _gcry_aes_cfb_dec; h->bulk.cbc_enc = _gcry_aes_cbc_enc; h->bulk.cbc_dec = _gcry_aes_cbc_dec; + h->bulk.ctr_enc = _gcry_aes_ctr_enc; break; #endif /*USE_AES*/ - + default: break; } @@ -882,7 +896,10 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen) memcpy ((void *) ((char *) &c->context.c + c->cipher->contextsize), (void *) &c->context.c, c->cipher->contextsize); + c->marks.key = 1; } + else + c->marks.key = 0; return gcry_error (ret); } @@ -894,7 +911,7 @@ static void cipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen ) { memset (c->u_iv.iv, 0, c->cipher->blocksize); - if (iv) + if (iv) { if (ivlen != c->cipher->blocksize) { @@ -905,7 +922,10 @@ cipher_setiv( gcry_cipher_hd_t c, const byte *iv, unsigned ivlen ) if (ivlen > c->cipher->blocksize) ivlen = c->cipher->blocksize; memcpy (c->u_iv.iv, iv, ivlen); + c->marks.iv = 1; } + else + c->marks.iv = 0; c->unused = 0; } @@ -918,61 +938,92 @@ cipher_reset (gcry_cipher_hd_t c) memcpy (&c->context.c, (char *) &c->context.c + c->cipher->contextsize, c->cipher->contextsize); + memset (&c->marks, 0, sizeof c->marks); memset (c->u_iv.iv, 0, c->cipher->blocksize); memset (c->lastiv, 0, c->cipher->blocksize); - memset (c->ctr, 0, c->cipher->blocksize); + memset (c->u_ctr.ctr, 0, c->cipher->blocksize); } -static void -do_ecb_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, - unsigned int nblocks ) + +static gcry_err_code_t +do_ecb_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { - unsigned int n; - + unsigned int blocksize = c->cipher->blocksize; + unsigned int n, nblocks; + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + if ((inbuflen % blocksize)) + return GPG_ERR_INV_LENGTH; + + nblocks = inbuflen / c->cipher->blocksize; + for (n=0; n < nblocks; n++ ) { - c->cipher->encrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf ); - inbuf += c->cipher->blocksize; - outbuf += c->cipher->blocksize; + c->cipher->encrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf); + inbuf += blocksize; + outbuf += blocksize; } + return 0; } -static void -do_ecb_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, - unsigned int nblocks ) +static gcry_err_code_t +do_ecb_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { - unsigned int n; + unsigned int blocksize = c->cipher->blocksize; + unsigned int n, nblocks; - for (n=0; n < nblocks; n++ ) + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + if ((inbuflen % blocksize)) + return GPG_ERR_INV_LENGTH; + nblocks = inbuflen / c->cipher->blocksize; + + for (n=0; n < nblocks; n++ ) { - c->cipher->decrypt ( &c->context.c, outbuf, (byte*)/*arggg*/inbuf ); - inbuf += c->cipher->blocksize; - outbuf += c->cipher->blocksize; + c->cipher->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf ); + inbuf += blocksize; + outbuf += blocksize; } + + return 0; } -static void -do_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, - const unsigned char *inbuf, unsigned int nbytes ) +static gcry_err_code_t +do_cbc_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { unsigned int n; unsigned char *ivp; int i; size_t blocksize = c->cipher->blocksize; - unsigned nblocks = nbytes / blocksize; + unsigned nblocks = inbuflen / blocksize; - if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) + if (outbuflen < ((c->flags & GCRY_CIPHER_CBC_MAC)? blocksize : inbuflen)) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ((inbuflen % c->cipher->blocksize) + && !(inbuflen > c->cipher->blocksize + && (c->flags & GCRY_CIPHER_CBC_CTS))) + return GPG_ERR_INV_LENGTH; + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { - if ((nbytes % blocksize) == 0) + if ((inbuflen % blocksize) == 0) nblocks--; } if (c->bulk.cbc_enc) { c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks, - (c->flags & GCRY_CIPHER_CBC_MAC)); + (c->flags & GCRY_CIPHER_CBC_MAC)); inbuf += nblocks * blocksize; if (!(c->flags & GCRY_CIPHER_CBC_MAC)) outbuf += nblocks * blocksize; @@ -991,17 +1042,17 @@ do_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, } } - if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { /* We have to be careful here, since outbuf might be equal to inbuf. */ int restbytes; unsigned char b; - if ((nbytes % blocksize) == 0) + if ((inbuflen % blocksize) == 0) restbytes = blocksize; else - restbytes = nbytes % blocksize; + restbytes = inbuflen % blocksize; outbuf -= blocksize; for (ivp = c->u_iv.iv, i = 0; i < restbytes; i++) @@ -1012,40 +1063,51 @@ do_cbc_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, } for (; i < blocksize; i++) outbuf[i] = 0 ^ *ivp++; - + c->cipher->encrypt (&c->context.c, outbuf, outbuf); memcpy (c->u_iv.iv, outbuf, blocksize); } + + return 0; } -static void -do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, - const unsigned char *inbuf, unsigned int nbytes) +static gcry_err_code_t +do_cbc_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { unsigned int n; unsigned char *ivp; int i; size_t blocksize = c->cipher->blocksize; - unsigned int nblocks = nbytes / blocksize; + unsigned int nblocks = inbuflen / blocksize; - if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ((inbuflen % c->cipher->blocksize) + && !(inbuflen > c->cipher->blocksize + && (c->flags & GCRY_CIPHER_CBC_CTS))) + return GPG_ERR_INV_LENGTH; + + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { nblocks--; - if ((nbytes % blocksize) == 0) + if ((inbuflen % blocksize) == 0) nblocks--; memcpy (c->lastiv, c->u_iv.iv, blocksize); } if (c->bulk.cbc_dec) { - c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); + c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); inbuf += nblocks * blocksize; outbuf += nblocks * blocksize; } else { - for (n=0; n < nblocks; n++ ) + for (n=0; n < nblocks; n++ ) { /* Because outbuf and inbuf might be the same, we have to * save the original ciphertext block. We use LASTIV for @@ -1060,22 +1122,22 @@ do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, } } - if ((c->flags & GCRY_CIPHER_CBC_CTS) && nbytes > blocksize) + if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { int restbytes; - - if ((nbytes % blocksize) == 0) + + if ((inbuflen % blocksize) == 0) restbytes = blocksize; else - restbytes = nbytes % blocksize; - + restbytes = inbuflen % blocksize; + memcpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */ memcpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */ c->cipher->decrypt ( &c->context.c, outbuf, inbuf ); for (ivp=c->u_iv.iv,i=0; i < restbytes; i++ ) outbuf[i] ^= *ivp++; - + memcpy(outbuf + blocksize, outbuf, restbytes); for(i=restbytes; i < blocksize; i++) c->u_iv.iv[i] = outbuf[i]; @@ -1084,32 +1146,38 @@ do_cbc_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, outbuf[i] ^= *ivp++; /* c->lastiv is now really lastlastiv, does this matter? */ } + + return 0; } -static void -do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf, - const unsigned char *inbuf, unsigned int nbytes ) +static gcry_err_code_t +do_cfb_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { unsigned char *ivp; size_t blocksize = c->cipher->blocksize; size_t blocksize_x_2 = blocksize + blocksize; - - if ( nbytes <= c->unused ) + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ( inbuflen <= c->unused ) { /* Short enough to be encoded by the remaining XOR mask. */ /* XOR the input with the IV and store input into IV. */ for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused; - nbytes; - nbytes--, c->unused-- ) + inbuflen; + inbuflen--, c->unused-- ) *outbuf++ = (*ivp++ ^= *inbuf++); - return; + return 0; } if ( c->unused ) { /* XOR the input with the IV and store input into IV */ - nbytes -= c->unused; + inbuflen -= c->unused; for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) *outbuf++ = (*ivp++ ^= *inbuf++); } @@ -1117,17 +1185,17 @@ do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf, /* Now we can process complete blocks. We use a loop as long as we have at least 2 blocks and use conditions for the rest. This also allows to use a bulk encryption function if available. */ - if (nbytes >= blocksize_x_2 && c->bulk.cfb_enc) + if (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc) { - unsigned int nblocks = nbytes / blocksize; - c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); + unsigned int nblocks = inbuflen / blocksize; + c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); outbuf += nblocks * blocksize; inbuf += nblocks * blocksize; - nbytes -= nblocks * blocksize; + inbuflen -= nblocks * blocksize; } else { - while ( nbytes >= blocksize_x_2 ) + while ( inbuflen >= blocksize_x_2 ) { int i; /* Encrypt the IV. */ @@ -1135,11 +1203,11 @@ do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf, /* XOR the input with the IV and store input into IV. */ for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) *outbuf++ = (*ivp++ ^= *inbuf++); - nbytes -= blocksize; + inbuflen -= blocksize; } } - if ( nbytes >= blocksize ) + if ( inbuflen >= blocksize ) { int i; /* Save the current IV and then encrypt the IV. */ @@ -1148,51 +1216,56 @@ do_cfb_encrypt( gcry_cipher_hd_t c, unsigned char *outbuf, /* XOR the input with the IV and store input into IV */ for(ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) *outbuf++ = (*ivp++ ^= *inbuf++); - nbytes -= blocksize; + inbuflen -= blocksize; } - if ( nbytes ) + if ( inbuflen ) { /* Save the current IV and then encrypt the IV. */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); c->unused = blocksize; /* Apply the XOR. */ - c->unused -= nbytes; - for(ivp=c->u_iv.iv; nbytes; nbytes-- ) + c->unused -= inbuflen; + for(ivp=c->u_iv.iv; inbuflen; inbuflen-- ) *outbuf++ = (*ivp++ ^= *inbuf++); } + return 0; } -static void -do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf, - const unsigned char *inbuf, unsigned int nbytes ) +static gcry_err_code_t +do_cfb_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { unsigned char *ivp; unsigned long temp; int i; size_t blocksize = c->cipher->blocksize; size_t blocksize_x_2 = blocksize + blocksize; - - if (nbytes <= c->unused) + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if (inbuflen <= c->unused) { /* Short enough to be encoded by the remaining XOR mask. */ /* XOR the input with the IV and store input into IV. */ for (ivp=c->u_iv.iv+blocksize - c->unused; - nbytes; - nbytes--, c->unused--) + inbuflen; + inbuflen--, c->unused--) { temp = *inbuf++; *outbuf++ = *ivp ^ temp; *ivp++ = temp; } - return; + return 0; } - + if (c->unused) { /* XOR the input with the IV and store input into IV. */ - nbytes -= c->unused; + inbuflen -= c->unused; for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) { temp = *inbuf++; @@ -1200,21 +1273,21 @@ do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf, *ivp++ = temp; } } - + /* Now we can process complete blocks. We use a loop as long as we have at least 2 blocks and use conditions for the rest. This also allows to use a bulk encryption function if available. */ - if (nbytes >= blocksize_x_2 && c->bulk.cfb_dec) + if (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec) { - unsigned int nblocks = nbytes / blocksize; - c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); + unsigned int nblocks = inbuflen / blocksize; + c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); outbuf += nblocks * blocksize; inbuf += nblocks * blocksize; - nbytes -= nblocks * blocksize; + inbuflen -= nblocks * blocksize; } else { - while (nbytes >= blocksize_x_2 ) + while (inbuflen >= blocksize_x_2 ) { /* Encrypt the IV. */ c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); @@ -1225,11 +1298,11 @@ do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf, *outbuf++ = *ivp ^ temp; *ivp++ = temp; } - nbytes -= blocksize; + inbuflen -= blocksize; } } - if (nbytes >= blocksize ) + if (inbuflen >= blocksize ) { /* Save the current IV and then encrypt the IV. */ memcpy ( c->lastiv, c->u_iv.iv, blocksize); @@ -1241,99 +1314,109 @@ do_cfb_decrypt( gcry_cipher_hd_t c, unsigned char *outbuf, *outbuf++ = *ivp ^ temp; *ivp++ = temp; } - nbytes -= blocksize; + inbuflen -= blocksize; } - if (nbytes) - { + if (inbuflen) + { /* Save the current IV and then encrypt the IV. */ memcpy ( c->lastiv, c->u_iv.iv, blocksize ); c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); c->unused = blocksize; /* Apply the XOR. */ - c->unused -= nbytes; - for (ivp=c->u_iv.iv; nbytes; nbytes-- ) + c->unused -= inbuflen; + for (ivp=c->u_iv.iv; inbuflen; inbuflen-- ) { temp = *inbuf++; *outbuf++ = *ivp ^ temp; *ivp++ = temp; } } + return 0; } -static void -do_ofb_encrypt( gcry_cipher_hd_t c, - byte *outbuf, const byte *inbuf, unsigned nbytes ) +static gcry_err_code_t +do_ofb_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { - byte *ivp; + unsigned char *ivp; size_t blocksize = c->cipher->blocksize; - if ( nbytes <= c->unused ) + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if ( inbuflen <= c->unused ) { /* Short enough to be encoded by the remaining XOR mask. */ /* XOR the input with the IV */ for (ivp=c->u_iv.iv+c->cipher->blocksize - c->unused; - nbytes; - nbytes--, c->unused-- ) + inbuflen; + inbuflen--, c->unused-- ) *outbuf++ = (*ivp++ ^ *inbuf++); - return; + return 0; } if( c->unused ) { - nbytes -= c->unused; + inbuflen -= c->unused; for(ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) *outbuf++ = (*ivp++ ^ *inbuf++); } /* Now we can process complete blocks. */ - while ( nbytes >= blocksize ) + while ( inbuflen >= blocksize ) { int i; /* Encrypt the IV (and save the current one). */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); - + for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) *outbuf++ = (*ivp++ ^ *inbuf++); - nbytes -= blocksize; + inbuflen -= blocksize; } - if ( nbytes ) + if ( inbuflen ) { /* process the remaining bytes */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); c->unused = blocksize; - c->unused -= nbytes; - for(ivp=c->u_iv.iv; nbytes; nbytes-- ) + c->unused -= inbuflen; + for(ivp=c->u_iv.iv; inbuflen; inbuflen-- ) *outbuf++ = (*ivp++ ^ *inbuf++); } + return 0; } -static void -do_ofb_decrypt( gcry_cipher_hd_t c, - byte *outbuf, const byte *inbuf, unsigned int nbytes ) +static gcry_err_code_t +do_ofb_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { - byte *ivp; + unsigned char *ivp; size_t blocksize = c->cipher->blocksize; - - if( nbytes <= c->unused ) + + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if( inbuflen <= c->unused ) { /* Short enough to be encoded by the remaining XOR mask. */ - for (ivp=c->u_iv.iv+blocksize - c->unused; nbytes; nbytes--,c->unused--) + for (ivp=c->u_iv.iv+blocksize - c->unused; inbuflen; inbuflen--,c->unused--) *outbuf++ = *ivp++ ^ *inbuf++; - return; + return 0; } if ( c->unused ) { - nbytes -= c->unused; + inbuflen -= c->unused; for (ivp=c->u_iv.iv+blocksize - c->unused; c->unused; c->unused-- ) *outbuf++ = *ivp++ ^ *inbuf++; } /* Now we can process complete blocks. */ - while ( nbytes >= blocksize ) + while ( inbuflen >= blocksize ) { int i; /* Encrypt the IV (and save the current one). */ @@ -1341,113 +1424,335 @@ do_ofb_decrypt( gcry_cipher_hd_t c, c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); for (ivp=c->u_iv.iv,i=0; i < blocksize; i++ ) *outbuf++ = *ivp++ ^ *inbuf++; - nbytes -= blocksize; + inbuflen -= blocksize; } - if ( nbytes ) + if ( inbuflen ) { /* Process the remaining bytes. */ /* Encrypt the IV (and save the current one). */ memcpy( c->lastiv, c->u_iv.iv, blocksize ); c->cipher->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv ); c->unused = blocksize; - c->unused -= nbytes; - for (ivp=c->u_iv.iv; nbytes; nbytes-- ) + c->unused -= inbuflen; + for (ivp=c->u_iv.iv; inbuflen; inbuflen-- ) *outbuf++ = *ivp++ ^ *inbuf++; } + return 0; } -static void -do_ctr_encrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, - unsigned int nbytes ) +static gcry_err_code_t +do_ctr_encrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { unsigned int n; - byte tmp[MAX_BLOCKSIZE]; int i; + unsigned int blocksize = c->cipher->blocksize; + unsigned int nblocks; - for(n=0; n < nbytes; n++) + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + /* First process a left over encrypted counter. */ + if (c->unused) { - if ((n % c->cipher->blocksize) == 0) - { - c->cipher->encrypt (&c->context.c, tmp, c->ctr); - - for (i = c->cipher->blocksize; i > 0; i--) - { - c->ctr[i-1]++; - if (c->ctr[i-1] != 0) - break; - } - } - - /* XOR input with encrypted counter and store in output. */ - outbuf[n] = inbuf[n] ^ tmp[n % c->cipher->blocksize]; + gcry_assert (c->unused < blocksize); + i = blocksize - c->unused; + for (n=0; c->unused && n < inbuflen; c->unused--, n++, i++) + { + /* XOR input with encrypted counter and store in output. */ + outbuf[n] = inbuf[n] ^ c->lastiv[i]; + } + inbuf += n; + outbuf += n; + inbuflen -= n; } + + + /* Use a bulk method if available. */ + nblocks = inbuflen / blocksize; + if (nblocks && c->bulk.ctr_enc) + { + c->bulk.ctr_enc (&c->context.c, c->u_ctr.ctr, outbuf, inbuf, nblocks); + inbuf += nblocks * blocksize; + outbuf += nblocks * blocksize; + inbuflen -= nblocks * blocksize; + } + + /* If we don't have a bulk method use the standard method. We also + use this method for the a remaining partial block. */ + if (inbuflen) + { + unsigned char tmp[MAX_BLOCKSIZE]; + + for (n=0; n < inbuflen; n++) + { + if ((n % blocksize) == 0) + { + c->cipher->encrypt (&c->context.c, tmp, c->u_ctr.ctr); + + for (i = blocksize; i > 0; i--) + { + c->u_ctr.ctr[i-1]++; + if (c->u_ctr.ctr[i-1] != 0) + break; + } + } + + /* XOR input with encrypted counter and store in output. */ + outbuf[n] = inbuf[n] ^ tmp[n % blocksize]; + } + + /* Save the unused bytes of the counter. */ + n %= blocksize; + c->unused = (blocksize - n) % blocksize; + if (c->unused) + memcpy (c->lastiv+n, tmp+n, c->unused); + + wipememory (tmp, sizeof tmp); + } + + return 0; } -static void -do_ctr_decrypt( gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, - unsigned int nbytes ) +static gcry_err_code_t +do_ctr_decrypt (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen) { - do_ctr_encrypt (c, outbuf, inbuf, nbytes); + return do_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); +} + + +/* Perform the AES-Wrap algorithm as specified by RFC3394. We + implement this as a mode usable with any cipher algorithm of + blocksize 128. */ +static gcry_err_code_t +do_aeswrap_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen ) +{ + int j, x; + unsigned int n, i; + unsigned char *r, *a, *b; + unsigned char t[8]; + +#if MAX_BLOCKSIZE < 8 +#error Invalid block size +#endif + /* We require a cipher with a 128 bit block length. */ + if (c->cipher->blocksize != 16) + return GPG_ERR_INV_LENGTH; + + /* The output buffer must be able to hold the input data plus one + additional block. */ + if (outbuflen < inbuflen + 8) + return GPG_ERR_BUFFER_TOO_SHORT; + /* Input data must be multiple of 64 bits. */ + if (inbuflen % 8) + return GPG_ERR_INV_ARG; + + n = inbuflen / 8; + + /* We need at least two 64 bit blocks. */ + if (n < 2) + return GPG_ERR_INV_ARG; + + r = outbuf; + a = outbuf; /* We store A directly in OUTBUF. */ + b = c->u_ctr.ctr; /* B is also used to concatenate stuff. */ + + /* If an IV has been set we use that IV as the Alternative Initial + Value; if it has not been set we use the standard value. */ + if (c->marks.iv) + memcpy (a, c->u_iv.iv, 8); + else + memset (a, 0xa6, 8); + + /* Copy the inbuf to the outbuf. */ + memmove (r+8, inbuf, inbuflen); + + memset (t, 0, sizeof t); /* t := 0. */ + + for (j = 0; j <= 5; j++) + { + for (i = 1; i <= n; i++) + { + /* B := AES_k( A | R[i] ) */ + memcpy (b, a, 8); + memcpy (b+8, r+i*8, 8); + c->cipher->encrypt (&c->context.c, b, b); + /* t := t + 1 */ + for (x = 7; x >= 0; x--) + { + t[x]++; + if (t[x]) + break; + } + /* A := MSB_64(B) ^ t */ + for (x=0; x < 8; x++) + a[x] = b[x] ^ t[x]; + /* R[i] := LSB_64(B) */ + memcpy (r+i*8, b+8, 8); + } + } + + return 0; +} + +/* Perform the AES-Unwrap algorithm as specified by RFC3394. We + implement this as a mode usable with any cipher algorithm of + blocksize 128. */ +static gcry_err_code_t +do_aeswrap_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) +{ + int j, x; + unsigned int n, i; + unsigned char *r, *a, *b; + unsigned char t[8]; + +#if MAX_BLOCKSIZE < 8 +#error Invalid block size +#endif + /* We require a cipher with a 128 bit block length. */ + if (c->cipher->blocksize != 16) + return GPG_ERR_INV_LENGTH; + + /* The output buffer must be able to hold the input data minus one + additional block. Fixme: The caller has more restrictive checks + - we may want to fix them for this mode. */ + if (outbuflen + 8 < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + /* Input data must be multiple of 64 bits. */ + if (inbuflen % 8) + return GPG_ERR_INV_ARG; + + n = inbuflen / 8; + + /* We need at least three 64 bit blocks. */ + if (n < 3) + return GPG_ERR_INV_ARG; + + r = outbuf; + a = c->lastiv; /* We use c->LASTIV as buffer for A. */ + b = c->u_ctr.ctr; /* B is also used to concatenate stuff. */ + + /* Copy the inbuf to the outbuf and save A. */ + memcpy (a, inbuf, 8); + memmove (r, inbuf+8, inbuflen-8); + n--; /* Reduce to actual number of data blocks. */ + + /* t := 6 * n */ + i = n * 6; /* The range is valid because: n = inbuflen / 8 - 1. */ + for (x=0; x < 8 && x < sizeof (i); x++) + t[7-x] = i >> (8*x); + for (; x < 8; x++) + t[7-x] = 0; + + for (j = 5; j >= 0; j--) + { + for (i = n; i >= 1; i--) + { + /* B := AES_k^1( (A ^ t)| R[i] ) */ + for (x = 0; x < 8; x++) + b[x] = a[x] ^ t[x]; + memcpy (b+8, r+(i-1)*8, 8); + c->cipher->decrypt (&c->context.c, b, b); + /* t := t - 1 */ + for (x = 7; x >= 0; x--) + { + t[x]--; + if (t[x] != 0xff) + break; + } + /* A := MSB_64(B) */ + memcpy (a, b, 8); + /* R[i] := LSB_64(B) */ + memcpy (r+(i-1)*8, b+8, 8); + } + } + + /* If an IV has been set we compare against this Alternative Initial + Value; if it has not been set we compare against the standard IV. */ + if (c->marks.iv) + j = memcmp (a, c->u_iv.iv, 8); + else + { + for (j=0, x=0; x < 8; x++) + if (a[x] != 0xa6) + { + j=1; + break; + } + } + return j? GPG_ERR_CHECKSUM : 0; } /**************** * Encrypt INBUF to OUTBUF with the mode selected at open. * inbuf and outbuf may overlap or be the same. - * Depending on the mode some contraints apply to NBYTES. + * Depending on the mode some constraints apply to INBUFLEN. */ static gcry_err_code_t -cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, - const byte *inbuf, unsigned int nbytes) +cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) { - gcry_err_code_t rc = GPG_ERR_NO_ERROR; + gcry_err_code_t rc; - switch( c->mode ) { - case GCRY_CIPHER_MODE_ECB: - if (!(nbytes%c->cipher->blocksize)) - do_ecb_encrypt(c, outbuf, inbuf, nbytes/c->cipher->blocksize ); - else - rc = GPG_ERR_INV_ARG; - break; - case GCRY_CIPHER_MODE_CBC: - if (!(nbytes%c->cipher->blocksize) - || (nbytes > c->cipher->blocksize - && (c->flags & GCRY_CIPHER_CBC_CTS))) - do_cbc_encrypt(c, outbuf, inbuf, nbytes ); - else - rc = GPG_ERR_INV_ARG; - break; - case GCRY_CIPHER_MODE_CFB: - do_cfb_encrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_OFB: - do_ofb_encrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_CTR: - do_ctr_encrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_STREAM: - c->cipher->stencrypt ( &c->context.c, - outbuf, (byte*)/*arggg*/inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_NONE: - if (fips_mode () || !_gcry_get_debug_flag (0)) - { - fips_signal_error ("cipher mode NONE used"); - rc = GPG_ERR_INV_CIPHER_MODE; - } - else - { - if ( inbuf != outbuf ) - memmove (outbuf, inbuf, nbytes); - } - break; - default: - log_fatal("cipher_encrypt: invalid mode %d\n", c->mode ); - rc = GPG_ERR_INV_CIPHER_MODE; - break; + switch (c->mode) + { + case GCRY_CIPHER_MODE_ECB: + rc = do_ecb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CBC: + rc = do_cbc_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CFB: + rc = do_cfb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_OFB: + rc = do_ofb_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CTR: + rc = do_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_AESWRAP: + rc = do_aeswrap_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_STREAM: + c->cipher->stencrypt (&c->context.c, + outbuf, (byte*)/*arggg*/inbuf, inbuflen); + rc = 0; + break; + + case GCRY_CIPHER_MODE_NONE: + if (fips_mode () || !_gcry_get_debug_flag (0)) + { + fips_signal_error ("cipher mode NONE used"); + rc = GPG_ERR_INV_CIPHER_MODE; + } + else + { + if (inbuf != outbuf) + memmove (outbuf, inbuf, inbuflen); + rc = 0; + } + break; + + default: + log_fatal ("cipher_encrypt: invalid mode %d\n", c->mode ); + rc = GPG_ERR_INV_CIPHER_MODE; + break; } - return rc; + + return rc; } @@ -1461,29 +1766,15 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize, { gcry_err_code_t err; - if (!in) - { - /* Caller requested in-place encryption. */ - /* Actually cipher_encrypt() does not need to know about it, but - * we may change it in the future to get better performance. */ - err = cipher_encrypt (h, out, out, outsize); - } - else if (outsize < ((h->flags & GCRY_CIPHER_CBC_MAC) ? - h->cipher->blocksize : inlen)) - err = GPG_ERR_TOO_SHORT; - else if ((h->mode == GCRY_CIPHER_MODE_ECB - || (h->mode == GCRY_CIPHER_MODE_CBC - && (! ((h->flags & GCRY_CIPHER_CBC_CTS) - && (inlen > h->cipher->blocksize))))) - && (inlen % h->cipher->blocksize)) - err = GPG_ERR_INV_ARG; + if (!in) /* Caller requested in-place encryption. */ + err = cipher_encrypt (h, out, outsize, out, outsize); else - err = cipher_encrypt (h, out, in, inlen); + err = cipher_encrypt (h, out, outsize, in, inlen); + /* Failsafe: Make sure that the plaintext will never make it into + OUT if the encryption returned an error. */ if (err && out) - memset (out, 0x42, outsize); /* Failsafe: Make sure that the - plaintext will never make it into - OUT. */ + memset (out, 0x42, outsize); return gcry_error (err); } @@ -1493,60 +1784,67 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize, /**************** * Decrypt INBUF to OUTBUF with the mode selected at open. * inbuf and outbuf may overlap or be the same. - * Depending on the mode some some contraints apply to NBYTES. + * Depending on the mode some some contraints apply to INBUFLEN. */ static gcry_err_code_t -cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, const byte *inbuf, - unsigned int nbytes) +cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) { - gcry_err_code_t rc = GPG_ERR_NO_ERROR; + gcry_err_code_t rc; - switch( c->mode ) { - case GCRY_CIPHER_MODE_ECB: - if (!(nbytes%c->cipher->blocksize)) - do_ecb_decrypt(c, outbuf, inbuf, nbytes/c->cipher->blocksize ); - else - rc = GPG_ERR_INV_ARG; - break; - case GCRY_CIPHER_MODE_CBC: - if (!(nbytes%c->cipher->blocksize) - || (nbytes > c->cipher->blocksize - && (c->flags & GCRY_CIPHER_CBC_CTS))) - do_cbc_decrypt(c, outbuf, inbuf, nbytes ); - else - rc = GPG_ERR_INV_ARG; - break; - case GCRY_CIPHER_MODE_CFB: - do_cfb_decrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_OFB: - do_ofb_decrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_CTR: - do_ctr_decrypt(c, outbuf, inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_STREAM: - c->cipher->stdecrypt ( &c->context.c, - outbuf, (byte*)/*arggg*/inbuf, nbytes ); - break; - case GCRY_CIPHER_MODE_NONE: - if (fips_mode () || !_gcry_get_debug_flag (0)) - { - fips_signal_error ("cipher mode NONE used"); - rc = GPG_ERR_INV_CIPHER_MODE; - } - else - { - if (inbuf != outbuf) - memmove (outbuf, inbuf, nbytes); - } - break; - default: - log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode ); - rc = GPG_ERR_INV_CIPHER_MODE; - break; + switch (c->mode) + { + case GCRY_CIPHER_MODE_ECB: + rc = do_ecb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CBC: + rc = do_cbc_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CFB: + rc = do_cfb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_OFB: + rc = do_ofb_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_CTR: + rc = do_ctr_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_AESWRAP: + rc = do_aeswrap_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + + case GCRY_CIPHER_MODE_STREAM: + c->cipher->stdecrypt (&c->context.c, + outbuf, (byte*)/*arggg*/inbuf, inbuflen); + rc = 0; + break; + + case GCRY_CIPHER_MODE_NONE: + if (fips_mode () || !_gcry_get_debug_flag (0)) + { + fips_signal_error ("cipher mode NONE used"); + rc = GPG_ERR_INV_CIPHER_MODE; + } + else + { + if (inbuf != outbuf) + memmove (outbuf, inbuf, inbuflen); + rc = 0; + } + break; + + default: + log_fatal ("cipher_decrypt: invalid mode %d\n", c->mode ); + rc = GPG_ERR_INV_CIPHER_MODE; + break; } - return rc; + + return rc; } @@ -1554,25 +1852,12 @@ gcry_error_t gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize, const void *in, size_t inlen) { - gcry_err_code_t err = 0; + gcry_err_code_t err; - if (!in) - { - /* Caller requested in-place encryption. */ - /* Actually cipher_encrypt() does not need to know about it, but - * we may change it in the future to get better performance. */ - err = cipher_decrypt (h, out, out, outsize); - } - else if (outsize < inlen) - err = GPG_ERR_TOO_SHORT; - else if (((h->mode == GCRY_CIPHER_MODE_ECB) - || ((h->mode == GCRY_CIPHER_MODE_CBC) - && (! ((h->flags & GCRY_CIPHER_CBC_CTS) - && (inlen > h->cipher->blocksize))))) - && (inlen % h->cipher->blocksize) != 0) - err = GPG_ERR_INV_ARG; + if (!in) /* Caller requested in-place encryption. */ + err = cipher_decrypt (h, out, outsize, out, outsize); else - err = cipher_decrypt (h, out, in, inlen); + err = cipher_decrypt (h, out, outsize, in, inlen); return gcry_error (err); } @@ -1618,9 +1903,15 @@ gpg_error_t _gcry_cipher_setctr (gcry_cipher_hd_t hd, const void *ctr, size_t ctrlen) { if (ctr && ctrlen == hd->cipher->blocksize) - memcpy (hd->ctr, ctr, hd->cipher->blocksize); + { + memcpy (hd->u_ctr.ctr, ctr, hd->cipher->blocksize); + hd->unused = 0; + } else if (!ctr || !ctrlen) - memset (hd->ctr, 0, hd->cipher->blocksize); + { + memset (hd->u_ctr.ctr, 0, hd->cipher->blocksize); + hd->unused = 0; + } else return gpg_error (GPG_ERR_INV_ARG); return 0; @@ -1679,17 +1970,12 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) break; case GCRYCTL_SET_CTR: /* Deprecated; use gcry_cipher_setctr. */ - if (buffer && buflen == h->cipher->blocksize) - memcpy (h->ctr, buffer, h->cipher->blocksize); - else if (buffer == NULL || buflen == 0) - memset (h->ctr, 0, h->cipher->blocksize); - else - rc = GPG_ERR_INV_ARG; + rc = gpg_err_code (_gcry_cipher_setctr (h, buffer, buflen)); break; case 61: /* Disable weak key detection (private). */ if (h->extraspec->set_extra_info) - rc = h->extraspec->set_extra_info + rc = h->extraspec->set_extra_info (&h->context.c, CIPHER_INFO_NO_WEAK_KEY, NULL, 0); else rc = GPG_ERR_NOT_SUPPORTED; @@ -1697,7 +1983,7 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) case 62: /* Return current input vector (private). */ /* This is the input block as used in CFB and OFB mode which has - initially been set as IV. The returned format is: + initially been set as IV. The returned format is: 1 byte Actual length of the block in bytes. n byte The block. If the provided buffer is too short, an error is returned. */ @@ -1708,7 +1994,7 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) unsigned char *ivp; unsigned char *dst = buffer; int n = h->unused; - + if (!n) n = h->cipher->blocksize; gcry_assert (n <= h->cipher->blocksize); @@ -1730,10 +2016,10 @@ gcry_cipher_ctl( gcry_cipher_hd_t h, int cmd, void *buffer, size_t buflen) /* Return information about the cipher handle H. CMD is the kind of information requested. BUFFER and NBYTES are reserved for now. - There are no values for CMD yet defined. + There are no values for CMD yet defined. + + The function always returns GPG_ERR_INV_OP. - The fucntion always returns GPG_ERR_INV_OP. - */ gcry_error_t gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes) @@ -1770,11 +2056,11 @@ gcry_cipher_info (gcry_cipher_hd_t h, int cmd, void *buffer, size_t *nbytes) GCRYCTL_TEST_ALGO: Returns 0 if the specified algorithm ALGO is available for use. BUFFER and NBYTES must be zero. - + Note: Because this function is in most cases used to return an integer value, we can make it easier for the caller to just look at the return value. The caller will in all cases consult the value - and thereby detecting whether a error occured or not (i.e. while + and thereby detecting whether a error occurred or not (i.e. while checking the block size) */ gcry_error_t @@ -1794,8 +2080,7 @@ gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes) if ((ui > 0) && (ui <= 512)) *nbytes = (size_t) ui / 8; else - /* The only reason is an invalid algo or a strange - blocksize. */ + /* The only reason for an error is an invalid algo. */ err = GPG_ERR_CIPHER_ALGO; } break; @@ -1839,7 +2124,7 @@ gcry_cipher_algo_info (int algo, int what, void *buffer, size_t *nbytes) gcry_cipher_algo_info because it allows for proper type checking. */ size_t -gcry_cipher_get_algo_keylen (int algo) +gcry_cipher_get_algo_keylen (int algo) { size_t n; @@ -1855,7 +2140,7 @@ gcry_cipher_get_algo_keylen (int algo) gcry_cipher_algo_info because it allows for proper type checking. */ size_t -gcry_cipher_get_algo_blklen (int algo) +gcry_cipher_get_algo_blklen (int algo) { size_t n; @@ -1916,7 +2201,7 @@ _gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report) { ec = GPG_ERR_CIPHER_ALGO; if (report) - report ("cipher", algo, "module", + report ("cipher", algo, "module", module && !(module->flags & FLAG_MODULE_DISABLED)? "no selftest available" : module? "algorithm disabled" : "algorithm not found"); diff --git a/grub-core/lib/libgcrypt/cipher/crc.c b/grub-core/lib/libgcrypt/cipher/crc.c index d04fff894..28454f8ab 100644 --- a/grub-core/lib/libgcrypt/cipher/crc.c +++ b/grub-core/lib/libgcrypt/cipher/crc.c @@ -25,120 +25,11 @@ #include #include "g10lib.h" -#include "memory.h" #include "cipher.h" #include "bithelp.h" +#include "bufhelp.h" -/* Table of CRCs of all 8-bit messages. Generated by running code - from RFC 1952 modified to print out the table. */ -static u32 crc32_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -/* - * The following function was extracted from RFC 1952 by Simon - * Josefsson, for the Shishi project, and modified to be compatible - * with the modified CRC-32 used by RFC 1510, and subsequently - * modified for GNU Libgcrypt to allow it to be used for calculating - * both unmodified CRC-32 and modified CRC-32 values. Original - * copyright and notice from the document follows: - * - * Copyright (c) 1996 L. Peter Deutsch - * - * Permission is granted to copy and distribute this document for - * any purpose and without charge, including translations into - * other languages and incorporation into compilations, provided - * that the copyright notice and this notice are preserved, and - * that any substantive changes or deletions from the original are - * clearly marked. - * - * The copyright on RFCs, and consequently the function below, are - * supposedly also retroactively claimed by the Internet Society - * (according to rfc-editor@rfc-editor.org), with the following - * copyright notice: - * - * Copyright (C) The Internet Society. All Rights Reserved. - * - * This document and translations of it may be copied and furnished - * to others, and derivative works that comment on or otherwise - * explain it or assist in its implementation may be prepared, - * copied, published and distributed, in whole or in part, without - * restriction of any kind, provided that the above copyright - * notice and this paragraph are included on all such copies and - * derivative works. However, this document itself may not be - * modified in any way, such as by removing the copyright notice or - * references to the Internet Society or other Internet - * organizations, except as needed for the purpose of developing - * Internet standards in which case the procedures for copyrights - * defined in the Internet Standards process must be followed, or - * as required to translate it into languages other than English. - * - * The limited permissions granted above are perpetual and will not be - * revoked by the Internet Society or its successors or assigns. - * - * This document and the information contained herein is provided - * on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET - * ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE - * OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A - * PARTICULAR PURPOSE. - * - */ -static u32 -update_crc32 (u32 crc, const void *buf_arg, size_t len) -{ - const char *buf = buf_arg; - size_t n; - - for (n = 0; n < len; n++) - crc = crc32_table[(crc ^ buf[n]) & 0xff] ^ (crc >> 8); - - return crc; -} typedef struct { @@ -147,8 +38,302 @@ typedef struct } CRC_CONTEXT; + +/* + * Code generated by universal_crc by Danjel McGougan + * + * CRC parameters used: + * bits: 32 + * poly: 0x04c11db7 + * init: 0xffffffff + * xor: 0xffffffff + * reverse: true + * non-direct: false + * + * CRC of the string "123456789" is 0xcbf43926 + */ + +static const u32 crc32_table[1024] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, + 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, + 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, + 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, + 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, + 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, + 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, + 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, + 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, + 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, + 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, + 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, + 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, + 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, + 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, + 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, + 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, + 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, + 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, + 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, + 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, + 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, + 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, + 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, + 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, + 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, + 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, + 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, + 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, + 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, + 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, + 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, + 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, + 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, + 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, + 0x00000000, 0x191b3141, 0x32366282, 0x2b2d53c3, + 0x646cc504, 0x7d77f445, 0x565aa786, 0x4f4196c7, + 0xc8d98a08, 0xd1c2bb49, 0xfaefe88a, 0xe3f4d9cb, + 0xacb54f0c, 0xb5ae7e4d, 0x9e832d8e, 0x87981ccf, + 0x4ac21251, 0x53d92310, 0x78f470d3, 0x61ef4192, + 0x2eaed755, 0x37b5e614, 0x1c98b5d7, 0x05838496, + 0x821b9859, 0x9b00a918, 0xb02dfadb, 0xa936cb9a, + 0xe6775d5d, 0xff6c6c1c, 0xd4413fdf, 0xcd5a0e9e, + 0x958424a2, 0x8c9f15e3, 0xa7b24620, 0xbea97761, + 0xf1e8e1a6, 0xe8f3d0e7, 0xc3de8324, 0xdac5b265, + 0x5d5daeaa, 0x44469feb, 0x6f6bcc28, 0x7670fd69, + 0x39316bae, 0x202a5aef, 0x0b07092c, 0x121c386d, + 0xdf4636f3, 0xc65d07b2, 0xed705471, 0xf46b6530, + 0xbb2af3f7, 0xa231c2b6, 0x891c9175, 0x9007a034, + 0x179fbcfb, 0x0e848dba, 0x25a9de79, 0x3cb2ef38, + 0x73f379ff, 0x6ae848be, 0x41c51b7d, 0x58de2a3c, + 0xf0794f05, 0xe9627e44, 0xc24f2d87, 0xdb541cc6, + 0x94158a01, 0x8d0ebb40, 0xa623e883, 0xbf38d9c2, + 0x38a0c50d, 0x21bbf44c, 0x0a96a78f, 0x138d96ce, + 0x5ccc0009, 0x45d73148, 0x6efa628b, 0x77e153ca, + 0xbabb5d54, 0xa3a06c15, 0x888d3fd6, 0x91960e97, + 0xded79850, 0xc7cca911, 0xece1fad2, 0xf5facb93, + 0x7262d75c, 0x6b79e61d, 0x4054b5de, 0x594f849f, + 0x160e1258, 0x0f152319, 0x243870da, 0x3d23419b, + 0x65fd6ba7, 0x7ce65ae6, 0x57cb0925, 0x4ed03864, + 0x0191aea3, 0x188a9fe2, 0x33a7cc21, 0x2abcfd60, + 0xad24e1af, 0xb43fd0ee, 0x9f12832d, 0x8609b26c, + 0xc94824ab, 0xd05315ea, 0xfb7e4629, 0xe2657768, + 0x2f3f79f6, 0x362448b7, 0x1d091b74, 0x04122a35, + 0x4b53bcf2, 0x52488db3, 0x7965de70, 0x607eef31, + 0xe7e6f3fe, 0xfefdc2bf, 0xd5d0917c, 0xcccba03d, + 0x838a36fa, 0x9a9107bb, 0xb1bc5478, 0xa8a76539, + 0x3b83984b, 0x2298a90a, 0x09b5fac9, 0x10aecb88, + 0x5fef5d4f, 0x46f46c0e, 0x6dd93fcd, 0x74c20e8c, + 0xf35a1243, 0xea412302, 0xc16c70c1, 0xd8774180, + 0x9736d747, 0x8e2de606, 0xa500b5c5, 0xbc1b8484, + 0x71418a1a, 0x685abb5b, 0x4377e898, 0x5a6cd9d9, + 0x152d4f1e, 0x0c367e5f, 0x271b2d9c, 0x3e001cdd, + 0xb9980012, 0xa0833153, 0x8bae6290, 0x92b553d1, + 0xddf4c516, 0xc4eff457, 0xefc2a794, 0xf6d996d5, + 0xae07bce9, 0xb71c8da8, 0x9c31de6b, 0x852aef2a, + 0xca6b79ed, 0xd37048ac, 0xf85d1b6f, 0xe1462a2e, + 0x66de36e1, 0x7fc507a0, 0x54e85463, 0x4df36522, + 0x02b2f3e5, 0x1ba9c2a4, 0x30849167, 0x299fa026, + 0xe4c5aeb8, 0xfdde9ff9, 0xd6f3cc3a, 0xcfe8fd7b, + 0x80a96bbc, 0x99b25afd, 0xb29f093e, 0xab84387f, + 0x2c1c24b0, 0x350715f1, 0x1e2a4632, 0x07317773, + 0x4870e1b4, 0x516bd0f5, 0x7a468336, 0x635db277, + 0xcbfad74e, 0xd2e1e60f, 0xf9ccb5cc, 0xe0d7848d, + 0xaf96124a, 0xb68d230b, 0x9da070c8, 0x84bb4189, + 0x03235d46, 0x1a386c07, 0x31153fc4, 0x280e0e85, + 0x674f9842, 0x7e54a903, 0x5579fac0, 0x4c62cb81, + 0x8138c51f, 0x9823f45e, 0xb30ea79d, 0xaa1596dc, + 0xe554001b, 0xfc4f315a, 0xd7626299, 0xce7953d8, + 0x49e14f17, 0x50fa7e56, 0x7bd72d95, 0x62cc1cd4, + 0x2d8d8a13, 0x3496bb52, 0x1fbbe891, 0x06a0d9d0, + 0x5e7ef3ec, 0x4765c2ad, 0x6c48916e, 0x7553a02f, + 0x3a1236e8, 0x230907a9, 0x0824546a, 0x113f652b, + 0x96a779e4, 0x8fbc48a5, 0xa4911b66, 0xbd8a2a27, + 0xf2cbbce0, 0xebd08da1, 0xc0fdde62, 0xd9e6ef23, + 0x14bce1bd, 0x0da7d0fc, 0x268a833f, 0x3f91b27e, + 0x70d024b9, 0x69cb15f8, 0x42e6463b, 0x5bfd777a, + 0xdc656bb5, 0xc57e5af4, 0xee530937, 0xf7483876, + 0xb809aeb1, 0xa1129ff0, 0x8a3fcc33, 0x9324fd72, + 0x00000000, 0x01c26a37, 0x0384d46e, 0x0246be59, + 0x0709a8dc, 0x06cbc2eb, 0x048d7cb2, 0x054f1685, + 0x0e1351b8, 0x0fd13b8f, 0x0d9785d6, 0x0c55efe1, + 0x091af964, 0x08d89353, 0x0a9e2d0a, 0x0b5c473d, + 0x1c26a370, 0x1de4c947, 0x1fa2771e, 0x1e601d29, + 0x1b2f0bac, 0x1aed619b, 0x18abdfc2, 0x1969b5f5, + 0x1235f2c8, 0x13f798ff, 0x11b126a6, 0x10734c91, + 0x153c5a14, 0x14fe3023, 0x16b88e7a, 0x177ae44d, + 0x384d46e0, 0x398f2cd7, 0x3bc9928e, 0x3a0bf8b9, + 0x3f44ee3c, 0x3e86840b, 0x3cc03a52, 0x3d025065, + 0x365e1758, 0x379c7d6f, 0x35dac336, 0x3418a901, + 0x3157bf84, 0x3095d5b3, 0x32d36bea, 0x331101dd, + 0x246be590, 0x25a98fa7, 0x27ef31fe, 0x262d5bc9, + 0x23624d4c, 0x22a0277b, 0x20e69922, 0x2124f315, + 0x2a78b428, 0x2bbade1f, 0x29fc6046, 0x283e0a71, + 0x2d711cf4, 0x2cb376c3, 0x2ef5c89a, 0x2f37a2ad, + 0x709a8dc0, 0x7158e7f7, 0x731e59ae, 0x72dc3399, + 0x7793251c, 0x76514f2b, 0x7417f172, 0x75d59b45, + 0x7e89dc78, 0x7f4bb64f, 0x7d0d0816, 0x7ccf6221, + 0x798074a4, 0x78421e93, 0x7a04a0ca, 0x7bc6cafd, + 0x6cbc2eb0, 0x6d7e4487, 0x6f38fade, 0x6efa90e9, + 0x6bb5866c, 0x6a77ec5b, 0x68315202, 0x69f33835, + 0x62af7f08, 0x636d153f, 0x612bab66, 0x60e9c151, + 0x65a6d7d4, 0x6464bde3, 0x662203ba, 0x67e0698d, + 0x48d7cb20, 0x4915a117, 0x4b531f4e, 0x4a917579, + 0x4fde63fc, 0x4e1c09cb, 0x4c5ab792, 0x4d98dda5, + 0x46c49a98, 0x4706f0af, 0x45404ef6, 0x448224c1, + 0x41cd3244, 0x400f5873, 0x4249e62a, 0x438b8c1d, + 0x54f16850, 0x55330267, 0x5775bc3e, 0x56b7d609, + 0x53f8c08c, 0x523aaabb, 0x507c14e2, 0x51be7ed5, + 0x5ae239e8, 0x5b2053df, 0x5966ed86, 0x58a487b1, + 0x5deb9134, 0x5c29fb03, 0x5e6f455a, 0x5fad2f6d, + 0xe1351b80, 0xe0f771b7, 0xe2b1cfee, 0xe373a5d9, + 0xe63cb35c, 0xe7fed96b, 0xe5b86732, 0xe47a0d05, + 0xef264a38, 0xeee4200f, 0xeca29e56, 0xed60f461, + 0xe82fe2e4, 0xe9ed88d3, 0xebab368a, 0xea695cbd, + 0xfd13b8f0, 0xfcd1d2c7, 0xfe976c9e, 0xff5506a9, + 0xfa1a102c, 0xfbd87a1b, 0xf99ec442, 0xf85cae75, + 0xf300e948, 0xf2c2837f, 0xf0843d26, 0xf1465711, + 0xf4094194, 0xf5cb2ba3, 0xf78d95fa, 0xf64fffcd, + 0xd9785d60, 0xd8ba3757, 0xdafc890e, 0xdb3ee339, + 0xde71f5bc, 0xdfb39f8b, 0xddf521d2, 0xdc374be5, + 0xd76b0cd8, 0xd6a966ef, 0xd4efd8b6, 0xd52db281, + 0xd062a404, 0xd1a0ce33, 0xd3e6706a, 0xd2241a5d, + 0xc55efe10, 0xc49c9427, 0xc6da2a7e, 0xc7184049, + 0xc25756cc, 0xc3953cfb, 0xc1d382a2, 0xc011e895, + 0xcb4dafa8, 0xca8fc59f, 0xc8c97bc6, 0xc90b11f1, + 0xcc440774, 0xcd866d43, 0xcfc0d31a, 0xce02b92d, + 0x91af9640, 0x906dfc77, 0x922b422e, 0x93e92819, + 0x96a63e9c, 0x976454ab, 0x9522eaf2, 0x94e080c5, + 0x9fbcc7f8, 0x9e7eadcf, 0x9c381396, 0x9dfa79a1, + 0x98b56f24, 0x99770513, 0x9b31bb4a, 0x9af3d17d, + 0x8d893530, 0x8c4b5f07, 0x8e0de15e, 0x8fcf8b69, + 0x8a809dec, 0x8b42f7db, 0x89044982, 0x88c623b5, + 0x839a6488, 0x82580ebf, 0x801eb0e6, 0x81dcdad1, + 0x8493cc54, 0x8551a663, 0x8717183a, 0x86d5720d, + 0xa9e2d0a0, 0xa820ba97, 0xaa6604ce, 0xaba46ef9, + 0xaeeb787c, 0xaf29124b, 0xad6fac12, 0xacadc625, + 0xa7f18118, 0xa633eb2f, 0xa4755576, 0xa5b73f41, + 0xa0f829c4, 0xa13a43f3, 0xa37cfdaa, 0xa2be979d, + 0xb5c473d0, 0xb40619e7, 0xb640a7be, 0xb782cd89, + 0xb2cddb0c, 0xb30fb13b, 0xb1490f62, 0xb08b6555, + 0xbbd72268, 0xba15485f, 0xb853f606, 0xb9919c31, + 0xbcde8ab4, 0xbd1ce083, 0xbf5a5eda, 0xbe9834ed, + 0x00000000, 0xb8bc6765, 0xaa09c88b, 0x12b5afee, + 0x8f629757, 0x37def032, 0x256b5fdc, 0x9dd738b9, + 0xc5b428ef, 0x7d084f8a, 0x6fbde064, 0xd7018701, + 0x4ad6bfb8, 0xf26ad8dd, 0xe0df7733, 0x58631056, + 0x5019579f, 0xe8a530fa, 0xfa109f14, 0x42acf871, + 0xdf7bc0c8, 0x67c7a7ad, 0x75720843, 0xcdce6f26, + 0x95ad7f70, 0x2d111815, 0x3fa4b7fb, 0x8718d09e, + 0x1acfe827, 0xa2738f42, 0xb0c620ac, 0x087a47c9, + 0xa032af3e, 0x188ec85b, 0x0a3b67b5, 0xb28700d0, + 0x2f503869, 0x97ec5f0c, 0x8559f0e2, 0x3de59787, + 0x658687d1, 0xdd3ae0b4, 0xcf8f4f5a, 0x7733283f, + 0xeae41086, 0x525877e3, 0x40edd80d, 0xf851bf68, + 0xf02bf8a1, 0x48979fc4, 0x5a22302a, 0xe29e574f, + 0x7f496ff6, 0xc7f50893, 0xd540a77d, 0x6dfcc018, + 0x359fd04e, 0x8d23b72b, 0x9f9618c5, 0x272a7fa0, + 0xbafd4719, 0x0241207c, 0x10f48f92, 0xa848e8f7, + 0x9b14583d, 0x23a83f58, 0x311d90b6, 0x89a1f7d3, + 0x1476cf6a, 0xaccaa80f, 0xbe7f07e1, 0x06c36084, + 0x5ea070d2, 0xe61c17b7, 0xf4a9b859, 0x4c15df3c, + 0xd1c2e785, 0x697e80e0, 0x7bcb2f0e, 0xc377486b, + 0xcb0d0fa2, 0x73b168c7, 0x6104c729, 0xd9b8a04c, + 0x446f98f5, 0xfcd3ff90, 0xee66507e, 0x56da371b, + 0x0eb9274d, 0xb6054028, 0xa4b0efc6, 0x1c0c88a3, + 0x81dbb01a, 0x3967d77f, 0x2bd27891, 0x936e1ff4, + 0x3b26f703, 0x839a9066, 0x912f3f88, 0x299358ed, + 0xb4446054, 0x0cf80731, 0x1e4da8df, 0xa6f1cfba, + 0xfe92dfec, 0x462eb889, 0x549b1767, 0xec277002, + 0x71f048bb, 0xc94c2fde, 0xdbf98030, 0x6345e755, + 0x6b3fa09c, 0xd383c7f9, 0xc1366817, 0x798a0f72, + 0xe45d37cb, 0x5ce150ae, 0x4e54ff40, 0xf6e89825, + 0xae8b8873, 0x1637ef16, 0x048240f8, 0xbc3e279d, + 0x21e91f24, 0x99557841, 0x8be0d7af, 0x335cb0ca, + 0xed59b63b, 0x55e5d15e, 0x47507eb0, 0xffec19d5, + 0x623b216c, 0xda874609, 0xc832e9e7, 0x708e8e82, + 0x28ed9ed4, 0x9051f9b1, 0x82e4565f, 0x3a58313a, + 0xa78f0983, 0x1f336ee6, 0x0d86c108, 0xb53aa66d, + 0xbd40e1a4, 0x05fc86c1, 0x1749292f, 0xaff54e4a, + 0x322276f3, 0x8a9e1196, 0x982bbe78, 0x2097d91d, + 0x78f4c94b, 0xc048ae2e, 0xd2fd01c0, 0x6a4166a5, + 0xf7965e1c, 0x4f2a3979, 0x5d9f9697, 0xe523f1f2, + 0x4d6b1905, 0xf5d77e60, 0xe762d18e, 0x5fdeb6eb, + 0xc2098e52, 0x7ab5e937, 0x680046d9, 0xd0bc21bc, + 0x88df31ea, 0x3063568f, 0x22d6f961, 0x9a6a9e04, + 0x07bda6bd, 0xbf01c1d8, 0xadb46e36, 0x15080953, + 0x1d724e9a, 0xa5ce29ff, 0xb77b8611, 0x0fc7e174, + 0x9210d9cd, 0x2aacbea8, 0x38191146, 0x80a57623, + 0xd8c66675, 0x607a0110, 0x72cfaefe, 0xca73c99b, + 0x57a4f122, 0xef189647, 0xfdad39a9, 0x45115ecc, + 0x764dee06, 0xcef18963, 0xdc44268d, 0x64f841e8, + 0xf92f7951, 0x41931e34, 0x5326b1da, 0xeb9ad6bf, + 0xb3f9c6e9, 0x0b45a18c, 0x19f00e62, 0xa14c6907, + 0x3c9b51be, 0x842736db, 0x96929935, 0x2e2efe50, + 0x2654b999, 0x9ee8defc, 0x8c5d7112, 0x34e11677, + 0xa9362ece, 0x118a49ab, 0x033fe645, 0xbb838120, + 0xe3e09176, 0x5b5cf613, 0x49e959fd, 0xf1553e98, + 0x6c820621, 0xd43e6144, 0xc68bceaa, 0x7e37a9cf, + 0xd67f4138, 0x6ec3265d, 0x7c7689b3, 0xc4caeed6, + 0x591dd66f, 0xe1a1b10a, 0xf3141ee4, 0x4ba87981, + 0x13cb69d7, 0xab770eb2, 0xb9c2a15c, 0x017ec639, + 0x9ca9fe80, 0x241599e5, 0x36a0360b, 0x8e1c516e, + 0x866616a7, 0x3eda71c2, 0x2c6fde2c, 0x94d3b949, + 0x090481f0, 0xb1b8e695, 0xa30d497b, 0x1bb12e1e, + 0x43d23e48, 0xfb6e592d, 0xe9dbf6c3, 0x516791a6, + 0xccb0a91f, 0x740cce7a, 0x66b96194, 0xde0506f1 +}; + /* CRC32 */ +static inline u32 +crc32_next (u32 crc, byte data) +{ + return (crc >> 8) ^ crc32_table[(crc & 0xff) ^ data]; +} + +/* + * Process 4 bytes in one go + */ +static inline u32 +crc32_next4 (u32 crc, u32 data) +{ + crc ^= data; + crc = crc32_table[(crc & 0xff) + 0x300] ^ + crc32_table[((crc >> 8) & 0xff) + 0x200] ^ + crc32_table[((crc >> 16) & 0xff) + 0x100] ^ + crc32_table[(crc >> 24) & 0xff]; + return crc; +} + static void crc32_init (void *context) { @@ -157,12 +342,40 @@ crc32_init (void *context) } static void -crc32_write (void *context, const void *inbuf, size_t inlen) +crc32_write (void *context, const void *inbuf_arg, size_t inlen) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; - if (!inbuf) + const byte *inbuf = inbuf_arg; + u32 crc; + + if (!inbuf || !inlen) return; - ctx->CRC = update_crc32 (ctx->CRC, inbuf, inlen); + + crc = ctx->CRC; + + while (inlen >= 16) + { + inlen -= 16; + crc = crc32_next4(crc, buf_get_le32(&inbuf[0])); + crc = crc32_next4(crc, buf_get_le32(&inbuf[4])); + crc = crc32_next4(crc, buf_get_le32(&inbuf[8])); + crc = crc32_next4(crc, buf_get_le32(&inbuf[12])); + inbuf += 16; + } + + while (inlen >= 4) + { + inlen -= 4; + crc = crc32_next4(crc, buf_get_le32(inbuf)); + inbuf += 4; + } + + while (inlen--) + { + crc = crc32_next(crc, *inbuf++); + } + + ctx->CRC = crc; } static byte * @@ -177,13 +390,12 @@ crc32_final (void *context) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; ctx->CRC ^= 0xffffffffL; - ctx->buf[0] = (ctx->CRC >> 24) & 0xFF; - ctx->buf[1] = (ctx->CRC >> 16) & 0xFF; - ctx->buf[2] = (ctx->CRC >> 8) & 0xFF; - ctx->buf[3] = (ctx->CRC ) & 0xFF; + buf_put_be32 (ctx->buf, ctx->CRC); } /* CRC32 a'la RFC 1510 */ +/* CRC of the string "123456789" is 0x2dfd2d88 */ + static void crc32rfc1510_init (void *context) { @@ -195,82 +407,366 @@ static void crc32rfc1510_final (void *context) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; - ctx->buf[0] = (ctx->CRC >> 24) & 0xFF; - ctx->buf[1] = (ctx->CRC >> 16) & 0xFF; - ctx->buf[2] = (ctx->CRC >> 8) & 0xFF; - ctx->buf[3] = (ctx->CRC ) & 0xFF; + buf_put_be32(ctx->buf, ctx->CRC); } /* CRC24 a'la RFC 2440 */ /* - * The following CRC 24 routines are adapted from RFC 2440, which has - * the following copyright notice: + * Code generated by universal_crc by Danjel McGougan * - * Copyright (C) The Internet Society (1998). All Rights Reserved. + * CRC parameters used: + * bits: 24 + * poly: 0x864cfb + * init: 0xb704ce + * xor: 0x000000 + * reverse: false + * non-direct: false * - * This document and translations of it may be copied and furnished - * to others, and derivative works that comment on or otherwise - * explain it or assist in its implementation may be prepared, - * copied, published and distributed, in whole or in part, without - * restriction of any kind, provided that the above copyright notice - * and this paragraph are included on all such copies and derivative - * works. However, this document itself may not be modified in any - * way, such as by removing the copyright notice or references to - * the Internet Society or other Internet organizations, except as - * needed for the purpose of developing Internet standards in which - * case the procedures for copyrights defined in the Internet - * Standards process must be followed, or as required to translate - * it into languages other than English. - * - * The limited permissions granted above are perpetual and will not be - * revoked by the Internet Society or its successors or assigns. - * - * This document and the information contained herein is provided on - * an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET - * ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE - * OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR - * PURPOSE. + * CRC of the string "123456789" is 0x21cf02 */ -#define CRC24_INIT 0xb704ceL -#define CRC24_POLY 0x1864cfbL +static const u32 crc24_table[1024] = +{ + 0x00000000, 0x00fb4c86, 0x000dd58a, 0x00f6990c, + 0x00e1e693, 0x001aaa15, 0x00ec3319, 0x00177f9f, + 0x003981a1, 0x00c2cd27, 0x0034542b, 0x00cf18ad, + 0x00d86732, 0x00232bb4, 0x00d5b2b8, 0x002efe3e, + 0x00894ec5, 0x00720243, 0x00849b4f, 0x007fd7c9, + 0x0068a856, 0x0093e4d0, 0x00657ddc, 0x009e315a, + 0x00b0cf64, 0x004b83e2, 0x00bd1aee, 0x00465668, + 0x005129f7, 0x00aa6571, 0x005cfc7d, 0x00a7b0fb, + 0x00e9d10c, 0x00129d8a, 0x00e40486, 0x001f4800, + 0x0008379f, 0x00f37b19, 0x0005e215, 0x00feae93, + 0x00d050ad, 0x002b1c2b, 0x00dd8527, 0x0026c9a1, + 0x0031b63e, 0x00cafab8, 0x003c63b4, 0x00c72f32, + 0x00609fc9, 0x009bd34f, 0x006d4a43, 0x009606c5, + 0x0081795a, 0x007a35dc, 0x008cacd0, 0x0077e056, + 0x00591e68, 0x00a252ee, 0x0054cbe2, 0x00af8764, + 0x00b8f8fb, 0x0043b47d, 0x00b52d71, 0x004e61f7, + 0x00d2a319, 0x0029ef9f, 0x00df7693, 0x00243a15, + 0x0033458a, 0x00c8090c, 0x003e9000, 0x00c5dc86, + 0x00eb22b8, 0x00106e3e, 0x00e6f732, 0x001dbbb4, + 0x000ac42b, 0x00f188ad, 0x000711a1, 0x00fc5d27, + 0x005beddc, 0x00a0a15a, 0x00563856, 0x00ad74d0, + 0x00ba0b4f, 0x004147c9, 0x00b7dec5, 0x004c9243, + 0x00626c7d, 0x009920fb, 0x006fb9f7, 0x0094f571, + 0x00838aee, 0x0078c668, 0x008e5f64, 0x007513e2, + 0x003b7215, 0x00c03e93, 0x0036a79f, 0x00cdeb19, + 0x00da9486, 0x0021d800, 0x00d7410c, 0x002c0d8a, + 0x0002f3b4, 0x00f9bf32, 0x000f263e, 0x00f46ab8, + 0x00e31527, 0x001859a1, 0x00eec0ad, 0x00158c2b, + 0x00b23cd0, 0x00497056, 0x00bfe95a, 0x0044a5dc, + 0x0053da43, 0x00a896c5, 0x005e0fc9, 0x00a5434f, + 0x008bbd71, 0x0070f1f7, 0x008668fb, 0x007d247d, + 0x006a5be2, 0x00911764, 0x00678e68, 0x009cc2ee, + 0x00a44733, 0x005f0bb5, 0x00a992b9, 0x0052de3f, + 0x0045a1a0, 0x00beed26, 0x0048742a, 0x00b338ac, + 0x009dc692, 0x00668a14, 0x00901318, 0x006b5f9e, + 0x007c2001, 0x00876c87, 0x0071f58b, 0x008ab90d, + 0x002d09f6, 0x00d64570, 0x0020dc7c, 0x00db90fa, + 0x00ccef65, 0x0037a3e3, 0x00c13aef, 0x003a7669, + 0x00148857, 0x00efc4d1, 0x00195ddd, 0x00e2115b, + 0x00f56ec4, 0x000e2242, 0x00f8bb4e, 0x0003f7c8, + 0x004d963f, 0x00b6dab9, 0x004043b5, 0x00bb0f33, + 0x00ac70ac, 0x00573c2a, 0x00a1a526, 0x005ae9a0, + 0x0074179e, 0x008f5b18, 0x0079c214, 0x00828e92, + 0x0095f10d, 0x006ebd8b, 0x00982487, 0x00636801, + 0x00c4d8fa, 0x003f947c, 0x00c90d70, 0x003241f6, + 0x00253e69, 0x00de72ef, 0x0028ebe3, 0x00d3a765, + 0x00fd595b, 0x000615dd, 0x00f08cd1, 0x000bc057, + 0x001cbfc8, 0x00e7f34e, 0x00116a42, 0x00ea26c4, + 0x0076e42a, 0x008da8ac, 0x007b31a0, 0x00807d26, + 0x009702b9, 0x006c4e3f, 0x009ad733, 0x00619bb5, + 0x004f658b, 0x00b4290d, 0x0042b001, 0x00b9fc87, + 0x00ae8318, 0x0055cf9e, 0x00a35692, 0x00581a14, + 0x00ffaaef, 0x0004e669, 0x00f27f65, 0x000933e3, + 0x001e4c7c, 0x00e500fa, 0x001399f6, 0x00e8d570, + 0x00c62b4e, 0x003d67c8, 0x00cbfec4, 0x0030b242, + 0x0027cddd, 0x00dc815b, 0x002a1857, 0x00d154d1, + 0x009f3526, 0x006479a0, 0x0092e0ac, 0x0069ac2a, + 0x007ed3b5, 0x00859f33, 0x0073063f, 0x00884ab9, + 0x00a6b487, 0x005df801, 0x00ab610d, 0x00502d8b, + 0x00475214, 0x00bc1e92, 0x004a879e, 0x00b1cb18, + 0x00167be3, 0x00ed3765, 0x001bae69, 0x00e0e2ef, + 0x00f79d70, 0x000cd1f6, 0x00fa48fa, 0x0001047c, + 0x002ffa42, 0x00d4b6c4, 0x00222fc8, 0x00d9634e, + 0x00ce1cd1, 0x00355057, 0x00c3c95b, 0x003885dd, + 0x00000000, 0x00488f66, 0x00901ecd, 0x00d891ab, + 0x00db711c, 0x0093fe7a, 0x004b6fd1, 0x0003e0b7, + 0x00b6e338, 0x00fe6c5e, 0x0026fdf5, 0x006e7293, + 0x006d9224, 0x00251d42, 0x00fd8ce9, 0x00b5038f, + 0x006cc771, 0x00244817, 0x00fcd9bc, 0x00b456da, + 0x00b7b66d, 0x00ff390b, 0x0027a8a0, 0x006f27c6, + 0x00da2449, 0x0092ab2f, 0x004a3a84, 0x0002b5e2, + 0x00015555, 0x0049da33, 0x00914b98, 0x00d9c4fe, + 0x00d88ee3, 0x00900185, 0x0048902e, 0x00001f48, + 0x0003ffff, 0x004b7099, 0x0093e132, 0x00db6e54, + 0x006e6ddb, 0x0026e2bd, 0x00fe7316, 0x00b6fc70, + 0x00b51cc7, 0x00fd93a1, 0x0025020a, 0x006d8d6c, + 0x00b44992, 0x00fcc6f4, 0x0024575f, 0x006cd839, + 0x006f388e, 0x0027b7e8, 0x00ff2643, 0x00b7a925, + 0x0002aaaa, 0x004a25cc, 0x0092b467, 0x00da3b01, + 0x00d9dbb6, 0x009154d0, 0x0049c57b, 0x00014a1d, + 0x004b5141, 0x0003de27, 0x00db4f8c, 0x0093c0ea, + 0x0090205d, 0x00d8af3b, 0x00003e90, 0x0048b1f6, + 0x00fdb279, 0x00b53d1f, 0x006dacb4, 0x002523d2, + 0x0026c365, 0x006e4c03, 0x00b6dda8, 0x00fe52ce, + 0x00279630, 0x006f1956, 0x00b788fd, 0x00ff079b, + 0x00fce72c, 0x00b4684a, 0x006cf9e1, 0x00247687, + 0x00917508, 0x00d9fa6e, 0x00016bc5, 0x0049e4a3, + 0x004a0414, 0x00028b72, 0x00da1ad9, 0x009295bf, + 0x0093dfa2, 0x00db50c4, 0x0003c16f, 0x004b4e09, + 0x0048aebe, 0x000021d8, 0x00d8b073, 0x00903f15, + 0x00253c9a, 0x006db3fc, 0x00b52257, 0x00fdad31, + 0x00fe4d86, 0x00b6c2e0, 0x006e534b, 0x0026dc2d, + 0x00ff18d3, 0x00b797b5, 0x006f061e, 0x00278978, + 0x002469cf, 0x006ce6a9, 0x00b47702, 0x00fcf864, + 0x0049fbeb, 0x0001748d, 0x00d9e526, 0x00916a40, + 0x00928af7, 0x00da0591, 0x0002943a, 0x004a1b5c, + 0x0096a282, 0x00de2de4, 0x0006bc4f, 0x004e3329, + 0x004dd39e, 0x00055cf8, 0x00ddcd53, 0x00954235, + 0x002041ba, 0x0068cedc, 0x00b05f77, 0x00f8d011, + 0x00fb30a6, 0x00b3bfc0, 0x006b2e6b, 0x0023a10d, + 0x00fa65f3, 0x00b2ea95, 0x006a7b3e, 0x0022f458, + 0x002114ef, 0x00699b89, 0x00b10a22, 0x00f98544, + 0x004c86cb, 0x000409ad, 0x00dc9806, 0x00941760, + 0x0097f7d7, 0x00df78b1, 0x0007e91a, 0x004f667c, + 0x004e2c61, 0x0006a307, 0x00de32ac, 0x0096bdca, + 0x00955d7d, 0x00ddd21b, 0x000543b0, 0x004dccd6, + 0x00f8cf59, 0x00b0403f, 0x0068d194, 0x00205ef2, + 0x0023be45, 0x006b3123, 0x00b3a088, 0x00fb2fee, + 0x0022eb10, 0x006a6476, 0x00b2f5dd, 0x00fa7abb, + 0x00f99a0c, 0x00b1156a, 0x006984c1, 0x00210ba7, + 0x00940828, 0x00dc874e, 0x000416e5, 0x004c9983, + 0x004f7934, 0x0007f652, 0x00df67f9, 0x0097e89f, + 0x00ddf3c3, 0x00957ca5, 0x004ded0e, 0x00056268, + 0x000682df, 0x004e0db9, 0x00969c12, 0x00de1374, + 0x006b10fb, 0x00239f9d, 0x00fb0e36, 0x00b38150, + 0x00b061e7, 0x00f8ee81, 0x00207f2a, 0x0068f04c, + 0x00b134b2, 0x00f9bbd4, 0x00212a7f, 0x0069a519, + 0x006a45ae, 0x0022cac8, 0x00fa5b63, 0x00b2d405, + 0x0007d78a, 0x004f58ec, 0x0097c947, 0x00df4621, + 0x00dca696, 0x009429f0, 0x004cb85b, 0x0004373d, + 0x00057d20, 0x004df246, 0x009563ed, 0x00ddec8b, + 0x00de0c3c, 0x0096835a, 0x004e12f1, 0x00069d97, + 0x00b39e18, 0x00fb117e, 0x002380d5, 0x006b0fb3, + 0x0068ef04, 0x00206062, 0x00f8f1c9, 0x00b07eaf, + 0x0069ba51, 0x00213537, 0x00f9a49c, 0x00b12bfa, + 0x00b2cb4d, 0x00fa442b, 0x0022d580, 0x006a5ae6, + 0x00df5969, 0x0097d60f, 0x004f47a4, 0x0007c8c2, + 0x00042875, 0x004ca713, 0x009436b8, 0x00dcb9de, + 0x00000000, 0x00d70983, 0x00555f80, 0x00825603, + 0x0051f286, 0x0086fb05, 0x0004ad06, 0x00d3a485, + 0x0059a88b, 0x008ea108, 0x000cf70b, 0x00dbfe88, + 0x00085a0d, 0x00df538e, 0x005d058d, 0x008a0c0e, + 0x00491c91, 0x009e1512, 0x001c4311, 0x00cb4a92, + 0x0018ee17, 0x00cfe794, 0x004db197, 0x009ab814, + 0x0010b41a, 0x00c7bd99, 0x0045eb9a, 0x0092e219, + 0x0041469c, 0x00964f1f, 0x0014191c, 0x00c3109f, + 0x006974a4, 0x00be7d27, 0x003c2b24, 0x00eb22a7, + 0x00388622, 0x00ef8fa1, 0x006dd9a2, 0x00bad021, + 0x0030dc2f, 0x00e7d5ac, 0x006583af, 0x00b28a2c, + 0x00612ea9, 0x00b6272a, 0x00347129, 0x00e378aa, + 0x00206835, 0x00f761b6, 0x007537b5, 0x00a23e36, + 0x00719ab3, 0x00a69330, 0x0024c533, 0x00f3ccb0, + 0x0079c0be, 0x00aec93d, 0x002c9f3e, 0x00fb96bd, + 0x00283238, 0x00ff3bbb, 0x007d6db8, 0x00aa643b, + 0x0029a4ce, 0x00fead4d, 0x007cfb4e, 0x00abf2cd, + 0x00785648, 0x00af5fcb, 0x002d09c8, 0x00fa004b, + 0x00700c45, 0x00a705c6, 0x002553c5, 0x00f25a46, + 0x0021fec3, 0x00f6f740, 0x0074a143, 0x00a3a8c0, + 0x0060b85f, 0x00b7b1dc, 0x0035e7df, 0x00e2ee5c, + 0x00314ad9, 0x00e6435a, 0x00641559, 0x00b31cda, + 0x003910d4, 0x00ee1957, 0x006c4f54, 0x00bb46d7, + 0x0068e252, 0x00bfebd1, 0x003dbdd2, 0x00eab451, + 0x0040d06a, 0x0097d9e9, 0x00158fea, 0x00c28669, + 0x001122ec, 0x00c62b6f, 0x00447d6c, 0x009374ef, + 0x001978e1, 0x00ce7162, 0x004c2761, 0x009b2ee2, + 0x00488a67, 0x009f83e4, 0x001dd5e7, 0x00cadc64, + 0x0009ccfb, 0x00dec578, 0x005c937b, 0x008b9af8, + 0x00583e7d, 0x008f37fe, 0x000d61fd, 0x00da687e, + 0x00506470, 0x00876df3, 0x00053bf0, 0x00d23273, + 0x000196f6, 0x00d69f75, 0x0054c976, 0x0083c0f5, + 0x00a9041b, 0x007e0d98, 0x00fc5b9b, 0x002b5218, + 0x00f8f69d, 0x002fff1e, 0x00ada91d, 0x007aa09e, + 0x00f0ac90, 0x0027a513, 0x00a5f310, 0x0072fa93, + 0x00a15e16, 0x00765795, 0x00f40196, 0x00230815, + 0x00e0188a, 0x00371109, 0x00b5470a, 0x00624e89, + 0x00b1ea0c, 0x0066e38f, 0x00e4b58c, 0x0033bc0f, + 0x00b9b001, 0x006eb982, 0x00ecef81, 0x003be602, + 0x00e84287, 0x003f4b04, 0x00bd1d07, 0x006a1484, + 0x00c070bf, 0x0017793c, 0x00952f3f, 0x004226bc, + 0x00918239, 0x00468bba, 0x00c4ddb9, 0x0013d43a, + 0x0099d834, 0x004ed1b7, 0x00cc87b4, 0x001b8e37, + 0x00c82ab2, 0x001f2331, 0x009d7532, 0x004a7cb1, + 0x00896c2e, 0x005e65ad, 0x00dc33ae, 0x000b3a2d, + 0x00d89ea8, 0x000f972b, 0x008dc128, 0x005ac8ab, + 0x00d0c4a5, 0x0007cd26, 0x00859b25, 0x005292a6, + 0x00813623, 0x00563fa0, 0x00d469a3, 0x00036020, + 0x0080a0d5, 0x0057a956, 0x00d5ff55, 0x0002f6d6, + 0x00d15253, 0x00065bd0, 0x00840dd3, 0x00530450, + 0x00d9085e, 0x000e01dd, 0x008c57de, 0x005b5e5d, + 0x0088fad8, 0x005ff35b, 0x00dda558, 0x000aacdb, + 0x00c9bc44, 0x001eb5c7, 0x009ce3c4, 0x004bea47, + 0x00984ec2, 0x004f4741, 0x00cd1142, 0x001a18c1, + 0x009014cf, 0x00471d4c, 0x00c54b4f, 0x001242cc, + 0x00c1e649, 0x0016efca, 0x0094b9c9, 0x0043b04a, + 0x00e9d471, 0x003eddf2, 0x00bc8bf1, 0x006b8272, + 0x00b826f7, 0x006f2f74, 0x00ed7977, 0x003a70f4, + 0x00b07cfa, 0x00677579, 0x00e5237a, 0x00322af9, + 0x00e18e7c, 0x003687ff, 0x00b4d1fc, 0x0063d87f, + 0x00a0c8e0, 0x0077c163, 0x00f59760, 0x00229ee3, + 0x00f13a66, 0x002633e5, 0x00a465e6, 0x00736c65, + 0x00f9606b, 0x002e69e8, 0x00ac3feb, 0x007b3668, + 0x00a892ed, 0x007f9b6e, 0x00fdcd6d, 0x002ac4ee, + 0x00000000, 0x00520936, 0x00a4126c, 0x00f61b5a, + 0x004825d8, 0x001a2cee, 0x00ec37b4, 0x00be3e82, + 0x006b0636, 0x00390f00, 0x00cf145a, 0x009d1d6c, + 0x002323ee, 0x00712ad8, 0x00873182, 0x00d538b4, + 0x00d60c6c, 0x0084055a, 0x00721e00, 0x00201736, + 0x009e29b4, 0x00cc2082, 0x003a3bd8, 0x006832ee, + 0x00bd0a5a, 0x00ef036c, 0x00191836, 0x004b1100, + 0x00f52f82, 0x00a726b4, 0x00513dee, 0x000334d8, + 0x00ac19d8, 0x00fe10ee, 0x00080bb4, 0x005a0282, + 0x00e43c00, 0x00b63536, 0x00402e6c, 0x0012275a, + 0x00c71fee, 0x009516d8, 0x00630d82, 0x003104b4, + 0x008f3a36, 0x00dd3300, 0x002b285a, 0x0079216c, + 0x007a15b4, 0x00281c82, 0x00de07d8, 0x008c0eee, + 0x0032306c, 0x0060395a, 0x00962200, 0x00c42b36, + 0x00111382, 0x00431ab4, 0x00b501ee, 0x00e708d8, + 0x0059365a, 0x000b3f6c, 0x00fd2436, 0x00af2d00, + 0x00a37f36, 0x00f17600, 0x00076d5a, 0x0055646c, + 0x00eb5aee, 0x00b953d8, 0x004f4882, 0x001d41b4, + 0x00c87900, 0x009a7036, 0x006c6b6c, 0x003e625a, + 0x00805cd8, 0x00d255ee, 0x00244eb4, 0x00764782, + 0x0075735a, 0x00277a6c, 0x00d16136, 0x00836800, + 0x003d5682, 0x006f5fb4, 0x009944ee, 0x00cb4dd8, + 0x001e756c, 0x004c7c5a, 0x00ba6700, 0x00e86e36, + 0x005650b4, 0x00045982, 0x00f242d8, 0x00a04bee, + 0x000f66ee, 0x005d6fd8, 0x00ab7482, 0x00f97db4, + 0x00474336, 0x00154a00, 0x00e3515a, 0x00b1586c, + 0x006460d8, 0x003669ee, 0x00c072b4, 0x00927b82, + 0x002c4500, 0x007e4c36, 0x0088576c, 0x00da5e5a, + 0x00d96a82, 0x008b63b4, 0x007d78ee, 0x002f71d8, + 0x00914f5a, 0x00c3466c, 0x00355d36, 0x00675400, + 0x00b26cb4, 0x00e06582, 0x00167ed8, 0x004477ee, + 0x00fa496c, 0x00a8405a, 0x005e5b00, 0x000c5236, + 0x0046ff6c, 0x0014f65a, 0x00e2ed00, 0x00b0e436, + 0x000edab4, 0x005cd382, 0x00aac8d8, 0x00f8c1ee, + 0x002df95a, 0x007ff06c, 0x0089eb36, 0x00dbe200, + 0x0065dc82, 0x0037d5b4, 0x00c1ceee, 0x0093c7d8, + 0x0090f300, 0x00c2fa36, 0x0034e16c, 0x0066e85a, + 0x00d8d6d8, 0x008adfee, 0x007cc4b4, 0x002ecd82, + 0x00fbf536, 0x00a9fc00, 0x005fe75a, 0x000dee6c, + 0x00b3d0ee, 0x00e1d9d8, 0x0017c282, 0x0045cbb4, + 0x00eae6b4, 0x00b8ef82, 0x004ef4d8, 0x001cfdee, + 0x00a2c36c, 0x00f0ca5a, 0x0006d100, 0x0054d836, + 0x0081e082, 0x00d3e9b4, 0x0025f2ee, 0x0077fbd8, + 0x00c9c55a, 0x009bcc6c, 0x006dd736, 0x003fde00, + 0x003cead8, 0x006ee3ee, 0x0098f8b4, 0x00caf182, + 0x0074cf00, 0x0026c636, 0x00d0dd6c, 0x0082d45a, + 0x0057ecee, 0x0005e5d8, 0x00f3fe82, 0x00a1f7b4, + 0x001fc936, 0x004dc000, 0x00bbdb5a, 0x00e9d26c, + 0x00e5805a, 0x00b7896c, 0x00419236, 0x00139b00, + 0x00ada582, 0x00ffacb4, 0x0009b7ee, 0x005bbed8, + 0x008e866c, 0x00dc8f5a, 0x002a9400, 0x00789d36, + 0x00c6a3b4, 0x0094aa82, 0x0062b1d8, 0x0030b8ee, + 0x00338c36, 0x00618500, 0x00979e5a, 0x00c5976c, + 0x007ba9ee, 0x0029a0d8, 0x00dfbb82, 0x008db2b4, + 0x00588a00, 0x000a8336, 0x00fc986c, 0x00ae915a, + 0x0010afd8, 0x0042a6ee, 0x00b4bdb4, 0x00e6b482, + 0x00499982, 0x001b90b4, 0x00ed8bee, 0x00bf82d8, + 0x0001bc5a, 0x0053b56c, 0x00a5ae36, 0x00f7a700, + 0x00229fb4, 0x00709682, 0x00868dd8, 0x00d484ee, + 0x006aba6c, 0x0038b35a, 0x00cea800, 0x009ca136, + 0x009f95ee, 0x00cd9cd8, 0x003b8782, 0x00698eb4, + 0x00d7b036, 0x0085b900, 0x0073a25a, 0x0021ab6c, + 0x00f493d8, 0x00a69aee, 0x005081b4, 0x00028882, + 0x00bcb600, 0x00eebf36, 0x0018a46c, 0x004aad5a +}; + +static inline +u32 crc24_init (void) +{ + return 0xce04b7; +} + +static inline +u32 crc24_next (u32 crc, byte data) +{ + return (crc >> 8) ^ crc24_table[(crc & 0xff) ^ data]; +} + +/* + * Process 4 bytes in one go + */ +static inline +u32 crc24_next4 (u32 crc, u32 data) +{ + crc ^= data; + crc = crc24_table[(crc & 0xff) + 0x300] ^ + crc24_table[((crc >> 8) & 0xff) + 0x200] ^ + crc24_table[((crc >> 16) & 0xff) + 0x100] ^ + crc24_table[(crc >> 24) & 0xff]; + return crc; +} + +static inline +u32 crc24_final (u32 crc) +{ + return crc & 0xffffff; +} static void crc24rfc2440_init (void *context) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; - ctx->CRC = CRC24_INIT; + ctx->CRC = crc24_init(); } static void crc24rfc2440_write (void *context, const void *inbuf_arg, size_t inlen) { const unsigned char *inbuf = inbuf_arg; - int i; CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; + u32 crc; - if (!inbuf) + if (!inbuf || !inlen) return; - while (inlen--) { - ctx->CRC ^= (*inbuf++) << 16; - for (i = 0; i < 8; i++) { - ctx->CRC <<= 1; - if (ctx->CRC & 0x1000000) - ctx->CRC ^= CRC24_POLY; + crc = ctx->CRC; + + while (inlen >= 16) + { + inlen -= 16; + crc = crc24_next4(crc, buf_get_le32(&inbuf[0])); + crc = crc24_next4(crc, buf_get_le32(&inbuf[4])); + crc = crc24_next4(crc, buf_get_le32(&inbuf[8])); + crc = crc24_next4(crc, buf_get_le32(&inbuf[12])); + inbuf += 16; } - } + + while (inlen >= 4) + { + inlen -= 4; + crc = crc24_next4(crc, buf_get_le32(inbuf)); + inbuf += 4; + } + + while (inlen--) + { + crc = crc24_next(crc, *inbuf++); + } + + ctx->CRC = crc; } static void crc24rfc2440_final (void *context) { CRC_CONTEXT *ctx = (CRC_CONTEXT *) context; - ctx->buf[0] = (ctx->CRC >> 16) & 0xFF; - ctx->buf[1] = (ctx->CRC >> 8) & 0xFF; - ctx->buf[2] = (ctx->CRC ) & 0xFF; + ctx->CRC = crc24_final(ctx->CRC); + buf_put_le32 (ctx->buf, ctx->CRC); } gcry_md_spec_t _gcry_digest_spec_crc32 = diff --git a/grub-core/lib/libgcrypt/cipher/des.c b/grub-core/lib/libgcrypt/cipher/des.c index f91df7771..96b06ae36 100644 --- a/grub-core/lib/libgcrypt/cipher/des.c +++ b/grub-core/lib/libgcrypt/cipher/des.c @@ -22,7 +22,7 @@ * Bruce Schneier: Applied Cryptography. Second Edition. * John Wiley & Sons, 1996. ISBN 0-471-12845-7. Pages 358 ff. * This implementation is according to the definition of DES in FIPS - * PUB 46-2 from December 1993. + * PUB 46-2 from December 1993. */ @@ -106,7 +106,7 @@ * * if ( (error_msg = selftest()) ) * { - * fprintf(stderr, "An error in the DES/Tripple-DES implementation occured: %s\n", error_msg); + * fprintf(stderr, "An error in the DES/Triple-DES implementation occurred: %s\n", error_msg); * abort(); * } */ @@ -388,7 +388,7 @@ static byte weak_keys[64][8] = }; static unsigned char weak_keys_chksum[20] = { 0xD0, 0xCF, 0x07, 0x38, 0x93, 0x70, 0x8A, 0x83, 0x7D, 0xD7, - 0x8A, 0x36, 0x65, 0x29, 0x6C, 0x1F, 0x7C, 0x3F, 0xD3, 0x41 + 0x8A, 0x36, 0x65, 0x29, 0x6C, 0x1F, 0x7C, 0x3F, 0xD3, 0x41 }; @@ -888,12 +888,12 @@ selftest (void) if (memcmp (input, result, 8)) return "Triple-DES test failed."; } - + /* * More Triple-DES test. These are testvectors as used by SSLeay, * thanks to Jeroen C. van Gelderen. */ - { + { struct { byte key[24]; byte plain[8]; byte cipher[8]; } testdata[] = { { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, @@ -901,7 +901,7 @@ selftest (void) { 0x95,0xF8,0xA5,0xE5,0xDD,0x31,0xD9,0x00 }, { 0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }, - + { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, @@ -966,7 +966,7 @@ selftest (void) { tripledes_set3keys (des3, testdata[i].key, testdata[i].key + 8, testdata[i].key + 16); - + tripledes_ecb_encrypt (des3, testdata[i].plain, result); if (memcmp (testdata[i].cipher, result, 8)) return "Triple-DES SSLeay test failed on encryption."; @@ -1047,7 +1047,7 @@ do_tripledes_set_extra_info (void *context, int what, break; default: - ec = GPG_ERR_INV_OP; + ec = GPG_ERR_INV_OP; break; } return ec; @@ -1112,7 +1112,7 @@ do_des_decrypt( void *context, byte *outbuf, const byte *inbuf ) -/* +/* Self-test section. */ @@ -1123,7 +1123,7 @@ selftest_fips (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; - + (void)extended; /* No extended tests available. */ what = "low-level"; @@ -1160,7 +1160,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) default: ec = GPG_ERR_CIPHER_ALGO; break; - + } return ec; } @@ -1189,7 +1189,7 @@ gcry_cipher_spec_t _gcry_cipher_spec_tripledes = do_tripledes_setkey, do_tripledes_encrypt, do_tripledes_decrypt }; -cipher_extra_spec_t _gcry_cipher_extraspec_tripledes = +cipher_extra_spec_t _gcry_cipher_extraspec_tripledes = { run_selftests, do_tripledes_set_extra_info diff --git a/grub-core/lib/libgcrypt/cipher/dsa.c b/grub-core/lib/libgcrypt/cipher/dsa.c index 100710f97..883a815f2 100644 --- a/grub-core/lib/libgcrypt/cipher/dsa.c +++ b/grub-core/lib/libgcrypt/cipher/dsa.c @@ -74,7 +74,7 @@ static const char sample_secret_key[] = " 42CAA7DC289F0C5A9D155F02D3D551DB741A81695B74D4C8F477F9C7838EB0FB#)" " (x #11D54E4ADBD3034160F2CED4B7CD292A4EBF3EC0#)))"; /* A sample 1024 bit DSA key used for the selftests (public only). */ -static const char sample_public_key[] = +static const char sample_public_key[] = "(public-key" " (dsa" " (p #00AD7C0025BA1A15F775F3F2D673718391D00456978D347B33D7B49E7F32EDAB" @@ -141,14 +141,19 @@ gen_k( gcry_mpi_t q ) unsigned int nbytes = (nbits+7)/8; char *rndbuf = NULL; + /* To learn why we don't use mpi_mod to get the requested bit size, + read the paper: "The Insecurity of the Digital Signature + Algorithm with Partially Known Nonces" by Nguyen and Shparlinski. + Journal of Cryptology, New York. Vol 15, nr 3 (2003) */ + if ( DBG_CIPHER ) log_debug("choosing a random k "); - for (;;) + for (;;) { if( DBG_CIPHER ) progress('.'); - if ( !rndbuf || nbits < 32 ) + if ( !rndbuf || nbits < 32 ) { gcry_free(rndbuf); rndbuf = gcry_random_bytes_secure( (nbits+7)/8, GCRY_STRONG_RANDOM ); @@ -156,13 +161,20 @@ gen_k( gcry_mpi_t q ) else { /* Change only some of the higher bits. We could improve this by directly requesting more memory at the first call - to get_random_bytes() and use this the here maybe it is - easier to do this directly in random.c. */ + to get_random_bytes() and use these extra bytes here. + However the required management code is more complex and + thus we better use this simple method. */ char *pp = gcry_random_bytes_secure( 4, GCRY_STRONG_RANDOM ); memcpy( rndbuf,pp, 4 ); gcry_free(pp); } _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 ); + + /* Make sure we have the requested number of bits. This code + looks a bit funny but it is easy to understand if you + consider that mpi_set_highbit clears all higher bits. We + don't have a clear_highbit, thus we first set the high bit + and then clear it again. */ if ( mpi_test_bit( k, nbits-1 ) ) mpi_set_highbit( k, nbits-1 ); else @@ -172,7 +184,7 @@ gen_k( gcry_mpi_t q ) } if( !(mpi_cmp( k, q ) < 0) ) /* check: k < q */ - { + { if( DBG_CIPHER ) progress('+'); continue; /* no */ @@ -188,7 +200,7 @@ gen_k( gcry_mpi_t q ) gcry_free(rndbuf); if( DBG_CIPHER ) progress('\n'); - + return k; } @@ -315,7 +327,7 @@ generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, mpi_add_ui (h, h, 1); /* g = h^e mod p */ gcry_mpi_powm (g, h, e, p); - } + } while (!mpi_cmp_ui (g, 1)); /* Continue until g != 1. */ } @@ -330,13 +342,13 @@ generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, x = mpi_alloc_secure( mpi_get_nlimbs(q) ); mpi_sub_ui( h, q, 1 ); /* put q-1 into h */ rndbuf = NULL; - do + do { if( DBG_CIPHER ) progress('.'); if( !rndbuf ) rndbuf = gcry_random_bytes_secure ((qbits+7)/8, random_level); - else + else { /* Change only some of the higher bits (= 2 bytes)*/ char *r = gcry_random_bytes_secure (2, random_level); memcpy(rndbuf, r, 2 ); @@ -345,7 +357,7 @@ generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, _gcry_mpi_set_buffer( x, rndbuf, (qbits+7)/8, 0 ); mpi_clear_highbit( x, qbits+1 ); - } + } while ( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, h )<0 ) ); gcry_free(rndbuf); mpi_free( e ); @@ -355,7 +367,7 @@ generate (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, y = mpi_alloc( mpi_get_nlimbs(p) ); gcry_mpi_powm( y, g, x, p ); - if( DBG_CIPHER ) + if( DBG_CIPHER ) { progress('\n'); log_mpidump("dsa p", p ); @@ -406,8 +418,8 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, const void *seed; size_t seedlen; } initial_seed = { NULL, NULL, 0 }; - gcry_mpi_t prime_q = NULL; - gcry_mpi_t prime_p = NULL; + gcry_mpi_t prime_q = NULL; + gcry_mpi_t prime_p = NULL; gcry_mpi_t value_g = NULL; /* The generator. */ gcry_mpi_t value_y = NULL; /* g^x mod p */ gcry_mpi_t value_x = NULL; /* The secret exponent. */ @@ -467,15 +479,15 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, initial_seed.seed = gcry_sexp_nth_data (initial_seed.sexp, 1, &initial_seed.seedlen); } - + /* Fixme: Enable 186-3 after it has been approved and after fixing the generation function. */ /* if (use_fips186_2) */ (void)use_fips186_2; - ec = _gcry_generate_fips186_2_prime (nbits, qbits, - initial_seed.seed, + ec = _gcry_generate_fips186_2_prime (nbits, qbits, + initial_seed.seed, initial_seed.seedlen, - &prime_q, &prime_p, + &prime_q, &prime_p, r_counter, r_seed, r_seedlen); /* else */ @@ -493,33 +505,33 @@ generate_fips186 (DSA_secret_key *sk, unsigned int nbits, unsigned int qbits, mpi_sub_ui (value_e, prime_p, 1); mpi_fdiv_q (value_e, value_e, prime_q ); value_g = mpi_alloc_like (prime_p); - value_h = mpi_alloc_set_ui (1); + value_h = mpi_alloc_set_ui (1); do { mpi_add_ui (value_h, value_h, 1); /* g = h^e mod p */ mpi_powm (value_g, value_h, value_e, prime_p); - } + } while (!mpi_cmp_ui (value_g, 1)); /* Continue until g != 1. */ } /* Select a random number x with: 0 < x < q */ value_x = gcry_mpi_snew (qbits); - do + do { if( DBG_CIPHER ) progress('.'); gcry_mpi_randomize (value_x, qbits, GCRY_VERY_STRONG_RANDOM); mpi_clear_highbit (value_x, qbits+1); - } + } while (!(mpi_cmp_ui (value_x, 0) > 0 && mpi_cmp (value_x, prime_q) < 0)); /* y = g^x mod p */ value_y = mpi_alloc_like (prime_p); gcry_mpi_powm (value_y, value_g, value_x, prime_p); - if (DBG_CIPHER) + if (DBG_CIPHER) { progress('\n'); log_mpidump("dsa p", prime_p ); @@ -691,7 +703,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, int use_fips186_2 = 0; int use_fips186 = 0; dsa_domain_t domain; - + (void)algo; /* No need to check it. */ (void)evalue; /* Not required for DSA. */ @@ -700,7 +712,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (genparms) { gcry_sexp_t domainsexp; - + /* Parse the optional qbits element. */ l1 = gcry_sexp_find_token (genparms, "qbits", 0); if (l1) @@ -708,7 +720,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, char buf[50]; const char *s; size_t n; - + s = gcry_sexp_nth_data (l1, 1, &n); if (!s || n >= DIM (buf) - 1 ) { @@ -760,7 +772,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, gcry_sexp_release (deriveparms); return GPG_ERR_INV_VALUE; } - + /* Put all domain parameters into the domain object. */ l1 = gcry_sexp_find_token (domainsexp, "p", 0); domain.p = gcry_sexp_nth_mpi (l1, 1, GCRYMPI_FMT_USG); @@ -804,7 +816,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, { /* Format the seed-values unless domain parameters are used for which a H_VALUE of NULL is an indication. */ - ec = gpg_err_code (gcry_sexp_build + ec = gpg_err_code (gcry_sexp_build (&seedinfo, NULL, "(seed-values(counter %d)(seed %b)(h %m))", counter, (int)seedlen, seed, h_value)); @@ -879,7 +891,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, p = stpcpy (p, ")"); } p = stpcpy (p, ")"); - + /* Allocate space for the list of factors plus one for an S-expression plus an extra NULL entry for safety and fill it with the factors. */ @@ -894,8 +906,8 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, for (j=0; j < nfactors; j++) arg_list[i++] = (*retfactors) + j; arg_list[i] = NULL; - - ec = gpg_err_code (gcry_sexp_build_array + + ec = gpg_err_code (gcry_sexp_build_array (r_extrainfo, NULL, format, arg_list)); } } @@ -907,6 +919,7 @@ dsa_generate_ext (int algo, unsigned int nbits, unsigned long evalue, gcry_mpi_release ((*retfactors)[i]); (*retfactors)[i] = NULL; } + gcry_free (*retfactors); *retfactors = NULL; if (ec) { @@ -1022,19 +1035,19 @@ dsa_get_nbits (int algo, gcry_mpi_t *pkey) -/* +/* Self-test section. */ static const char * selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) { - static const char sample_data[] = - "(data (flags pkcs1)" - " (hash sha1 #a0b1c2d3e4f500102030405060708090a1b2c3d4#))"; - static const char sample_data_bad[] = - "(data (flags pkcs1)" - " (hash sha1 #a0b1c2d3e4f510102030405060708090a1b2c3d4#))"; + static const char sample_data[] = + "(data (flags raw)" + " (value #a0b1c2d3e4f500102030405060708090a1b2c3d4#))"; + static const char sample_data_bad[] = + "(data (flags raw)" + " (value #a0b1c2d3e4f510102030405060708090a1b2c3d4#))"; const char *errtxt = NULL; gcry_error_t err; @@ -1045,7 +1058,7 @@ selftest_sign_1024 (gcry_sexp_t pkey, gcry_sexp_t skey) err = gcry_sexp_sscan (&data, NULL, sample_data, strlen (sample_data)); if (!err) - err = gcry_sexp_sscan (&data_bad, NULL, + err = gcry_sexp_sscan (&data_bad, NULL, sample_data_bad, strlen (sample_data_bad)); if (err) { @@ -1092,10 +1105,10 @@ selftests_dsa (selftest_report_func_t report) /* Convert the S-expressions into the internal representation. */ what = "convert"; - err = gcry_sexp_sscan (&skey, NULL, + err = gcry_sexp_sscan (&skey, NULL, sample_secret_key, strlen (sample_secret_key)); if (!err) - err = gcry_sexp_sscan (&pkey, NULL, + err = gcry_sexp_sscan (&pkey, NULL, sample_public_key, strlen (sample_public_key)); if (err) { @@ -1145,7 +1158,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) default: ec = GPG_ERR_PUBKEY_ALGO; break; - + } return ec; } @@ -1162,7 +1175,7 @@ static const char *dsa_names[] = gcry_pk_spec_t _gcry_pubkey_spec_dsa = { - "DSA", dsa_names, + "DSA", dsa_names, "pqgy", "pqgyx", "", "rs", "pqgy", GCRY_PK_USAGE_SIGN, dsa_generate, @@ -1173,9 +1186,8 @@ gcry_pk_spec_t _gcry_pubkey_spec_dsa = dsa_verify, dsa_get_nbits }; -pk_extra_spec_t _gcry_pubkey_extraspec_dsa = +pk_extra_spec_t _gcry_pubkey_extraspec_dsa = { run_selftests, dsa_generate_ext }; - diff --git a/grub-core/lib/libgcrypt/cipher/ecc.c b/grub-core/lib/libgcrypt/cipher/ecc.c index fcbd8e3a9..b8487dc13 100644 --- a/grub-core/lib/libgcrypt/cipher/ecc.c +++ b/grub-core/lib/libgcrypt/cipher/ecc.c @@ -1,18 +1,18 @@ /* ecc.c - Elliptic Curve Cryptography - Copyright (C) 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc. This file is part of Libgcrypt. - + Libgcrypt is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + Libgcrypt 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 Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, @@ -33,20 +33,21 @@ up. In fact there is not much left of the orginally code except for some variable names and the text book implementaion of the sign and verification algorithms. The arithmetic functions have entirely - been rewritten and moved to mpi/ec.c. */ + been rewritten and moved to mpi/ec.c. + + ECDH encrypt and decrypt code written by Andrey Jivsov, +*/ /* TODO: - - If we support point compression we need to decide how to compute - the keygrip - it should not change due to compression. + - If we support point compression we need to uncompress before + computing the keygrip - In mpi/ec.c we use mpi_powm for x^2 mod p: Either implement a special case in mpi_powm or check whether mpi_mulm is faster. - Decide whether we should hide the mpi_point_t definition. - - - Support more than just ECDSA. */ @@ -59,7 +60,6 @@ #include "mpi.h" #include "cipher.h" - /* Definition of a curve. */ typedef struct { @@ -68,7 +68,8 @@ typedef struct gcry_mpi_t b; /* Second coefficient of the Weierstrass equation. */ mpi_point_t G; /* Base point (generator). */ gcry_mpi_t n; /* Order of G. */ -} elliptic_curve_t; + const char *name; /* Name of curve or NULL. */ +} elliptic_curve_t; typedef struct @@ -90,7 +91,7 @@ static const struct { const char *name; /* Our name. */ const char *other; /* Other name. */ -} curve_aliases[] = +} curve_aliases[] = { { "NIST P-192", "1.2.840.10045.3.1.1" }, /* X9.62 OID */ { "NIST P-192", "prime192v1" }, /* X9.62 name. */ @@ -100,11 +101,11 @@ static const struct { "NIST P-224", "1.3.132.0.33" }, /* SECP OID. */ { "NIST P-256", "1.2.840.10045.3.1.7" }, /* From NIST SP 800-78-1. */ - { "NIST P-256", "prime256v1" }, + { "NIST P-256", "prime256v1" }, { "NIST P-256", "secp256r1" }, { "NIST P-384", "secp384r1" }, - { "NIST P-384", "1.3.132.0.34" }, + { "NIST P-384", "1.3.132.0.34" }, { "NIST P-521", "secp521r1" }, { "NIST P-521", "1.3.132.0.35" }, @@ -120,11 +121,7 @@ static const struct { NULL, NULL} }; - - -/* This static table defines all available curves. */ -static const struct -{ +typedef struct { const char *desc; /* Description of the curve. */ unsigned int nbits; /* Number of bits. */ unsigned int fips:1; /* True if this is a FIPS140-2 approved curve. */ @@ -132,7 +129,10 @@ static const struct const char *a, *b; /* The coefficients. */ const char *n; /* The order of the base point. */ const char *g_x, *g_y; /* Base point. */ -} domain_parms[] = +} ecc_domain_parms_t; + +/* This static table defines all available curves. */ +static const ecc_domain_parms_t domain_parms[] = { { "NIST P-192", 192, 1, @@ -197,7 +197,7 @@ static const struct "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650" }, - { "brainpoolP160r1", 160, 0, + { "brainpoolP160r1", 160, 0, "0xe95e4a5f737059dc60dfc7ad95b3d8139515620f", "0x340e7be2a280eb74e2be61bada745d97e8f7c300", "0x1e589a8595423412134faa2dbdec95c8d8675e58", @@ -206,7 +206,7 @@ static const struct "0x1667cb477a1a8ec338f94741669c976316da6321" }, - { "brainpoolP192r1", 192, 0, + { "brainpoolP192r1", 192, 0, "0xc302f41d932a36cda7a3463093d18db78fce476de1a86297", "0x6a91174076b1e0e19c39c031fe8685c1cae040e5c69a28ef", "0x469a28ef7c28cca3dc721d044f4496bcca7ef4146fbf25c9", @@ -369,7 +369,6 @@ curve_copy (elliptic_curve_t E) } - /* Helper to scan a hex string. */ static gcry_mpi_t scanval (const char *string) @@ -400,10 +399,10 @@ gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base) axb = mpi_new (0); y = mpi_new (0); - mpi_powm (x_3, x, three, base->p); - mpi_mulm (axb, base->a, x, base->p); - mpi_addm (axb, axb, base->b, base->p); - mpi_addm (y, x_3, axb, base->p); + mpi_powm (x_3, x, three, base->p); + mpi_mulm (axb, base->a, x, base->p); + mpi_addm (axb, axb, base->b, base->p); + mpi_addm (y, x_3, axb, base->p); mpi_free (x_3); mpi_free (axb); @@ -412,9 +411,6 @@ gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base) } - - - /* Generate a random secret scalar k with an order of p At the beginning this was identical to the code is in elgamal.c. @@ -428,7 +424,8 @@ gen_k (gcry_mpi_t p, int security_level) nbits = mpi_get_nbits (p); k = mpi_snew (nbits); if (DBG_CIPHER) - log_debug ("choosing a random k of %u bits\n", nbits); + log_debug ("choosing a random k of %u bits at seclevel %d\n", + nbits, security_level); gcry_mpi_randomize (k, nbits, security_level); @@ -437,23 +434,27 @@ gen_k (gcry_mpi_t p, int security_level) return k; } -/**************** - * Generate the crypto system setup. - * As of now the fix NIST recommended values are used. - * The subgroup generator point is in another function: gen_big_point. - */ + +/* Generate the crypto system setup. This function takes the NAME of + a curve or the desired number of bits and stores at R_CURVE the + parameters of the named curve or those of a suitable curve. The + chosen number of bits is stored on R_NBITS. */ static gpg_err_code_t -generate_curve (unsigned int nbits, const char *name, - elliptic_curve_t *curve, unsigned int *r_nbits) +fill_in_curve (unsigned int nbits, const char *name, + elliptic_curve_t *curve, unsigned int *r_nbits) { int idx, aliasno; + const char *resname = NULL; /* Set to a found curve name. */ if (name) { - /* First check nor native curves. */ + /* First check our native curves. */ for (idx = 0; domain_parms[idx].desc; idx++) if (!strcmp (name, domain_parms[idx].desc)) - break; + { + resname = domain_parms[idx].desc; + break; + } /* If not found consult the alias table. */ if (!domain_parms[idx].desc) { @@ -465,7 +466,10 @@ generate_curve (unsigned int nbits, const char *name, for (idx = 0; domain_parms[idx].desc; idx++) if (!strcmp (curve_aliases[aliasno].name, domain_parms[idx].desc)) - break; + { + resname = domain_parms[idx].desc; + break; + } } } } @@ -482,8 +486,7 @@ generate_curve (unsigned int nbits, const char *name, possible to bypass this check by specifying the curve parameters directly. */ if (fips_mode () && !domain_parms[idx].fips ) - return GPG_ERR_NOT_SUPPORTED; - + return GPG_ERR_NOT_SUPPORTED; *r_nbits = domain_parms[idx].nbits; curve->p = scanval (domain_parms[idx].p); @@ -493,6 +496,7 @@ generate_curve (unsigned int nbits, const char *name, curve->G.x = scanval (domain_parms[idx].g_x); curve->G.y = scanval (domain_parms[idx].g_y); curve->G.z = mpi_alloc_set_ui (1); + curve->name = resname; return 0; } @@ -504,33 +508,39 @@ generate_curve (unsigned int nbits, const char *name, */ static gpg_err_code_t generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, + int transient_key, gcry_mpi_t g_x, gcry_mpi_t g_y, - gcry_mpi_t q_x, gcry_mpi_t q_y) + gcry_mpi_t q_x, gcry_mpi_t q_y, + const char **r_usedcurve) { gpg_err_code_t err; elliptic_curve_t E; gcry_mpi_t d; mpi_point_t Q; mpi_ec_t ctx; + gcry_random_level_t random_level; - err = generate_curve (nbits, name, &E, &nbits); + *r_usedcurve = NULL; + + err = fill_in_curve (nbits, name, &E, &nbits); if (err) return err; if (DBG_CIPHER) { - log_mpidump ("ecc generation p", E.p); - log_mpidump ("ecc generation a", E.a); - log_mpidump ("ecc generation b", E.b); - log_mpidump ("ecc generation n", E.n); - log_mpidump ("ecc generation Gx", E.G.x); - log_mpidump ("ecc generation Gy", E.G.y); - log_mpidump ("ecc generation Gz", E.G.z); + log_mpidump ("ecgen curve p", E.p); + log_mpidump ("ecgen curve a", E.a); + log_mpidump ("ecgen curve b", E.b); + log_mpidump ("ecgen curve n", E.n); + log_mpidump ("ecgen curve Gx", E.G.x); + log_mpidump ("ecgen curve Gy", E.G.y); + log_mpidump ("ecgen curve Gz", E.G.z); + if (E.name) + log_debug ("ecgen curve used: %s\n", E.name); } - if (DBG_CIPHER) - log_debug ("choosing a random x of size %u\n", nbits); - d = gen_k (E.n, GCRY_VERY_STRONG_RANDOM); + random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; + d = gen_k (E.n, random_level); /* Compute Q. */ point_init (&Q); @@ -552,27 +562,29 @@ generate_key (ECC_secret_key *sk, unsigned int nbits, const char *name, if (g_x && g_y) { if (_gcry_mpi_ec_get_affine (g_x, g_y, &sk->E.G, ctx)) - log_fatal ("ecc generate: Failed to get affine coordinates\n"); + log_fatal ("ecgen: Failed to get affine coordinates\n"); } if (q_x && q_y) { if (_gcry_mpi_ec_get_affine (q_x, q_y, &sk->Q, ctx)) - log_fatal ("ecc generate: Failed to get affine coordinates\n"); + log_fatal ("ecgen: Failed to get affine coordinates\n"); } _gcry_mpi_ec_free (ctx); point_free (&Q); mpi_free (d); + + *r_usedcurve = E.name; curve_free (&E); - /* Now we can test our keys (this should never fail!). */ + /* Now we can test our keys (this should never fail!). */ test_keys (sk, nbits - 64); return 0; } -/**************** +/* * To verify correct skey it use a random information. * First, encrypt and decrypt this dummy value, * test if the information is recuperated. @@ -622,54 +634,56 @@ test_keys (ECC_secret_key *sk, unsigned int nbits) mpi_free (test); } -/**************** + +/* * To check the validity of the value, recalculate the correspondence * between the public value and the secret one. */ static int check_secret_key (ECC_secret_key * sk) { + int rc = 1; mpi_point_t Q; - gcry_mpi_t y_2, y2 = mpi_alloc (0); - mpi_ec_t ctx; + gcry_mpi_t y_2, y2; + mpi_ec_t ctx = NULL; + + point_init (&Q); /* ?primarity test of 'p' */ /* (...) //!! */ /* G in E(F_p) */ y_2 = gen_y_2 (sk->E.G.x, &sk->E); /* y^2=x^3+a*x+b */ + y2 = mpi_alloc (0); mpi_mulm (y2, sk->E.G.y, sk->E.G.y, sk->E.p); /* y^2=y*y */ if (mpi_cmp (y_2, y2)) { if (DBG_CIPHER) log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n"); - return (1); + goto leave; } /* G != PaI */ if (!mpi_cmp_ui (sk->E.G.z, 0)) { if (DBG_CIPHER) log_debug ("Bad check: 'G' cannot be Point at Infinity!\n"); - return (1); + goto leave; } - point_init (&Q); ctx = _gcry_mpi_ec_init (sk->E.p, sk->E.a); + _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx); if (mpi_cmp_ui (Q.z, 0)) { if (DBG_CIPHER) log_debug ("check_secret_key: E is not a curve of order n\n"); - point_free (&Q); - _gcry_mpi_ec_free (ctx); - return 1; + goto leave; } /* pubkey cannot be PaI */ if (!mpi_cmp_ui (sk->Q.z, 0)) { if (DBG_CIPHER) log_debug ("Bad check: Q can not be a Point at Infinity!\n"); - _gcry_mpi_ec_free (ctx); - return (1); + goto leave; } /* pubkey = [d]G over E */ _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx); @@ -678,12 +692,16 @@ check_secret_key (ECC_secret_key * sk) if (DBG_CIPHER) log_debug ("Bad check: There is NO correspondence between 'd' and 'Q'!\n"); - _gcry_mpi_ec_free (ctx); - return (1); + goto leave; } + rc = 0; /* Okay. */ + + leave: _gcry_mpi_ec_free (ctx); + mpi_free (y2); + mpi_free (y_2); point_free (&Q); - return 0; + return rc; } @@ -699,6 +717,9 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) mpi_point_t I; mpi_ec_t ctx; + if (DBG_CIPHER) + log_mpidump ("ecdsa sign hash ", input ); + k = NULL; dr = mpi_alloc (0); sum = mpi_alloc (0); @@ -721,7 +742,7 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) has to be recomputed. */ mpi_free (k); k = gen_k (skey->E.n, GCRY_STRONG_RANDOM); - _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx); + _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx); if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx)) { if (DBG_CIPHER) @@ -737,6 +758,12 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) mpi_mulm (s, k_1, sum, skey->E.n); /* s = k^(-1)*(hash+(d*r)) mod n */ } + if (DBG_CIPHER) + { + log_mpidump ("ecdsa sign result r ", r); + log_mpidump ("ecdsa sign result s ", s); + } + leave: _gcry_mpi_ec_free (ctx); point_free (&I); @@ -749,6 +776,7 @@ sign (gcry_mpi_t input, ECC_secret_key *skey, gcry_mpi_t r, gcry_mpi_t s) return err; } + /* * Check if R and S verifies INPUT. */ @@ -820,10 +848,10 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) { if (DBG_CIPHER) { - log_mpidump (" x", x); - log_mpidump (" y", y); - log_mpidump (" r", r); - log_mpidump (" s", s); + log_mpidump (" x", x); + log_mpidump (" y", y); + log_mpidump (" r", r); + log_mpidump (" s", s); log_debug ("ecc verify: Not verified\n"); } err = GPG_ERR_BAD_SIGNATURE; @@ -846,7 +874,7 @@ verify (gcry_mpi_t input, ECC_public_key *pkey, gcry_mpi_t r, gcry_mpi_t s) } - + /********************************************* ************** interface ****************** *********************************************/ @@ -879,18 +907,16 @@ ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p) memmove (ptr+(pbytes-n), ptr, n); memset (ptr, 0, (pbytes-n)); } - + err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG, buf, 1+2*pbytes, NULL); if (err) log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err)); gcry_free (buf); - mpi_free (x); - mpi_free (y); - return result; } + /* RESULT must have been initialized and is set on success to the point given by VALUE. */ static gcry_error_t @@ -909,7 +935,7 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) gcry_free (buf); return err; } - if (n < 1) + if (n < 1) { gcry_free (buf); return GPG_ERR_INV_OBJ; @@ -919,7 +945,7 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) gcry_free (buf); return GPG_ERR_NOT_IMPLEMENTED; /* No support for point compression. */ } - if ( ((n-1)%2) ) + if ( ((n-1)%2) ) { gcry_free (buf); return GPG_ERR_INV_OBJ; @@ -945,7 +971,7 @@ os2ec (mpi_point_t *result, gcry_mpi_t value) mpi_free (x); mpi_free (y); - + return 0; } @@ -962,10 +988,11 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, gcry_mpi_t g_x, g_y, q_x, q_y; char *curve_name = NULL; gcry_sexp_t l1; + int transient_key = 0; + const char *usedcurve = NULL; (void)algo; (void)evalue; - (void)r_extrainfo; if (genparms) { @@ -978,6 +1005,14 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, if (!curve_name) return GPG_ERR_INV_OBJ; /* No curve name or value too large. */ } + + /* Parse the optional transient-key flag. */ + l1 = gcry_sexp_find_token (genparms, "transient-key", 0); + if (l1) + { + transient_key = 1; + gcry_sexp_release (l1); + } } /* NBITS is required if no curve name has been given. */ @@ -988,28 +1023,45 @@ ecc_generate_ext (int algo, unsigned int nbits, unsigned long evalue, g_y = mpi_new (0); q_x = mpi_new (0); q_y = mpi_new (0); - ec = generate_key (&sk, nbits, curve_name, g_x, g_y, q_x, q_y); + ec = generate_key (&sk, nbits, curve_name, transient_key, g_x, g_y, q_x, q_y, + &usedcurve); gcry_free (curve_name); if (ec) return ec; + if (usedcurve) /* Fixme: No error return checking. */ + gcry_sexp_build (r_extrainfo, NULL, "(curve %s)", usedcurve); skey[0] = sk.E.p; skey[1] = sk.E.a; skey[2] = sk.E.b; - /* The function ec2os releases g_x and g_y. */ skey[3] = ec2os (g_x, g_y, sk.E.p); skey[4] = sk.E.n; - /* The function ec2os releases g_x and g_y. */ skey[5] = ec2os (q_x, q_y, sk.E.p); skey[6] = sk.d; + mpi_free (g_x); + mpi_free (g_y); + mpi_free (q_x); + mpi_free (q_y); + point_free (&sk.E.G); point_free (&sk.Q); /* Make an empty list of factors. */ *retfactors = gcry_calloc ( 1, sizeof **retfactors ); if (!*retfactors) - return gpg_err_code_from_syserror (); + return gpg_err_code_from_syserror (); /* Fixme: relase mem? */ + + if (DBG_CIPHER) + { + log_mpidump ("ecgen result p", skey[0]); + log_mpidump ("ecgen result a", skey[1]); + log_mpidump ("ecgen result b", skey[2]); + log_mpidump ("ecgen result G", skey[3]); + log_mpidump ("ecgen result n", skey[4]); + log_mpidump ("ecgen result Q", skey[5]); + log_mpidump ("ecgen result d", skey[6]); + } return 0; } @@ -1024,7 +1076,7 @@ ecc_generate (int algo, unsigned int nbits, unsigned long evalue, } -/* Return the parameters of the curve NAME. */ +/* Return the parameters of the curve NAME in an MPI array. */ static gcry_err_code_t ecc_get_param (const char *name, gcry_mpi_t *pkey) { @@ -1033,8 +1085,8 @@ ecc_get_param (const char *name, gcry_mpi_t *pkey) elliptic_curve_t E; mpi_ec_t ctx; gcry_mpi_t g_x, g_y; - - err = generate_curve (0, name, &E, &nbits); + + err = fill_in_curve (0, name, &E, &nbits); if (err) return err; @@ -1053,10 +1105,120 @@ ecc_get_param (const char *name, gcry_mpi_t *pkey) pkey[4] = E.n; pkey[5] = NULL; + mpi_free (g_x); + mpi_free (g_y); + return 0; } +/* Return the parameters of the curve NAME as an S-expression. */ +static gcry_sexp_t +ecc_get_param_sexp (const char *name) +{ + gcry_mpi_t pkey[6]; + gcry_sexp_t result; + int i; + + if (ecc_get_param (name, pkey)) + return NULL; + + if (gcry_sexp_build (&result, NULL, + "(public-key(ecc(p%m)(a%m)(b%m)(g%m)(n%m)))", + pkey[0], pkey[1], pkey[2], pkey[3], pkey[4])) + result = NULL; + + for (i=0; pkey[i]; i++) + gcry_mpi_release (pkey[i]); + + return result; +} + + +/* Return the name matching the parameters in PKEY. */ +static const char * +ecc_get_curve (gcry_mpi_t *pkey, int iterator, unsigned int *r_nbits) +{ + gpg_err_code_t err; + elliptic_curve_t E; + int idx; + gcry_mpi_t tmp; + const char *result = NULL; + + if (r_nbits) + *r_nbits = 0; + + if (!pkey) + { + idx = iterator; + if (idx >= 0 && idx < DIM (domain_parms)) + { + result = domain_parms[idx].desc; + if (r_nbits) + *r_nbits = domain_parms[idx].nbits; + } + return result; + } + + if (!pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4]) + return NULL; + + E.p = pkey[0]; + E.a = pkey[1]; + E.b = pkey[2]; + point_init (&E.G); + err = os2ec (&E.G, pkey[3]); + if (err) + { + point_free (&E.G); + return NULL; + } + E.n = pkey[4]; + + for (idx = 0; domain_parms[idx].desc; idx++) + { + tmp = scanval (domain_parms[idx].p); + if (!mpi_cmp (tmp, E.p)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].a); + if (!mpi_cmp (tmp, E.a)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].b); + if (!mpi_cmp (tmp, E.b)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].n); + if (!mpi_cmp (tmp, E.n)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].g_x); + if (!mpi_cmp (tmp, E.G.x)) + { + mpi_free (tmp); + tmp = scanval (domain_parms[idx].g_y); + if (!mpi_cmp (tmp, E.G.y)) + { + result = domain_parms[idx].desc; + if (r_nbits) + *r_nbits = domain_parms[idx].nbits; + break; + } + } + } + } + } + } + mpi_free (tmp); + } + + point_free (&E.G); + + return result; +} + + static gcry_err_code_t ecc_check_secret_key (int algo, gcry_mpi_t *skey) { @@ -1065,8 +1227,9 @@ ecc_check_secret_key (int algo, gcry_mpi_t *skey) (void)algo; + /* FIXME: This check looks a bit fishy: Now long is the array? */ if (!skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] || !skey[5] - || !skey[6] || !skey[7] || !skey[8] || !skey[9] || !skey[10]) + || !skey[6]) return GPG_ERR_BAD_MPI; sk.E.p = skey[0]; @@ -1150,6 +1313,7 @@ ecc_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) return err; } + static gcry_err_code_t ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, int (*cmp)(void *, gcry_mpi_t), void *opaquev) @@ -1193,6 +1357,221 @@ ecc_verify (int algo, gcry_mpi_t hash, gcry_mpi_t *data, gcry_mpi_t *pkey, } +/* ecdh raw is classic 2-round DH protocol published in 1976. + * + * Overview of ecc_encrypt_raw and ecc_decrypt_raw. + * + * As with any PK operation, encrypt version uses a public key and + * decrypt -- private. + * + * Symbols used below: + * G - field generator point + * d - private long-term scalar + * dG - public long-term key + * k - ephemeral scalar + * kG - ephemeral public key + * dkG - shared secret + * + * ecc_encrypt_raw description: + * input: + * data[0] : private scalar (k) + * output: + * result[0] : shared point (kdG) + * result[1] : generated ephemeral public key (kG) + * + * ecc_decrypt_raw description: + * input: + * data[0] : a point kG (ephemeral public key) + * output: + * result[0] : shared point (kdG) + */ +static gcry_err_code_t +ecc_encrypt_raw (int algo, gcry_mpi_t *resarr, gcry_mpi_t k, + gcry_mpi_t *pkey, int flags) +{ + ECC_public_key pk; + mpi_ec_t ctx; + gcry_mpi_t result[2]; + int err; + + (void)algo; + (void)flags; + + if (!k + || !pkey[0] || !pkey[1] || !pkey[2] || !pkey[3] || !pkey[4] || !pkey[5]) + return GPG_ERR_BAD_MPI; + + pk.E.p = pkey[0]; + pk.E.a = pkey[1]; + pk.E.b = pkey[2]; + point_init (&pk.E.G); + err = os2ec (&pk.E.G, pkey[3]); + if (err) + { + point_free (&pk.E.G); + return err; + } + pk.E.n = pkey[4]; + point_init (&pk.Q); + err = os2ec (&pk.Q, pkey[5]); + if (err) + { + point_free (&pk.E.G); + point_free (&pk.Q); + return err; + } + + ctx = _gcry_mpi_ec_init (pk.E.p, pk.E.a); + + /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ + { + mpi_point_t R; /* Result that we return. */ + gcry_mpi_t x, y; + + x = mpi_new (0); + y = mpi_new (0); + + point_init (&R); + + /* R = kQ <=> R = kdG */ + _gcry_mpi_ec_mul_point (&R, k, &pk.Q, ctx); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates for kdG\n"); + + result[0] = ec2os (x, y, pk.E.p); + + /* R = kG */ + _gcry_mpi_ec_mul_point (&R, k, &pk.E.G, ctx); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates for kG\n"); + + result[1] = ec2os (x, y, pk.E.p); + + mpi_free (x); + mpi_free (y); + + point_free (&R); + } + + _gcry_mpi_ec_free (ctx); + point_free (&pk.E.G); + point_free (&pk.Q); + + if (!result[0] || !result[1]) + { + mpi_free (result[0]); + mpi_free (result[1]); + return GPG_ERR_ENOMEM; + } + + /* Success. */ + resarr[0] = result[0]; + resarr[1] = result[1]; + + return 0; +} + +/* input: + * data[0] : a point kG (ephemeral public key) + * output: + * resaddr[0] : shared point kdG + * + * see ecc_encrypt_raw for details. + */ +static gcry_err_code_t +ecc_decrypt_raw (int algo, gcry_mpi_t *result, gcry_mpi_t *data, + gcry_mpi_t *skey, int flags) +{ + ECC_secret_key sk; + mpi_point_t R; /* Result that we return. */ + mpi_point_t kG; + mpi_ec_t ctx; + gcry_mpi_t r; + int err; + + (void)algo; + (void)flags; + + *result = NULL; + + if (!data || !data[0] + || !skey[0] || !skey[1] || !skey[2] || !skey[3] || !skey[4] + || !skey[5] || !skey[6] ) + return GPG_ERR_BAD_MPI; + + point_init (&kG); + err = os2ec (&kG, data[0]); + if (err) + { + point_free (&kG); + return err; + } + + + sk.E.p = skey[0]; + sk.E.a = skey[1]; + sk.E.b = skey[2]; + point_init (&sk.E.G); + err = os2ec (&sk.E.G, skey[3]); + if (err) + { + point_free (&kG); + point_free (&sk.E.G); + return err; + } + sk.E.n = skey[4]; + point_init (&sk.Q); + err = os2ec (&sk.Q, skey[5]); + if (err) + { + point_free (&kG); + point_free (&sk.E.G); + point_free (&sk.Q); + return err; + } + sk.d = skey[6]; + + ctx = _gcry_mpi_ec_init (sk.E.p, sk.E.a); + + /* R = dkG */ + point_init (&R); + _gcry_mpi_ec_mul_point (&R, sk.d, &kG, ctx); + + point_free (&kG); + + /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so: */ + { + gcry_mpi_t x, y; + + x = mpi_new (0); + y = mpi_new (0); + + if (_gcry_mpi_ec_get_affine (x, y, &R, ctx)) + log_fatal ("ecdh: Failed to get affine coordinates\n"); + + r = ec2os (x, y, sk.E.p); + mpi_free (x); + mpi_free (y); + } + + point_free (&R); + _gcry_mpi_ec_free (ctx); + point_free (&kG); + point_free (&sk.E.G); + point_free (&sk.Q); + + if (!r) + return GPG_ERR_ENOMEM; + + /* Success. */ + + *result = r; + + return 0; +} + static unsigned int ecc_get_nbits (int algo, gcry_mpi_t *pkey) @@ -1203,23 +1582,23 @@ ecc_get_nbits (int algo, gcry_mpi_t *pkey) } - /* See rsa.c for a description of this function. */ static gpg_err_code_t compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) { - static const char names[] = "pabgnq"; +#define N_COMPONENTS 6 + static const char names[N_COMPONENTS+1] = "pabgnq"; gpg_err_code_t ec = 0; gcry_sexp_t l1; - gcry_mpi_t values[6]; + gcry_mpi_t values[N_COMPONENTS]; int idx; /* Clear the values for easier error cleanup. */ - for (idx=0; idx < 6; idx++) + for (idx=0; idx < N_COMPONENTS; idx++) values[idx] = NULL; - - /* Fill values with all available parameters. */ - for (idx=0; idx < 6; idx++) + + /* Fill values with all provided parameters. */ + for (idx=0; idx < N_COMPONENTS; idx++) { l1 = gcry_sexp_find_token (keyparam, names+idx, 1); if (l1) @@ -1233,19 +1612,20 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } } } - + /* Check whether a curve parameter is available and use that to fill in missing values. */ l1 = gcry_sexp_find_token (keyparam, "curve", 5); if (l1) { char *curve; - gcry_mpi_t tmpvalues[6]; - - for (idx = 0; idx < 6; idx++) + gcry_mpi_t tmpvalues[N_COMPONENTS]; + + for (idx = 0; idx < N_COMPONENTS; idx++) tmpvalues[idx] = NULL; curve = _gcry_sexp_nth_string (l1, 1); + gcry_sexp_release (l1); if (!curve) { ec = GPG_ERR_INV_OBJ; /* Name missing or out of core. */ @@ -1256,7 +1636,7 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) if (ec) goto leave; - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) { if (!values[idx]) values[idx] = tmpvalues[idx]; @@ -1266,9 +1646,9 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } /* Check that all parameters are known and normalize all MPIs (that - should not be required but we use an internal fucntion later and + should not be required but we use an internal function later and thus we better make 100% sure that they are normalized). */ - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) if (!values[idx]) { ec = GPG_ERR_NO_OBJ; @@ -1276,14 +1656,14 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } else _gcry_mpi_normalize (values[idx]); - + /* Hash them all. */ - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) { char buf[30]; unsigned char *rawmpi; unsigned int rawmpilen; - + rawmpi = _gcry_mpi_get_buffer (values[idx], &rawmpilen, NULL); if (!rawmpi) { @@ -1298,17 +1678,18 @@ compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam) } leave: - for (idx = 0; idx < 6; idx++) + for (idx = 0; idx < N_COMPONENTS; idx++) _gcry_mpi_release (values[idx]); - + return ec; +#undef N_COMPONENTS } -/* +/* Self-test section. */ @@ -1318,7 +1699,7 @@ selftests_ecdsa (selftest_report_func_t report) { const char *what; const char *errtxt; - + what = "low-level"; errtxt = NULL; /*selftest ();*/ if (errtxt) @@ -1351,7 +1732,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) default: ec = GPG_ERR_PUBKEY_ALGO; break; - + } return ec; } @@ -1365,6 +1746,12 @@ static const char *ecdsa_names[] = "ecc", NULL, }; +static const char *ecdh_names[] = + { + "ecdh", + "ecc", + NULL, + }; gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = { @@ -1380,11 +1767,27 @@ gcry_pk_spec_t _gcry_pubkey_spec_ecdsa = ecc_get_nbits }; -pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = +gcry_pk_spec_t _gcry_pubkey_spec_ecdh = + { + "ECDH", ecdh_names, + "pabgnq", "pabgnqd", "se", "", "pabgnq", + GCRY_PK_USAGE_ENCR, + ecc_generate, + ecc_check_secret_key, + ecc_encrypt_raw, + ecc_decrypt_raw, + NULL, + NULL, + ecc_get_nbits + }; + + +pk_extra_spec_t _gcry_pubkey_extraspec_ecdsa = { run_selftests, ecc_generate_ext, compute_keygrip, - ecc_get_param + ecc_get_param, + ecc_get_curve, + ecc_get_param_sexp }; - diff --git a/grub-core/lib/libgcrypt/cipher/elgamal.c b/grub-core/lib/libgcrypt/cipher/elgamal.c index 0b0c07cb4..ce4be8524 100644 --- a/grub-core/lib/libgcrypt/cipher/elgamal.c +++ b/grub-core/lib/libgcrypt/cipher/elgamal.c @@ -115,7 +115,7 @@ wiener_map( unsigned int n ) }; int i; - for(i=0; t[i].p_n; i++ ) + for(i=0; t[i].p_n; i++ ) { if( n <= t[i].p_n ) return t[i].q_n; @@ -158,7 +158,7 @@ test_keys ( ELG_secret_key *sk, unsigned int nbits, int nodie ) log_fatal ("Elgamal test key for %s %s failed\n", (failed & 1)? "encrypt+decrypt":"", (failed & 2)? "sign+verify":""); - if (failed && DBG_CIPHER) + if (failed && DBG_CIPHER) log_debug ("Elgamal test key for %s %s failed\n", (failed & 1)? "encrypt+decrypt":"", (failed & 2)? "sign+verify":""); @@ -199,15 +199,15 @@ gen_k( gcry_mpi_t p, int small_k ) if( DBG_CIPHER ) log_debug("choosing a random k "); mpi_sub_ui( p_1, p, 1); - for(;;) + for(;;) { - if( !rndbuf || nbits < 32 ) + if( !rndbuf || nbits < 32 ) { gcry_free(rndbuf); rndbuf = gcry_random_bytes_secure( nbytes, GCRY_STRONG_RANDOM ); } else - { + { /* Change only some of the higher bits. We could improve this by directly requesting more memory at the first call to get_random_bytes() and use this the here maybe it is @@ -218,7 +218,7 @@ gen_k( gcry_mpi_t p, int small_k ) gcry_free(pp); } _gcry_mpi_set_buffer( k, rndbuf, nbytes, 0 ); - + for(;;) { if( !(mpi_cmp( k, p_1 ) < 0) ) /* check: k < (p-1) */ @@ -294,7 +294,7 @@ generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors ) if( DBG_CIPHER ) log_debug("choosing a random x of size %u", xbits ); rndbuf = NULL; - do + do { if( DBG_CIPHER ) progress('.'); @@ -314,21 +314,21 @@ generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors ) gcry_free(r); } } - else + else { rndbuf = gcry_random_bytes_secure( (xbits+7)/8, GCRY_VERY_STRONG_RANDOM ); } _gcry_mpi_set_buffer( x, rndbuf, (xbits+7)/8, 0 ); mpi_clear_highbit( x, xbits+1 ); - } + } while( !( mpi_cmp_ui( x, 0 )>0 && mpi_cmp( x, p_min1 )<0 ) ); gcry_free(rndbuf); y = gcry_mpi_new (nbits); gcry_mpi_powm( y, g, x, p ); - if( DBG_CIPHER ) + if( DBG_CIPHER ) { progress('\n'); log_mpidump("elg p= ", p ); @@ -354,7 +354,7 @@ generate ( ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t **ret_factors ) value for the secret key but the one given as X. This is useful to implement a passphrase based decryption for a public key based encryption. It has appliactions in backup systems. - + Returns: A structure filled with all needed values and an array with n-1 factors of (p-1). */ static gcry_err_code_t @@ -399,7 +399,7 @@ generate_using_x (ELG_secret_key *sk, unsigned int nbits, gcry_mpi_t x, y = gcry_mpi_new (nbits); gcry_mpi_powm ( y, g, x, p ); - if ( DBG_CIPHER ) + if ( DBG_CIPHER ) { progress ('\n'); log_mpidump ("elg p= ", p ); @@ -493,7 +493,7 @@ decrypt(gcry_mpi_t output, gcry_mpi_t a, gcry_mpi_t b, ELG_secret_key *skey ) mpi_invm( t1, t1, skey->p ); mpi_mulm( output, b, t1, skey->p ); #if 0 - if( DBG_CIPHER ) + if( DBG_CIPHER ) { log_mpidump("elg decrypted x= ", skey->x); log_mpidump("elg decrypted p= ", skey->p); @@ -533,7 +533,7 @@ sign(gcry_mpi_t a, gcry_mpi_t b, gcry_mpi_t input, ELG_secret_key *skey ) mpi_mulm(b, t, inv, p_1 ); #if 0 - if( DBG_CIPHER ) + if( DBG_CIPHER ) { log_mpidump("elg sign p= ", skey->p); log_mpidump("elg sign g= ", skey->g); @@ -652,7 +652,7 @@ elg_generate_ext (int algo, unsigned int nbits, unsigned long evalue, skey[1] = sk.g; skey[2] = sk.y; skey[3] = sk.x; - + return ec; } @@ -671,7 +671,7 @@ elg_generate (int algo, unsigned int nbits, unsigned long evalue, skey[1] = sk.g; skey[2] = sk.y; skey[3] = sk.x; - + return GPG_ERR_NO_ERROR; } @@ -692,7 +692,7 @@ elg_check_secret_key (int algo, gcry_mpi_t *skey) sk.g = skey[1]; sk.y = skey[2]; sk.x = skey[3]; - + if (! check_secret_key (&sk)) err = GPG_ERR_BAD_SECKEY; } @@ -773,7 +773,7 @@ elg_sign (int algo, gcry_mpi_t *resarr, gcry_mpi_t data, gcry_mpi_t *skey) resarr[1] = mpi_alloc (mpi_get_nlimbs (sk.p)); sign (resarr[0], resarr[1], data, &sk); } - + return err; } @@ -837,10 +837,9 @@ gcry_pk_spec_t _gcry_pubkey_spec_elg = elg_get_nbits }; -pk_extra_spec_t _gcry_pubkey_extraspec_elg = +pk_extra_spec_t _gcry_pubkey_extraspec_elg = { NULL, elg_generate_ext, NULL }; - diff --git a/grub-core/lib/libgcrypt/cipher/hash-common.c b/grub-core/lib/libgcrypt/cipher/hash-common.c index 656e180e2..8c413bcba 100644 --- a/grub-core/lib/libgcrypt/cipher/hash-common.c +++ b/grub-core/lib/libgcrypt/cipher/hash-common.c @@ -21,7 +21,7 @@ #include #include #include -#ifdef HAVE_STDINT_H +#ifdef HAVE_STDINT_H # include #endif @@ -35,10 +35,10 @@ describing the error. DATAMODE controls what will be hashed according to this table: - + 0 - Hash the supplied DATA of DATALEN. 1 - Hash one million times a 'a'. DATA and DATALEN are ignored. - + */ const char * _gcry_hash_selftest_check_one (int algo, @@ -49,14 +49,14 @@ _gcry_hash_selftest_check_one (int algo, gcry_error_t err = 0; gcry_md_hd_t hd; unsigned char *digest; - + if (_gcry_md_get_algo_dlen (algo) != expectlen) return "digest size does not match expected size"; - + err = _gcry_md_open (&hd, algo, 0); if (err) return "gcry_md_open failed"; - + switch (datamode) { case 0: @@ -64,7 +64,7 @@ _gcry_hash_selftest_check_one (int algo, break; case 1: /* Hash one million times an "a". */ - { + { char aaa[1000]; int i; @@ -82,7 +82,7 @@ _gcry_hash_selftest_check_one (int algo, if (!result) { digest = _gcry_md_read (hd, algo); - + if ( memcmp (digest, expect, expectlen) ) result = "digest mismatch"; } @@ -91,4 +91,3 @@ _gcry_hash_selftest_check_one (int algo, return result; } - diff --git a/grub-core/lib/libgcrypt/cipher/hash-common.h b/grub-core/lib/libgcrypt/cipher/hash-common.h index 9c4e33359..fdebef42a 100644 --- a/grub-core/lib/libgcrypt/cipher/hash-common.h +++ b/grub-core/lib/libgcrypt/cipher/hash-common.h @@ -21,11 +21,11 @@ #define GCRY_HASH_COMMON_H -const char * _gcry_hash_selftest_check_one -/**/ (int algo, +const char * _gcry_hash_selftest_check_one +/**/ (int algo, int datamode, const void *data, size_t datalen, const void *expect, size_t expectlen); - + diff --git a/grub-core/lib/libgcrypt/cipher/hmac-tests.c b/grub-core/lib/libgcrypt/cipher/hmac-tests.c index 56c9b203c..a32ece75d 100644 --- a/grub-core/lib/libgcrypt/cipher/hmac-tests.c +++ b/grub-core/lib/libgcrypt/cipher/hmac-tests.c @@ -17,7 +17,7 @@ * License along with this program; if not, see . */ -/* +/* Although algorithm self-tests are usually implemented in the module implementing the algorithm, the case for HMAC is different because HMAC is implemnetd on a higher level using a special feature of the @@ -33,7 +33,7 @@ #include #include #include -#ifdef HAVE_STDINT_H +#ifdef HAVE_STDINT_H # include #endif @@ -47,7 +47,7 @@ succdess or a string describing the failure. */ static const char * check_one (int algo, - const void *data, size_t datalen, + const void *data, size_t datalen, const void *key, size_t keylen, const void *expect, size_t expectlen) { @@ -88,7 +88,7 @@ check_one (int algo, return "does not match"; } _gcry_md_close (hd); - return NULL; + return NULL; } @@ -123,7 +123,7 @@ selftests_sha1 (int extended, selftest_report_func_t report) "\xa4\x58\x30\x73\x7d\x5c\xc6\xc7\x5d\x24", 20); if (errtxt) goto failed; - + what = "FIPS-198a, A.3"; for (i=0, j=0x50; i < 100; i++) key[i] = j++; @@ -134,7 +134,7 @@ selftests_sha1 (int extended, selftest_report_func_t report) "\x5c\xaf\x7c\xb0\x92\xec\xf8\xd1\xa3\xaa", 20 ); if (errtxt) goto failed; - + what = "FIPS-198a, A.4"; for (i=0, j=0x70; i < 49; i++) key[i] = j++; @@ -160,7 +160,7 @@ selftests_sha1 (int extended, selftest_report_func_t report) static gpg_err_code_t selftests_sha224 (int extended, selftest_report_func_t report) { - static struct + static struct { const char * const desc; const char * const data; @@ -169,7 +169,7 @@ selftests_sha224 (int extended, selftest_report_func_t report) } tv[] = { { "data-28 key-4", - "what do ya want for nothing?", + "what do ya want for nothing?", "Jefe", { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f, @@ -248,7 +248,7 @@ selftests_sha224 (int extended, selftest_report_func_t report) const char *what; const char *errtxt; int tvidx; - + for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; @@ -274,7 +274,7 @@ selftests_sha224 (int extended, selftest_report_func_t report) static gpg_err_code_t selftests_sha256 (int extended, selftest_report_func_t report) { - static struct + static struct { const char * const desc; const char * const data; @@ -283,7 +283,7 @@ selftests_sha256 (int extended, selftest_report_func_t report) } tv[] = { { "data-28 key-4", - "what do ya want for nothing?", + "what do ya want for nothing?", "Jefe", { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, @@ -362,7 +362,7 @@ selftests_sha256 (int extended, selftest_report_func_t report) const char *what; const char *errtxt; int tvidx; - + for (tvidx=0; tv[tvidx].desc; tvidx++) { hmac256_context_t hmachd; @@ -416,7 +416,7 @@ selftests_sha256 (int extended, selftest_report_func_t report) static gpg_err_code_t selftests_sha384 (int extended, selftest_report_func_t report) { - static struct + static struct { const char * const desc; const char * const data; @@ -425,7 +425,7 @@ selftests_sha384 (int extended, selftest_report_func_t report) } tv[] = { { "data-28 key-4", - "what do ya want for nothing?", + "what do ya want for nothing?", "Jefe", { 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b, @@ -516,7 +516,7 @@ selftests_sha384 (int extended, selftest_report_func_t report) const char *what; const char *errtxt; int tvidx; - + for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; @@ -542,7 +542,7 @@ selftests_sha384 (int extended, selftest_report_func_t report) static gpg_err_code_t selftests_sha512 (int extended, selftest_report_func_t report) { - static struct + static struct { const char * const desc; const char * const data; @@ -551,7 +551,7 @@ selftests_sha512 (int extended, selftest_report_func_t report) } tv[] = { { "data-28 key-4", - "what do ya want for nothing?", + "what do ya want for nothing?", "Jefe", { 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, @@ -654,7 +654,7 @@ selftests_sha512 (int extended, selftest_report_func_t report) const char *what; const char *errtxt; int tvidx; - + for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; diff --git a/grub-core/lib/libgcrypt/cipher/idea.c b/grub-core/lib/libgcrypt/cipher/idea.c new file mode 100644 index 000000000..3c5578f95 --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/idea.c @@ -0,0 +1,378 @@ +/* idea.c - IDEA function + * Copyright 1997, 1998, 1999, 2001 Werner Koch (dd9jn) + * Copyright 2013 g10 Code GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * WERNER KOCH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of Werner Koch shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from Werner Koch. + * + * Patents on IDEA have expired: + * Europe: EP0482154 on 2011-05-16, + * Japan: JP3225440 on 2011-05-16, + * U.S.: 5,214,703 on 2012-01-07. + */ + +/* + * Please see http://www.noepatents.org/ to learn why software patents + * are bad for society and what you can do to fight them. + * + * The code herein is based on the one from: + * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. + * ISBN 0-471-11709-9. + */ + + +#include +#include +#include +#include +#include + +#include "types.h" /* for byte and u32 typedefs */ +#include "g10lib.h" +#include "cipher.h" + + +#define IDEA_KEYSIZE 16 +#define IDEA_BLOCKSIZE 8 +#define IDEA_ROUNDS 8 +#define IDEA_KEYLEN (6*IDEA_ROUNDS+4) + +typedef struct { + u16 ek[IDEA_KEYLEN]; + u16 dk[IDEA_KEYLEN]; + int have_dk; +} IDEA_context; + +static const char *selftest(void); + + +static u16 +mul_inv( u16 x ) +{ + u16 t0, t1; + u16 q, y; + + if( x < 2 ) + return x; + t1 = 0x10001UL / x; + y = 0x10001UL % x; + if( y == 1 ) + return (1-t1) & 0xffff; + + t0 = 1; + do { + q = x / y; + x = x % y; + t0 += q * t1; + if( x == 1 ) + return t0; + q = y / x; + y = y % x; + t1 += q * t0; + } while( y != 1 ); + return (1-t1) & 0xffff; +} + + + +static void +expand_key( const byte *userkey, u16 *ek ) +{ + int i,j; + + for(j=0; j < 8; j++ ) { + ek[j] = (*userkey << 8) + userkey[1]; + userkey += 2; + } + for(i=0; j < IDEA_KEYLEN; j++ ) { + i++; + ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7; + ek += i & 8; + i &= 7; + } +} + + +static void +invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] ) +{ + int i; + u16 t1, t2, t3; + u16 temp[IDEA_KEYLEN]; + u16 *p = temp + IDEA_KEYLEN; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t3; + *--p = t2; + *--p = t1; + + for(i=0; i < IDEA_ROUNDS-1; i++ ) { + t1 = *ek++; + *--p = *ek++; + *--p = t1; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t2; + *--p = t3; + *--p = t1; + } + t1 = *ek++; + *--p = *ek++; + *--p = t1; + + t1 = mul_inv( *ek++ ); + t2 = -*ek++; + t3 = -*ek++; + *--p = mul_inv( *ek++ ); + *--p = t3; + *--p = t2; + *--p = t1; + memcpy(dk, temp, sizeof(temp) ); + memset(temp, 0, sizeof(temp) ); /* burn temp */ +} + + +static void +cipher( byte *outbuf, const byte *inbuf, u16 *key ) +{ + u16 s2, s3; + u16 in[4]; + int r = IDEA_ROUNDS; +#define x1 (in[0]) +#define x2 (in[1]) +#define x3 (in[2]) +#define x4 (in[3]) +#define MUL(x,y) \ + do {u16 _t16; u32 _t32; \ + if( (_t16 = (y)) ) { \ + if( (x = (x)&0xffff) ) { \ + _t32 = (u32)x * _t16; \ + x = _t32 & 0xffff; \ + _t16 = _t32 >> 16; \ + x = ((x)-_t16) + (x<_t16?1:0); \ + } \ + else { \ + x = 1 - _t16; \ + } \ + } \ + else { \ + x = 1 - x; \ + } \ + } while(0) + + memcpy (in, inbuf, sizeof in); +#ifndef WORDS_BIGENDIAN + x1 = (x1>>8) | (x1<<8); + x2 = (x2>>8) | (x2<<8); + x3 = (x3>>8) | (x3<<8); + x4 = (x4>>8) | (x4<<8); +#endif + do { + MUL(x1, *key++); + x2 += *key++; + x3 += *key++; + MUL(x4, *key++ ); + + s3 = x3; + x3 ^= x1; + MUL(x3, *key++); + s2 = x2; + x2 ^=x4; + x2 += x3; + MUL(x2, *key++); + x3 += x2; + + x1 ^= x2; + x4 ^= x3; + + x2 ^= s3; + x3 ^= s2; + } while( --r ); + MUL(x1, *key++); + x3 += *key++; + x2 += *key++; + MUL(x4, *key); + +#ifndef WORDS_BIGENDIAN + x1 = (x1>>8) | (x1<<8); + x2 = (x2>>8) | (x2<<8); + x3 = (x3>>8) | (x3<<8); + x4 = (x4>>8) | (x4<<8); +#endif + memcpy (outbuf+0, &x1, 2); + memcpy (outbuf+2, &x3, 2); + memcpy (outbuf+4, &x2, 2); + memcpy (outbuf+6, &x4, 2); +#undef MUL +#undef x1 +#undef x2 +#undef x3 +#undef x4 +} + + +static int +do_setkey( IDEA_context *c, const byte *key, unsigned int keylen ) +{ + static int initialized = 0; + static const char *selftest_failed = 0; + + if( !initialized ) { + initialized = 1; + selftest_failed = selftest(); + if( selftest_failed ) + log_error( "%s\n", selftest_failed ); + } + if( selftest_failed ) + return GPG_ERR_SELFTEST_FAILED; + + assert(keylen == 16); + c->have_dk = 0; + expand_key( key, c->ek ); + invert_key( c->ek, c->dk ); + return 0; +} + +static gcry_err_code_t +idea_setkey (void *context, const byte *key, unsigned int keylen) +{ + IDEA_context *ctx = context; + int rc = do_setkey (ctx, key, keylen); + _gcry_burn_stack (23+6*sizeof(void*)); + return rc; +} + +static void +encrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) +{ + cipher( outbuf, inbuf, c->ek ); +} + +static void +idea_encrypt (void *context, byte *out, const byte *in) +{ + IDEA_context *ctx = context; + encrypt_block (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + +static void +decrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) +{ + if( !c->have_dk ) { + c->have_dk = 1; + invert_key( c->ek, c->dk ); + } + cipher( outbuf, inbuf, c->dk ); +} + +static void +idea_decrypt (void *context, byte *out, const byte *in) +{ + IDEA_context *ctx = context; + decrypt_block (ctx, out, in); + _gcry_burn_stack (24+3*sizeof (void*)); +} + + +static const char * +selftest( void ) +{ +static struct { + byte key[16]; + byte plain[8]; + byte cipher[8]; +} test_vectors[] = { + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 }, + { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x54, 0x0E, 0x5F, 0xEA, 0x18, 0xC2, 0xF8, 0xB1 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x00, 0x19, 0x32, 0x4B, 0x64, 0x7D, 0x96, 0xAF }, + { 0x9F, 0x0A, 0x0A, 0xB6, 0xE1, 0x0C, 0xED, 0x78 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0xF5, 0x20, 0x2D, 0x5B, 0x9C, 0x67, 0x1B, 0x08 }, + { 0xCF, 0x18, 0xFD, 0x73, 0x55, 0xE2, 0xC5, 0xC5 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0xFA, 0xE6, 0xD2, 0xBE, 0xAA, 0x96, 0x82, 0x6E }, + { 0x85, 0xDF, 0x52, 0x00, 0x56, 0x08, 0x19, 0x3D } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x46, 0x50 }, + { 0x2F, 0x7D, 0xE7, 0x50, 0x21, 0x2F, 0xB7, 0x34 } }, + { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, + 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, + { 0x05, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x23, 0x28 }, + { 0x7B, 0x73, 0x14, 0x92, 0x5D, 0xE5, 0x9C, 0x09 } }, + { { 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x14, + 0x00, 0x19, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x28 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x3E, 0xC0, 0x47, 0x80, 0xBE, 0xFF, 0x6E, 0x20 } }, + { { 0x3A, 0x98, 0x4E, 0x20, 0x00, 0x19, 0x5D, 0xB3, + 0x2E, 0xE5, 0x01, 0xC8, 0xC4, 0x7C, 0xEA, 0x60 }, + { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, + { 0x97, 0xBC, 0xD8, 0x20, 0x07, 0x80, 0xDA, 0x86 } }, + { { 0x00, 0x64, 0x00, 0xC8, 0x01, 0x2C, 0x01, 0x90, + 0x01, 0xF4, 0x02, 0x58, 0x02, 0xBC, 0x03, 0x20 }, + { 0x05, 0x32, 0x0A, 0x64, 0x14, 0xC8, 0x19, 0xFA }, + { 0x65, 0xBE, 0x87, 0xE7, 0xA2, 0x53, 0x8A, 0xED } }, + { { 0x9D, 0x40, 0x75, 0xC1, 0x03, 0xBC, 0x32, 0x2A, + 0xFB, 0x03, 0xE7, 0xBE, 0x6A, 0xB3, 0x00, 0x06 }, + { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, + { 0xF5, 0xDB, 0x1A, 0xC4, 0x5E, 0x5E, 0xF9, 0xF9 } } +}; + IDEA_context c; + byte buffer[8]; + int i; + + for(i=0; i < DIM(test_vectors); i++ ) { + do_setkey( &c, test_vectors[i].key, 16 ); + encrypt_block( &c, buffer, test_vectors[i].plain ); + if( memcmp( buffer, test_vectors[i].cipher, 8 ) ) + return "IDEA test encryption failed."; + decrypt_block( &c, buffer, test_vectors[i].cipher ); + if( memcmp( buffer, test_vectors[i].plain, 8 ) ) + return "IDEA test decryption failed."; + } + + return NULL; +} + + +gcry_cipher_spec_t _gcry_cipher_spec_idea = +{ + "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128, + sizeof (IDEA_context), + idea_setkey, idea_encrypt, idea_decrypt +}; diff --git a/grub-core/lib/libgcrypt/cipher/kdf.c b/grub-core/lib/libgcrypt/cipher/kdf.c new file mode 100644 index 000000000..46e8550df --- /dev/null +++ b/grub-core/lib/libgcrypt/cipher/kdf.c @@ -0,0 +1,278 @@ +/* kdf.c - Key Derivation Functions + * Copyright (C) 1998, 2011 Free Software Foundation, Inc. + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "cipher.h" +#include "ath.h" + + +/* Transform a passphrase into a suitable key of length KEYSIZE and + store this key in the caller provided buffer KEYBUFFER. The caller + must provide an HASHALGO, a valid ALGO and depending on that algo a + SALT of 8 bytes and the number of ITERATIONS. Code taken from + gnupg/agent/protect.c:hash_passphrase. */ +gpg_err_code_t +openpgp_s2k (const void *passphrase, size_t passphraselen, + int algo, int hashalgo, + const void *salt, size_t saltlen, + unsigned long iterations, + size_t keysize, void *keybuffer) +{ + gpg_err_code_t ec; + gcry_md_hd_t md; + char *key = keybuffer; + int pass, i; + int used = 0; + int secmode; + + if ((algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K) + && (!salt || saltlen != 8)) + return GPG_ERR_INV_VALUE; + + secmode = gcry_is_secure (passphrase) || gcry_is_secure (keybuffer); + + ec = gpg_err_code (gcry_md_open (&md, hashalgo, + secmode? GCRY_MD_FLAG_SECURE : 0)); + if (ec) + return ec; + + for (pass=0; used < keysize; pass++) + { + if (pass) + { + gcry_md_reset (md); + for (i=0; i < pass; i++) /* Preset the hash context. */ + gcry_md_putc (md, 0); + } + + if (algo == GCRY_KDF_SALTED_S2K || algo == GCRY_KDF_ITERSALTED_S2K) + { + int len2 = passphraselen + 8; + unsigned long count = len2; + + if (algo == GCRY_KDF_ITERSALTED_S2K) + { + count = iterations; + if (count < len2) + count = len2; + } + + while (count > len2) + { + gcry_md_write (md, salt, saltlen); + gcry_md_write (md, passphrase, passphraselen); + count -= len2; + } + if (count < saltlen) + gcry_md_write (md, salt, count); + else + { + gcry_md_write (md, salt, saltlen); + count -= saltlen; + gcry_md_write (md, passphrase, count); + } + } + else + gcry_md_write (md, passphrase, passphraselen); + + gcry_md_final (md); + i = gcry_md_get_algo_dlen (hashalgo); + if (i > keysize - used) + i = keysize - used; + memcpy (key+used, gcry_md_read (md, hashalgo), i); + used += i; + } + gcry_md_close (md); + return 0; +} + + +/* Transform a passphrase into a suitable key of length KEYSIZE and + store this key in the caller provided buffer KEYBUFFER. The caller + must provide PRFALGO which indicates the pseudorandom function to + use: This shall be the algorithms id of a hash algorithm; it is + used in HMAC mode. SALT is a salt of length SALTLEN and ITERATIONS + gives the number of iterations. */ +gpg_err_code_t +pkdf2 (const void *passphrase, size_t passphraselen, + int hashalgo, + const void *salt, size_t saltlen, + unsigned long iterations, + size_t keysize, void *keybuffer) +{ + gpg_err_code_t ec; + gcry_md_hd_t md; + int secmode; + unsigned int dklen = keysize; + char *dk = keybuffer; + unsigned int hlen; /* Output length of the digest function. */ + unsigned int l; /* Rounded up number of blocks. */ + unsigned int r; /* Number of octets in the last block. */ + char *sbuf; /* Malloced buffer to concatenate salt and iter + as well as space to hold TBUF and UBUF. */ + char *tbuf; /* Buffer for T; ptr into SBUF, size is HLEN. */ + char *ubuf; /* Buffer for U; ptr into SBUF, size is HLEN. */ + unsigned int lidx; /* Current block number. */ + unsigned long iter; /* Current iteration number. */ + unsigned int i; + + if (!salt || !saltlen || !iterations || !dklen) + return GPG_ERR_INV_VALUE; + + hlen = gcry_md_get_algo_dlen (hashalgo); + if (!hlen) + return GPG_ERR_DIGEST_ALGO; + + secmode = gcry_is_secure (passphrase) || gcry_is_secure (keybuffer); + + /* We ignore step 1 from pksc5v2.1 which demands a check that dklen + is not larger that 0xffffffff * hlen. */ + + /* Step 2 */ + l = ((dklen - 1)/ hlen) + 1; + r = dklen - (l - 1) * hlen; + + /* Setup buffers and prepare a hash context. */ + sbuf = (secmode + ? gcry_malloc_secure (saltlen + 4 + hlen + hlen) + : gcry_malloc (saltlen + 4 + hlen + hlen)); + if (!sbuf) + return gpg_err_code_from_syserror (); + tbuf = sbuf + saltlen + 4; + ubuf = tbuf + hlen; + + ec = gpg_err_code (gcry_md_open (&md, hashalgo, + (GCRY_MD_FLAG_HMAC + | (secmode?GCRY_MD_FLAG_SECURE:0)))); + if (ec) + { + gcry_free (sbuf); + return ec; + } + + /* Step 3 and 4. */ + memcpy (sbuf, salt, saltlen); + for (lidx = 1; lidx <= l; lidx++) + { + for (iter = 0; iter < iterations; iter++) + { + ec = gpg_err_code (gcry_md_setkey (md, passphrase, passphraselen)); + if (ec) + { + gcry_md_close (md); + gcry_free (sbuf); + return ec; + } + if (!iter) /* Compute U_1: */ + { + sbuf[saltlen] = (lidx >> 24); + sbuf[saltlen + 1] = (lidx >> 16); + sbuf[saltlen + 2] = (lidx >> 8); + sbuf[saltlen + 3] = lidx; + gcry_md_write (md, sbuf, saltlen + 4); + memcpy (ubuf, gcry_md_read (md, 0), hlen); + memcpy (tbuf, ubuf, hlen); + } + else /* Compute U_(2..c): */ + { + gcry_md_write (md, ubuf, hlen); + memcpy (ubuf, gcry_md_read (md, 0), hlen); + for (i=0; i < hlen; i++) + tbuf[i] ^= ubuf[i]; + } + } + if (lidx == l) /* Last block. */ + memcpy (dk, tbuf, r); + else + { + memcpy (dk, tbuf, hlen); + dk += hlen; + } + } + + gcry_md_close (md); + gcry_free (sbuf); + return 0; +} + + +/* Derive a key from a passphrase. KEYSIZE gives the requested size + of the keys in octets. KEYBUFFER is a caller provided buffer + filled on success with the derived key. The input passphrase is + taken from (PASSPHRASE,PASSPHRASELEN) which is an arbitrary memory + buffer. ALGO specifies the KDF algorithm to use; these are the + constants GCRY_KDF_*. SUBALGO specifies an algorithm used + internally by the KDF algorithms; this is usually a hash algorithm + but certain KDF algorithm may use it differently. {SALT,SALTLEN} + is a salt as needed by most KDF algorithms. ITERATIONS is a + positive integer parameter to most KDFs. 0 is returned on success, + or an error code on failure. */ +gpg_error_t +gcry_kdf_derive (const void *passphrase, size_t passphraselen, + int algo, int subalgo, + const void *salt, size_t saltlen, + unsigned long iterations, + size_t keysize, void *keybuffer) +{ + gpg_err_code_t ec; + + if (!passphrase || (!passphraselen && algo != GCRY_KDF_PBKDF2)) + { + ec = GPG_ERR_INV_DATA; + goto leave; + } + if (!keybuffer || !keysize) + { + ec = GPG_ERR_INV_VALUE; + goto leave; + } + + + switch (algo) + { + case GCRY_KDF_SIMPLE_S2K: + case GCRY_KDF_SALTED_S2K: + case GCRY_KDF_ITERSALTED_S2K: + ec = openpgp_s2k (passphrase, passphraselen, algo, subalgo, + salt, saltlen, iterations, keysize, keybuffer); + break; + + case GCRY_KDF_PBKDF1: + ec = GPG_ERR_UNSUPPORTED_ALGORITHM; + break; + + case GCRY_KDF_PBKDF2: + ec = pkdf2 (passphrase, passphraselen, subalgo, + salt, saltlen, iterations, keysize, keybuffer); + break; + + default: + ec = GPG_ERR_UNKNOWN_ALGORITHM; + break; + } + + leave: + return gpg_error (ec); +} diff --git a/grub-core/lib/libgcrypt/cipher/md.c b/grub-core/lib/libgcrypt/cipher/md.c index 5dfbbd95a..c3b3a4f3a 100644 --- a/grub-core/lib/libgcrypt/cipher/md.c +++ b/grub-core/lib/libgcrypt/cipher/md.c @@ -43,15 +43,15 @@ static struct digest_table_entry gcry_md_spec_t *digest; md_extra_spec_t *extraspec; unsigned int algorithm; - int fips_allowed; + int fips_allowed; } digest_table[] = { -#if USE_CRC +#if USE_CRC /* We allow the CRC algorithms even in FIPS mode because they are actually no cryptographic primitives. */ - { &_gcry_digest_spec_crc32, + { &_gcry_digest_spec_crc32, &dummy_extra_spec, GCRY_MD_CRC32, 1 }, - { &_gcry_digest_spec_crc32_rfc1510, + { &_gcry_digest_spec_crc32_rfc1510, &dummy_extra_spec, GCRY_MD_CRC32_RFC1510, 1 }, { &_gcry_digest_spec_crc24_rfc2440, &dummy_extra_spec, GCRY_MD_CRC24_RFC2440, 1 }, @@ -69,7 +69,7 @@ static struct digest_table_entry &dummy_extra_spec, GCRY_MD_RMD160 }, #endif #if USE_SHA1 - { &_gcry_digest_spec_sha1, + { &_gcry_digest_spec_sha1, &_gcry_digest_extraspec_sha1, GCRY_MD_SHA1, 1 }, #endif #if USE_SHA256 @@ -87,6 +87,10 @@ static struct digest_table_entry #if USE_TIGER { &_gcry_digest_spec_tiger, &dummy_extra_spec, GCRY_MD_TIGER }, + { &_gcry_digest_spec_tiger1, + &dummy_extra_spec, GCRY_MD_TIGER1 }, + { &_gcry_digest_spec_tiger2, + &dummy_extra_spec, GCRY_MD_TIGER2 }, #endif #if USE_WHIRLPOOL { &_gcry_digest_spec_whirlpool, @@ -101,7 +105,7 @@ static gcry_module_t digests_registered; /* This is the lock protecting DIGESTS_REGISTERED. */ static ath_mutex_t digests_registered_lock = ATH_MUTEX_INITIALIZER; -/* Flag to check wether the default ciphers have already been +/* Flag to check whether the default ciphers have already been registered. */ static int default_digests_registered; @@ -173,7 +177,7 @@ md_register_default (void) { gcry_err_code_t err = 0; int i; - + for (i = 0; !err && digest_table[i].digest; i++) { if ( fips_mode ()) @@ -226,7 +230,7 @@ gcry_md_lookup_func_oid (void *spec, void *data) } /* Internal function. Lookup a digest entry by it's name. */ -static gcry_module_t +static gcry_module_t gcry_md_lookup_name (const char *name) { gcry_module_t digest; @@ -267,11 +271,11 @@ _gcry_md_register (gcry_md_spec_t *digest, ath_mutex_lock (&digests_registered_lock); err = _gcry_module_add (&digests_registered, 0, - (void *) digest, - (void *)(extraspec? extraspec : &dummy_extra_spec), + (void *) digest, + (void *)(extraspec? extraspec : &dummy_extra_spec), &mod); ath_mutex_unlock (&digests_registered_lock); - + if (! err) { *module = mod; @@ -292,7 +296,7 @@ gcry_md_unregister (gcry_module_t module) } -static int +static int search_oid (const char *oid, int *algorithm, gcry_md_oid_spec_t *oid_spec) { gcry_module_t module; @@ -563,7 +567,7 @@ md_enable (gcry_md_hd_t hd, int algorithm) else digest = (gcry_md_spec_t *) module->spec; - + if (!err && algorithm == GCRY_MD_MD5 && fips_mode ()) { _gcry_inactivate_fips_mode ("MD5 used"); @@ -574,7 +578,7 @@ md_enable (gcry_md_hd_t hd, int algorithm) err = GPG_ERR_DIGEST_ALGO; } } - + if (!err) { size_t size = (sizeof (*entry) @@ -631,7 +635,7 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd) GcryDigestEntry *ar, *br; gcry_md_hd_t bhd; size_t n; - + if (ahd->bufpos) md_write (ahd, NULL, 0); @@ -693,7 +697,7 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd) - sizeof (ar->context))); br->next = b->list; b->list = br; - + /* Add a reference to the module. */ ath_mutex_lock (&digests_registered_lock); _gcry_module_use (br->module); @@ -783,7 +787,7 @@ static void md_write (gcry_md_hd_t a, const void *inbuf, size_t inlen) { GcryDigestEntry *r; - + if (a->ctx->debug) { if (a->bufpos && fwrite (a->buf, a->bufpos, 1, a->ctx->debug) != 1) @@ -834,8 +838,8 @@ md_final (gcry_md_hd_t a) if (err) _gcry_fatal_error (err, NULL); - md_write (om, - (a->ctx->macpads)+(a->ctx->macpads_Bsize), + md_write (om, + (a->ctx->macpads)+(a->ctx->macpads_Bsize), a->ctx->macpads_Bsize); md_write (om, p, dlen); md_final (om); @@ -856,7 +860,7 @@ prepare_macpads (gcry_md_hd_t hd, const unsigned char *key, size_t keylen) if (!algo) return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */ - if ( keylen > hd->ctx->macpads_Bsize ) + if ( keylen > hd->ctx->macpads_Bsize ) { helpkey = gcry_malloc_secure (md_digest_length (algo)); if (!helpkey) @@ -872,7 +876,7 @@ prepare_macpads (gcry_md_hd_t hd, const unsigned char *key, size_t keylen) opad = (hd->ctx->macpads)+(hd->ctx->macpads_Bsize); memcpy ( ipad, key, keylen ); memcpy ( opad, key, keylen ); - for (i=0; i < hd->ctx->macpads_Bsize; i++ ) + for (i=0; i < hd->ctx->macpads_Bsize; i++ ) { ipad[i] ^= 0x36; opad[i] ^= 0x5c; @@ -886,7 +890,7 @@ gcry_error_t gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen) { gcry_err_code_t rc = 0; - + switch (cmd) { case GCRYCTL_FINALIZE: @@ -948,10 +952,13 @@ md_read( gcry_md_hd_t a, int algo ) if (! algo) { - /* return the first algorithm */ - if (r && r->next) - log_debug ("more than one algorithm in md_read(0)\n"); - return r->digest->read( &r->context.c ); + /* Return the first algorithm */ + if (r) + { + if (r->next) + log_debug ("more than one algorithm in md_read(0)\n"); + return r->digest->read (&r->context.c); + } } else { @@ -1135,7 +1142,7 @@ md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen) * Note: Because this function is in most cases used to return an * integer value, we can make it easier for the caller to just look at * the return value. The caller will in all cases consult the value - * and thereby detecting whether a error occured or not (i.e. while checking + * and thereby detecting whether a error occurred or not (i.e. while checking * the block size) */ gcry_error_t @@ -1160,7 +1167,7 @@ gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes) { const char unsigned *asn; size_t asnlen; - + asn = md_asn_oid (algo, &asnlen, NULL); if (buffer && (*nbytes >= asnlen)) { @@ -1195,7 +1202,7 @@ md_start_debug ( gcry_md_hd_t md, const char *suffix ) if (fips_mode ()) return; - + if ( md->ctx->debug ) { log_debug("Oops: md debug already started\n"); @@ -1225,6 +1232,7 @@ md_stop_debug( gcry_md_hd_t md ) volatile u64 b = 42; volatile u64 c; c = a * b; + (void)c; } #endif } @@ -1261,7 +1269,7 @@ gcry_md_info (gcry_md_hd_t h, int cmd, void *buffer, size_t *nbytes) else { algo = *(int*)buffer; - + *nbytes = 0; for(r=h->ctx->list; r; r = r->next ) { if (r->module->mod_id == algo) @@ -1295,7 +1303,7 @@ _gcry_md_init (void) int -gcry_md_is_secure (gcry_md_hd_t a) +gcry_md_is_secure (gcry_md_hd_t a) { size_t value; @@ -1307,7 +1315,7 @@ gcry_md_is_secure (gcry_md_hd_t a) int -gcry_md_is_enabled (gcry_md_hd_t a, int algo) +gcry_md_is_enabled (gcry_md_hd_t a, int algo) { size_t value; @@ -1359,7 +1367,7 @@ _gcry_md_selftest (int algo, int extended, selftest_report_func_t report) { ec = GPG_ERR_DIGEST_ALGO; if (report) - report ("digest", algo, "module", + report ("digest", algo, "module", module && !(module->flags & FLAG_MODULE_DISABLED)? "no selftest available" : module? "algorithm disabled" : "algorithm not found"); diff --git a/grub-core/lib/libgcrypt/cipher/md4.c b/grub-core/lib/libgcrypt/cipher/md4.c index aa180f0d4..22fbf8d90 100644 --- a/grub-core/lib/libgcrypt/cipher/md4.c +++ b/grub-core/lib/libgcrypt/cipher/md4.c @@ -53,7 +53,6 @@ #include #include "g10lib.h" -#include "memory.h" #include "cipher.h" #include "bithelp.h" @@ -199,7 +198,7 @@ md4_write ( void *context, const void *inbuf_arg, size_t inlen) MD4_CONTEXT *hd = context; if( hd->count == 64 ) /* flush the buffer */ - { + { transform( hd, hd->buf ); _gcry_burn_stack (80+6*sizeof(void*)); hd->count = 0; @@ -260,15 +259,15 @@ md4_final( void *context ) lsb <<= 3; msb <<= 3; msb |= t >> 29; - + if( hd->count < 56 ) /* enough room */ { hd->buf[hd->count++] = 0x80; /* pad */ while( hd->count < 56 ) hd->buf[hd->count++] = 0; /* pad */ } - else /* need one extra block */ - { + else /* need one extra block */ + { hd->buf[hd->count++] = 0x80; /* pad character */ while( hd->count < 64 ) hd->buf[hd->count++] = 0; @@ -326,4 +325,3 @@ gcry_md_spec_t _gcry_digest_spec_md4 = md4_init, md4_write, md4_final, md4_read, sizeof (MD4_CONTEXT) }; - diff --git a/grub-core/lib/libgcrypt/cipher/md5.c b/grub-core/lib/libgcrypt/cipher/md5.c index 3d3046df2..a98678a9b 100644 --- a/grub-core/lib/libgcrypt/cipher/md5.c +++ b/grub-core/lib/libgcrypt/cipher/md5.c @@ -20,8 +20,8 @@ * * According to the definition of MD5 in RFC 1321 from April 1992. * NOTE: This is *not* the same file as the one from glibc. - * Written by Ulrich Drepper , 1995. - * heavily modified for GnuPG by Werner Koch + * Written by Ulrich Drepper , 1995. + * heavily modified for GnuPG by Werner Koch */ /* Test values: @@ -37,7 +37,6 @@ #include #include "g10lib.h" -#include "memory.h" #include "cipher.h" #include "bithelp.h" @@ -88,9 +87,9 @@ transform ( MD5_CONTEXT *ctx, const unsigned char *data ) register u32 C = ctx->C; register u32 D = ctx->D; u32 *cwp = correct_words; - + #ifdef WORDS_BIGENDIAN - { + { int i; byte *p2; const byte *p1; @@ -222,7 +221,7 @@ md5_write( void *context, const void *inbuf_arg , size_t inlen) { const unsigned char *inbuf = inbuf_arg; MD5_CONTEXT *hd = context; - + if( hd->count == 64 ) /* flush the buffer */ { transform( hd, hd->buf ); @@ -243,7 +242,7 @@ md5_write( void *context, const void *inbuf_arg , size_t inlen) } _gcry_burn_stack (80+6*sizeof(void*)); - while( inlen >= 64 ) + while( inlen >= 64 ) { transform( hd, inbuf ); hd->count = 0; @@ -270,7 +269,7 @@ md5_final( void *context) MD5_CONTEXT *hd = context; u32 t, msb, lsb; byte *p; - + md5_write(hd, NULL, 0); /* flush */; t = hd->nblocks; diff --git a/grub-core/lib/libgcrypt/cipher/primegen.c b/grub-core/lib/libgcrypt/cipher/primegen.c index b869bee83..b12e79b19 100644 --- a/grub-core/lib/libgcrypt/cipher/primegen.c +++ b/grub-core/lib/libgcrypt/cipher/primegen.c @@ -31,7 +31,7 @@ #include "cipher.h" #include "ath.h" -static gcry_mpi_t gen_prime (unsigned int nbits, int secret, int randomlevel, +static gcry_mpi_t gen_prime (unsigned int nbits, int secret, int randomlevel, int (*extra_check)(void *, gcry_mpi_t), void *extra_check_arg); static int check_prime( gcry_mpi_t prime, gcry_mpi_t val_2, int rm_rounds, @@ -132,7 +132,7 @@ static int no_of_small_prime_numbers = DIM (small_prime_numbers) - 1; /* An object and a list to build up a global pool of primes. See save_pool_prime and get_pool_prime. */ -struct primepool_s +struct primepool_s { struct primepool_s *next; gcry_mpi_t prime; /* If this is NULL the entry is not used. */ @@ -163,7 +163,7 @@ save_pool_prime (gcry_mpi_t prime, gcry_random_level_t randomlevel) /* Remove some of the entries. Our strategy is removing the last third from the list. */ int i; - + for (i=0, item2 = primepool; item2; item2 = item2->next) { if (i >= n/3*2) @@ -182,7 +182,7 @@ save_pool_prime (gcry_mpi_t prime, gcry_random_level_t randomlevel) { /* Out of memory. Silently giving up. */ gcry_mpi_release (prime); - return; + return; } item->next = primepool; primepool = item; @@ -359,7 +359,7 @@ prime_generate_internal (int need_q_factor, fbits = (pbits - req_qbits -1) / n; qbits = pbits - n * fbits; } - + if (DBG_CIPHER) log_debug ("gen prime: pbits=%u qbits=%u fbits=%u/%u n=%d\n", pbits, req_qbits, qbits, fbits, n); @@ -373,7 +373,7 @@ prime_generate_internal (int need_q_factor, /* Generate a specific Q-Factor if requested. */ if (need_q_factor) q_factor = gen_prime (req_qbits, is_secret, randomlevel, NULL, NULL); - + /* Allocate an array to hold all factors + 2 for later usage. */ factors = gcry_calloc (n + 2, sizeof (*factors)); if (!factors) @@ -383,7 +383,7 @@ prime_generate_internal (int need_q_factor, } /* Allocate an array to track pool usage. */ - pool_in_use = gcry_malloc (n * sizeof *pool_in_use); + pool_in_use = gcry_calloc (n, sizeof *pool_in_use); if (!pool_in_use) { err = gpg_err_code_from_errno (errno); @@ -391,10 +391,10 @@ prime_generate_internal (int need_q_factor, } for (i=0; i < n; i++) pool_in_use[i] = -1; - + /* Make a pool of 3n+5 primes (this is an arbitrary value). We - require at least 30 primes for are useful selection process. - + require at least 30 primes for are useful selection process. + Fixme: We need to research the best formula for sizing the pool. */ m = n * 3 + 5; @@ -443,7 +443,7 @@ prime_generate_internal (int need_q_factor, is_locked = 1; for (i = 0; i < n; i++) { - perms[i] = 1; + perms[i] = 1; /* At a maximum we use strong random for the factors. This saves us a lot of entropy. Given that Q and possible Q-factor are also used in the final prime @@ -523,12 +523,12 @@ prime_generate_internal (int need_q_factor, gcry_free (perms); perms = NULL; progress ('!'); - goto next_try; + goto next_try; } } /* Generate next prime candidate: - p = 2 * q [ * q_factor] * factor_0 * factor_1 * ... * factor_n + 1. + p = 2 * q [ * q_factor] * factor_0 * factor_1 * ... * factor_n + 1. */ mpi_set (prime, q); mpi_mul_ui (prime, prime, 2); @@ -553,7 +553,7 @@ prime_generate_internal (int need_q_factor, } else count1 = 0; - + if (nprime > pbits) { if (++count2 > 20) @@ -624,14 +624,14 @@ prime_generate_internal (int need_q_factor, factors_new[i] = mpi_copy (factors[i]); } } - + if (g) { /* Create a generator (start with 3). */ gcry_mpi_t tmp = mpi_alloc (mpi_get_nlimbs (prime)); gcry_mpi_t b = mpi_alloc (mpi_get_nlimbs (prime)); gcry_mpi_t pmin1 = mpi_alloc (mpi_get_nlimbs (prime)); - + if (need_q_factor) err = GPG_ERR_NOT_IMPLEMENTED; else @@ -662,7 +662,7 @@ prime_generate_internal (int need_q_factor, } if (DBG_CIPHER) progress('\n'); - } + } while (i < n + 2); mpi_free (factors[n+1]); @@ -671,7 +671,7 @@ prime_generate_internal (int need_q_factor, mpi_free (pmin1); } } - + if (! DBG_CIPHER) progress ('\n'); @@ -738,19 +738,19 @@ gcry_mpi_t _gcry_generate_elg_prime (int mode, unsigned pbits, unsigned qbits, gcry_mpi_t g, gcry_mpi_t **ret_factors) { - gcry_err_code_t err = GPG_ERR_NO_ERROR; gcry_mpi_t prime = NULL; - - err = prime_generate_internal ((mode == 1), &prime, pbits, qbits, g, - ret_factors, GCRY_WEAK_RANDOM, 0, 0, - NULL, NULL); + + if (prime_generate_internal ((mode == 1), &prime, pbits, qbits, g, + ret_factors, GCRY_WEAK_RANDOM, 0, 0, + NULL, NULL)) + prime = NULL; /* (Should be NULL in the error case anyway.) */ return prime; } static gcry_mpi_t -gen_prime (unsigned int nbits, int secret, int randomlevel, +gen_prime (unsigned int nbits, int secret, int randomlevel, int (*extra_check)(void *, gcry_mpi_t), void *extra_check_arg) { gcry_mpi_t prime, ptest, pminus1, val_2, val_3, result; @@ -758,14 +758,14 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, unsigned int x, step; unsigned int count1, count2; int *mods; - + /* if ( DBG_CIPHER ) */ /* log_debug ("generate a prime of %u bits ", nbits ); */ if (nbits < 16) log_fatal ("can't generate a prime with less than %d bits\n", 16); - mods = gcry_xmalloc( no_of_small_prime_numbers * sizeof *mods ); + mods = gcry_xcalloc( no_of_small_prime_numbers, sizeof *mods); /* Make nbits fit into gcry_mpi_t implementation. */ val_2 = mpi_alloc_set_ui( 2 ); val_3 = mpi_alloc_set_ui( 3); @@ -777,10 +777,10 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, for (;;) { /* try forvever */ int dotcount=0; - + /* generate a random number */ gcry_mpi_randomize( prime, nbits, randomlevel ); - + /* Set high order bit to 1, set low order bit to 1. If we are generating a secret prime we are most probably doing that for RSA, to make sure that the modulus does have the @@ -789,17 +789,17 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, if (secret) mpi_set_bit (prime, nbits-2); mpi_set_bit(prime, 0); - + /* Calculate all remainders. */ for (i=0; (x = small_prime_numbers[i]); i++ ) mods[i] = mpi_fdiv_r_ui(NULL, prime, x); - + /* Now try some primes starting with prime. */ - for(step=0; step < 20000; step += 2 ) + for(step=0; step < 20000; step += 2 ) { /* Check against all the small primes we have in mods. */ count1++; - for (i=0; (x = small_prime_numbers[i]); i++ ) + for (i=0; (x = small_prime_numbers[i]); i++ ) { while ( mods[i] + step >= x ) mods[i] -= x; @@ -808,7 +808,7 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, } if ( x ) continue; /* Found a multiple of an already known prime. */ - + mpi_add_ui( ptest, prime, step ); /* Do a fast Fermat test now. */ @@ -816,7 +816,7 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, mpi_sub_ui( pminus1, ptest, 1); gcry_mpi_powm( result, val_2, pminus1, ptest ); if ( !mpi_cmp_ui( result, 1 ) ) - { + { /* Not composite, perform stronger tests */ if (is_prime(ptest, 5, &count2 )) { @@ -828,13 +828,13 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, } if (extra_check && extra_check (extra_check_arg, ptest)) - { + { /* The extra check told us that this prime is not of the caller's taste. */ progress ('/'); } else - { + { /* Got it. */ mpi_free(val_2); mpi_free(val_3); @@ -842,7 +842,7 @@ gen_prime (unsigned int nbits, int secret, int randomlevel, mpi_free(pminus1); mpi_free(prime); gcry_free(mods); - return ptest; + return ptest; } } } @@ -883,7 +883,7 @@ check_prime( gcry_mpi_t prime, gcry_mpi_t val_2, int rm_rounds, gcry_mpi_powm( result, val_2, pminus1, prime ); mpi_free( pminus1 ); if ( mpi_cmp_ui( result, 1 ) ) - { + { /* Is composite. */ mpi_free( result ); progress('.'); @@ -924,7 +924,7 @@ is_prime (gcry_mpi_t n, int steps, unsigned int *count) unsigned nbits = mpi_get_nbits( n ); if (steps < 5) /* Make sure that we do at least 5 rounds. */ - steps = 5; + steps = 5; mpi_sub_ui( nminus1, n, 1 ); @@ -988,7 +988,7 @@ is_prime (gcry_mpi_t n, int steps, unsigned int *count) /* Given ARRAY of size N with M elements set to true produce a modified array with the next permutation of M elements. Note, that ARRAY is used in a one-bit-per-byte approach. To detected the last - permutation it is useful to intialize the array with the first M + permutation it is useful to initialize the array with the first M element set to true and use this test: m_out_of_n (array, m, n); for (i = j = 0; i < n && j < m; i++) @@ -996,7 +996,7 @@ is_prime (gcry_mpi_t n, int steps, unsigned int *count) j++; if (j == m) goto ready; - + This code is based on the algorithm 452 from the "Collected Algorithms From ACM, Volume II" by C. N. Liu and D. T. Tang. */ @@ -1010,7 +1010,7 @@ m_out_of_n ( char *array, int m, int n ) /* Need to handle this simple case separately. */ if( m == 1 ) - { + { for (i=0; i < n; i++ ) { if ( array[i] ) @@ -1060,7 +1060,7 @@ m_out_of_n ( char *array, int m, int n ) else k1 = k2 + 1; } - else + else { /* M is even. */ if( !array[n-1] ) @@ -1069,7 +1069,7 @@ m_out_of_n ( char *array, int m, int n ) k2 = k1 + 1; goto leave; } - + if( !(j1 & 1) ) { k1 = n - j1; @@ -1080,7 +1080,7 @@ m_out_of_n ( char *array, int m, int n ) } scan: jp = n - j1 - 1; - for (i=1; i <= jp; i++ ) + for (i=1; i <= jp; i++ ) { i1 = jp + 2 - i; if( array[i1-1] ) @@ -1128,7 +1128,7 @@ gcry_prime_generate (gcry_mpi_t *prime, unsigned int prime_bits, if (!prime) return gpg_error (GPG_ERR_INV_ARG); - *prime = NULL; + *prime = NULL; if (flags & GCRY_PRIME_FLAG_SPECIAL_FACTOR) mode = 1; @@ -1156,7 +1156,7 @@ gcry_prime_generate (gcry_mpi_t *prime, unsigned int prime_bits, mpi_free (factors_generated[i]); gcry_free (factors_generated); } - err = GPG_ERR_GENERAL; + err = GPG_ERR_GENERAL; } } @@ -1170,7 +1170,7 @@ gcry_prime_generate (gcry_mpi_t *prime, unsigned int prime_bits, return gcry_error (err); } -/* Check wether the number X is prime. */ +/* Check whether the number X is prime. */ gcry_error_t gcry_prime_check (gcry_mpi_t x, unsigned int flags) { @@ -1207,29 +1207,29 @@ gcry_prime_group_generator (gcry_mpi_t *r_g, if (!factors || !r_g || !prime) return gpg_error (GPG_ERR_INV_ARG); - *r_g = NULL; + *r_g = NULL; for (n=0; factors[n]; n++) ; if (n < 2) return gpg_error (GPG_ERR_INV_ARG); - /* Extra sanity check - usually disabled. */ + /* Extra sanity check - usually disabled. */ /* mpi_set (tmp, factors[0]); */ /* for(i = 1; i < n; i++) */ /* mpi_mul (tmp, tmp, factors[i]); */ /* mpi_add_ui (tmp, tmp, 1); */ /* if (mpi_cmp (prime, tmp)) */ /* return gpg_error (GPG_ERR_INV_ARG); */ - - gcry_mpi_sub_ui (pmin1, prime, 1); - do + + gcry_mpi_sub_ui (pmin1, prime, 1); + do { if (first) first = 0; else gcry_mpi_add_ui (g, g, 1); - + if (DBG_CIPHER) { log_debug ("checking g:"); @@ -1238,7 +1238,7 @@ gcry_prime_group_generator (gcry_mpi_t *r_g, } else progress('^'); - + for (i = 0; i < n; i++) { mpi_fdiv_q (tmp, pmin1, factors[i]); @@ -1250,13 +1250,13 @@ gcry_prime_group_generator (gcry_mpi_t *r_g, progress('\n'); } while (i < n); - - gcry_mpi_release (tmp); - gcry_mpi_release (b); - gcry_mpi_release (pmin1); - *r_g = g; - return 0; + gcry_mpi_release (tmp); + gcry_mpi_release (b); + gcry_mpi_release (pmin1); + *r_g = g; + + return 0; } /* Convenience function to release the factors array. */ @@ -1266,7 +1266,7 @@ gcry_prime_release_factors (gcry_mpi_t *factors) if (factors) { int i; - + for (i=0; factors[i]; i++) mpi_free (factors[i]); gcry_free (factors); @@ -1279,11 +1279,11 @@ gcry_prime_release_factors (gcry_mpi_t *factors) static gcry_mpi_t find_x931_prime (const gcry_mpi_t pfirst) { - gcry_mpi_t val_2 = mpi_alloc_set_ui (2); + gcry_mpi_t val_2 = mpi_alloc_set_ui (2); gcry_mpi_t prime; - + prime = gcry_mpi_copy (pfirst); - /* If P is even add 1. */ + /* If P is even add 1. */ mpi_set_bit (prime, 0); /* We use 64 Rabin-Miller rounds which is better and thus @@ -1299,7 +1299,7 @@ find_x931_prime (const gcry_mpi_t pfirst) } -/* Generate a prime using the algorithm from X9.31 appendix B.4. +/* Generate a prime using the algorithm from X9.31 appendix B.4. This function requires that the provided public exponent E is odd. XP, XP1 and XP2 are the seed values. All values are mandatory. @@ -1308,7 +1308,7 @@ find_x931_prime (const gcry_mpi_t pfirst) internal values P1 and P2 are saved at these addresses. On error NULL is returned. */ gcry_mpi_t -_gcry_derive_x931_prime (const gcry_mpi_t xp, +_gcry_derive_x931_prime (const gcry_mpi_t xp, const gcry_mpi_t xp1, const gcry_mpi_t xp2, const gcry_mpi_t e, gcry_mpi_t *r_p1, gcry_mpi_t *r_p2) @@ -1327,20 +1327,20 @@ _gcry_derive_x931_prime (const gcry_mpi_t xp, { gcry_mpi_t r1, tmp; - + /* r1 = (p2^{-1} mod p1)p2 - (p1^{-1} mod p2) */ tmp = mpi_alloc_like (p1); mpi_invm (tmp, p2, p1); mpi_mul (tmp, tmp, p2); r1 = tmp; - + tmp = mpi_alloc_like (p2); mpi_invm (tmp, p1, p2); mpi_mul (tmp, tmp, p1); mpi_sub (r1, r1, tmp); /* Fixup a negative value. */ - if (mpi_is_neg (r1)) + if (mpi_is_neg (r1)) mpi_add (r1, r1, p1p2); /* yp0 = xp + (r1 - xp mod p1*p2) */ @@ -1350,7 +1350,7 @@ _gcry_derive_x931_prime (const gcry_mpi_t xp, mpi_free (r1); /* Fixup a negative value. */ - if (mpi_cmp (yp0, xp) < 0 ) + if (mpi_cmp (yp0, xp) < 0 ) mpi_add (yp0, yp0, p1p2); } @@ -1378,10 +1378,10 @@ _gcry_derive_x931_prime (const gcry_mpi_t xp, */ { - gcry_mpi_t val_2 = mpi_alloc_set_ui (2); + gcry_mpi_t val_2 = mpi_alloc_set_ui (2); gcry_mpi_t gcdtmp = mpi_alloc_like (yp0); int gcdres; - + mpi_sub_ui (p1p2, p1p2, 1); /* Adjust for loop body. */ mpi_sub_ui (yp0, yp0, 1); /* Ditto. */ for (;;) @@ -1453,7 +1453,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, ; /* No seed value given: We are asked to generate it. */ else if (!seed || seedlen < qbits/8) return GPG_ERR_INV_ARG; - + /* Allocate a buffer to later compute SEED+some_increment. */ seed_plus = gcry_malloc (seedlen < 20? 20:seedlen); if (!seed_plus) @@ -1468,7 +1468,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, value_w = gcry_mpi_new (pbits); value_x = gcry_mpi_new (pbits); - restart: + restart: /* Generate Q. */ for (;;) { @@ -1479,7 +1479,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, gcry_create_nonce (seed_help_buffer, seedlen); seed = seed_help_buffer; } - + /* Step 2: U = sha1(seed) ^ sha1((seed+1) mod 2^{qbits}) */ memcpy (seed_plus, seed, seedlen); for (i=seedlen-1; i >= 0; i--) @@ -1492,16 +1492,16 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen); for (i=0; i < sizeof value_u; i++) value_u[i] ^= digest[i]; - + /* Step 3: Form q from U */ gcry_mpi_release (prime_q); prime_q = NULL; - ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, + ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, value_u, sizeof value_u, NULL)); if (ec) goto leave; mpi_set_highbit (prime_q, qbits-1 ); mpi_set_bit (prime_q, 0); - + /* Step 4: Test whether Q is prime using 64 round of Rabin-Miller. */ if (check_prime (prime_q, val_2, 64, NULL, NULL)) break; /* Yes, Q is prime. */ @@ -1509,7 +1509,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, /* Step 5. */ seed = NULL; /* Force a new seed at Step 1. */ } - + /* Step 6. Note that we do no use an explicit offset but increment SEED_PLUS accordingly. SEED_PLUS is currently SEED+1. */ counter = 0; @@ -1518,12 +1518,12 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, prime_p = gcry_mpi_new (pbits); for (;;) { - /* Step 7: For k = 0,...n let - V_k = sha1(seed+offset+k) mod 2^{qbits} - Step 8: W = V_0 + V_1*2^160 + - ... + /* Step 7: For k = 0,...n let + V_k = sha1(seed+offset+k) mod 2^{qbits} + Step 8: W = V_0 + V_1*2^160 + + ... + V_{n-1}*2^{(n-1)*160} - + (V_{n} mod 2^b)*2^{n*160} + + (V_{n} mod 2^b)*2^{n*160} */ mpi_set_ui (value_w, 0); for (value_k=0; value_k <= value_n; value_k++) @@ -1542,7 +1542,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, break; } gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen); - + gcry_mpi_release (tmpval); tmpval = NULL; ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG, digest, sizeof digest, NULL)); @@ -1631,7 +1631,7 @@ _gcry_generate_fips186_2_prime (unsigned int pbits, unsigned int qbits, value is stored at R_COUNTER and the seed actually used for generation is stored at R_SEED and R_SEEDVALUE. The hash algorithm used is stored at R_HASHALGO. - + Note that this function is very similar to the fips186_2 code. Due to the minor differences, other buffer sizes and for documentarion, we use a separate function. @@ -1652,7 +1652,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, gcry_mpi_t tmpval = NULL; /* Helper variable. */ int hashalgo; /* The id of the Approved Hash Function. */ int i; - + unsigned char value_u[256/8]; int value_n, value_b, value_j; int counter; @@ -1690,10 +1690,10 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, ; /* No seed value given: We are asked to generate it. */ else if (!seed || seedlen < qbits/8) return GPG_ERR_INV_ARG; - + /* Allocate a buffer to later compute SEED+some_increment and a few helper variables. */ - seed_plus = gcry_malloc (seedlen < sizeof seed_help_buffer? + seed_plus = gcry_malloc (seedlen < sizeof seed_help_buffer? sizeof seed_help_buffer : seedlen); if (!seed_plus) { @@ -1709,7 +1709,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, /* Step 4: b = L - 1 - (n * outlen) */ value_b = pbits - 1 - (value_n * qbits); - restart: + restart: /* Generate Q. */ for (;;) { @@ -1721,7 +1721,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, gcry_create_nonce (seed_help_buffer, seedlen); seed = seed_help_buffer; } - + /* Step 6: U = hash(seed) */ gcry_md_hash_buffer (hashalgo, value_u, seed, seedlen); @@ -1736,12 +1736,12 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, } } gcry_mpi_release (prime_q); prime_q = NULL; - ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, + ec = gpg_err_code (gcry_mpi_scan (&prime_q, GCRYMPI_FMT_USG, value_u, sizeof value_u, NULL)); if (ec) goto leave; mpi_set_highbit (prime_q, qbits-1 ); - + /* Step 8: Test whether Q is prime using 64 round of Rabin-Miller. According to table C.1 this is sufficient for all supported prime sizes (i.e. up 3072/256). */ @@ -1751,7 +1751,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, /* Step 8. */ seed = NULL; /* Force a new seed at Step 5. */ } - + /* Step 11. Note that we do no use an explicit offset but increment SEED_PLUS accordingly. */ memcpy (seed_plus, seed, seedlen); @@ -1761,12 +1761,12 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, prime_p = gcry_mpi_new (pbits); for (;;) { - /* Step 11.1: For j = 0,...n let - V_j = hash(seed+offset+j) - Step 11.2: W = V_0 + V_1*2^outlen + - ... + /* Step 11.1: For j = 0,...n let + V_j = hash(seed+offset+j) + Step 11.2: W = V_0 + V_1*2^outlen + + ... + V_{n-1}*2^{(n-1)*outlen} - + (V_{n} mod 2^b)*2^{n*outlen} + + (V_{n} mod 2^b)*2^{n*outlen} */ mpi_set_ui (value_w, 0); for (value_j=0; value_j <= value_n; value_j++) @@ -1783,7 +1783,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, break; } gcry_md_hash_buffer (GCRY_MD_SHA1, digest, seed_plus, seedlen); - + gcry_mpi_release (tmpval); tmpval = NULL; ec = gpg_err_code (gcry_mpi_scan (&tmpval, GCRYMPI_FMT_USG, digest, sizeof digest, NULL)); @@ -1813,7 +1813,7 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, if (mpi_get_nbits (prime_p) >= pbits-1 && check_prime (prime_p, val_2, 64, NULL, NULL) ) break; /* Yes, P is prime, continue with Step 15. */ - + /* Step 11.9: counter = counter + 1, offset = offset + n + 1. If counter >= 4L goto Step 5. */ counter++; @@ -1859,4 +1859,3 @@ _gcry_generate_fips186_3_prime (unsigned int pbits, unsigned int qbits, gcry_mpi_release (val_2); return ec; } - diff --git a/grub-core/lib/libgcrypt/cipher/pubkey.c b/grub-core/lib/libgcrypt/cipher/pubkey.c index 08abcbfde..ca087ad75 100644 --- a/grub-core/lib/libgcrypt/cipher/pubkey.c +++ b/grub-core/lib/libgcrypt/cipher/pubkey.c @@ -1,6 +1,6 @@ /* pubkey.c - pubkey dispatcher - * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005, - * 2007, 2008 Free Software Foundation, Inc. + * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005, + * 2007, 2008, 2011 Free Software Foundation, Inc. * * This file is part of Libgcrypt. * @@ -55,7 +55,7 @@ static struct pubkey_table_entry gcry_pk_spec_t *pubkey; pk_extra_spec_t *extraspec; unsigned int algorithm; - int fips_allowed; + int fips_allowed; } pubkey_table[] = { #if USE_RSA @@ -75,6 +75,8 @@ static struct pubkey_table_entry #if USE_ECC { &_gcry_pubkey_spec_ecdsa, &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDSA, 0 }, + { &_gcry_pubkey_spec_ecdh, + &_gcry_pubkey_extraspec_ecdsa, GCRY_PK_ECDH, 0 }, #endif { NULL, 0 }, }; @@ -85,7 +87,7 @@ static gcry_module_t pubkeys_registered; /* This is the lock protecting PUBKEYS_REGISTERED. */ static ath_mutex_t pubkeys_registered_lock = ATH_MUTEX_INITIALIZER;; -/* Flag to check wether the default pubkeys have already been +/* Flag to check whether the default pubkeys have already been registered. */ static int default_pubkeys_registered; @@ -197,7 +199,7 @@ pk_register_default (void) { gcry_err_code_t err = 0; int i; - + for (i = 0; (! err) && pubkey_table[i].pubkey; i++) { #define pubkey_use_dummy(func) \ @@ -215,8 +217,8 @@ pk_register_default (void) err = _gcry_module_add (&pubkeys_registered, pubkey_table[i].algorithm, - (void *) pubkey_table[i].pubkey, - (void *) pubkey_table[i].extraspec, + (void *) pubkey_table[i].pubkey, + (void *) pubkey_table[i].extraspec, NULL); } @@ -240,7 +242,7 @@ gcry_pk_lookup_func_name (void *spec, void *data) } /* Internal function. Lookup a pubkey entry by it's name. */ -static gcry_module_t +static gcry_module_t gcry_pk_lookup_name (const char *name) { gcry_module_t pubkey; @@ -269,8 +271,8 @@ _gcry_pk_register (gcry_pk_spec_t *pubkey, ath_mutex_lock (&pubkeys_registered_lock); err = _gcry_module_add (&pubkeys_registered, 0, - (void *) pubkey, - (void *)(extraspec? extraspec : &dummy_extra_spec), + (void *) pubkey, + (void *)(extraspec? extraspec : &dummy_extra_spec), &mod); ath_mutex_unlock (&pubkeys_registered_lock); @@ -559,13 +561,13 @@ pubkey_generate (int algorithm, if (extraspec && extraspec->ext_generate) { /* Use the extended generate function. */ - ec = extraspec->ext_generate + ec = extraspec->ext_generate (algorithm, nbits, use_e, genparms, skey, retfactors, r_extrainfo); } else { /* Use the standard generate function. */ - ec = ((gcry_pk_spec_t *) pubkey->spec)->generate + ec = ((gcry_pk_spec_t *) pubkey->spec)->generate (algorithm, nbits, use_e, skey, retfactors); } _gcry_module_release (pubkey); @@ -615,7 +617,7 @@ pubkey_encrypt (int algorithm, gcry_mpi_t *resarr, gcry_mpi_t data, /* Note: In fips mode DBG_CIPHER will enver evaluate to true but as an extra failsafe protection we explicitly test for fips mode - here. */ + here. */ if (DBG_CIPHER && !fips_mode ()) { log_debug ("pubkey_encrypt: algo=%d\n", algorithm); @@ -684,7 +686,7 @@ pubkey_decrypt (int algorithm, gcry_mpi_t *result, gcry_mpi_t *data, } rc = GPG_ERR_PUBKEY_ALGO; - + ready: ath_mutex_unlock (&pubkeys_registered_lock); @@ -758,10 +760,10 @@ pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, { log_debug ("pubkey_verify: algo=%d\n", algorithm); for (i = 0; i < pubkey_get_npkey (algorithm); i++) - log_mpidump (" pkey:", pkey[i]); + log_mpidump (" pkey", pkey[i]); for (i = 0; i < pubkey_get_nsig (algorithm); i++) - log_mpidump (" sig:", data[i]); - log_mpidump (" hash:", hash); + log_mpidump (" sig", data[i]); + log_mpidump (" hash", hash); } ath_mutex_lock (&pubkeys_registered_lock); @@ -782,6 +784,1018 @@ pubkey_verify (int algorithm, gcry_mpi_t hash, gcry_mpi_t *data, } +/* Turn VALUE into an octet string and store it in an allocated buffer + at R_FRAME or - if R_RAME is NULL - copy it into the caller + provided buffer SPACE; either SPACE or R_FRAME may be used. If + SPACE if not NULL, the caller must provide a buffer of at least + NBYTES. If the resulting octet string is shorter than NBYTES pad + it to the left with zeroes. If VALUE does not fit into NBYTES + return an error code. */ +static gpg_err_code_t +octet_string_from_mpi (unsigned char **r_frame, void *space, + gcry_mpi_t value, size_t nbytes) +{ + gpg_err_code_t rc; + size_t nframe, noff, n; + unsigned char *frame; + + if (!r_frame == !space) + return GPG_ERR_INV_ARG; /* Only one may be used. */ + + if (r_frame) + *r_frame = NULL; + + rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG, + NULL, 0, &nframe, value)); + if (rc) + return rc; + if (nframe > nbytes) + return GPG_ERR_TOO_LARGE; /* Value too long to fit into NBYTES. */ + + noff = (nframe < nbytes)? nbytes - nframe : 0; + n = nframe + noff; + if (space) + frame = space; + else + { + frame = mpi_is_secure (value)? gcry_malloc_secure (n) : gcry_malloc (n); + if (!frame) + { + rc = gpg_err_code_from_syserror (); + return rc; + } + } + if (noff) + memset (frame, 0, noff); + nframe += noff; + rc = gcry_err_code (gcry_mpi_print (GCRYMPI_FMT_USG, + frame+noff, nframe-noff, NULL, value)); + if (rc) + { + gcry_free (frame); + return rc; + } + + if (r_frame) + *r_frame = frame; + return 0; +} + + +/* Encode {VALUE,VALUELEN} for an NBITS keys using the pkcs#1 block + type 2 padding. On sucess the result is stored as a new MPI at + R_RESULT. On error the value at R_RESULT is undefined. + + If {RANDOM_OVERRIDE, RANDOM_OVERRIDE_LEN} is given it is used as + the seed instead of using a random string for it. This feature is + only useful for regression tests. Note that this value may not + contain zero bytes. + + We encode the value in this way: + + 0 2 RND(n bytes) 0 VALUE + + 0 is a marker we unfortunately can't encode because we return an + MPI which strips all leading zeroes. + 2 is the block type. + RND are non-zero random bytes. + + (Note that OpenPGP includes the cipher algorithm and a checksum in + VALUE; the caller needs to prepare the value accordingly.) + */ +static gcry_err_code_t +pkcs1_encode_for_encryption (gcry_mpi_t *r_result, unsigned int nbits, + const unsigned char *value, size_t valuelen, + const unsigned char *random_override, + size_t random_override_len) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + unsigned char *frame = NULL; + size_t nframe = (nbits+7) / 8; + int i; + size_t n; + unsigned char *p; + + if (valuelen + 7 > nframe || !nframe) + { + /* Can't encode a VALUELEN value in a NFRAME bytes frame. */ + return GPG_ERR_TOO_SHORT; /* The key is too short. */ + } + + if ( !(frame = gcry_malloc_secure (nframe))) + return gpg_err_code_from_syserror (); + + n = 0; + frame[n++] = 0; + frame[n++] = 2; /* block type */ + i = nframe - 3 - valuelen; + gcry_assert (i > 0); + + if (random_override) + { + int j; + + if (random_override_len != i) + { + gcry_free (frame); + return GPG_ERR_INV_ARG; + } + /* Check that random does not include a zero byte. */ + for (j=0; j < random_override_len; j++) + if (!random_override[j]) + { + gcry_free (frame); + return GPG_ERR_INV_ARG; + } + memcpy (frame + n, random_override, random_override_len); + n += random_override_len; + } + else + { + p = gcry_random_bytes_secure (i, GCRY_STRONG_RANDOM); + /* Replace zero bytes by new values. */ + for (;;) + { + int j, k; + unsigned char *pp; + + /* Count the zero bytes. */ + for (j=k=0; j < i; j++) + { + if (!p[j]) + k++; + } + if (!k) + break; /* Okay: no (more) zero bytes. */ + + k += k/128 + 3; /* Better get some more. */ + pp = gcry_random_bytes_secure (k, GCRY_STRONG_RANDOM); + for (j=0; j < i && k; ) + { + if (!p[j]) + p[j] = pp[--k]; + if (p[j]) + j++; + } + gcry_free (pp); + } + memcpy (frame+n, p, i); + n += i; + gcry_free (p); + } + + frame[n++] = 0; + memcpy (frame+n, value, valuelen); + n += valuelen; + gcry_assert (n == nframe); + + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, n, &nframe); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("PKCS#1 block type 2 encoded data", *r_result); + gcry_free (frame); + + return rc; +} + + +/* Decode a plaintext in VALUE assuming pkcs#1 block type 2 padding. + NBITS is the size of the secret key. On success the result is + stored as a newly allocated buffer at R_RESULT and its valid length at + R_RESULTLEN. On error NULL is stored at R_RESULT. */ +static gcry_err_code_t +pkcs1_decode_for_encryption (unsigned char **r_result, size_t *r_resultlen, + unsigned int nbits, gcry_mpi_t value) +{ + gcry_error_t err; + unsigned char *frame = NULL; + size_t nframe = (nbits+7) / 8; + size_t n; + + *r_result = NULL; + + if ( !(frame = gcry_malloc_secure (nframe))) + return gpg_err_code_from_syserror (); + + err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &n, value); + if (err) + { + gcry_free (frame); + return gcry_err_code (err); + } + + nframe = n; /* Set NFRAME to the actual length. */ + + /* FRAME = 0x00 || 0x02 || PS || 0x00 || M + + pkcs#1 requires that the first byte is zero. Our MPIs usually + strip leading zero bytes; thus we are not able to detect them. + However due to the way gcry_mpi_print is implemented we may see + leading zero bytes nevertheless. We handle this by making the + first zero byte optional. */ + if (nframe < 4) + { + gcry_free (frame); + return GPG_ERR_ENCODING_PROBLEM; /* Too short. */ + } + n = 0; + if (!frame[0]) + n++; + if (frame[n++] != 0x02) + { + gcry_free (frame); + return GPG_ERR_ENCODING_PROBLEM; /* Wrong block type. */ + } + + /* Skip the non-zero random bytes and the terminating zero byte. */ + for (; n < nframe && frame[n] != 0x00; n++) + ; + if (n+1 >= nframe) + { + gcry_free (frame); + return GPG_ERR_ENCODING_PROBLEM; /* No zero byte. */ + } + n++; /* Skip the zero byte. */ + + /* To avoid an extra allocation we reuse the frame buffer. The only + caller of this function will anyway free the result soon. */ + memmove (frame, frame + n, nframe - n); + *r_result = frame; + *r_resultlen = nframe - n; + + if (DBG_CIPHER) + log_printhex ("value extracted from PKCS#1 block type 2 encoded data:", + *r_result, *r_resultlen); + + return 0; +} + + +/* Encode {VALUE,VALUELEN} for an NBITS keys and hash algorith ALGO + using the pkcs#1 block type 1 padding. On success the result is + stored as a new MPI at R_RESULT. On error the value at R_RESULT is + undefined. + + We encode the value in this way: + + 0 1 PAD(n bytes) 0 ASN(asnlen bytes) VALUE(valuelen bytes) + + 0 is a marker we unfortunately can't encode because we return an + MPI which strips all leading zeroes. + 1 is the block type. + PAD consists of 0xff bytes. + 0 marks the end of the padding. + ASN is the DER encoding of the hash algorithm; along with the VALUE + it yields a valid DER encoding. + + (Note that PGP prior to version 2.3 encoded the message digest as: + 0 1 MD(16 bytes) 0 PAD(n bytes) 1 + The MD is always 16 bytes here because it's always MD5. GnuPG + does not not support pre-v2.3 signatures, but I'm including this + comment so the information is easily found if needed.) +*/ +static gcry_err_code_t +pkcs1_encode_for_signature (gcry_mpi_t *r_result, unsigned int nbits, + const unsigned char *value, size_t valuelen, + int algo) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + byte asn[100]; + byte *frame = NULL; + size_t nframe = (nbits+7) / 8; + int i; + size_t n; + size_t asnlen, dlen; + + asnlen = DIM(asn); + dlen = gcry_md_get_algo_dlen (algo); + + if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) + { + /* We don't have yet all of the above algorithms. */ + return GPG_ERR_NOT_IMPLEMENTED; + } + + if ( valuelen != dlen ) + { + /* Hash value does not match the length of digest for + the given algorithm. */ + return GPG_ERR_CONFLICT; + } + + if ( !dlen || dlen + asnlen + 4 > nframe) + { + /* Can't encode an DLEN byte digest MD into an NFRAME byte + frame. */ + return GPG_ERR_TOO_SHORT; + } + + if ( !(frame = gcry_malloc (nframe)) ) + return gpg_err_code_from_syserror (); + + /* Assemble the pkcs#1 block type 1. */ + n = 0; + frame[n++] = 0; + frame[n++] = 1; /* block type */ + i = nframe - valuelen - asnlen - 3 ; + gcry_assert (i > 1); + memset (frame+n, 0xff, i ); + n += i; + frame[n++] = 0; + memcpy (frame+n, asn, asnlen); + n += asnlen; + memcpy (frame+n, value, valuelen ); + n += valuelen; + gcry_assert (n == nframe); + + /* Convert it into an MPI. */ + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, n, &nframe); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("PKCS#1 block type 1 encoded data", *r_result); + gcry_free (frame); + + return rc; +} + + +/* Mask generation function for OAEP. See RFC-3447 B.2.1. */ +static gcry_err_code_t +mgf1 (unsigned char *output, size_t outlen, unsigned char *seed, size_t seedlen, + int algo) +{ + size_t dlen, nbytes, n; + int idx; + gcry_md_hd_t hd; + gcry_error_t err; + + err = gcry_md_open (&hd, algo, 0); + if (err) + return gpg_err_code (err); + + dlen = gcry_md_get_algo_dlen (algo); + + /* We skip step 1 which would be assert(OUTLEN <= 2^32). The loop + in step 3 is merged with step 4 by concatenating no more octets + than what would fit into OUTPUT. The ceiling for the counter IDX + is implemented indirectly. */ + nbytes = 0; /* Step 2. */ + idx = 0; + while ( nbytes < outlen ) + { + unsigned char c[4], *digest; + + if (idx) + gcry_md_reset (hd); + + c[0] = (idx >> 24) & 0xFF; + c[1] = (idx >> 16) & 0xFF; + c[2] = (idx >> 8) & 0xFF; + c[3] = idx & 0xFF; + idx++; + + gcry_md_write (hd, seed, seedlen); + gcry_md_write (hd, c, 4); + digest = gcry_md_read (hd, 0); + + n = (outlen - nbytes < dlen)? (outlen - nbytes) : dlen; + memcpy (output+nbytes, digest, n); + nbytes += n; + } + + gcry_md_close (hd); + return GPG_ERR_NO_ERROR; +} + + +/* RFC-3447 (pkcs#1 v2.1) OAEP encoding. NBITS is the length of the + key measured in bits. ALGO is the hash function; it must be a + valid and usable algorithm. {VALUE,VALUELEN} is the message to + encrypt. {LABEL,LABELLEN} is the optional label to be associated + with the message, if LABEL is NULL the default is to use the empty + string as label. On success the encoded ciphertext is returned at + R_RESULT. + + If {RANDOM_OVERRIDE, RANDOM_OVERRIDE_LEN} is given it is used as + the seed instead of using a random string for it. This feature is + only useful for regression tests. + + Here is figure 1 from the RFC depicting the process: + + +----------+---------+-------+ + DB = | lHash | PS | M | + +----------+---------+-------+ + | + +----------+ V + | seed |--> MGF ---> xor + +----------+ | + | | + +--+ V | + |00| xor <----- MGF <-----| + +--+ | | + | | | + V V V + +--+----------+----------------------------+ + EM = |00|maskedSeed| maskedDB | + +--+----------+----------------------------+ + */ +static gcry_err_code_t +oaep_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo, + const unsigned char *value, size_t valuelen, + const unsigned char *label, size_t labellen, + const void *random_override, size_t random_override_len) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + unsigned char *frame = NULL; + size_t nframe = (nbits+7) / 8; + unsigned char *p; + size_t hlen; + size_t n; + + *r_result = NULL; + + /* Set defaults for LABEL. */ + if (!label || !labellen) + { + label = (const unsigned char*)""; + labellen = 0; + } + + hlen = gcry_md_get_algo_dlen (algo); + + /* We skip step 1a which would be to check that LABELLEN is not + greater than 2^61-1. See rfc-3447 7.1.1. */ + + /* Step 1b. Note that the obsolete rfc-2437 uses the check: + valuelen > nframe - 2 * hlen - 1 . */ + if (valuelen > nframe - 2 * hlen - 2 || !nframe) + { + /* Can't encode a VALUELEN value in a NFRAME bytes frame. */ + return GPG_ERR_TOO_SHORT; /* The key is too short. */ + } + + /* Allocate the frame. */ + frame = gcry_calloc_secure (1, nframe); + if (!frame) + return gpg_err_code_from_syserror (); + + /* Step 2a: Compute the hash of the label. We store it in the frame + where later the maskedDB will commence. */ + gcry_md_hash_buffer (algo, frame + 1 + hlen, label, labellen); + + /* Step 2b: Set octet string to zero. */ + /* This has already been done while allocating FRAME. */ + + /* Step 2c: Create DB by concatenating lHash, PS, 0x01 and M. */ + n = nframe - valuelen - 1; + frame[n] = 0x01; + memcpy (frame + n + 1, value, valuelen); + + /* Step 3d: Generate seed. We store it where the maskedSeed will go + later. */ + if (random_override) + { + if (random_override_len != hlen) + { + gcry_free (frame); + return GPG_ERR_INV_ARG; + } + memcpy (frame + 1, random_override, hlen); + } + else + gcry_randomize (frame + 1, hlen, GCRY_STRONG_RANDOM); + + /* Step 2e and 2f: Create maskedDB. */ + { + unsigned char *dmask; + + dmask = gcry_malloc_secure (nframe - hlen - 1); + if (!dmask) + { + rc = gpg_err_code_from_syserror (); + gcry_free (frame); + return rc; + } + rc = mgf1 (dmask, nframe - hlen - 1, frame+1, hlen, algo); + if (rc) + { + gcry_free (dmask); + gcry_free (frame); + return rc; + } + for (n = 1 + hlen, p = dmask; n < nframe; n++) + frame[n] ^= *p++; + gcry_free (dmask); + } + + /* Step 2g and 2h: Create maskedSeed. */ + { + unsigned char *smask; + + smask = gcry_malloc_secure (hlen); + if (!smask) + { + rc = gpg_err_code_from_syserror (); + gcry_free (frame); + return rc; + } + rc = mgf1 (smask, hlen, frame + 1 + hlen, nframe - hlen - 1, algo); + if (rc) + { + gcry_free (smask); + gcry_free (frame); + return rc; + } + for (n = 1, p = smask; n < 1 + hlen; n++) + frame[n] ^= *p++; + gcry_free (smask); + } + + /* Step 2i: Concatenate 0x00, maskedSeed and maskedDB. */ + /* This has already been done by using in-place operations. */ + + /* Convert the stuff into an MPI as expected by the caller. */ + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, frame, nframe, NULL); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("OAEP encoded data", *r_result); + gcry_free (frame); + + return rc; +} + + +/* RFC-3447 (pkcs#1 v2.1) OAEP decoding. NBITS is the length of the + key measured in bits. ALGO is the hash function; it must be a + valid and usable algorithm. VALUE is the raw decrypted message + {LABEL,LABELLEN} is the optional label to be associated with the + message, if LABEL is NULL the default is to use the empty string as + label. On success the plaintext is returned as a newly allocated + buffer at R_RESULT; its valid length is stored at R_RESULTLEN. On + error NULL is stored at R_RESULT. */ +static gcry_err_code_t +oaep_decode (unsigned char **r_result, size_t *r_resultlen, + unsigned int nbits, int algo, + gcry_mpi_t value, const unsigned char *label, size_t labellen) +{ + gcry_err_code_t rc; + unsigned char *frame = NULL; /* Encoded messages (EM). */ + unsigned char *masked_seed; /* Points into FRAME. */ + unsigned char *masked_db; /* Points into FRAME. */ + unsigned char *seed = NULL; /* Allocated space for the seed and DB. */ + unsigned char *db; /* Points into SEED. */ + unsigned char *lhash = NULL; /* Hash of the label. */ + size_t nframe; /* Length of the ciphertext (EM). */ + size_t hlen; /* Length of the hash digest. */ + size_t db_len; /* Length of DB and masked_db. */ + size_t nkey = (nbits+7)/8; /* Length of the key in bytes. */ + int failed = 0; /* Error indicator. */ + size_t n; + + *r_result = NULL; + + /* This code is implemented as described by rfc-3447 7.1.2. */ + + /* Set defaults for LABEL. */ + if (!label || !labellen) + { + label = (const unsigned char*)""; + labellen = 0; + } + + /* Get the length of the digest. */ + hlen = gcry_md_get_algo_dlen (algo); + + /* Hash the label right away. */ + lhash = gcry_malloc (hlen); + if (!lhash) + return gpg_err_code_from_syserror (); + gcry_md_hash_buffer (algo, lhash, label, labellen); + + /* Turn the MPI into an octet string. If the octet string is + shorter than the key we pad it to the left with zeroes. This may + happen due to the leading zero in OAEP frames and due to the + following random octets (seed^mask) which may have leading zero + bytes. This all is needed to cope with our leading zeroes + suppressing MPI implementation. The code implictly implements + Step 1b (bail out if NFRAME != N). */ + rc = octet_string_from_mpi (&frame, NULL, value, nkey); + if (rc) + { + gcry_free (lhash); + return GPG_ERR_ENCODING_PROBLEM; + } + nframe = nkey; + + /* Step 1c: Check that the key is long enough. */ + if ( nframe < 2 * hlen + 2 ) + { + gcry_free (frame); + gcry_free (lhash); + return GPG_ERR_ENCODING_PROBLEM; + } + + /* Step 2 has already been done by the caller and the + gcry_mpi_aprint above. */ + + /* Allocate space for SEED and DB. */ + seed = gcry_malloc_secure (nframe - 1); + if (!seed) + { + rc = gpg_err_code_from_syserror (); + gcry_free (frame); + gcry_free (lhash); + return rc; + } + db = seed + hlen; + + /* To avoid choosen ciphertext attacks from now on we make sure to + run all code even in the error case; this avoids possible timing + attacks as described by Manger. */ + + /* Step 3a: Hash the label. */ + /* This has already been done. */ + + /* Step 3b: Separate the encoded message. */ + masked_seed = frame + 1; + masked_db = frame + 1 + hlen; + db_len = nframe - 1 - hlen; + + /* Step 3c and 3d: seed = maskedSeed ^ mgf(maskedDB, hlen). */ + if (mgf1 (seed, hlen, masked_db, db_len, algo)) + failed = 1; + for (n = 0; n < hlen; n++) + seed[n] ^= masked_seed[n]; + + /* Step 3e and 3f: db = maskedDB ^ mgf(seed, db_len). */ + if (mgf1 (db, db_len, seed, hlen, algo)) + failed = 1; + for (n = 0; n < db_len; n++) + db[n] ^= masked_db[n]; + + /* Step 3g: Check lhash, an possible empty padding string terminated + by 0x01 and the first byte of EM being 0. */ + if (memcmp (lhash, db, hlen)) + failed = 1; + for (n = hlen; n < db_len; n++) + if (db[n] == 0x01) + break; + if (n == db_len) + failed = 1; + if (frame[0]) + failed = 1; + + gcry_free (lhash); + gcry_free (frame); + if (failed) + { + gcry_free (seed); + return GPG_ERR_ENCODING_PROBLEM; + } + + /* Step 4: Output M. */ + /* To avoid an extra allocation we reuse the seed buffer. The only + caller of this function will anyway free the result soon. */ + n++; + memmove (seed, db + n, db_len - n); + *r_result = seed; + *r_resultlen = db_len - n; + seed = NULL; + + if (DBG_CIPHER) + log_printhex ("value extracted from OAEP encoded data:", + *r_result, *r_resultlen); + + return 0; +} + + +/* RFC-3447 (pkcs#1 v2.1) PSS encoding. Encode {VALUE,VALUELEN} for + an NBITS key. Note that VALUE is already the mHash from the + picture below. ALGO is a valid hash algorithm and SALTLEN is the + length of salt to be used. On success the result is stored as a + new MPI at R_RESULT. On error the value at R_RESULT is undefined. + + If {RANDOM_OVERRIDE, RANDOM_OVERRIDE_LEN} is given it is used as + the salt instead of using a random string for the salt. This + feature is only useful for regression tests. + + Here is figure 2 from the RFC (errata 595 applied) depicting the + process: + + +-----------+ + | M | + +-----------+ + | + V + Hash + | + V + +--------+----------+----------+ + M' = |Padding1| mHash | salt | + +--------+----------+----------+ + | + +--------+----------+ V + DB = |Padding2| salt | Hash + +--------+----------+ | + | | + V | +----+ + xor <--- MGF <---| |0xbc| + | | +----+ + | | | + V V V + +-------------------+----------+----+ + EM = | maskedDB | H |0xbc| + +-------------------+----------+----+ + + */ +static gcry_err_code_t +pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo, + const unsigned char *value, size_t valuelen, int saltlen, + const void *random_override, size_t random_override_len) +{ + gcry_err_code_t rc = 0; + gcry_error_t err; + size_t hlen; /* Length of the hash digest. */ + unsigned char *em = NULL; /* Encoded message. */ + size_t emlen = (nbits+7)/8; /* Length in bytes of EM. */ + unsigned char *h; /* Points into EM. */ + unsigned char *buf = NULL; /* Help buffer. */ + size_t buflen; /* Length of BUF. */ + unsigned char *mhash; /* Points into BUF. */ + unsigned char *salt; /* Points into BUF. */ + unsigned char *dbmask; /* Points into BUF. */ + unsigned char *p; + size_t n; + + /* This code is implemented as described by rfc-3447 9.1.1. */ + + /* Get the length of the digest. */ + hlen = gcry_md_get_algo_dlen (algo); + gcry_assert (hlen); /* We expect a valid ALGO here. */ + + /* Allocate a help buffer and setup some pointers. */ + buflen = 8 + hlen + saltlen + (emlen - hlen - 1); + buf = gcry_malloc (buflen); + if (!buf) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + mhash = buf + 8; + salt = mhash + hlen; + dbmask= salt + saltlen; + + /* Step 2: That would be: mHash = Hash(M) but our input is already + mHash thus we do only a consistency check and copy to MHASH. */ + if (valuelen != hlen) + { + rc = GPG_ERR_INV_LENGTH; + goto leave; + } + memcpy (mhash, value, hlen); + + /* Step 3: Check length constraints. */ + if (emlen < hlen + saltlen + 2) + { + rc = GPG_ERR_TOO_SHORT; + goto leave; + } + + /* Allocate space for EM. */ + em = gcry_malloc (emlen); + if (!em) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + h = em + emlen - 1 - hlen; + + /* Step 4: Create a salt. */ + if (saltlen) + { + if (random_override) + { + if (random_override_len != saltlen) + { + rc = GPG_ERR_INV_ARG; + goto leave; + } + memcpy (salt, random_override, saltlen); + } + else + gcry_randomize (salt, saltlen, GCRY_STRONG_RANDOM); + } + + /* Step 5 and 6: M' = Hash(Padding1 || mHash || salt). */ + memset (buf, 0, 8); /* Padding. */ + gcry_md_hash_buffer (algo, h, buf, 8 + hlen + saltlen); + + /* Step 7 and 8: DB = PS || 0x01 || salt. */ + /* Note that we use EM to store DB and later Xor in-place. */ + p = em + emlen - 1 - hlen - saltlen - 1; + memset (em, 0, p - em); + *p++ = 0x01; + memcpy (p, salt, saltlen); + + /* Step 9: dbmask = MGF(H, emlen - hlen - 1). */ + mgf1 (dbmask, emlen - hlen - 1, h, hlen, algo); + + /* Step 10: maskedDB = DB ^ dbMask */ + for (n = 0, p = dbmask; n < emlen - hlen - 1; n++, p++) + em[n] ^= *p; + + /* Step 11: Set the leftmost bits to zero. */ + em[0] &= 0xFF >> (8 * emlen - nbits); + + /* Step 12: EM = maskedDB || H || 0xbc. */ + em[emlen-1] = 0xbc; + + /* Convert EM into an MPI. */ + err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, em, emlen, NULL); + if (err) + rc = gcry_err_code (err); + else if (DBG_CIPHER) + log_mpidump ("PSS encoded data", *r_result); + + leave: + if (em) + { + wipememory (em, emlen); + gcry_free (em); + } + if (buf) + { + wipememory (buf, buflen); + gcry_free (buf); + } + return rc; +} + + +/* Verify a signature assuming PSS padding. VALUE is the hash of the + message (mHash) encoded as an MPI; its length must match the digest + length of ALGO. ENCODED is the output of the RSA public key + function (EM). NBITS is the size of the public key. ALGO is the + hash algorithm and SALTLEN is the length of the used salt. The + function returns 0 on success or on error code. */ +static gcry_err_code_t +pss_verify (gcry_mpi_t value, gcry_mpi_t encoded, unsigned int nbits, int algo, + size_t saltlen) +{ + gcry_err_code_t rc = 0; + size_t hlen; /* Length of the hash digest. */ + unsigned char *em = NULL; /* Encoded message. */ + size_t emlen = (nbits+7)/8; /* Length in bytes of EM. */ + unsigned char *salt; /* Points into EM. */ + unsigned char *h; /* Points into EM. */ + unsigned char *buf = NULL; /* Help buffer. */ + size_t buflen; /* Length of BUF. */ + unsigned char *dbmask; /* Points into BUF. */ + unsigned char *mhash; /* Points into BUF. */ + unsigned char *p; + size_t n; + + /* This code is implemented as described by rfc-3447 9.1.2. */ + + /* Get the length of the digest. */ + hlen = gcry_md_get_algo_dlen (algo); + gcry_assert (hlen); /* We expect a valid ALGO here. */ + + /* Allocate a help buffer and setup some pointers. + This buffer is used for two purposes: + +------------------------------+-------+ + 1. | dbmask | mHash | + +------------------------------+-------+ + emlen - hlen - 1 hlen + + +----------+-------+---------+-+-------+ + 2. | padding1 | mHash | salt | | mHash | + +----------+-------+---------+-+-------+ + 8 hlen saltlen hlen + */ + buflen = 8 + hlen + saltlen; + if (buflen < emlen - hlen - 1) + buflen = emlen - hlen - 1; + buflen += hlen; + buf = gcry_malloc (buflen); + if (!buf) + { + rc = gpg_err_code_from_syserror (); + goto leave; + } + dbmask = buf; + mhash = buf + buflen - hlen; + + /* Step 2: That would be: mHash = Hash(M) but our input is already + mHash thus we only need to convert VALUE into MHASH. */ + rc = octet_string_from_mpi (NULL, mhash, value, hlen); + if (rc) + goto leave; + + /* Convert the signature into an octet string. */ + rc = octet_string_from_mpi (&em, NULL, encoded, emlen); + if (rc) + goto leave; + + /* Step 3: Check length of EM. Because we internally use MPI + functions we can't do this properly; EMLEN is always the length + of the key because octet_string_from_mpi needs to left pad the + result with zero to cope with the fact that our MPIs suppress all + leading zeroes. Thus what we test here are merely the digest and + salt lengths to the key. */ + if (emlen < hlen + saltlen + 2) + { + rc = GPG_ERR_TOO_SHORT; /* For the hash and saltlen. */ + goto leave; + } + + /* Step 4: Check last octet. */ + if (em[emlen - 1] != 0xbc) + { + rc = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + + /* Step 5: Split EM. */ + h = em + emlen - 1 - hlen; + + /* Step 6: Check the leftmost bits. */ + if ((em[0] & ~(0xFF >> (8 * emlen - nbits)))) + { + rc = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + + /* Step 7: dbmask = MGF(H, emlen - hlen - 1). */ + mgf1 (dbmask, emlen - hlen - 1, h, hlen, algo); + + /* Step 8: maskedDB = DB ^ dbMask. */ + for (n = 0, p = dbmask; n < emlen - hlen - 1; n++, p++) + em[n] ^= *p; + + /* Step 9: Set leftmost bits in DB to zero. */ + em[0] &= 0xFF >> (8 * emlen - nbits); + + /* Step 10: Check the padding of DB. */ + for (n = 0; n < emlen - hlen - saltlen - 2 && !em[n]; n++) + ; + if (n != emlen - hlen - saltlen - 2 || em[n++] != 1) + { + rc = GPG_ERR_BAD_SIGNATURE; + goto leave; + } + + /* Step 11: Extract salt from DB. */ + salt = em + n; + + /* Step 12: M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt */ + memset (buf, 0, 8); + memcpy (buf+8, mhash, hlen); + memcpy (buf+8+hlen, salt, saltlen); + + /* Step 13: H' = Hash(M'). */ + gcry_md_hash_buffer (algo, buf, buf, 8 + hlen + saltlen); + + /* Step 14: Check H == H'. */ + rc = memcmp (h, buf, hlen) ? GPG_ERR_BAD_SIGNATURE : GPG_ERR_NO_ERROR; + + leave: + if (em) + { + wipememory (em, emlen); + gcry_free (em); + } + if (buf) + { + wipememory (buf, buflen); + gcry_free (buf); + } + return rc; +} + + +/* Callback for the pubkey algorithm code to verify PSS signatures. + OPAQUE is the data provided by the actual caller. The meaning of + TMP depends on the actual algorithm (but there is only RSA); now + for RSA it is the output of running the public key function on the + input. */ +static int +pss_verify_cmp (void *opaque, gcry_mpi_t tmp) +{ + struct pk_encoding_ctx *ctx = opaque; + gcry_mpi_t hash = ctx->verify_arg; + + return pss_verify (hash, tmp, ctx->nbits - 1, ctx->hash_algo, ctx->saltlen); +} + + /* Internal function. */ static gcry_err_code_t sexp_elements_extract (gcry_sexp_t key_sexp, const char *element_names, @@ -855,7 +1869,11 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, /* Clear the array for easier error cleanup. */ for (name = element_names, idx = 0; *name; name++, idx++) elements[idx] = NULL; - gcry_assert (idx >= 6); /* We know that ECC has at least 6 elements. */ + gcry_assert (idx >= 5); /* We know that ECC has at least 5 elements + (params only) or 6 (full public key). */ + if (idx == 5) + elements[5] = NULL; /* Extra clear for the params only case. */ + /* Init the array with the available curve parameters. */ for (name = element_names, idx = 0; *name && !err; name++, idx++) @@ -884,23 +1902,23 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, { char *curve; gcry_mpi_t params[6]; - + for (idx = 0; idx < DIM(params); idx++) params[idx] = NULL; - + curve = _gcry_sexp_nth_string (list, 1); gcry_sexp_release (list); if (!curve) { /* No curve name given (or out of core). */ - err = GPG_ERR_INV_OBJ; + err = GPG_ERR_INV_OBJ; goto leave; } err = extraspec->get_param (curve, params); gcry_free (curve); if (err) goto leave; - + for (idx = 0; idx < DIM(params); idx++) { if (!elements[idx]) @@ -924,7 +1942,7 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, err = GPG_ERR_NO_OBJ; goto leave; } - + leave: if (err) { @@ -948,6 +1966,7 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, * openpgp-elg * openpgp-elg-sig * ecdsa + * ecdh * Provide a SE with the first element be either "private-key" or * or "public-key". It is followed by a list with its first element * be one of the above algorithm identifiers and the remaning @@ -955,6 +1974,10 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, * NOTE: we look through the list to find a list beginning with * "private-key" or "public-key" - the first one found is used. * + * If OVERRIDE_ELEMS is not NULL those elems override the parameter + * specification taken from the module. This ise used by + * gcry_pk_get_curve. + * * Returns: A pointer to an allocated array of MPIs if the return value is * zero; the caller has to release this array. * @@ -970,8 +1993,8 @@ sexp_elements_extract_ecc (gcry_sexp_t key_sexp, const char *element_names, * The are expected to be in GCRYMPI_FMT_USG */ static gcry_err_code_t -sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, - gcry_module_t *retalgo) +sexp_to_key (gcry_sexp_t sexp, int want_private, const char *override_elems, + gcry_mpi_t **retarray, gcry_module_t *retalgo) { gcry_err_code_t err = 0; gcry_sexp_t list, l2; @@ -984,7 +2007,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, int is_ecc; /* Check that the first element is valid. */ - list = gcry_sexp_find_token (sexp, + list = gcry_sexp_find_token (sexp, want_private? "private-key":"public-key", 0); if (!list) return GPG_ERR_INV_OBJ; /* Does not contain a key object. */ @@ -1002,16 +2025,18 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, ath_mutex_lock (&pubkeys_registered_lock); module = gcry_pk_lookup_name (name); ath_mutex_unlock (&pubkeys_registered_lock); - + /* Fixme: We should make sure that an ECC key is always named "ecc" and not "ecdsa". "ecdsa" should be used for the signature itself. We need a function to test whether an algorithm given with a key is compatible with an application of the key (signing, encryption). For RSA this is easy, but ECC is the first - algorithm which has many flavours. */ - is_ecc = ( !strcmp (name, "ecdsa") || !strcmp (name, "ecc") ); + algorithm which has many flavours. */ + is_ecc = ( !strcmp (name, "ecdsa") + || !strcmp (name, "ecdh") + || !strcmp (name, "ecc") ); gcry_free (name); - + if (!module) { gcry_sexp_release (list); @@ -1023,10 +2048,15 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, extraspec = module->extraspec; } - elems = want_private ? pubkey->elements_skey : pubkey->elements_pkey; + if (override_elems) + elems = override_elems; + else if (want_private) + elems = pubkey->elements_skey; + else + elems = pubkey->elements_pkey; array = gcry_calloc (strlen (elems) + 1, sizeof (*array)); if (!array) - err = gpg_err_code_from_errno (errno); + err = gpg_err_code_from_syserror (); if (!err) { if (is_ecc) @@ -1034,9 +2064,9 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, else err = sexp_elements_extract (list, elems, array, pubkey->name); } - + gcry_sexp_release (list); - + if (err) { gcry_free (array); @@ -1050,7 +2080,7 @@ sexp_to_key (gcry_sexp_t sexp, int want_private, gcry_mpi_t **retarray, *retarray = array; *retalgo = module; } - + return err; } @@ -1066,7 +2096,7 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_mpi_t *array; gcry_module_t module; gcry_pk_spec_t *pubkey; - + /* Check that the first element is valid. */ list = gcry_sexp_find_token( sexp, "sig-val" , 0 ); if (!list) @@ -1085,7 +2115,7 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, gcry_sexp_release (l2); return GPG_ERR_INV_OBJ; /* Invalid structure of object. */ } - else if (!strcmp (name, "flags")) + else if (!strcmp (name, "flags")) { /* Skip flags, since they are not used but here just for the sake of consistent S-expressions. */ @@ -1099,7 +2129,7 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, } name = _gcry_sexp_nth_string (l2, 0); } - + ath_mutex_lock (&pubkeys_registered_lock); module = gcry_pk_lookup_name (name); ath_mutex_unlock (&pubkeys_registered_lock); @@ -1118,7 +2148,7 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, elems = pubkey->elements_sig; array = gcry_calloc (strlen (elems) + 1 , sizeof *array ); if (!array) - err = gpg_err_code_from_errno (errno); + err = gpg_err_code_from_syserror (); if (!err) err = sexp_elements_extract (list, elems, array, NULL); @@ -1131,7 +2161,7 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, ath_mutex_lock (&pubkeys_registered_lock); _gcry_module_release (module); ath_mutex_unlock (&pubkeys_registered_lock); - + gcry_free (array); } else @@ -1139,26 +2169,82 @@ sexp_to_sig (gcry_sexp_t sexp, gcry_mpi_t **retarray, *retarray = array; *retalgo = module; } - + return err; } +static inline int +get_hash_algo (const char *s, size_t n) +{ + static const struct { const char *name; int algo; } hashnames[] = { + { "sha1", GCRY_MD_SHA1 }, + { "md5", GCRY_MD_MD5 }, + { "sha256", GCRY_MD_SHA256 }, + { "ripemd160", GCRY_MD_RMD160 }, + { "rmd160", GCRY_MD_RMD160 }, + { "sha384", GCRY_MD_SHA384 }, + { "sha512", GCRY_MD_SHA512 }, + { "sha224", GCRY_MD_SHA224 }, + { "md2", GCRY_MD_MD2 }, + { "md4", GCRY_MD_MD4 }, + { "tiger", GCRY_MD_TIGER }, + { "haval", GCRY_MD_HAVAL }, + { NULL, 0 } + }; + int algo; + int i; + + for (i=0; hashnames[i].name; i++) + { + if ( strlen (hashnames[i].name) == n + && !memcmp (hashnames[i].name, s, n)) + break; + } + if (hashnames[i].name) + algo = hashnames[i].algo; + else + { + /* In case of not listed or dynamically allocated hash + algorithm we fall back to this somewhat slower + method. Further, it also allows to use OIDs as + algorithm names. */ + char *tmpname; + + tmpname = gcry_malloc (n+1); + if (!tmpname) + algo = 0; /* Out of core - silently give up. */ + else + { + memcpy (tmpname, s, n); + tmpname[n] = 0; + algo = gcry_md_map_name (tmpname); + gcry_free (tmpname); + } + } + return algo; +} + /**************** * Take sexp and return an array of MPI as used for our internal decrypt * function. * s_data = (enc-val - * [(flags [pkcs1])] + * [(flags [raw, pkcs1, oaep, no-blinding])] + * [(hash-algo )] + * [(label